LCOV - code coverage report
Current view: top level - data/source/storage - data_database_consistency_checker.c (source / functions) Coverage Total Hit
Test: crystal-facet-uml_v1.63.2_covts Lines: 79.0 % 420 332
Test Date: 2025-05-01 10:10:14 Functions: 100.0 % 11 11

            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_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_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_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_VOID != ((*this_).private_temp_diagram_ids_buf)[diag_idx][1] );
     320           45 :         if ( diag_has_parent )
     321              :         {
     322            8 :             data_row_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_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_t diag_id = sqlite3_column_int64( prepared_statement, RESULT_DIAGRAMS_DIAG_ID_COLUMN );
     384           45 :                     data_row_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_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_t diagele_id = sqlite3_column_int64( prepared_statement, RESULT_DIAGRAMELEMENTS_DIAGELE_ID_COLUMN );
     474           45 :                     data_row_t diagele_diagram_id = sqlite3_column_int64( prepared_statement, RESULT_DIAGRAMELEMENTS_DIAGELE_DIAGRAM_ID_COLUMN );
     475           45 :                     data_row_t diagele_classifier_id = sqlite3_column_int64( prepared_statement, RESULT_DIAGRAMELEMENTS_DIAGELE_CLASSIFIER_ID_COLUMN );
     476              :                     /*data_row_t diagram_id = sqlite3_column_int64( prepared_statement, RESULT_DIAGRAMELEMENTS_DIAGRAM_ID_COLUMN );*/
     477              :                     /*data_row_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_t diagele_id;
     570              :                     data_row_t diagele_classifier_id;
     571              :                     bool diagele_has_focused_feature;
     572              :                     data_row_t diagele_focused_feature_id;
     573              :                     bool feature_exists;
     574              :                     data_row_t feature_id;
     575              :                     data_row_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_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_VOID;
     598           37 :                         feature_classifier_id = DATA_ROW_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_t classifier_id = sqlite3_column_int64( prepared_statement, RESULT_CLASSIFIERS_CLASSIFIER_ID_COLUMN );
     694              :                     /*
     695              :                     data_row_t diagele_classifier_id = sqlite3_column_int64( prepared_statement, RESULT_CLASSIFIERS_DIAGELE_CLASSIFIER_ID_COLUMN );
     696              :                     */
     697           44 :                     data_row_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_t feature_id = sqlite3_column_int64( prepared_statement, RESULT_FEATURES_FEATURE_ID_COLUMN );
     776           16 :                     data_row_t feature_classifier_id = sqlite3_column_int64( prepared_statement, RESULT_FEATURES_FEATURE_CLASSIFIER_ID_COLUMN );
     777              :                     /*data_row_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_t relation_id = sqlite3_column_int64( prepared_statement, RESULT_RELATIONSHIPS_RELATIONSHIP_ID_COLUMN );
     856           20 :                     data_row_t relation_from_id = sqlite3_column_int64( prepared_statement, RESULT_RELATIONSHIPS_RELATIONSHIP_FROM_ID_COLUMN );
     857           20 :                     data_row_t relation_to_id = sqlite3_column_int64( prepared_statement, RESULT_RELATIONSHIPS_RELATIONSHIP_TO_ID_COLUMN );
     858              :                     /*data_row_t source_id = sqlite3_column_int64( prepared_statement, RESULT_RELATIONSHIPS_SOURCE_ID_COLUMN );*/
     859              :                     /*data_row_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_t relation_id;
     952              :                     data_row_t relation_from_classifier_id;
     953              :                     data_row_t relation_to_classifier_id;
     954              :                     bool relation_has_from_feature;
     955              :                     data_row_t relation_from_feature_id;
     956              :                     bool relation_has_to_feature;
     957              :                     data_row_t relation_to_feature_id;
     958              :                     bool source_feature_exists;
     959              :                     data_row_t source_feature_id;
     960              :                     data_row_t source_feature_classifier_id;
     961              :                     bool dest_feature_exists;
     962              :                     data_row_t dest_feature_id;
     963              :                     data_row_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_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_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_VOID;
     996            9 :                         source_feature_classifier_id = DATA_ROW_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_VOID;
    1007            9 :                         dest_feature_classifier_id = DATA_ROW_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_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-2025 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              : */
        

Generated by: LCOV version 2.0-1