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 264 : void data_diagram_iterator_init_empty ( data_diagram_iterator_t *this_ )
93 : {
94 264 : U8_TRACE_BEGIN();
95 :
96 264 : data_database_borrowed_stmt_init_void( &((*this_).statement) );
97 264 : (*this_).is_at_end = true;
98 :
99 264 : U8_TRACE_END();
100 264 : }
101 :
102 264 : u8_error_t data_diagram_iterator_reinit ( data_diagram_iterator_t *this_,
103 : data_database_borrowed_stmt_t statement )
104 : {
105 264 : U8_TRACE_BEGIN();
106 264 : assert( data_database_borrowed_stmt_is_valid( &statement ) );
107 264 : u8_error_t result = U8_ERROR_NONE;
108 :
109 : /* destroy old state */
110 264 : result = data_diagram_iterator_destroy( this_ );
111 :
112 : /* init new state */
113 264 : (*this_).statement = statement;
114 264 : (*this_).is_at_end = false;
115 264 : result |= data_diagram_iterator_private_step_to_next( this_ );
116 :
117 264 : U8_TRACE_END_ERR(result);
118 264 : return result;
119 : }
120 :
121 528 : u8_error_t data_diagram_iterator_destroy ( data_diagram_iterator_t *this_ )
122 : {
123 528 : U8_TRACE_BEGIN();
124 528 : u8_error_t result = U8_ERROR_NONE;
125 :
126 528 : result |= data_database_borrowed_stmt_destroy( &((*this_).statement) );
127 528 : (*this_).is_at_end = true;
128 :
129 528 : U8_TRACE_END_ERR(result);
130 528 : return result;
131 : }
132 :
133 393 : bool data_diagram_iterator_has_next ( const data_diagram_iterator_t *this_ )
134 : {
135 393 : return ( ! (*this_).is_at_end );
136 : }
137 :
138 140 : u8_error_t data_diagram_iterator_next ( data_diagram_iterator_t *this_, data_diagram_t *out_diagram )
139 : {
140 140 : U8_TRACE_BEGIN();
141 140 : assert( NULL != out_diagram );
142 140 : assert( data_database_borrowed_stmt_is_valid( &((*this_).statement) ) );
143 140 : u8_error_t result = U8_ERROR_NONE;
144 :
145 140 : if ( ! (*this_).is_at_end )
146 : {
147 138 : sqlite3_stmt *const sql_statement = data_database_borrowed_stmt_get_statement( &((*this_).statement) );
148 138 : result |= data_diagram_init( out_diagram,
149 138 : sqlite3_column_int64( sql_statement, RESULT_DIAGRAM_ID_COLUMN ),
150 138 : sqlite3_column_int64( sql_statement, RESULT_DIAGRAM_PARENT_ID_COLUMN ),
151 138 : sqlite3_column_int( sql_statement, RESULT_DIAGRAM_TYPE_COLUMN ),
152 138 : (const char*) sqlite3_column_text( sql_statement, RESULT_DIAGRAM_STEREOTYPE_COLUMN ),
153 138 : (const char*) sqlite3_column_text( sql_statement, RESULT_DIAGRAM_NAME_COLUMN ),
154 138 : (const char*) sqlite3_column_text( sql_statement, RESULT_DIAGRAM_DESCRIPTION_COLUMN ),
155 138 : sqlite3_column_int( sql_statement, RESULT_DIAGRAM_LIST_ORDER_COLUMN ),
156 138 : sqlite3_column_int64( sql_statement, RESULT_DIAGRAM_DISPLAY_FLAGS_COLUMN ),
157 138 : (const char*) sqlite3_column_text( sql_statement, RESULT_DIAGRAM_UUID_COLUMN )
158 : );
159 138 : if ( SQLITE_NULL == sqlite3_column_type( sql_statement, RESULT_DIAGRAM_PARENT_ID_COLUMN ) )
160 : {
161 87 : data_diagram_set_parent_row( out_diagram, DATA_ROW_VOID );
162 : }
163 138 : data_diagram_trace( out_diagram );
164 :
165 : /* step to next */
166 138 : result |= data_diagram_iterator_private_step_to_next( this_ );
167 : }
168 : else
169 : {
170 2 : U8_TRACE_INFO( "iterator already at end" );
171 2 : (*this_).is_at_end = true;
172 2 : result |= U8_ERROR_INVALID_REQUEST;
173 : }
174 :
175 140 : U8_TRACE_END_ERR( result );
176 140 : return result;
177 : }
178 :
179 402 : u8_error_t data_diagram_iterator_private_step_to_next ( data_diagram_iterator_t *this_ )
180 : {
181 402 : U8_TRACE_BEGIN();
182 402 : assert( data_database_borrowed_stmt_is_valid( &((*this_).statement) ) );
183 402 : u8_error_t result = U8_ERROR_NONE;
184 :
185 : /* do one step, check if is_at_end */
186 : {
187 : int sqlite_err;
188 402 : U8_TRACE_INFO( "sqlite3_step()" );
189 402 : sqlite_err = sqlite3_step( data_database_borrowed_stmt_get_statement( &((*this_).statement) ) );
190 402 : if ( SQLITE_DONE == sqlite_err )
191 : {
192 256 : U8_TRACE_INFO( "sqlite3_step finished: SQLITE_DONE" );
193 256 : (*this_).is_at_end = true;
194 : }
195 146 : else if ( SQLITE_ROW == sqlite_err )
196 : {
197 146 : (*this_).is_at_end = false;
198 : }
199 : else
200 : {
201 0 : U8_LOG_ERROR_INT( "sqlite3_step failed:", sqlite_err );
202 0 : (*this_).is_at_end = true;
203 0 : result |= data_diagram_iterator_destroy( this_ );
204 0 : result |= U8_ERROR_AT_DB;
205 : }
206 : }
207 :
208 402 : U8_TRACE_END_ERR(result);
209 402 : return result;
210 : }
211 :
212 :
213 : /*
214 : Copyright 2024-2026 Andreas Warnke
215 :
216 : Licensed under the Apache License, Version 2.0 (the "License");
217 : you may not use this file except in compliance with the License.
218 : You may obtain a copy of the License at
219 :
220 : http://www.apache.org/licenses/LICENSE-2.0
221 :
222 : Unless required by applicable law or agreed to in writing, software
223 : distributed under the License is distributed on an "AS IS" BASIS,
224 : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
225 : See the License for the specific language governing permissions and
226 : limitations under the License.
227 : */
|