Line data Source code
1 : /* File: data_diagram_iterator.c; Copyright and License: see below */
2 :
3 : #include "storage/data_diagram_iterator.h"
4 : #include "u8/u8_trace.h"
5 : #include "u8/u8_log.h"
6 : #include "utf8stringbuf/utf8stringbuf.h"
7 : #include <sqlite3.h>
8 : #include <assert.h>
9 : #include <stdint.h>
10 :
11 : const char *const DATA_DIAGRAM_ITERATOR_SELECT_DIAGRAMS_BY_PARENT_ID =
12 : "SELECT id,parent_id,diagram_type,stereotype,name,description,list_order,display_flags,uuid "
13 : "FROM diagrams WHERE parent_id=? ORDER BY list_order ASC;";
14 :
15 : const char *const DATA_DIAGRAM_ITERATOR_SELECT_DIAGRAMS_BY_PARENT_ID_NULL =
16 : "SELECT id,parent_id,diagram_type,stereotype,name,description,list_order,display_flags,uuid "
17 : "FROM diagrams WHERE parent_id IS NULL ORDER BY list_order ASC,diagrams.id ASC;"; /* ensure always the same order */
18 :
19 : const char *const DATA_DIAGRAM_ITERATOR_SELECT_DIAGRAMS_BY_CLASSIFIER_ID =
20 : "SELECT diagrams.id,diagrams.parent_id,diagrams.diagram_type,diagrams.stereotype,"
21 : "diagrams.name,diagrams.description,diagrams.list_order,diagrams.display_flags,diagrams.uuid "
22 : "FROM diagrams "
23 : "INNER JOIN diagramelements ON diagramelements.diagram_id=diagrams.id "
24 : "WHERE diagramelements.classifier_id=? "
25 : "GROUP BY diagrams.id " /* filter duplicates if a classifier exists twice in a diagram */
26 : "ORDER BY diagrams.list_order ASC,diagrams.id ASC;"; /* ensure always the same order */
27 :
28 : const char *const DATA_DIAGRAM_ITERATOR_SELECT_DIAGRAMS_BY_RELATIONSHIP_ID =
29 : "SELECT diagrams.id,diagrams.parent_id,diagrams.diagram_type,diagrams.stereotype,"
30 : "diagrams.name,diagrams.description,diagrams.list_order,diagrams.display_flags,diagrams.uuid "
31 : "FROM relationships "
32 : "INNER JOIN diagramelements AS source ON source.classifier_id=relationships.from_classifier_id "
33 : "INNER JOIN diagramelements AS dest ON (dest.classifier_id=relationships.to_classifier_id) AND (dest.diagram_id=source.diagram_id) "
34 : "INNER JOIN diagrams ON diagrams.id=source.diagram_id "
35 : "WHERE relationships.id=? "
36 : "AND ( (source.focused_feature_id=relationships.from_feature_id) OR (source.focused_feature_id ISNULL) ) "
37 : "AND ( (dest.focused_feature_id=relationships.to_feature_id) OR (dest.focused_feature_id ISNULL) ) "
38 : "GROUP BY diagrams.id " /* filter duplicates if a relationship exists twice in a diagram */
39 : "ORDER BY ( (source.focused_feature_id ISNULL) AND (dest.focused_feature_id ISNULL) ) ASC," /* start with interactions/scenarios */
40 : "diagrams.list_order ASC,diagrams.id ASC;"; /* ensure always the same order */
41 :
42 : /* Note: This query omits scenario/interaction diagrams */
43 : /* which either contain the searched relationship as invariant/non-scenario relationship */
44 : /* or which show another lifeline than the one of the searched relationship. */
45 : /* It does not filter any invariant/non-scenario diagram even if the relationship is not visible there. */
46 :
47 : /*!
48 : * \brief the column id of the result where this parameter is stored: id
49 : */
50 : static const int RESULT_DIAGRAM_ID_COLUMN = 0;
51 :
52 : /*!
53 : * \brief the column id of the result where this parameter is stored: parent_id
54 : */
55 : static const int RESULT_DIAGRAM_PARENT_ID_COLUMN = 1;
56 :
57 : /*!
58 : * \brief the column id of the result where this parameter is stored: type
59 : */
60 : static const int RESULT_DIAGRAM_TYPE_COLUMN = 2;
61 :
62 : /*!
63 : * \brief the column id of the result where this parameter is stored: stereotype
64 : */
65 : static const int RESULT_DIAGRAM_STEREOTYPE_COLUMN = 3;
66 :
67 : /*!
68 : * \brief the column id of the result where this parameter is stored: name
69 : */
70 : static const int RESULT_DIAGRAM_NAME_COLUMN = 4;
71 :
72 : /*!
73 : * \brief the column id of the result where this parameter is stored: description
74 : */
75 : static const int RESULT_DIAGRAM_DESCRIPTION_COLUMN = 5;
76 :
77 : /*!
78 : * \brief the column id of the result where this parameter is stored: list_order
79 : */
80 : static const int RESULT_DIAGRAM_LIST_ORDER_COLUMN = 6;
81 :
82 : /*!
83 : * \brief the column id of the result where this parameter is stored: display_flags
84 : */
85 : static const int RESULT_DIAGRAM_DISPLAY_FLAGS_COLUMN = 7;
86 :
87 : /*!
88 : * \brief the column id of the result where this parameter is stored: uuid
89 : */
90 : static const int RESULT_DIAGRAM_UUID_COLUMN = 8;
91 :
92 189 : u8_error_t data_diagram_iterator_init_empty ( data_diagram_iterator_t *this_ )
93 : {
94 189 : U8_TRACE_BEGIN();
95 189 : u8_error_t result = U8_ERROR_NONE;
96 :
97 189 : data_database_borrowed_stmt_init_void( &((*this_).statement) );
98 189 : (*this_).is_at_end = true;
99 :
100 189 : U8_TRACE_END_ERR(result);
101 189 : return result;
102 : }
103 :
104 189 : u8_error_t data_diagram_iterator_reinit ( data_diagram_iterator_t *this_,
105 : data_database_borrowed_stmt_t statement )
106 : {
107 189 : U8_TRACE_BEGIN();
108 189 : assert( data_database_borrowed_stmt_is_valid( &statement ) );
109 189 : u8_error_t result = U8_ERROR_NONE;
110 :
111 : /* destroy old state */
112 189 : result = data_diagram_iterator_destroy( this_ );
113 :
114 : /* init new state */
115 189 : (*this_).statement = statement;
116 189 : (*this_).is_at_end = false;
117 189 : result |= data_diagram_iterator_private_step_to_next( this_ );
118 :
119 189 : U8_TRACE_END_ERR(result);
120 189 : return result;
121 : }
122 :
123 378 : u8_error_t data_diagram_iterator_destroy ( data_diagram_iterator_t *this_ )
124 : {
125 378 : U8_TRACE_BEGIN();
126 378 : u8_error_t result = U8_ERROR_NONE;
127 :
128 378 : result |= data_database_borrowed_stmt_destroy( &((*this_).statement) );
129 378 : (*this_).is_at_end = true;
130 :
131 378 : U8_TRACE_END_ERR(result);
132 378 : return result;
133 : }
134 :
135 221 : bool data_diagram_iterator_has_next ( const data_diagram_iterator_t *this_ )
136 : {
137 221 : return ( ! (*this_).is_at_end );
138 : }
139 :
140 43 : u8_error_t data_diagram_iterator_next ( data_diagram_iterator_t *this_, data_diagram_t *out_diagram )
141 : {
142 43 : U8_TRACE_BEGIN();
143 43 : assert( NULL != out_diagram );
144 43 : assert( data_database_borrowed_stmt_is_valid( &((*this_).statement) ) );
145 43 : u8_error_t result = U8_ERROR_NONE;
146 :
147 43 : if ( ! (*this_).is_at_end )
148 : {
149 41 : sqlite3_stmt *const sql_statement = data_database_borrowed_stmt_get_statement( &((*this_).statement) );
150 82 : result |= data_diagram_init( out_diagram,
151 41 : sqlite3_column_int64( sql_statement, RESULT_DIAGRAM_ID_COLUMN ),
152 41 : sqlite3_column_int64( sql_statement, RESULT_DIAGRAM_PARENT_ID_COLUMN ),
153 41 : sqlite3_column_int( sql_statement, RESULT_DIAGRAM_TYPE_COLUMN ),
154 41 : (const char*) sqlite3_column_text( sql_statement, RESULT_DIAGRAM_STEREOTYPE_COLUMN ),
155 41 : (const char*) sqlite3_column_text( sql_statement, RESULT_DIAGRAM_NAME_COLUMN ),
156 41 : (const char*) sqlite3_column_text( sql_statement, RESULT_DIAGRAM_DESCRIPTION_COLUMN ),
157 : sqlite3_column_int( sql_statement, RESULT_DIAGRAM_LIST_ORDER_COLUMN ),
158 41 : sqlite3_column_int64( sql_statement, RESULT_DIAGRAM_DISPLAY_FLAGS_COLUMN ),
159 41 : (const char*) sqlite3_column_text( sql_statement, RESULT_DIAGRAM_UUID_COLUMN )
160 : );
161 41 : if ( SQLITE_NULL == sqlite3_column_type( sql_statement, RESULT_DIAGRAM_PARENT_ID_COLUMN ) )
162 : {
163 38 : data_diagram_set_parent_row_id( out_diagram, DATA_ROW_VOID );
164 : }
165 41 : data_diagram_trace( out_diagram );
166 :
167 : /* step to next */
168 41 : result |= data_diagram_iterator_private_step_to_next( this_ );
169 : }
170 : else
171 : {
172 2 : U8_TRACE_INFO( "iterator already at end" );
173 2 : (*this_).is_at_end = true;
174 2 : result |= U8_ERROR_INVALID_REQUEST;
175 : }
176 :
177 43 : U8_TRACE_END_ERR( result );
178 43 : return result;
179 : }
180 :
181 230 : u8_error_t data_diagram_iterator_private_step_to_next ( data_diagram_iterator_t *this_ )
182 : {
183 230 : U8_TRACE_BEGIN();
184 230 : assert( data_database_borrowed_stmt_is_valid( &((*this_).statement) ) );
185 230 : u8_error_t result = U8_ERROR_NONE;
186 :
187 : /* do one step, check if is_at_end */
188 : {
189 : int sqlite_err;
190 230 : U8_TRACE_INFO( "sqlite3_step()" );
191 230 : sqlite_err = sqlite3_step( data_database_borrowed_stmt_get_statement( &((*this_).statement) ) );
192 230 : if ( SQLITE_DONE == sqlite_err )
193 : {
194 184 : U8_TRACE_INFO( "sqlite3_step finished: SQLITE_DONE" );
195 184 : (*this_).is_at_end = true;
196 : }
197 46 : else if ( SQLITE_ROW == sqlite_err )
198 : {
199 46 : (*this_).is_at_end = false;
200 : }
201 : else
202 : {
203 0 : U8_LOG_ERROR_INT( "sqlite3_step failed:", sqlite_err );
204 0 : (*this_).is_at_end = true;
205 0 : result |= data_diagram_iterator_destroy( this_ );
206 0 : result |= U8_ERROR_AT_DB;
207 : }
208 : }
209 :
210 230 : U8_TRACE_END_ERR(result);
211 230 : return result;
212 : }
213 :
214 :
215 : /*
216 : Copyright 2024-2025 Andreas Warnke
217 :
218 : Licensed under the Apache License, Version 2.0 (the "License");
219 : you may not use this file except in compliance with the License.
220 : You may obtain a copy of the License at
221 :
222 : http://www.apache.org/licenses/LICENSE-2.0
223 :
224 : Unless required by applicable law or agreed to in writing, software
225 : distributed under the License is distributed on an "AS IS" BASIS,
226 : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
227 : See the License for the specific language governing permissions and
228 : limitations under the License.
229 : */
|