Line data Source code
1 : /* File: data_feature_iterator.c; Copyright and License: see below */ 2 : 3 : #include "storage/data_feature_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 : * \brief predefined search statement to find features by diagram-id 13 : */ 14 : const char *const DATA_FEATURE_ITERATOR_SELECT_FEATURES_BY_DIAGRAM_ID = 15 : "SELECT features.id,features.main_type,features.classifier_id," 16 : "features.key,features.value,features.description,features.list_order,features.uuid," 17 : "diagramelements.id " /* diagramelements.id needed only for debugging */ 18 : "FROM features INNER JOIN diagramelements ON diagramelements.classifier_id=features.classifier_id " 19 : /* "WHERE diagramelements.diagram_id=? " */ 20 : "WHERE diagramelements.diagram_id=? AND ( diagramelements.focused_feature_id=features.id OR features.main_type<>3 ) " 21 : "GROUP BY features.id " 22 : "ORDER BY features.list_order ASC,features.id ASC;"; /* ensure always the same order */ 23 : /* Note: 3 == DATA_FEATURE_TYPE_LIFELINE */ 24 : 25 : /* if you ignore the type, "non-scenario features" of "classifiers that have a lifeline" would be skipped: */ 26 : /* "WHERE diagramelements.diagram_id=? AND ( (diagramelements.focused_feature_id=features.id) OR (diagramelements.focused_feature_id ISNULL) ) " */ 27 : /* but we want to skip only lifelines and only if these belong to foreign diagrams */ 28 : 29 : /*! 30 : * \brief predefined search statement to find features by classifier-id 31 : * 32 : * Order by id to ensure a defined, non-changeing order of relationships in json export 33 : */ 34 : const char *const DATA_FEATURE_ITERATOR_SELECT_FEATURES_BY_CLASSIFIER_ID = 35 : "SELECT id,main_type,classifier_id,key,value,description,list_order,uuid,-1 " 36 : "FROM features " 37 : "WHERE classifier_id=? ORDER BY id ASC;"; /* ensure always the same order */ 38 : 39 : /*! 40 : * \brief the column id of the result where this parameter is stored: id 41 : */ 42 : static const int RESULT_FEATURE_ID_COLUMN = 0; 43 : 44 : /*! 45 : * \brief the column id of the result where this parameter is stored: main_type 46 : */ 47 : static const int RESULT_FEATURE_MAIN_TYPE_COLUMN = 1; 48 : 49 : /*! 50 : * \brief the column id of the result where this parameter is stored: classifier_id 51 : */ 52 : static const int RESULT_FEATURE_CLASSIFIER_ID_COLUMN = 2; 53 : 54 : /*! 55 : * \brief the column id of the result where this parameter is stored: key 56 : */ 57 : static const int RESULT_FEATURE_KEY_COLUMN = 3; 58 : 59 : /*! 60 : * \brief the column id of the result where this parameter is stored: value 61 : */ 62 : static const int RESULT_FEATURE_VALUE_COLUMN = 4; 63 : 64 : /*! 65 : * \brief the column id of the result where this parameter is stored: description 66 : */ 67 : static const int RESULT_FEATURE_DESCRIPTION_COLUMN = 5; 68 : 69 : /*! 70 : * \brief the column id of the result where this parameter is stored: list_order 71 : */ 72 : static const int RESULT_FEATURE_LIST_ORDER_COLUMN = 6; 73 : 74 : /*! 75 : * \brief the column id of the result where this parameter is stored: uuid 76 : */ 77 : static const int RESULT_FEATURE_LIST_UUID_COLUMN = 7; 78 : 79 : /*! 80 : * \brief the column id of the result where this parameter is stored: diagramelements.id 81 : */ 82 : static const int RESULT_FEATURE_DIAGRAMELEMENTS_ID_COLUMN = 8; 83 : 84 21 : u8_error_t data_feature_iterator_init_empty ( data_feature_iterator_t *this_ ) 85 : { 86 21 : U8_TRACE_BEGIN(); 87 21 : u8_error_t result = U8_ERROR_NONE; 88 : 89 21 : data_database_borrowed_stmt_init_void( &((*this_).statement) ); 90 21 : (*this_).is_at_end = true; 91 : 92 21 : U8_TRACE_END_ERR(result); 93 21 : return result; 94 : } 95 : 96 21 : u8_error_t data_feature_iterator_reinit ( data_feature_iterator_t *this_, 97 : data_database_borrowed_stmt_t statement ) 98 : { 99 21 : U8_TRACE_BEGIN(); 100 21 : assert( data_database_borrowed_stmt_is_valid( &statement ) ); 101 21 : u8_error_t result = U8_ERROR_NONE; 102 : 103 : /* destroy old state */ 104 21 : result = data_feature_iterator_destroy( this_ ); 105 : 106 : /* init new state */ 107 21 : (*this_).statement = statement; 108 21 : (*this_).is_at_end = false; 109 21 : result |= data_feature_iterator_private_step_to_next( this_ ); 110 : 111 21 : U8_TRACE_END_ERR(result); 112 21 : return result; 113 : } 114 : 115 42 : u8_error_t data_feature_iterator_destroy ( data_feature_iterator_t *this_ ) 116 : { 117 42 : U8_TRACE_BEGIN(); 118 42 : u8_error_t result = U8_ERROR_NONE; 119 : 120 42 : result |= data_database_borrowed_stmt_destroy( &((*this_).statement) ); 121 42 : (*this_).is_at_end = true; 122 : 123 42 : U8_TRACE_END_ERR(result); 124 42 : return result; 125 : } 126 : 127 281 : bool data_feature_iterator_has_next ( const data_feature_iterator_t *this_ ) 128 : { 129 281 : return ( ! (*this_).is_at_end ); 130 : } 131 : 132 273 : u8_error_t data_feature_iterator_next ( data_feature_iterator_t *this_, data_feature_t *out_feature ) 133 : { 134 273 : U8_TRACE_BEGIN(); 135 273 : assert( NULL != out_feature ); 136 273 : assert( data_database_borrowed_stmt_is_valid( &((*this_).statement) ) ); 137 273 : u8_error_t result = U8_ERROR_NONE; 138 : 139 273 : if ( ! (*this_).is_at_end ) 140 : { 141 271 : sqlite3_stmt *const sql_statement = data_database_borrowed_stmt_get_statement( &((*this_).statement) ); 142 : 143 542 : result |= data_feature_init( out_feature, 144 271 : sqlite3_column_int64( sql_statement, RESULT_FEATURE_ID_COLUMN ), 145 271 : sqlite3_column_int( sql_statement, RESULT_FEATURE_MAIN_TYPE_COLUMN ), 146 271 : sqlite3_column_int64( sql_statement, RESULT_FEATURE_CLASSIFIER_ID_COLUMN ), 147 271 : (const char*) sqlite3_column_text( sql_statement, RESULT_FEATURE_KEY_COLUMN ), 148 271 : (const char*) sqlite3_column_text( sql_statement, RESULT_FEATURE_VALUE_COLUMN ), 149 271 : (const char*) sqlite3_column_text( sql_statement, RESULT_FEATURE_DESCRIPTION_COLUMN ), 150 : sqlite3_column_int( sql_statement, RESULT_FEATURE_LIST_ORDER_COLUMN ), 151 271 : (const char*) sqlite3_column_text( sql_statement, RESULT_FEATURE_LIST_UUID_COLUMN ) 152 : ); 153 271 : U8_TRACE_INFO_INT( "diagramelements.id:", sqlite3_column_int64( sql_statement, RESULT_FEATURE_DIAGRAMELEMENTS_ID_COLUMN ) ); 154 271 : data_feature_trace( out_feature ); 155 : 156 : /* step to next */ 157 271 : result |= data_feature_iterator_private_step_to_next( this_ ); 158 : } 159 : else 160 : { 161 2 : U8_TRACE_INFO( "iterator already at end" ); 162 2 : (*this_).is_at_end = true; 163 2 : result |= U8_ERROR_INVALID_REQUEST; 164 : } 165 : 166 273 : U8_TRACE_END_ERR( result ); 167 273 : return result; 168 : } 169 : 170 292 : u8_error_t data_feature_iterator_private_step_to_next ( data_feature_iterator_t *this_ ) 171 : { 172 292 : U8_TRACE_BEGIN(); 173 292 : assert( data_database_borrowed_stmt_is_valid( &((*this_).statement) ) ); 174 292 : u8_error_t result = U8_ERROR_NONE; 175 : 176 : /* do one step, check if is_at_end */ 177 : { 178 : int sqlite_err; 179 292 : U8_TRACE_INFO( "sqlite3_step()" ); 180 292 : sqlite_err = sqlite3_step( data_database_borrowed_stmt_get_statement( &((*this_).statement) ) ); 181 292 : if ( SQLITE_DONE == sqlite_err ) 182 : { 183 20 : U8_TRACE_INFO( "sqlite3_step finished: SQLITE_DONE" ); 184 20 : (*this_).is_at_end = true; 185 : } 186 272 : else if ( SQLITE_ROW == sqlite_err ) 187 : { 188 272 : (*this_).is_at_end = false; 189 : } 190 : else 191 : { 192 0 : U8_LOG_ERROR_INT( "sqlite3_step failed:", sqlite_err ); 193 0 : (*this_).is_at_end = true; 194 0 : result |= data_feature_iterator_destroy( this_ ); 195 0 : result |= U8_ERROR_AT_DB; 196 : } 197 : } 198 : 199 292 : U8_TRACE_END_ERR(result); 200 292 : return result; 201 : } 202 : 203 : 204 : /* 205 : Copyright 2024-2025 Andreas Warnke 206 : 207 : Licensed under the Apache License, Version 2.0 (the "License"); 208 : you may not use this file except in compliance with the License. 209 : You may obtain a copy of the License at 210 : 211 : http://www.apache.org/licenses/LICENSE-2.0 212 : 213 : Unless required by applicable law or agreed to in writing, software 214 : distributed under the License is distributed on an "AS IS" BASIS, 215 : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 216 : See the License for the specific language governing permissions and 217 : limitations under the License. 218 : */