Line data Source code
1 : /* File: data_database_consistency_checker.c; Copyright and License: see below */
2 :
3 : #include "storage/data_database_consistency_checker.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 :
10 84 : u8_error_t data_database_consistency_checker_init ( data_database_consistency_checker_t *this_, data_database_t *database )
11 : {
12 84 : U8_TRACE_BEGIN();
13 84 : assert( NULL != database );
14 84 : u8_error_t result = U8_ERROR_NONE;
15 :
16 84 : (*this_).database = database;
17 :
18 84 : U8_TRACE_END_ERR(result);
19 84 : return result;
20 : }
21 :
22 :
23 84 : u8_error_t data_database_consistency_checker_destroy ( data_database_consistency_checker_t *this_ )
24 : {
25 84 : U8_TRACE_BEGIN();
26 84 : u8_error_t result = U8_ERROR_NONE;
27 :
28 84 : (*this_).database = NULL;
29 :
30 84 : U8_TRACE_END_ERR(result);
31 84 : return result;
32 : }
33 :
34 : /*!
35 : * \brief the length of an sql query shall be determined by the terminating 0 of the string
36 : */
37 : static const int AUTO_DETECT_SQL_LENGTH = -1;
38 :
39 : /*!
40 : * \brief the last evaluated sql string character shall not be reported to the caller
41 : */
42 : static void* NO_SQL_DEBUG_INFORMATION = NULL;
43 :
44 : /*!
45 : * \brief break the loop of evaluating search results after a predefined high number
46 : */
47 : static const int MAX_ROWS_TO_CHECK = 1000000;
48 :
49 : /*!
50 : * \brief search statement to find diagrams and their parent ids
51 : */
52 : static const char SELECT_DIAGRAMS_IDS[] =
53 : "SELECT diagrams.id,diagrams.parent_id FROM diagrams;";
54 :
55 : /*!
56 : * \brief the column id of the result where this parameter is stored: diagrams.id
57 : */
58 : static const int RESULT_DIAGRAMS_DIAG_ID_COLUMN = 0;
59 :
60 : /*!
61 : * \brief the column id of the result where this parameter is stored: diagrams.parent_id
62 : */
63 : static const int RESULT_DIAGRAMS_DIAG_PARENT_ID_COLUMN = 1;
64 :
65 : /*!
66 : * \brief search statement to find diagramelements with illegal related diagrams and classifiers
67 : */
68 : static const char SELECT_DIAGRAMELEMENTS_AND_RELATED[] =
69 : "SELECT diagramelements.id,diagramelements.diagram_id,diagramelements.classifier_id,diagrams.id,classifiers.id "
70 : "FROM diagramelements "
71 : "LEFT JOIN diagrams ON diagramelements.diagram_id=diagrams.id "
72 : "LEFT JOIN classifiers ON diagramelements.classifier_id=classifiers.id;";
73 :
74 : /*!
75 : * \brief the column id of the result where this parameter is stored: diagramelements.id
76 : */
77 : static const int RESULT_DIAGRAMELEMENTS_DIAGELE_ID_COLUMN = 0;
78 :
79 : /*!
80 : * \brief the column id of the result where this parameter is stored: diagramelements.diagram_id
81 : */
82 : static const int RESULT_DIAGRAMELEMENTS_DIAGELE_DIAGRAM_ID_COLUMN = 1;
83 :
84 : /*!
85 : * \brief the column id of the result where this parameter is stored: diagramelements.classifier_id
86 : */
87 : static const int RESULT_DIAGRAMELEMENTS_DIAGELE_CLASSIFIER_ID_COLUMN = 2;
88 :
89 : /*!
90 : * \brief the column id of the result where this parameter is stored: diagrams.id
91 : */
92 : static const int RESULT_DIAGRAMELEMENTS_DIAGRAM_ID_COLUMN = 3;
93 :
94 : /*!
95 : * \brief the column id of the result where this parameter is stored: classifiers.id
96 : */
97 : static const int RESULT_DIAGRAMELEMENTS_CLASSIFIER_ID_COLUMN = 4;
98 :
99 : /*!
100 : * \brief search statement to find diagramelements with illegal focused features
101 : */
102 : static const char SELECT_FOCUSED_FEATURES[] =
103 : "SELECT diagramelements.id,diagramelements.classifier_id,diagramelements.focused_feature_id,"
104 : "features.id,features.classifier_id "
105 : "FROM diagramelements "
106 : "LEFT JOIN features ON diagramelements.focused_feature_id=features.id;";
107 :
108 : /*!
109 : * \brief the column id of the result where this parameter is stored: diagramelements.id
110 : */
111 : static const int RESULT_FOCUSED_FEATURES_DIAGELE_ID_COLUMN = 0;
112 :
113 : /*!
114 : * \brief the column id of the result where this parameter is stored: diagramelements.classifier_id
115 : */
116 : static const int RESULT_FOCUSED_FEATURES_DIAGELE_CLASSIFIER_ID_COLUMN = 1;
117 :
118 : /*!
119 : * \brief the column id of the result where this parameter is stored: diagramelements.focused_feature_id
120 : */
121 : static const int RESULT_FOCUSED_FEATURES_DIAGELE_FEATURE_ID_COLUMN = 2;
122 :
123 : /*!
124 : * \brief the column id of the result where this parameter is stored: features.id
125 : */
126 : static const int RESULT_FOCUSED_FEATURES_FEATURE_ID_COLUMN = 3;
127 :
128 : /*!
129 : * \brief the column id of the result where this parameter is stored: features.classifier_id
130 : */
131 : static const int RESULT_FOCUSED_FEATURES_FEATURE_CLASSIFIER_ID_COLUMN = 4;
132 :
133 : /*!
134 : * \brief search statement to find classifiers that are not referenced
135 : */
136 : static const char SELECT_CLASSIFIERS_AND_DIAGRAMELEMENTS[] =
137 : "SELECT classifiers.id,diagramelements.classifier_id,"
138 : "diagramelements.id " /* diagramelements.id needed only for debugging */
139 : "FROM classifiers LEFT JOIN diagramelements ON classifiers.id=diagramelements.classifier_id;";
140 :
141 : /*!
142 : * \brief the column id of the result where this parameter is stored: classifiers.id
143 : */
144 : static const int RESULT_CLASSIFIERS_CLASSIFIER_ID_COLUMN = 0;
145 :
146 : /*!
147 : * \brief the column id of the result where this parameter is stored: diagramelements.classifier_id
148 : */
149 : static const int RESULT_CLASSIFIERS_DIAGELE_CLASSIFIER_ID_COLUMN = 1;
150 :
151 : /*!
152 : * \brief the column id of the result where this parameter is stored: diagramelements.id
153 : */
154 : static const int RESULT_CLASSIFIERS_DIAGELE_ID_COLUMN = 2;
155 :
156 : /*!
157 : * \brief search statement to find features that are not referenced
158 : */
159 : static const char SELECT_FEATURES_AND_CLASSIFIERS[] =
160 : "SELECT features.id,features.classifier_id,classifiers.id "
161 : "FROM features "
162 : "LEFT JOIN classifiers ON features.classifier_id=classifiers.id;";
163 :
164 : /*!
165 : * \brief the column id of the result where this parameter is stored: features.id
166 : */
167 : static const int RESULT_FEATURES_FEATURE_ID_COLUMN = 0;
168 :
169 : /*!
170 : * \brief the column id of the result where this parameter is stored: features.classifier_id
171 : */
172 : static const int RESULT_FEATURES_FEATURE_CLASSIFIER_ID_COLUMN = 1;
173 :
174 : /*!
175 : * \brief the column id of the result where this parameter is stored: classifiers.id
176 : */
177 : static const int RESULT_FEATURES_CLASSIFIER_ID_COLUMN = 2;
178 :
179 : /*!
180 : * \brief search statement to find relationships that contain invalid classifier references
181 : */
182 : static const char SELECT_RELATIONSHIPS_AND_CLASSIFIERS[] =
183 : "SELECT relationships.id,relationships.from_classifier_id,relationships.to_classifier_id,source.id,dest.id "
184 : "FROM relationships "
185 : "LEFT JOIN classifiers AS source ON relationships.from_classifier_id=source.id "
186 : "LEFT JOIN classifiers AS dest ON relationships.to_classifier_id=dest.id;";
187 :
188 : /*!
189 : * \brief the column id of the result where this parameter is stored: relationships.id
190 : */
191 : static const int RESULT_RELATIONSHIPS_RELATIONSHIP_ID_COLUMN = 0;
192 :
193 : /*!
194 : * \brief the column id of the result where this parameter is stored: relationships.from_classifier_id
195 : */
196 : static const int RESULT_RELATIONSHIPS_RELATIONSHIP_FROM_ID_COLUMN = 1;
197 :
198 : /*!
199 : * \brief the column id of the result where this parameter is stored: relationships.to_classifier_id
200 : */
201 : static const int RESULT_RELATIONSHIPS_RELATIONSHIP_TO_ID_COLUMN = 2;
202 :
203 : /*!
204 : * \brief the column id of the result where this parameter is stored: source.id
205 : */
206 : static const int RESULT_RELATIONSHIPS_SOURCE_ID_COLUMN = 3;
207 :
208 : /*!
209 : * \brief the column id of the result where this parameter is stored: dest.id
210 : */
211 : static const int RESULT_RELATIONSHIPS_DEST_ID_COLUMN = 4;
212 :
213 : /*!
214 : * \brief search statement to find relationships that contain invalid feature references
215 : */
216 : static const char SELECT_FEATURE_RELATIONSHIPS[] =
217 : "SELECT relationships.id,relationships.from_classifier_id,relationships.to_classifier_id,"
218 : "relationships.from_feature_id,relationships.to_feature_id,source.id,source.classifier_id,dest.id,dest.classifier_id "
219 : "FROM relationships "
220 : "LEFT JOIN features AS source ON relationships.from_feature_id=source.id "
221 : "LEFT JOIN features AS dest ON relationships.to_feature_id=dest.id;";
222 :
223 : /*!
224 : * \brief the column id of the result where this parameter is stored: relationships.id
225 : */
226 : static const int RESULT_FEATURE_RELATIONSHIPS_RELATION_ID_COLUMN = 0;
227 :
228 : /*!
229 : * \brief the column id of the result where this parameter is stored: relationships.from_classifier_id
230 : */
231 : static const int RESULT_FEATURE_RELATIONSHIPS_RELATION_FROM_CLASSIFIER_ID_COLUMN = 1;
232 :
233 : /*!
234 : * \brief the column id of the result where this parameter is stored: relationships.to_classifier_id
235 : */
236 : static const int RESULT_FEATURE_RELATIONSHIPS_RELATION_TO_CLASIFIER_ID_COLUMN = 2;
237 :
238 : /*!
239 : * \brief the column id of the result where this parameter is stored: relationships.from_feature_id
240 : */
241 : static const int RESULT_FEATURE_RELATIONSHIPS_RELATION_FROM_FEATURE_ID_COLUMN = 3;
242 :
243 : /*!
244 : * \brief the column id of the result where this parameter is stored: relationships.to_feature_id
245 : */
246 : static const int RESULT_FEATURE_RELATIONSHIPS_RELATION_TO_FEATURE_ID_COLUMN = 4;
247 :
248 : /*!
249 : * \brief the column id of the result where this parameter is stored: source.id
250 : */
251 : static const int RESULT_FEATURE_RELATIONSHIPS_SOURCE_FEATURE_ID_COLUMN = 5;
252 :
253 : /*!
254 : * \brief the column id of the result where this parameter is stored: source.classifier_id
255 : */
256 : static const int RESULT_FEATURE_RELATIONSHIPS_SOURCE_FEATURE_CLASSIFIER_ID_COLUMN = 6;
257 :
258 : /*!
259 : * \brief the column id of the result where this parameter is stored: dest.id
260 : */
261 : static const int RESULT_FEATURE_RELATIONSHIPS_DEST_FEATURE_ID_COLUMN = 7;
262 :
263 : /*!
264 : * \brief the column id of the result where this parameter is stored: dest.classifier_id
265 : */
266 : static const int RESULT_FEATURE_RELATIONSHIPS_DEST_FEATURE_CLASSIFIER_ID_COLUMN = 8;
267 :
268 30 : u8_error_t data_database_consistency_checker_find_circular_diagram_parents ( data_database_consistency_checker_t *this_, data_small_set_t *io_set )
269 : {
270 30 : U8_TRACE_BEGIN();
271 30 : assert( NULL != io_set );
272 30 : u8_error_t result = U8_ERROR_NONE;
273 :
274 : /* fetch all diagram ids from the database */
275 : uint32_t diagram_id_pair_count;
276 30 : result = data_database_consistency_checker_private_get_diagram_ids ( this_,
277 : DATA_DATABASE_CONSISTENCY_CHECKER_MAX_TEMP_DIAG_IDS,
278 30 : &((*this_).private_temp_diagram_ids_buf),
279 : &diagram_id_pair_count
280 : );
281 :
282 : /* delete all parent-ids from diagrams that have parents who have empty parent ids */
283 30 : bool finished = false;
284 64 : for ( uint_fast32_t tree_depth = 0; ( tree_depth < diagram_id_pair_count ) && ( ! finished ); tree_depth ++ )
285 : {
286 34 : uint_fast32_t found_children = 0;
287 89 : for ( uint_fast32_t child_idx = 0; child_idx < diagram_id_pair_count; child_idx ++ )
288 : {
289 : bool child_has_parent;
290 55 : child_has_parent = ( DATA_ROW_ID_VOID != ((*this_).private_temp_diagram_ids_buf)[child_idx][1] );
291 55 : if ( child_has_parent )
292 : {
293 54 : for ( uint_fast32_t probe_parent_idx = 0; probe_parent_idx < diagram_id_pair_count; probe_parent_idx ++ )
294 : {
295 : bool is_parent;
296 40 : is_parent = ( ((*this_).private_temp_diagram_ids_buf)[child_idx][1] == ((*this_).private_temp_diagram_ids_buf)[probe_parent_idx][0] );
297 40 : if ( is_parent )
298 : {
299 : bool parent_has_parent;
300 10 : parent_has_parent = ( DATA_ROW_ID_VOID != ((*this_).private_temp_diagram_ids_buf)[probe_parent_idx][1] );
301 10 : if ( ! parent_has_parent )
302 : {
303 : /* this diagram is child to a parent that has no parent. */
304 6 : ((*this_).private_temp_diagram_ids_buf)[child_idx][1] = DATA_ROW_ID_VOID;
305 6 : found_children ++;
306 : }
307 : }
308 : }
309 : }
310 : }
311 34 : U8_TRACE_INFO_INT_INT( "invalid+circular references search: round,found_children:", tree_depth, found_children );
312 34 : finished = ( found_children == 0 );
313 : }
314 :
315 : /* add all the rest to the io_set */
316 75 : for ( uint_fast32_t diag_idx = 0; diag_idx < diagram_id_pair_count; diag_idx ++ )
317 : {
318 : bool diag_has_parent;
319 45 : diag_has_parent = ( DATA_ROW_ID_VOID != ((*this_).private_temp_diagram_ids_buf)[diag_idx][1] );
320 45 : if ( diag_has_parent )
321 : {
322 8 : data_row_id_t diag_id = ((*this_).private_temp_diagram_ids_buf)[diag_idx][0];
323 8 : U8_LOG_ERROR_INT( "Diagram has a parent that is not linked to root:", diag_id );
324 8 : data_small_set_add_row_id( io_set, DATA_TABLE_DIAGRAM, diag_id );
325 : }
326 : }
327 :
328 30 : U8_TRACE_END_ERR( result );
329 30 : return result;
330 : }
331 :
332 30 : u8_error_t data_database_consistency_checker_private_get_diagram_ids ( data_database_consistency_checker_t *this_,
333 : uint32_t max_out_array_size,
334 : data_row_id_t (*out_diagram_id_pair)[][2],
335 : uint32_t *out_diagram_id_pair_count )
336 : {
337 30 : U8_TRACE_BEGIN();
338 30 : assert( NULL != out_diagram_id_pair );
339 30 : assert( NULL != out_diagram_id_pair_count );
340 30 : assert( max_out_array_size <= MAX_ROWS_TO_CHECK );
341 30 : u8_error_t result = U8_ERROR_NONE;
342 : int sqlite_err;
343 30 : (*out_diagram_id_pair_count) = 0;
344 :
345 30 : if ( ! data_database_is_open( (*this_).database ) )
346 : {
347 0 : result = U8_ERROR_NO_DB;
348 0 : U8_LOG_WARNING( "Database not open, cannot request data." );
349 : }
350 : else
351 : {
352 : sqlite3 *native_db;
353 30 : native_db = data_database_get_database_ptr( (*this_).database );
354 : sqlite3_stmt *prepared_statement;
355 :
356 30 : U8_LOG_EVENT_STR( "sqlite3_prepare_v2():", SELECT_DIAGRAMS_IDS );
357 30 : sqlite_err = sqlite3_prepare_v2 ( native_db,
358 : SELECT_DIAGRAMS_IDS,
359 : AUTO_DETECT_SQL_LENGTH,
360 : &prepared_statement,
361 : NO_SQL_DEBUG_INFORMATION
362 : );
363 :
364 30 : if ( 0 != sqlite_err )
365 : {
366 0 : U8_LOG_ERROR_INT( "sqlite3_prepare_v2():", sqlite_err );
367 0 : result |= U8_ERROR_AT_DB;
368 : }
369 : else
370 : {
371 30 : sqlite_err = SQLITE_ROW;
372 105 : for ( uint_fast32_t row_index = 0; (SQLITE_ROW == sqlite_err) && (row_index <= MAX_ROWS_TO_CHECK) && (result == U8_ERROR_NONE); row_index ++ )
373 : {
374 75 : U8_TRACE_INFO( "sqlite3_step()" );
375 75 : sqlite_err = sqlite3_step( prepared_statement );
376 :
377 75 : if ( SQLITE_DONE == sqlite_err )
378 : {
379 30 : U8_TRACE_INFO( "sqlite3_step finished: SQLITE_DONE" );
380 : }
381 45 : else if ( SQLITE_ROW == sqlite_err )
382 : {
383 45 : data_row_id_t diag_id = sqlite3_column_int64( prepared_statement, RESULT_DIAGRAMS_DIAG_ID_COLUMN );
384 45 : data_row_id_t diag_parent_id = sqlite3_column_int64( prepared_statement, RESULT_DIAGRAMS_DIAG_PARENT_ID_COLUMN );
385 45 : if ( SQLITE_NULL == sqlite3_column_type( prepared_statement, RESULT_DIAGRAMS_DIAG_PARENT_ID_COLUMN ) )
386 : {
387 31 : diag_parent_id = DATA_ROW_ID_VOID;
388 31 : U8_TRACE_INFO_INT( "root:", diag_id );
389 : }
390 : else
391 : {
392 14 : U8_TRACE_INFO_INT_INT( "ok: diag_id, parent_id:", diag_id, diag_parent_id );
393 : }
394 :
395 : /* diagram found */
396 45 : if ( row_index < max_out_array_size )
397 : {
398 45 : (*out_diagram_id_pair)[row_index][0] = diag_id;
399 45 : (*out_diagram_id_pair)[row_index][1] = diag_parent_id;
400 45 : (*out_diagram_id_pair_count) = row_index + 1;
401 : }
402 : else
403 : {
404 0 : U8_LOG_ERROR_INT( "Number of diagrams in the database exceeds max_out_array_size:", max_out_array_size );
405 0 : result |= U8_ERROR_ARRAY_BUFFER_EXCEEDED;
406 : }
407 : }
408 : else /*if (( SQLITE_ROW != sqlite_err )&&( SQLITE_DONE != sqlite_err ))*/
409 : {
410 0 : U8_LOG_ERROR_INT( "sqlite3_step failed:", sqlite_err );
411 0 : result |= U8_ERROR_AT_DB;
412 : }
413 : }
414 : }
415 :
416 30 : sqlite_err = sqlite3_finalize( prepared_statement );
417 30 : if ( 0 != sqlite_err )
418 : {
419 0 : U8_LOG_ERROR_INT( "sqlite3_finalize():", sqlite_err );
420 0 : result |= U8_ERROR_AT_DB;
421 : }
422 : }
423 :
424 30 : U8_TRACE_END_ERR( result );
425 30 : return result;
426 : }
427 :
428 30 : u8_error_t data_database_consistency_checker_find_nonreferencing_diagramelements ( data_database_consistency_checker_t *this_, data_small_set_t *io_set )
429 : {
430 30 : U8_TRACE_BEGIN();
431 30 : assert( NULL != io_set );
432 30 : u8_error_t result = U8_ERROR_NONE;
433 : int sqlite_err;
434 :
435 30 : if ( ! data_database_is_open( (*this_).database ) )
436 : {
437 0 : result = U8_ERROR_NO_DB;
438 0 : U8_LOG_WARNING( "Database not open, cannot request data." );
439 : }
440 : else
441 : {
442 : sqlite3 *native_db;
443 30 : native_db = data_database_get_database_ptr( (*this_).database );
444 : sqlite3_stmt *prepared_statement;
445 :
446 30 : U8_LOG_EVENT_STR( "sqlite3_prepare_v2():", SELECT_DIAGRAMELEMENTS_AND_RELATED );
447 30 : sqlite_err = sqlite3_prepare_v2 ( native_db,
448 : SELECT_DIAGRAMELEMENTS_AND_RELATED,
449 : AUTO_DETECT_SQL_LENGTH,
450 : &prepared_statement,
451 : NO_SQL_DEBUG_INFORMATION
452 : );
453 :
454 30 : if ( 0 != sqlite_err )
455 : {
456 0 : U8_LOG_ERROR_INT( "sqlite3_prepare_v2():", sqlite_err );
457 0 : result |= U8_ERROR_AT_DB;
458 : }
459 : else
460 : {
461 30 : sqlite_err = SQLITE_ROW;
462 105 : for ( uint_fast32_t row_index = 0; (SQLITE_ROW == sqlite_err) && (row_index <= MAX_ROWS_TO_CHECK); row_index ++ )
463 : {
464 75 : U8_TRACE_INFO( "sqlite3_step()" );
465 75 : sqlite_err = sqlite3_step( prepared_statement );
466 :
467 75 : if ( SQLITE_DONE == sqlite_err )
468 : {
469 30 : U8_TRACE_INFO( "sqlite3_step finished: SQLITE_DONE" );
470 : }
471 45 : else if ( SQLITE_ROW == sqlite_err )
472 : {
473 45 : data_row_id_t diagele_id = sqlite3_column_int64( prepared_statement, RESULT_DIAGRAMELEMENTS_DIAGELE_ID_COLUMN );
474 45 : data_row_id_t diagele_diagram_id = sqlite3_column_int64( prepared_statement, RESULT_DIAGRAMELEMENTS_DIAGELE_DIAGRAM_ID_COLUMN );
475 45 : data_row_id_t diagele_classifier_id = sqlite3_column_int64( prepared_statement, RESULT_DIAGRAMELEMENTS_DIAGELE_CLASSIFIER_ID_COLUMN );
476 : /*data_row_id_t diagram_id = sqlite3_column_int64( prepared_statement, RESULT_DIAGRAMELEMENTS_DIAGRAM_ID_COLUMN );*/
477 : /*data_row_id_t classifier_id = sqlite3_column_int64( prepared_statement, RESULT_DIAGRAMELEMENTS_CLASSIFIER_ID_COLUMN );*/
478 45 : bool diagram_exists = ( SQLITE_INTEGER == sqlite3_column_type( prepared_statement, RESULT_DIAGRAMELEMENTS_DIAGRAM_ID_COLUMN ) );
479 45 : bool classifier_exists = ( SQLITE_INTEGER == sqlite3_column_type( prepared_statement, RESULT_DIAGRAMELEMENTS_CLASSIFIER_ID_COLUMN ) );
480 45 : if (( ! diagram_exists ) && ( ! classifier_exists ))
481 : {
482 2 : U8_LOG_ERROR_INT( "referenced diagram and classifier not existing, diagramelement:", diagele_id );
483 2 : U8_TRACE_INFO_INT_INT( "referenced diagram not existing: diagramelement, diagram:", diagele_id, diagele_diagram_id );
484 2 : U8_TRACE_INFO_INT_INT( "referenced classifier not existing: diagramelement, classifier:", diagele_id, diagele_classifier_id );
485 2 : data_small_set_add_row_id( io_set, DATA_TABLE_DIAGRAMELEMENT, diagele_id );
486 : }
487 43 : else if ( ! diagram_exists )
488 : {
489 2 : U8_LOG_ERROR_INT( "referenced diagram not existing, diagramelement:", diagele_id );
490 2 : U8_TRACE_INFO_INT_INT( "referenced diagram not existing: diagramelement, diagram:", diagele_id, diagele_diagram_id );
491 2 : data_small_set_add_row_id( io_set, DATA_TABLE_DIAGRAMELEMENT, diagele_id );
492 : }
493 41 : else if ( ! classifier_exists )
494 : {
495 2 : U8_LOG_ERROR_INT( "referenced classifier not existing, diagramelement:", diagele_id );
496 2 : U8_TRACE_INFO_INT_INT( "referenced classifier not existing: diagramelement, classifier:", diagele_id, diagele_classifier_id );
497 2 : data_small_set_add_row_id( io_set, DATA_TABLE_DIAGRAMELEMENT, diagele_id );
498 : }
499 : else
500 : {
501 39 : U8_TRACE_INFO_INT( "ok:", diagele_id );
502 : }
503 : }
504 : else /*if (( SQLITE_ROW != sqlite_err )&&( SQLITE_DONE != sqlite_err ))*/
505 : {
506 0 : U8_LOG_ERROR_INT( "sqlite3_step failed:", sqlite_err );
507 0 : result |= U8_ERROR_AT_DB;
508 : }
509 : }
510 : }
511 :
512 30 : sqlite_err = sqlite3_finalize( prepared_statement );
513 30 : if ( 0 != sqlite_err )
514 : {
515 0 : U8_LOG_ERROR_INT( "sqlite3_finalize():", sqlite_err );
516 0 : result |= U8_ERROR_AT_DB;
517 : }
518 : }
519 :
520 30 : U8_TRACE_END_ERR( result );
521 30 : return result;
522 : }
523 :
524 30 : u8_error_t data_database_consistency_checker_find_invalid_focused_features ( data_database_consistency_checker_t *this_, data_small_set_t *io_set )
525 : {
526 30 : U8_TRACE_BEGIN();
527 30 : assert( NULL != io_set );
528 30 : u8_error_t result = U8_ERROR_NONE;
529 : int sqlite_err;
530 :
531 30 : if ( ! data_database_is_open( (*this_).database ) )
532 : {
533 0 : result = U8_ERROR_NO_DB;
534 0 : U8_LOG_WARNING( "Database not open, cannot request data." );
535 : }
536 : else
537 : {
538 : sqlite3 *native_db;
539 30 : native_db = data_database_get_database_ptr( (*this_).database );
540 : sqlite3_stmt *prepared_statement;
541 :
542 30 : U8_LOG_EVENT_STR( "sqlite3_prepare_v2():", SELECT_FOCUSED_FEATURES );
543 30 : sqlite_err = sqlite3_prepare_v2 ( native_db,
544 : SELECT_FOCUSED_FEATURES,
545 : AUTO_DETECT_SQL_LENGTH,
546 : &prepared_statement,
547 : NO_SQL_DEBUG_INFORMATION
548 : );
549 :
550 30 : if ( 0 != sqlite_err )
551 : {
552 0 : U8_LOG_ERROR_INT( "sqlite3_prepare_v2():", sqlite_err );
553 0 : result |= U8_ERROR_AT_DB;
554 : }
555 : else
556 : {
557 30 : sqlite_err = SQLITE_ROW;
558 102 : for ( uint_fast32_t row_index = 0; (SQLITE_ROW == sqlite_err) && (row_index <= MAX_ROWS_TO_CHECK); row_index ++ )
559 : {
560 72 : U8_TRACE_INFO( "sqlite3_step()" );
561 72 : sqlite_err = sqlite3_step( prepared_statement );
562 :
563 72 : if ( SQLITE_DONE == sqlite_err )
564 : {
565 30 : U8_TRACE_INFO( "sqlite3_step finished: SQLITE_DONE" );
566 : }
567 42 : else if ( SQLITE_ROW == sqlite_err )
568 : {
569 : data_row_id_t diagele_id;
570 : data_row_id_t diagele_classifier_id;
571 : bool diagele_has_focused_feature;
572 : data_row_id_t diagele_focused_feature_id;
573 : bool feature_exists;
574 : data_row_id_t feature_id;
575 : data_row_id_t feature_classifier_id;
576 :
577 : /* fetch data record */
578 42 : diagele_id = sqlite3_column_int64( prepared_statement, RESULT_FOCUSED_FEATURES_DIAGELE_ID_COLUMN );
579 42 : diagele_classifier_id = sqlite3_column_int64( prepared_statement, RESULT_FOCUSED_FEATURES_DIAGELE_CLASSIFIER_ID_COLUMN );
580 42 : diagele_has_focused_feature = ( SQLITE_NULL != sqlite3_column_type( prepared_statement, RESULT_FOCUSED_FEATURES_DIAGELE_FEATURE_ID_COLUMN ) );
581 42 : if ( diagele_has_focused_feature )
582 : {
583 7 : diagele_focused_feature_id = sqlite3_column_int64( prepared_statement, RESULT_FOCUSED_FEATURES_DIAGELE_FEATURE_ID_COLUMN );
584 : }
585 : else
586 : {
587 35 : diagele_focused_feature_id = DATA_ROW_ID_VOID;
588 : }
589 42 : feature_exists = ( SQLITE_NULL != sqlite3_column_type( prepared_statement, RESULT_FOCUSED_FEATURES_FEATURE_ID_COLUMN ) );
590 42 : if ( feature_exists )
591 : {
592 5 : feature_id = sqlite3_column_int64( prepared_statement, RESULT_FOCUSED_FEATURES_FEATURE_ID_COLUMN );
593 5 : feature_classifier_id = sqlite3_column_int64( prepared_statement, RESULT_FOCUSED_FEATURES_FEATURE_CLASSIFIER_ID_COLUMN );
594 : }
595 : else
596 : {
597 37 : feature_id = DATA_ROW_ID_VOID;
598 37 : feature_classifier_id = DATA_ROW_ID_VOID;
599 : }
600 :
601 : /* evaluate the data record */
602 42 : if ( ! diagele_has_focused_feature )
603 : {
604 35 : U8_TRACE_INFO_INT( "ok (no focused feature):", diagele_id );
605 : }
606 : else
607 : {
608 7 : if ( ! feature_exists )
609 : {
610 2 : U8_LOG_ERROR_INT( "focused feature not existing, diagramelement:", diagele_id );
611 2 : U8_TRACE_INFO_INT_INT( "referenced classifier, classifier of feature:", diagele_classifier_id, feature_classifier_id );
612 2 : U8_TRACE_INFO_INT_INT( "referenced feature, feature:", diagele_focused_feature_id, feature_id );
613 2 : data_small_set_add_row_id( io_set, DATA_TABLE_DIAGRAMELEMENT, diagele_id );
614 : }
615 5 : else if ( diagele_classifier_id != feature_classifier_id )
616 : {
617 2 : U8_LOG_ERROR_INT( "referenced classifier of diagramelement and focused_feature differ, diagramelement:", diagele_id );
618 2 : U8_TRACE_INFO_INT_INT( "referenced classifier, classifier of feature:", diagele_classifier_id, feature_classifier_id );
619 2 : U8_TRACE_INFO_INT_INT( "referenced feature, feature:", diagele_focused_feature_id, feature_id );
620 2 : data_small_set_add_row_id( io_set, DATA_TABLE_DIAGRAMELEMENT, diagele_id );
621 : }
622 : else
623 : {
624 3 : U8_TRACE_INFO_INT( "ok (valid focused feature):", diagele_id );
625 : }
626 : }
627 : }
628 : else /*if (( SQLITE_ROW != sqlite_err )&&( SQLITE_DONE != sqlite_err ))*/
629 : {
630 0 : U8_LOG_ERROR_INT( "sqlite3_step failed:", sqlite_err );
631 0 : result |= U8_ERROR_AT_DB;
632 : }
633 : }
634 : }
635 :
636 30 : sqlite_err = sqlite3_finalize( prepared_statement );
637 30 : if ( 0 != sqlite_err )
638 : {
639 0 : U8_LOG_ERROR_INT( "sqlite3_finalize():", sqlite_err );
640 0 : result |= U8_ERROR_AT_DB;
641 : }
642 : }
643 :
644 30 : U8_TRACE_END_ERR( result );
645 30 : return result;
646 : }
647 :
648 30 : u8_error_t data_database_consistency_checker_find_unreferenced_classifiers ( data_database_consistency_checker_t *this_, data_small_set_t *io_set )
649 : {
650 30 : U8_TRACE_BEGIN();
651 30 : assert( NULL != io_set );
652 30 : u8_error_t result = U8_ERROR_NONE;
653 : int sqlite_err;
654 :
655 30 : if ( ! data_database_is_open( (*this_).database ) )
656 : {
657 0 : result = U8_ERROR_NO_DB;
658 0 : U8_LOG_WARNING( "Database not open, cannot request data." );
659 : }
660 : else
661 : {
662 : sqlite3 *native_db;
663 30 : native_db = data_database_get_database_ptr( (*this_).database );
664 : sqlite3_stmt *prepared_statement;
665 :
666 30 : U8_LOG_EVENT_STR( "sqlite3_prepare_v2():", SELECT_CLASSIFIERS_AND_DIAGRAMELEMENTS );
667 30 : sqlite_err = sqlite3_prepare_v2 ( native_db,
668 : SELECT_CLASSIFIERS_AND_DIAGRAMELEMENTS,
669 : AUTO_DETECT_SQL_LENGTH,
670 : &prepared_statement,
671 : NO_SQL_DEBUG_INFORMATION
672 : );
673 :
674 30 : if ( 0 != sqlite_err )
675 : {
676 0 : U8_LOG_ERROR_INT( "sqlite3_prepare_v2():", sqlite_err );
677 0 : result |= U8_ERROR_AT_DB;
678 : }
679 : else
680 : {
681 30 : sqlite_err = SQLITE_ROW;
682 104 : for ( uint_fast32_t row_index = 0; (SQLITE_ROW == sqlite_err) && (row_index <= MAX_ROWS_TO_CHECK); row_index ++ )
683 : {
684 74 : U8_TRACE_INFO( "sqlite3_step()" );
685 74 : sqlite_err = sqlite3_step( prepared_statement );
686 :
687 74 : if ( SQLITE_DONE == sqlite_err )
688 : {
689 30 : U8_TRACE_INFO( "sqlite3_step finished: SQLITE_DONE" );
690 : }
691 44 : else if ( SQLITE_ROW == sqlite_err )
692 : {
693 44 : data_row_id_t classifier_id = sqlite3_column_int64( prepared_statement, RESULT_CLASSIFIERS_CLASSIFIER_ID_COLUMN );
694 : /*
695 : data_row_id_t diagele_classifier_id = sqlite3_column_int64( prepared_statement, RESULT_CLASSIFIERS_DIAGELE_CLASSIFIER_ID_COLUMN );
696 : */
697 44 : data_row_id_t diagele_id = sqlite3_column_int64( prepared_statement, RESULT_CLASSIFIERS_DIAGELE_ID_COLUMN );
698 44 : bool diagele_exists = ( SQLITE_INTEGER == sqlite3_column_type( prepared_statement, RESULT_CLASSIFIERS_DIAGELE_CLASSIFIER_ID_COLUMN ) );
699 44 : if ( ! diagele_exists )
700 : {
701 4 : U8_LOG_ERROR_INT( "referencing diagramelement not existing, classifier :", classifier_id );
702 4 : U8_TRACE_INFO_INT( "referencing diagramelement not existing: classifier:", classifier_id );
703 4 : data_small_set_add_row_id( io_set, DATA_TABLE_CLASSIFIER, classifier_id );
704 : }
705 : else
706 : {
707 40 : U8_TRACE_INFO_INT_INT( "ok (classifier_id,diagele_id):", classifier_id, diagele_id );
708 : }
709 : }
710 : else /*if (( SQLITE_ROW != sqlite_err )&&( SQLITE_DONE != sqlite_err ))*/
711 : {
712 0 : U8_LOG_ERROR_INT( "sqlite3_step failed:", sqlite_err );
713 0 : result |= U8_ERROR_AT_DB;
714 : }
715 : }
716 : }
717 :
718 30 : sqlite_err = sqlite3_finalize( prepared_statement );
719 30 : if ( 0 != sqlite_err )
720 : {
721 0 : U8_LOG_ERROR_INT( "sqlite3_finalize():", sqlite_err );
722 0 : result |= U8_ERROR_AT_DB;
723 : }
724 : }
725 :
726 30 : U8_TRACE_END_ERR( result );
727 30 : return result;
728 : }
729 :
730 30 : u8_error_t data_database_consistency_checker_find_unreferenced_features ( data_database_consistency_checker_t *this_, data_small_set_t *io_set )
731 : {
732 30 : U8_TRACE_BEGIN();
733 30 : assert( NULL != io_set );
734 30 : u8_error_t result = U8_ERROR_NONE;
735 : int sqlite_err;
736 :
737 30 : if ( ! data_database_is_open( (*this_).database ) )
738 : {
739 0 : result = U8_ERROR_NO_DB;
740 0 : U8_LOG_WARNING( "Database not open, cannot request data." );
741 : }
742 : else
743 : {
744 : sqlite3 *native_db;
745 30 : native_db = data_database_get_database_ptr( (*this_).database );
746 : sqlite3_stmt *prepared_statement;
747 :
748 30 : U8_LOG_EVENT_STR( "sqlite3_prepare_v2():", SELECT_FEATURES_AND_CLASSIFIERS );
749 30 : sqlite_err = sqlite3_prepare_v2 ( native_db,
750 : SELECT_FEATURES_AND_CLASSIFIERS,
751 : AUTO_DETECT_SQL_LENGTH,
752 : &prepared_statement,
753 : NO_SQL_DEBUG_INFORMATION
754 : );
755 :
756 30 : if ( 0 != sqlite_err )
757 : {
758 0 : U8_LOG_ERROR_INT( "sqlite3_prepare_v2():", sqlite_err );
759 0 : result |= U8_ERROR_AT_DB;
760 : }
761 : else
762 : {
763 30 : sqlite_err = SQLITE_ROW;
764 76 : for ( uint_fast32_t row_index = 0; (SQLITE_ROW == sqlite_err) && (row_index <= MAX_ROWS_TO_CHECK); row_index ++ )
765 : {
766 46 : U8_TRACE_INFO( "sqlite3_step()" );
767 46 : sqlite_err = sqlite3_step( prepared_statement );
768 :
769 46 : if ( SQLITE_DONE == sqlite_err )
770 : {
771 30 : U8_TRACE_INFO( "sqlite3_step finished: SQLITE_DONE" );
772 : }
773 16 : else if ( SQLITE_ROW == sqlite_err )
774 : {
775 16 : data_row_id_t feature_id = sqlite3_column_int64( prepared_statement, RESULT_FEATURES_FEATURE_ID_COLUMN );
776 16 : data_row_id_t feature_classifier_id = sqlite3_column_int64( prepared_statement, RESULT_FEATURES_FEATURE_CLASSIFIER_ID_COLUMN );
777 : /*data_row_id_t classifier_id = sqlite3_column_int64( prepared_statement, RESULT_FEATURES_CLASSIFIER_ID_COLUMN );*/
778 16 : bool classifier_exists = ( SQLITE_INTEGER == sqlite3_column_type( prepared_statement, RESULT_FEATURES_CLASSIFIER_ID_COLUMN ) );
779 16 : if ( ! classifier_exists )
780 : {
781 3 : U8_LOG_ERROR_INT( "referenced classifier not existing, feature:", feature_id );
782 3 : U8_TRACE_INFO_INT_INT( "referenced classifier not existing: feature, classifier:", feature_id, feature_classifier_id );
783 3 : data_small_set_add_row_id( io_set, DATA_TABLE_FEATURE, feature_id );
784 : }
785 : else
786 : {
787 13 : U8_TRACE_INFO_INT( "ok:", feature_id );
788 : }
789 : }
790 : else /*if (( SQLITE_ROW != sqlite_err )&&( SQLITE_DONE != sqlite_err ))*/
791 : {
792 0 : U8_LOG_ERROR_INT( "sqlite3_step failed:", sqlite_err );
793 0 : result |= U8_ERROR_AT_DB;
794 : }
795 : }
796 : }
797 :
798 30 : sqlite_err = sqlite3_finalize( prepared_statement );
799 30 : if ( 0 != sqlite_err )
800 : {
801 0 : U8_LOG_ERROR_INT( "sqlite3_finalize():", sqlite_err );
802 0 : result |= U8_ERROR_AT_DB;
803 : }
804 : }
805 :
806 30 : U8_TRACE_END_ERR( result );
807 30 : return result;
808 : }
809 :
810 30 : u8_error_t data_database_consistency_checker_find_unreferenced_relationships ( data_database_consistency_checker_t *this_, data_small_set_t *io_set )
811 : {
812 30 : U8_TRACE_BEGIN();
813 30 : assert( NULL != io_set );
814 30 : u8_error_t result = U8_ERROR_NONE;
815 : int sqlite_err;
816 :
817 30 : if ( ! data_database_is_open( (*this_).database ) )
818 : {
819 0 : result = U8_ERROR_NO_DB;
820 0 : U8_LOG_WARNING( "Database not open, cannot request data." );
821 : }
822 : else
823 : {
824 : sqlite3 *native_db;
825 30 : native_db = data_database_get_database_ptr( (*this_).database );
826 : sqlite3_stmt *prepared_statement;
827 :
828 30 : U8_LOG_EVENT_STR( "sqlite3_prepare_v2():", SELECT_RELATIONSHIPS_AND_CLASSIFIERS );
829 30 : sqlite_err = sqlite3_prepare_v2 ( native_db,
830 : SELECT_RELATIONSHIPS_AND_CLASSIFIERS,
831 : AUTO_DETECT_SQL_LENGTH,
832 : &prepared_statement,
833 : NO_SQL_DEBUG_INFORMATION
834 : );
835 :
836 30 : if ( 0 != sqlite_err )
837 : {
838 0 : U8_LOG_ERROR_INT( "sqlite3_prepare_v2():", sqlite_err );
839 0 : result |= U8_ERROR_AT_DB;
840 : }
841 : else
842 : {
843 30 : sqlite_err = SQLITE_ROW;
844 80 : for ( uint_fast32_t row_index = 0; (SQLITE_ROW == sqlite_err) && (row_index <= MAX_ROWS_TO_CHECK); row_index ++ )
845 : {
846 50 : U8_TRACE_INFO( "sqlite3_step()" );
847 50 : sqlite_err = sqlite3_step( prepared_statement );
848 :
849 50 : if ( SQLITE_DONE == sqlite_err )
850 : {
851 30 : U8_TRACE_INFO( "sqlite3_step finished: SQLITE_DONE" );
852 : }
853 20 : else if ( SQLITE_ROW == sqlite_err )
854 : {
855 20 : data_row_id_t relation_id = sqlite3_column_int64( prepared_statement, RESULT_RELATIONSHIPS_RELATIONSHIP_ID_COLUMN );
856 20 : data_row_id_t relation_from_id = sqlite3_column_int64( prepared_statement, RESULT_RELATIONSHIPS_RELATIONSHIP_FROM_ID_COLUMN );
857 20 : data_row_id_t relation_to_id = sqlite3_column_int64( prepared_statement, RESULT_RELATIONSHIPS_RELATIONSHIP_TO_ID_COLUMN );
858 : /*data_row_id_t source_id = sqlite3_column_int64( prepared_statement, RESULT_RELATIONSHIPS_SOURCE_ID_COLUMN );*/
859 : /*data_row_id_t dest_id = sqlite3_column_int64( prepared_statement, RESULT_RELATIONSHIPS_DEST_ID_COLUMN );*/
860 20 : bool source_exists = ( SQLITE_INTEGER == sqlite3_column_type( prepared_statement, RESULT_RELATIONSHIPS_SOURCE_ID_COLUMN ) );
861 20 : bool dest_exists = ( SQLITE_INTEGER == sqlite3_column_type( prepared_statement, RESULT_RELATIONSHIPS_DEST_ID_COLUMN ) );
862 20 : if (( ! source_exists ) && ( ! dest_exists ))
863 : {
864 3 : U8_LOG_ERROR_INT( "relationship referencing non-existing source and destiation, relationship:", relation_id );
865 3 : U8_TRACE_INFO_INT_INT( "relationship referencing non-existing source: relation_id, classifier:", relation_id, relation_from_id );
866 3 : U8_TRACE_INFO_INT_INT( "relationship referencing non-existing destination: relation_id, classifier:", relation_id, relation_to_id );
867 3 : data_small_set_add_row_id( io_set, DATA_TABLE_RELATIONSHIP, relation_id );
868 : }
869 17 : else if ( ! source_exists )
870 : {
871 2 : U8_LOG_ERROR_INT( "referenced relationship referencing non-existing source, relationship:", relation_id );
872 2 : U8_TRACE_INFO_INT_INT( "referenced relationship referencing non-existing source: relation_id, classifier:", relation_id, relation_from_id );
873 2 : data_small_set_add_row_id( io_set, DATA_TABLE_RELATIONSHIP, relation_id );
874 : }
875 15 : else if ( ! dest_exists )
876 : {
877 2 : U8_LOG_ERROR_INT( "referenced relationship referencing non-existing destination, relationship:", relation_id );
878 2 : U8_TRACE_INFO_INT_INT( "referenced relationship referencing non-existing destination: relation_id, classifier:", relation_id, relation_to_id );
879 2 : data_small_set_add_row_id( io_set, DATA_TABLE_RELATIONSHIP, relation_id );
880 : }
881 : else
882 : {
883 13 : U8_TRACE_INFO_INT( "ok:", relation_id );
884 : }
885 : }
886 : else /*if (( SQLITE_ROW != sqlite_err )&&( SQLITE_DONE != sqlite_err ))*/
887 : {
888 0 : U8_LOG_ERROR_INT( "sqlite3_step failed:", sqlite_err );
889 0 : result |= U8_ERROR_AT_DB;
890 : }
891 : }
892 : }
893 :
894 30 : sqlite_err = sqlite3_finalize( prepared_statement );
895 30 : if ( 0 != sqlite_err )
896 : {
897 0 : U8_LOG_ERROR_INT( "sqlite3_finalize():", sqlite_err );
898 0 : result |= U8_ERROR_AT_DB;
899 : }
900 : }
901 :
902 30 : U8_TRACE_END_ERR( result );
903 30 : return result;
904 : }
905 :
906 30 : u8_error_t data_database_consistency_checker_find_invalid_relationship_features ( data_database_consistency_checker_t *this_, data_small_set_t *io_set )
907 : {
908 30 : U8_TRACE_BEGIN();
909 30 : assert( NULL != io_set );
910 30 : u8_error_t result = U8_ERROR_NONE;
911 : int sqlite_err;
912 :
913 30 : if ( ! data_database_is_open( (*this_).database ) )
914 : {
915 0 : result = U8_ERROR_NO_DB;
916 0 : U8_LOG_WARNING( "Database not open, cannot request data." );
917 : }
918 : else
919 : {
920 : sqlite3 *native_db;
921 30 : native_db = data_database_get_database_ptr( (*this_).database );
922 : sqlite3_stmt *prepared_statement;
923 :
924 30 : U8_LOG_EVENT_STR( "sqlite3_prepare_v2():", SELECT_FEATURE_RELATIONSHIPS );
925 30 : sqlite_err = sqlite3_prepare_v2 ( native_db,
926 : SELECT_FEATURE_RELATIONSHIPS,
927 : AUTO_DETECT_SQL_LENGTH,
928 : &prepared_statement,
929 : NO_SQL_DEBUG_INFORMATION
930 : );
931 :
932 30 : if ( 0 != sqlite_err )
933 : {
934 0 : U8_LOG_ERROR_INT( "sqlite3_prepare_v2():", sqlite_err );
935 0 : result |= U8_ERROR_AT_DB;
936 : }
937 : else
938 : {
939 30 : sqlite_err = SQLITE_ROW;
940 76 : for ( uint_fast32_t row_index = 0; (SQLITE_ROW == sqlite_err) && (row_index <= MAX_ROWS_TO_CHECK); row_index ++ )
941 : {
942 46 : U8_TRACE_INFO( "sqlite3_step()" );
943 46 : sqlite_err = sqlite3_step( prepared_statement );
944 :
945 46 : if ( SQLITE_DONE == sqlite_err )
946 : {
947 30 : U8_TRACE_INFO( "sqlite3_step finished: SQLITE_DONE" );
948 : }
949 16 : else if ( SQLITE_ROW == sqlite_err )
950 : {
951 : data_row_id_t relation_id;
952 : data_row_id_t relation_from_classifier_id;
953 : data_row_id_t relation_to_classifier_id;
954 : bool relation_has_from_feature;
955 : data_row_id_t relation_from_feature_id;
956 : bool relation_has_to_feature;
957 : data_row_id_t relation_to_feature_id;
958 : bool source_feature_exists;
959 : data_row_id_t source_feature_id;
960 : data_row_id_t source_feature_classifier_id;
961 : bool dest_feature_exists;
962 : data_row_id_t dest_feature_id;
963 : data_row_id_t dest_feature_classifier_id;
964 :
965 : /* fetch data record */
966 16 : relation_id = sqlite3_column_int64( prepared_statement, RESULT_FEATURE_RELATIONSHIPS_RELATION_ID_COLUMN );
967 16 : relation_from_classifier_id = sqlite3_column_int64( prepared_statement, RESULT_FEATURE_RELATIONSHIPS_RELATION_FROM_CLASSIFIER_ID_COLUMN );
968 16 : relation_to_classifier_id = sqlite3_column_int64( prepared_statement, RESULT_FEATURE_RELATIONSHIPS_RELATION_TO_CLASIFIER_ID_COLUMN );
969 16 : relation_has_from_feature = ( SQLITE_NULL != sqlite3_column_type( prepared_statement, RESULT_FEATURE_RELATIONSHIPS_RELATION_FROM_FEATURE_ID_COLUMN ) );
970 16 : if ( relation_has_from_feature )
971 : {
972 9 : relation_from_feature_id = sqlite3_column_int64( prepared_statement, RESULT_FEATURE_RELATIONSHIPS_RELATION_FROM_FEATURE_ID_COLUMN );
973 : }
974 : else
975 : {
976 7 : relation_from_feature_id = DATA_ROW_ID_VOID;
977 : }
978 16 : relation_has_to_feature = ( SQLITE_NULL != sqlite3_column_type( prepared_statement, RESULT_FEATURE_RELATIONSHIPS_RELATION_TO_FEATURE_ID_COLUMN ) );
979 16 : if ( relation_has_to_feature )
980 : {
981 9 : relation_to_feature_id = sqlite3_column_int64( prepared_statement, RESULT_FEATURE_RELATIONSHIPS_RELATION_TO_FEATURE_ID_COLUMN );
982 : }
983 : else
984 : {
985 7 : relation_to_feature_id = DATA_ROW_ID_VOID;
986 : }
987 16 : source_feature_exists = ( SQLITE_NULL != sqlite3_column_type( prepared_statement, RESULT_FEATURE_RELATIONSHIPS_SOURCE_FEATURE_ID_COLUMN ) );
988 16 : if ( source_feature_exists )
989 : {
990 7 : source_feature_id = sqlite3_column_int64( prepared_statement, RESULT_FEATURE_RELATIONSHIPS_SOURCE_FEATURE_ID_COLUMN );
991 7 : source_feature_classifier_id = sqlite3_column_int64( prepared_statement, RESULT_FEATURE_RELATIONSHIPS_SOURCE_FEATURE_CLASSIFIER_ID_COLUMN );
992 : }
993 : else
994 : {
995 9 : source_feature_id = DATA_ROW_ID_VOID;
996 9 : source_feature_classifier_id = DATA_ROW_ID_VOID;
997 : }
998 16 : dest_feature_exists = ( SQLITE_NULL != sqlite3_column_type( prepared_statement, RESULT_FEATURE_RELATIONSHIPS_DEST_FEATURE_ID_COLUMN ) );
999 16 : if ( dest_feature_exists )
1000 : {
1001 7 : dest_feature_id = sqlite3_column_int64( prepared_statement, RESULT_FEATURE_RELATIONSHIPS_DEST_FEATURE_ID_COLUMN );
1002 7 : dest_feature_classifier_id = sqlite3_column_int64( prepared_statement, RESULT_FEATURE_RELATIONSHIPS_DEST_FEATURE_CLASSIFIER_ID_COLUMN );
1003 : }
1004 : else
1005 : {
1006 9 : dest_feature_id = DATA_ROW_ID_VOID;
1007 9 : dest_feature_classifier_id = DATA_ROW_ID_VOID;
1008 : }
1009 :
1010 : /* evaluate the data record */
1011 16 : if ( ! relation_has_from_feature )
1012 : {
1013 7 : if ( ! relation_has_to_feature )
1014 : {
1015 7 : U8_TRACE_INFO_INT( "ok (no feature relation):", relation_id );
1016 : }
1017 : else
1018 : {
1019 0 : if ( ! dest_feature_exists )
1020 : {
1021 0 : U8_LOG_ERROR_INT( "relation destination feature not existing, relationship:", relation_id );
1022 0 : data_small_set_add_row_id( io_set, DATA_TABLE_RELATIONSHIP, relation_id );
1023 : }
1024 0 : else if ( relation_to_classifier_id != dest_feature_classifier_id )
1025 : {
1026 0 : U8_LOG_ERROR_INT( "referenced classifier of relationship and feature differ, relationship:", relation_id );
1027 0 : U8_TRACE_INFO_INT_INT( "referenced to classifier, dest feature classifier:", relation_to_classifier_id, dest_feature_classifier_id );
1028 0 : U8_TRACE_INFO_INT_INT( "referenced to feature, dest feature:", relation_to_feature_id, dest_feature_id );
1029 0 : data_small_set_add_row_id( io_set, DATA_TABLE_RELATIONSHIP, relation_id );
1030 : }
1031 : else
1032 : {
1033 0 : U8_TRACE_INFO_INT( "ok (valid destination feature, no source feature):", relation_id );
1034 : }
1035 : }
1036 : }
1037 : else
1038 : {
1039 9 : if ( ! relation_has_to_feature )
1040 : {
1041 0 : if ( ! source_feature_exists )
1042 : {
1043 0 : U8_LOG_ERROR_INT( "relation source feature not existing, relationship:", relation_id );
1044 0 : data_small_set_add_row_id( io_set, DATA_TABLE_RELATIONSHIP, relation_id );
1045 : }
1046 0 : else if ( relation_from_classifier_id != source_feature_classifier_id )
1047 : {
1048 0 : U8_LOG_ERROR_INT( "referenced classifier of relationship and feature differ, relationship:", relation_id );
1049 0 : U8_TRACE_INFO_INT_INT( "referenced from classifier, src feature classifier:", relation_from_classifier_id, source_feature_classifier_id );
1050 0 : U8_TRACE_INFO_INT_INT( "referenced from feature, src feature:", relation_from_feature_id, source_feature_id );
1051 0 : data_small_set_add_row_id( io_set, DATA_TABLE_RELATIONSHIP, relation_id );
1052 : }
1053 : else
1054 : {
1055 0 : U8_TRACE_INFO_INT( "ok (valid source feature, no destination feature):", relation_id );
1056 : }
1057 : }
1058 : else
1059 : {
1060 9 : if ( ! source_feature_exists )
1061 : {
1062 2 : U8_LOG_ERROR_INT( "relation source feature not existing, relationship:", relation_id );
1063 2 : data_small_set_add_row_id( io_set, DATA_TABLE_RELATIONSHIP, relation_id );
1064 : }
1065 7 : else if ( ! dest_feature_exists )
1066 : {
1067 2 : U8_LOG_ERROR_INT( "relation destination feature not existing, relationship:", relation_id );
1068 2 : data_small_set_add_row_id( io_set, DATA_TABLE_RELATIONSHIP, relation_id );
1069 : }
1070 5 : else if ( relation_from_classifier_id != source_feature_classifier_id )
1071 : {
1072 0 : U8_LOG_ERROR_INT( "referenced classifier of relationship and feature differ, relationship:", relation_id );
1073 0 : U8_TRACE_INFO_INT_INT( "referenced from classifier, src feature classifier:", relation_from_classifier_id, source_feature_classifier_id );
1074 0 : U8_TRACE_INFO_INT_INT( "referenced from feature, src feature:", relation_from_feature_id, source_feature_id );
1075 0 : data_small_set_add_row_id( io_set, DATA_TABLE_RELATIONSHIP, relation_id );
1076 : }
1077 5 : else if ( relation_to_classifier_id != dest_feature_classifier_id )
1078 : {
1079 2 : U8_LOG_ERROR_INT( "referenced classifier of relationship and feature differ, relationship:", relation_id );
1080 2 : U8_TRACE_INFO_INT_INT( "referenced to classifier, dest feature classifier:", relation_to_classifier_id, dest_feature_classifier_id );
1081 2 : U8_TRACE_INFO_INT_INT( "referenced to feature, dest feature:", relation_to_feature_id, dest_feature_id );
1082 2 : data_small_set_add_row_id( io_set, DATA_TABLE_RELATIONSHIP, relation_id );
1083 : }
1084 : else
1085 : {
1086 3 : U8_TRACE_INFO_INT( "ok (valid source and destination features):", relation_id );
1087 : }
1088 : }
1089 : }
1090 : }
1091 : else /*if (( SQLITE_ROW != sqlite_err )&&( SQLITE_DONE != sqlite_err ))*/
1092 : {
1093 0 : U8_LOG_ERROR_INT( "sqlite3_step failed:", sqlite_err );
1094 0 : result |= U8_ERROR_AT_DB;
1095 : }
1096 : }
1097 : }
1098 :
1099 30 : sqlite_err = sqlite3_finalize( prepared_statement );
1100 30 : if ( 0 != sqlite_err )
1101 : {
1102 0 : U8_LOG_ERROR_INT( "sqlite3_finalize():", sqlite_err );
1103 0 : result |= U8_ERROR_AT_DB;
1104 : }
1105 : }
1106 :
1107 30 : U8_TRACE_END_ERR( result );
1108 30 : return result;
1109 : }
1110 :
1111 : /*!
1112 : * \brief prefix string constant to delete a classifier
1113 : */
1114 : static const char *DATA_DATABASE_CONSISTENCY_CHECKER_DELETE_CLASSIFIER_PREFIX =
1115 : "DELETE FROM classifiers WHERE (id=";
1116 :
1117 : /*!
1118 : * \brief postfix string constant to delete a classifier
1119 : */
1120 : static const char *DATA_DATABASE_CONSISTENCY_CHECKER_DELETE_CLASSIFIER_POSTFIX = ");";
1121 :
1122 2 : u8_error_t data_database_consistency_checker_kill_classifier( data_database_consistency_checker_t *this_, data_row_id_t obj_id )
1123 : {
1124 2 : U8_TRACE_BEGIN();
1125 2 : u8_error_t result = U8_ERROR_NONE;
1126 : int sqlite_err;
1127 2 : char *error_msg = NULL;
1128 2 : sqlite3 *db = data_database_get_database_ptr( (*this_).database );
1129 :
1130 2 : if ( data_database_is_open( (*this_).database ) )
1131 : {
1132 2 : result |= data_database_transaction_begin ( (*this_).database );
1133 :
1134 : char delete_statement_buf[56];
1135 2 : utf8stringbuf_t delete_statement = UTF8STRINGBUF( delete_statement_buf );
1136 2 : utf8stringbuf_copy_str( delete_statement, DATA_DATABASE_CONSISTENCY_CHECKER_DELETE_CLASSIFIER_PREFIX );
1137 2 : utf8stringbuf_append_int( delete_statement, obj_id );
1138 2 : utf8stringbuf_append_str( delete_statement, DATA_DATABASE_CONSISTENCY_CHECKER_DELETE_CLASSIFIER_POSTFIX );
1139 2 : U8_LOG_EVENT_STR( "sqlite3_exec:", utf8stringbuf_get_string(delete_statement) );
1140 2 : sqlite_err = sqlite3_exec( db, utf8stringbuf_get_string(delete_statement), NULL, NULL, &error_msg );
1141 2 : if ( SQLITE_OK != sqlite_err )
1142 : {
1143 0 : U8_LOG_ERROR_STR( "sqlite3_exec() failed:", utf8stringbuf_get_string(delete_statement) );
1144 0 : U8_LOG_ERROR_INT( "sqlite3_exec() failed:", sqlite_err );
1145 0 : result |= (sqlite_err == SQLITE_READONLY) ? U8_ERROR_READ_ONLY_DB : U8_ERROR_AT_DB;
1146 : }
1147 2 : if ( error_msg != NULL )
1148 : {
1149 0 : U8_LOG_ERROR_STR( "sqlite3_exec() failed:", error_msg );
1150 0 : sqlite3_free( error_msg );
1151 0 : error_msg = NULL;
1152 : }
1153 :
1154 2 : result |= data_database_transaction_commit ( (*this_).database );
1155 : }
1156 : else
1157 : {
1158 0 : U8_LOG_WARNING( "database not open." );
1159 0 : result = U8_ERROR_NO_DB;
1160 : }
1161 :
1162 2 : U8_TRACE_END_ERR( result );
1163 2 : return result;
1164 : }
1165 :
1166 :
1167 : /*
1168 : Copyright 2016-2024 Andreas Warnke
1169 :
1170 : Licensed under the Apache License, Version 2.0 (the "License");
1171 : you may not use this file except in compliance with the License.
1172 : You may obtain a copy of the License at
1173 :
1174 : http://www.apache.org/licenses/LICENSE-2.0
1175 :
1176 : Unless required by applicable law or agreed to in writing, software
1177 : distributed under the License is distributed on an "AS IS" BASIS,
1178 : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1179 : See the License for the specific language governing permissions and
1180 : limitations under the License.
1181 : */
|