Line data Source code
1 : /* File: data_classifier_iterator.c; Copyright and License: see below */
2 :
3 : #include "storage/data_classifier_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 : /*
12 : * The "order by cnt" is important to ensure parent objects are iterated first, e.g. for xmi export
13 : * The "order by id" is important to get reproducable results
14 : */
15 : const char *const DATA_CLASSIFIER_ITERATOR_SELECT_ALL_HIERARCHICAL =
16 : "SELECT id,main_type,stereotype,name,description,x_order,y_order,list_order,uuid,"
17 : "(SELECT count(*) FROM relationships "
18 : "WHERE (relationships.to_classifier_id=classifiers.id) AND (relationships.to_feature_id IS NULL) "
19 : "AND (relationships.main_type=300)) AS cnt "
20 : "FROM classifiers "
21 : "ORDER BY cnt ASC,id ASC;";
22 :
23 : /*
24 : * The "order by id" is important to get reproducable results, e.g. for json export
25 : */
26 : const char *const DATA_CLASSIFIER_ITERATOR_SELECT_ALL =
27 : "SELECT id,main_type,stereotype,name,description,x_order,y_order,list_order,uuid,-1 "
28 : "FROM classifiers "
29 : "ORDER BY id ASC;";
30 :
31 : /*!
32 : * \brief the column id of the result where this parameter is stored: id
33 : */
34 : static const int RESULT_CLASSIFIER_ID_COLUMN = 0;
35 :
36 : /*!
37 : * \brief the column id of the result where this parameter is stored: main_type
38 : */
39 : static const int RESULT_CLASSIFIER_MAIN_TYPE_COLUMN = 1;
40 :
41 : /*!
42 : * \brief the column id of the result where this parameter is stored: stereotype
43 : */
44 : static const int RESULT_CLASSIFIER_STEREOTYPE_COLUMN = 2;
45 :
46 : /*!
47 : * \brief the column id of the result where this parameter is stored: name
48 : */
49 : static const int RESULT_CLASSIFIER_NAME_COLUMN = 3;
50 :
51 : /*!
52 : * \brief the column id of the result where this parameter is stored: description
53 : */
54 : static const int RESULT_CLASSIFIER_DESCRIPTION_COLUMN = 4;
55 :
56 : /*!
57 : * \brief the column id of the result where this parameter is stored: x_order
58 : */
59 : static const int RESULT_CLASSIFIER_X_ORDER_COLUMN = 5;
60 :
61 : /*!
62 : * \brief the column id of the result where this parameter is stored: y_order
63 : */
64 : static const int RESULT_CLASSIFIER_Y_ORDER_COLUMN = 6;
65 :
66 : /*!
67 : * \brief the column id of the result where this parameter is stored: list_order
68 : */
69 : static const int RESULT_CLASSIFIER_LIST_ORDER_COLUMN = 7;
70 :
71 : /*!
72 : * \brief the column id of the result where this parameter is stored: uuid
73 : */
74 : static const int RESULT_CLASSIFIER_UUID_COLUMN = 8;
75 :
76 : /*!
77 : * \brief the column id of the result where this parameter is stored: count of containment parents
78 : */
79 : static const int RESULT_CLASSIFIER_CONTAINMENT_PARENTS_COLUMN = 9;
80 :
81 5 : void data_classifier_iterator_init_empty ( data_classifier_iterator_t *this_ )
82 : {
83 5 : U8_TRACE_BEGIN();
84 :
85 5 : data_database_borrowed_stmt_init_void( &((*this_).statement) );
86 5 : (*this_).is_at_end = true;
87 :
88 5 : U8_TRACE_END();
89 5 : }
90 :
91 5 : u8_error_t data_classifier_iterator_reinit ( data_classifier_iterator_t *this_,
92 : data_database_borrowed_stmt_t statement )
93 : {
94 5 : U8_TRACE_BEGIN();
95 5 : assert( data_database_borrowed_stmt_is_valid( &statement ) );
96 5 : u8_error_t result = U8_ERROR_NONE;
97 :
98 : /* destroy old state */
99 5 : result = data_classifier_iterator_destroy( this_ );
100 :
101 : /* init new state */
102 5 : (*this_).statement = statement;
103 5 : (*this_).is_at_end = false;
104 5 : result |= data_classifier_iterator_private_step_to_next( this_ );
105 :
106 5 : U8_TRACE_END_ERR(result);
107 5 : return result;
108 : }
109 :
110 10 : u8_error_t data_classifier_iterator_destroy ( data_classifier_iterator_t *this_ )
111 : {
112 10 : U8_TRACE_BEGIN();
113 10 : u8_error_t result = U8_ERROR_NONE;
114 :
115 10 : result |= data_database_borrowed_stmt_destroy( &((*this_).statement) );
116 10 : (*this_).is_at_end = true;
117 :
118 10 : U8_TRACE_END_ERR(result);
119 10 : return result;
120 : }
121 :
122 7 : bool data_classifier_iterator_has_next ( const data_classifier_iterator_t *this_ )
123 : {
124 7 : return ( ! (*this_).is_at_end );
125 : }
126 :
127 3 : u8_error_t data_classifier_iterator_next ( data_classifier_iterator_t *this_, data_classifier_t *out_classifier )
128 : {
129 3 : U8_TRACE_BEGIN();
130 3 : assert( NULL != out_classifier );
131 3 : assert( data_database_borrowed_stmt_is_valid( &((*this_).statement) ) );
132 3 : u8_error_t result = U8_ERROR_NONE;
133 :
134 3 : if ( ! (*this_).is_at_end )
135 : {
136 2 : sqlite3_stmt *const sql_statement = data_database_borrowed_stmt_get_statement( &((*this_).statement) );
137 2 : data_row_t classifier_id = sqlite3_column_int64( sql_statement, RESULT_CLASSIFIER_ID_COLUMN );
138 2 : result |= data_classifier_reinit( out_classifier,
139 : classifier_id,
140 2 : sqlite3_column_int( sql_statement, RESULT_CLASSIFIER_MAIN_TYPE_COLUMN ),
141 2 : (const char*) sqlite3_column_text( sql_statement, RESULT_CLASSIFIER_STEREOTYPE_COLUMN ),
142 2 : (const char*) sqlite3_column_text( sql_statement, RESULT_CLASSIFIER_NAME_COLUMN ),
143 2 : (const char*) sqlite3_column_text( sql_statement, RESULT_CLASSIFIER_DESCRIPTION_COLUMN ),
144 2 : sqlite3_column_int( sql_statement, RESULT_CLASSIFIER_X_ORDER_COLUMN ),
145 2 : sqlite3_column_int( sql_statement, RESULT_CLASSIFIER_Y_ORDER_COLUMN ),
146 2 : sqlite3_column_int( sql_statement, RESULT_CLASSIFIER_LIST_ORDER_COLUMN ),
147 2 : (const char*) sqlite3_column_text( sql_statement, RESULT_CLASSIFIER_UUID_COLUMN )
148 : );
149 2 : data_classifier_trace( out_classifier );
150 2 : U8_TRACE_INFO_INT( "count of containment parents:", sqlite3_column_int( sql_statement, RESULT_CLASSIFIER_CONTAINMENT_PARENTS_COLUMN ));
151 :
152 : /* step to next */
153 2 : result |= data_classifier_iterator_private_step_to_next( this_ );
154 : }
155 : else
156 : {
157 1 : U8_TRACE_INFO( "iterator already at end" );
158 1 : (*this_).is_at_end = true;
159 1 : result |= U8_ERROR_INVALID_REQUEST;
160 : }
161 :
162 3 : U8_TRACE_END_ERR( result );
163 3 : return result;
164 : }
165 :
166 7 : u8_error_t data_classifier_iterator_private_step_to_next ( data_classifier_iterator_t *this_ )
167 : {
168 7 : U8_TRACE_BEGIN();
169 7 : assert( data_database_borrowed_stmt_is_valid( &((*this_).statement) ) );
170 7 : u8_error_t result = U8_ERROR_NONE;
171 :
172 : /* do one step, check if is_at_end */
173 : {
174 : int sqlite_err;
175 7 : U8_TRACE_INFO( "sqlite3_step()" );
176 7 : sqlite_err = sqlite3_step( data_database_borrowed_stmt_get_statement( &((*this_).statement) ) );
177 7 : if ( SQLITE_DONE == sqlite_err )
178 : {
179 5 : U8_TRACE_INFO( "sqlite3_step finished: SQLITE_DONE" );
180 5 : (*this_).is_at_end = true;
181 : }
182 2 : else if ( SQLITE_ROW == sqlite_err )
183 : {
184 2 : (*this_).is_at_end = false;
185 : }
186 : else
187 : {
188 0 : U8_LOG_ERROR_INT( "sqlite3_step failed:", sqlite_err );
189 0 : (*this_).is_at_end = true;
190 0 : result |= data_classifier_iterator_destroy( this_ );
191 0 : result |= U8_ERROR_AT_DB;
192 : }
193 : }
194 :
195 7 : U8_TRACE_END_ERR(result);
196 7 : return result;
197 : }
198 :
199 :
200 : /*
201 : Copyright 2020-2026 Andreas Warnke
202 :
203 : Licensed under the Apache License, Version 2.0 (the "License");
204 : you may not use this file except in compliance with the License.
205 : You may obtain a copy of the License at
206 :
207 : http://www.apache.org/licenses/LICENSE-2.0
208 :
209 : Unless required by applicable law or agreed to in writing, software
210 : distributed under the License is distributed on an "AS IS" BASIS,
211 : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
212 : See the License for the specific language governing permissions and
213 : limitations under the License.
214 : */
|