LCOV - code coverage report
Current view: top level - data/source/storage - data_database_consistency_checker.c (source / functions) Hit Total Coverage
Test: crystal-facet-uml_v1.61.0_covts Lines: 332 420 79.0 %
Date: 2024-10-26 21:44:38 Functions: 11 11 100.0 %

          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             : */

Generated by: LCOV version 1.16