LCOV - code coverage report
Current view: top level - data/source/storage - data_search_result_iterator.c (source / functions) Coverage Total Hit
Test: crystal-facet-uml_v1.70.5_covts Lines: 87.4 % 247 216
Test Date: 2026-05-28 21:31:40 Functions: 100.0 % 10 10

            Line data    Source code
       1              : /* File: data_search_result_iterator.c; Copyright and License: see below */
       2              : 
       3              : #include "storage/data_search_result_iterator.h"
       4              : #include "u8/u8_trace.h"
       5              : #include "u8/u8_log.h"
       6              : #include "utf8stringbuf/utf8stringbuf.h"
       7              : #include <sqlite3.h>
       8              : #include <assert.h>
       9              : #include <stdint.h>
      10              : 
      11            2 : void data_search_result_iterator_init_empty ( data_search_result_iterator_t *this_ )
      12              : {
      13            2 :     U8_TRACE_BEGIN();
      14              : 
      15            2 :     data_database_borrowed_stmt_init_void( &((*this_).diagram_statement) );
      16            2 :     data_database_borrowed_stmt_init_void( &((*this_).classifier_statement) );
      17            2 :     data_database_borrowed_stmt_init_void( &((*this_).feature_statement) );
      18            2 :     data_database_borrowed_stmt_init_void( &((*this_).relationship_statement) );
      19            2 :     (*this_).is_at_diagram_end = true;
      20            2 :     (*this_).is_at_classifier_end = true;
      21            2 :     (*this_).is_at_feature_end = true;
      22            2 :     (*this_).is_at_relationship_end = true;
      23            2 :     data_search_result_init_void( &((*this_).next_search_result_buf) );
      24              : 
      25            2 :     data_rules_init ( &((*this_).data_rules) );
      26              : 
      27            2 :     (*this_).last_relationship_id = DATA_ROW_VOID;
      28            2 :     (*this_).last_relationship_was_scenario = false;
      29              : 
      30            2 :     U8_TRACE_END();
      31            2 : }
      32              : 
      33            2 : u8_error_t data_search_result_iterator_reinit ( data_search_result_iterator_t *this_,
      34              :                                                 data_database_borrowed_stmt_t diagram_statement,
      35              :                                                 data_database_borrowed_stmt_t classifier_statement,
      36              :                                                 data_database_borrowed_stmt_t feature_statement,
      37              :                                                 data_database_borrowed_stmt_t relationship_statement )
      38              : {
      39            2 :     U8_TRACE_BEGIN();
      40            2 :     assert( data_database_borrowed_stmt_is_valid( &diagram_statement ) );
      41            2 :     assert( data_database_borrowed_stmt_is_valid( &classifier_statement ) );
      42            2 :     assert( data_database_borrowed_stmt_is_valid( &feature_statement ) );
      43            2 :     assert( data_database_borrowed_stmt_is_valid( &relationship_statement ) );
      44            2 :     u8_error_t result = U8_ERROR_NONE;
      45              : 
      46              :     /* destroy old state */
      47            2 :     result = data_search_result_iterator_destroy( this_ );
      48              : 
      49              :     /* init new state */
      50            2 :     (*this_).diagram_statement = diagram_statement;
      51            2 :     (*this_).classifier_statement = classifier_statement;
      52            2 :     (*this_).feature_statement = feature_statement;
      53            2 :     (*this_).relationship_statement = relationship_statement;
      54            2 :     (*this_).is_at_diagram_end = false;
      55            2 :     (*this_).is_at_classifier_end = false;
      56            2 :     (*this_).is_at_feature_end = false;
      57            2 :     (*this_).is_at_relationship_end = false;
      58            2 :     data_search_result_init_void( &((*this_).next_search_result_buf) );
      59            2 :     (*this_).last_relationship_id = DATA_ROW_VOID;
      60            2 :     (*this_).last_relationship_was_scenario = false;
      61              : 
      62            2 :     result |= data_search_result_iterator_private_step_to_next( this_ );
      63              : 
      64            2 :     data_rules_init ( &((*this_).data_rules) );
      65              : 
      66            2 :     U8_TRACE_END_ERR(result);
      67            2 :     return result;
      68              : }
      69              : 
      70            4 : u8_error_t data_search_result_iterator_destroy ( data_search_result_iterator_t *this_ )
      71              : {
      72            4 :     U8_TRACE_BEGIN();
      73            4 :     u8_error_t result = U8_ERROR_NONE;
      74              : 
      75            4 :     (*this_).last_relationship_id = DATA_ROW_VOID;
      76            4 :     (*this_).last_relationship_was_scenario = false;
      77              : 
      78            4 :     data_rules_destroy ( &((*this_).data_rules) );
      79              : 
      80            4 :     result |= data_database_borrowed_stmt_destroy( &((*this_).diagram_statement) );
      81            4 :     result |= data_database_borrowed_stmt_destroy( &((*this_).classifier_statement) );
      82            4 :     result |= data_database_borrowed_stmt_destroy( &((*this_).feature_statement) );
      83            4 :     result |= data_database_borrowed_stmt_destroy( &((*this_).relationship_statement) );
      84            4 :     (*this_).is_at_diagram_end = true;
      85            4 :     (*this_).is_at_classifier_end = true;
      86            4 :     (*this_).is_at_feature_end = true;
      87            4 :     (*this_).is_at_relationship_end = true;
      88            4 :     data_search_result_destroy( &((*this_).next_search_result_buf) );
      89              : 
      90            4 :     U8_TRACE_END_ERR(result);
      91            4 :     return result;
      92              : }
      93              : 
      94            6 : bool data_search_result_iterator_has_next ( const data_search_result_iterator_t *this_ )
      95              : {
      96            5 :     const bool finished = (*this_).is_at_diagram_end && (*this_).is_at_classifier_end
      97           11 :                           && (*this_).is_at_feature_end && (*this_).is_at_relationship_end;
      98            6 :     assert( ( ! finished ) == data_search_result_is_valid( &((*this_).next_search_result_buf) ) );
      99            6 :     return ( ! finished );
     100              : }
     101              : 
     102            4 : u8_error_t data_search_result_iterator_next ( data_search_result_iterator_t *this_, data_search_result_t *out_search_result )
     103              : {
     104            4 :     U8_TRACE_BEGIN();
     105            4 :     assert( NULL != out_search_result );
     106            4 :     assert( data_database_borrowed_stmt_is_valid( &((*this_).diagram_statement) ) );
     107            4 :     assert( data_database_borrowed_stmt_is_valid( &((*this_).classifier_statement) ) );
     108            4 :     assert( data_database_borrowed_stmt_is_valid( &((*this_).feature_statement) ) );
     109            4 :     assert( data_database_borrowed_stmt_is_valid( &((*this_).relationship_statement) ) );
     110            4 :     u8_error_t result = U8_ERROR_NONE;
     111              : 
     112              :     /* copy the next data_search_result_t to out */
     113            4 :     data_search_result_copy( out_search_result, &((*this_).next_search_result_buf) );
     114              : 
     115              :     /* search (and filter) for the next valid, unfiltered search result */
     116            4 :     data_search_result_iterator_private_step_to_next( this_ );
     117              : 
     118            4 :     U8_TRACE_END_ERR( result );
     119            4 :     return result;
     120              : }
     121              : 
     122            6 : u8_error_t data_search_result_iterator_private_step_to_next ( data_search_result_iterator_t *this_ )
     123              : {
     124            6 :     U8_TRACE_BEGIN();
     125            6 :     assert( data_database_borrowed_stmt_is_valid( &((*this_).diagram_statement) ) );
     126            6 :     assert( data_database_borrowed_stmt_is_valid( &((*this_).classifier_statement) ) );
     127            6 :     assert( data_database_borrowed_stmt_is_valid( &((*this_).feature_statement) ) );
     128            6 :     assert( data_database_borrowed_stmt_is_valid( &((*this_).relationship_statement) ) );
     129            6 :     u8_error_t result = U8_ERROR_NONE;
     130              : 
     131              :     /* invalidate the next_search_result_buf */
     132            6 :     data_search_result_init_void( &((*this_).next_search_result_buf) );
     133              : 
     134            6 :     if ( ! (*this_).is_at_diagram_end )
     135              :     {
     136            3 :         sqlite3_stmt *const sql_statement = data_database_borrowed_stmt_get_statement( &((*this_).diagram_statement) );
     137              : 
     138              :         /* do one step, check if is_at_end */
     139            3 :         U8_TRACE_INFO( "sqlite3_step() at diagrams" );
     140            3 :         const int sqlite_err = sqlite3_step( sql_statement );
     141            3 :         if ( SQLITE_DONE == sqlite_err )
     142              :         {
     143            2 :             U8_TRACE_INFO( "sqlite3_step finished: SQLITE_DONE" );
     144            2 :             (*this_).is_at_diagram_end = true;
     145              :         }
     146            1 :         else if ( SQLITE_ROW == sqlite_err )
     147              :         {
     148            1 :             (*this_).is_at_diagram_end = false;
     149              :             /* read next */
     150            1 :             result |= data_search_result_iterator_private_get_diagram( this_, &((*this_).next_search_result_buf) );
     151              :         }
     152              :         else
     153              :         {
     154            0 :             U8_LOG_ERROR_INT( "sqlite3_step failed:", sqlite_err );
     155            0 :             (*this_).is_at_diagram_end = true;
     156            0 :             result |= U8_ERROR_AT_DB;
     157              :         }
     158              :     }
     159              : 
     160            6 :     if ( (*this_).is_at_diagram_end && ( ! (*this_).is_at_classifier_end ))
     161              :     {
     162            3 :         sqlite3_stmt *const sql_statement = data_database_borrowed_stmt_get_statement( &((*this_).classifier_statement) );
     163              : 
     164              :         /* do one step, check if is_at_end */
     165            3 :         U8_TRACE_INFO( "sqlite3_step() at classifiers" );
     166            3 :         const int sqlite_err = sqlite3_step( sql_statement );
     167            3 :         if ( SQLITE_DONE == sqlite_err )
     168              :         {
     169            2 :             U8_TRACE_INFO( "sqlite3_step finished: SQLITE_DONE" );
     170            2 :             (*this_).is_at_classifier_end = true;
     171              :         }
     172            1 :         else if ( SQLITE_ROW == sqlite_err )
     173              :         {
     174            1 :             (*this_).is_at_classifier_end = false;
     175              :             /* read next */
     176            1 :             result |= data_search_result_iterator_private_get_classifier( this_, &((*this_).next_search_result_buf) );
     177              :         }
     178              :         else
     179              :         {
     180            0 :             U8_LOG_ERROR_INT( "sqlite3_step failed:", sqlite_err );
     181            0 :             (*this_).is_at_classifier_end = true;
     182            0 :             result |= U8_ERROR_AT_DB;
     183              :         }
     184              :     }
     185              : 
     186            9 :     while ( (*this_).is_at_classifier_end && ( ! (*this_).is_at_feature_end ) && ( ! data_search_result_is_valid( &((*this_).next_search_result_buf) ) ) )
     187              :     {
     188            3 :         sqlite3_stmt *const sql_statement = data_database_borrowed_stmt_get_statement( &((*this_).feature_statement) );
     189              : 
     190              :         /* do one step, check if is_at_end */
     191            3 :         U8_TRACE_INFO( "sqlite3_step() at features" );
     192            3 :         const int sqlite_err = sqlite3_step( sql_statement );
     193            3 :         if ( SQLITE_DONE == sqlite_err )
     194              :         {
     195            2 :             U8_TRACE_INFO( "sqlite3_step finished: SQLITE_DONE" );
     196            2 :             (*this_).is_at_feature_end = true;
     197              :         }
     198            1 :         else if ( SQLITE_ROW == sqlite_err )
     199              :         {
     200            1 :             (*this_).is_at_feature_end = false;
     201              :             /* read next */
     202            1 :             result |= data_search_result_iterator_private_get_feature( this_, &((*this_).next_search_result_buf) );
     203              :         }
     204              :         else
     205              :         {
     206            0 :             U8_LOG_ERROR_INT( "sqlite3_step failed:", sqlite_err );
     207            0 :             (*this_).is_at_feature_end = true;
     208            0 :             result |= U8_ERROR_AT_DB;
     209              :         }
     210              :     }
     211              : 
     212            9 :     while ( (*this_).is_at_feature_end && ( ! (*this_).is_at_relationship_end ) && ( ! data_search_result_is_valid( &((*this_).next_search_result_buf) ) ) )
     213              :     {
     214            3 :         sqlite3_stmt *const sql_statement = data_database_borrowed_stmt_get_statement( &((*this_).relationship_statement) );
     215              : 
     216              :         /* do one step, check if is_at_end */
     217            3 :         U8_TRACE_INFO( "sqlite3_step() at relationships" );
     218            3 :         const int sqlite_err = sqlite3_step( sql_statement );
     219            3 :         if ( SQLITE_DONE == sqlite_err )
     220              :         {
     221            2 :             U8_TRACE_INFO( "sqlite3_step finished: SQLITE_DONE" );
     222            2 :             (*this_).is_at_relationship_end = true;
     223              :         }
     224            1 :         else if ( SQLITE_ROW == sqlite_err )
     225              :         {
     226            1 :             (*this_).is_at_relationship_end = false;
     227              :             /* read next */
     228            1 :             result |= data_search_result_iterator_private_get_relationship( this_, &((*this_).next_search_result_buf) );
     229              :         }
     230              :         else
     231              :         {
     232            0 :             U8_LOG_ERROR_INT( "sqlite3_step failed:", sqlite_err );
     233            0 :             (*this_).is_at_relationship_end = true;
     234            0 :             result |= U8_ERROR_AT_DB;
     235              :         }
     236              :     }
     237              : 
     238            6 :     U8_TRACE_END_ERR(result);
     239            6 :     return result;
     240              : }
     241              : 
     242              : /* ================================ DIAGRAM ================================ */
     243              : 
     244              : /*!
     245              :  *  \brief predefined search statement to find diagrams by textfragment
     246              :  *
     247              :  *  note: name is needed for debugging only
     248              :  */
     249              : const char *const DATA_SEARCH_RESULT_ITERATOR_SELECT_DIAGRAM_BY_TEXTFRAGMENT =
     250              : "SELECT id,diagram_type,name "
     251              : "FROM diagrams "
     252              : "WHERE name LIKE ? ESCAPE \"\\\" "
     253              : "OR stereotype LIKE ? ESCAPE \"\\\" "
     254              : "OR description LIKE ? ESCAPE \"\\\";";
     255              : 
     256              : /*!
     257              :  *  \brief the column id of the result where this parameter is stored: id
     258              :  */
     259              : static const int RESULT_DIAGRAM_ID_COLUMN = 0;
     260              : 
     261              : /*!
     262              :  *  \brief the column id of the result where this parameter is stored: diagram_type
     263              :  */
     264              : static const int RESULT_DIAGRAM_TYPE_COLUMN = 1;
     265              : 
     266              : /*!
     267              :  *  \brief the column id of the result where this parameter is stored: name
     268              :  */
     269              : static const int RESULT_DIAGRAM_NAME_COLUMN = 2;
     270              : 
     271              : 
     272            1 : u8_error_t data_search_result_iterator_private_get_diagram( data_search_result_iterator_t *this_,
     273              :                                                             data_search_result_t *out_search_result )
     274              : {
     275            1 :     U8_TRACE_BEGIN();
     276            1 :     assert( NULL != out_search_result );
     277            1 :     u8_error_t result = U8_ERROR_NONE;
     278              : 
     279            1 :     sqlite3_stmt *const prepared_statement = data_database_borrowed_stmt_get_statement( &((*this_).diagram_statement) );
     280              : 
     281            1 :     data_search_result_init_diagram( out_search_result,
     282            1 :                                      sqlite3_column_int64( prepared_statement, RESULT_DIAGRAM_ID_COLUMN ),
     283            1 :                                      sqlite3_column_int( prepared_statement, RESULT_DIAGRAM_TYPE_COLUMN ),
     284            1 :                                      (const char*) sqlite3_column_text( prepared_statement, RESULT_DIAGRAM_NAME_COLUMN )
     285              :                                    );
     286            1 :     data_search_result_trace( out_search_result );
     287              : 
     288            1 :     U8_TRACE_END_ERR( result );
     289            1 :     return result;
     290              : }
     291              : 
     292              : 
     293              : /* ================================ CLASSIFIER ================================ */
     294              : 
     295              : /*!
     296              :  *  \brief predefined search statement to find classifiers by textfragment
     297              :  *
     298              :  *  note: classifiers.name is needed for debugging only
     299              :  */
     300              : const char *const DATA_SEARCH_RESULT_ITERATOR_SELECT_CLASSIFIER_BY_TEXTFRAGMENT =
     301              : "SELECT classifiers.id,classifiers.main_type,classifiers.name,diagrams.id "
     302              : "FROM classifiers "
     303              : "INNER JOIN diagramelements ON diagramelements.classifier_id=classifiers.id "
     304              : "INNER JOIN diagrams ON diagramelements.diagram_id=diagrams.id "
     305              : "WHERE classifiers.name LIKE ? ESCAPE \"\\\" "
     306              : "OR classifiers.stereotype LIKE ? ESCAPE \"\\\" "
     307              : "OR classifiers.description LIKE ? ESCAPE \"\\\" "
     308              : "GROUP BY classifiers.id,diagrams.id;";  /* no duplicates if a classifier is twice in a diagram */
     309              : 
     310              : /*!
     311              :  *  \brief the column id of the result where this parameter is stored: id
     312              :  */
     313              : static const int RESULT_CLASSIFIER_ID_COLUMN = 0;
     314              : 
     315              : /*!
     316              :  *  \brief the column id of the result where this parameter is stored: main_type
     317              :  */
     318              : static const int RESULT_CLASSIFIER_MAIN_TYPE_COLUMN = 1;
     319              : 
     320              : /*!
     321              :  *  \brief the column id of the result where this parameter is stored: name
     322              :  */
     323              : static const int RESULT_CLASSIFIER_NAME_COLUMN = 2;
     324              : 
     325              : /*!
     326              :  *  \brief the column id of the result where this parameter is stored: diagrams.id
     327              :  */
     328              : static const int RESULT_CLASSIFIER_DIAGRAM_ID_COLUMN = 3;
     329              : 
     330            1 : u8_error_t data_search_result_iterator_private_get_classifier( data_search_result_iterator_t *this_,
     331              :                                                                data_search_result_t *out_search_result )
     332              : {
     333            1 :     U8_TRACE_BEGIN();
     334            1 :     assert( NULL != out_search_result );
     335            1 :     u8_error_t result = U8_ERROR_NONE;
     336              : 
     337            1 :     sqlite3_stmt *const prepared_statement = data_database_borrowed_stmt_get_statement( &((*this_).classifier_statement) );
     338              : 
     339            1 :     data_search_result_init_classifier( out_search_result,
     340            1 :                                         sqlite3_column_int64( prepared_statement, RESULT_CLASSIFIER_ID_COLUMN ),
     341            1 :                                         sqlite3_column_int( prepared_statement, RESULT_CLASSIFIER_MAIN_TYPE_COLUMN ),
     342            1 :                                         (const char*) sqlite3_column_text( prepared_statement, RESULT_CLASSIFIER_NAME_COLUMN ),
     343            1 :                                         sqlite3_column_int64( prepared_statement, RESULT_CLASSIFIER_DIAGRAM_ID_COLUMN )
     344              :                                       );
     345            1 :     data_search_result_trace( out_search_result );
     346              : 
     347            1 :     U8_TRACE_END_ERR( result );
     348            1 :     return result;
     349              : }
     350              : 
     351              : /* ================================ DIAGRAMELEMENT ================================ */
     352              : 
     353              : /* ================================ FEATURE ================================ */
     354              : 
     355              : /*!
     356              :  *  \brief predefined search statement to find features by textfragment
     357              :  *
     358              :  *  note: features.key is needed for debugging only
     359              :  */
     360              : const char *const DATA_SEARCH_RESULT_ITERATOR_SELECT_FEATURE_BY_TEXTFRAGMENT =
     361              : "SELECT features.id,features.main_type,features.key,features.classifier_id,"
     362              : "classifiers.main_type,diagrams.id,diagrams.diagram_type "
     363              : "FROM features "
     364              : "INNER JOIN classifiers ON features.classifier_id=classifiers.id "
     365              : "INNER JOIN diagramelements ON diagramelements.classifier_id=classifiers.id "
     366              : "INNER JOIN diagrams ON diagramelements.diagram_id=diagrams.id "
     367              : "WHERE features.key LIKE ? ESCAPE \"\\\" "
     368              : "OR features.value LIKE ? ESCAPE \"\\\" "
     369              : "OR features.description LIKE ? ESCAPE \"\\\" "
     370              : "GROUP BY features.id,diagrams.id;";  /* no duplicates if a classifier is twice in a diagram */
     371              : 
     372              : /*!
     373              :  *  \brief the column id of the result where this parameter is stored: id
     374              :  */
     375              : static const int RESULT_FEATURE_ID_COLUMN = 0;
     376              : 
     377              : /*!
     378              :  *  \brief the column id of the result where this parameter is stored: main_type
     379              :  */
     380              : static const int RESULT_FEATURE_MAIN_TYPE_COLUMN = 1;
     381              : 
     382              : /*!
     383              :  *  \brief the column id of the result where this parameter is stored: key
     384              :  */
     385              : static const int RESULT_FEATURE_KEY_COLUMN = 2;
     386              : 
     387              : /*!
     388              :  *  \brief the column id of the result where this parameter is stored: classifiers.id
     389              :  */
     390              : static const int RESULT_FEATURE_CLASSIFIER_ID_COLUMN = 3;
     391              : 
     392              : /*!
     393              :  *  \brief the column id of the result where this parameter is stored: classifiers.main_type
     394              :  */
     395              : static const int RESULT_FEATURE_CLASSIFIER_MAIN_TYPE_COLUMN = 4;
     396              : 
     397              : /*!
     398              :  *  \brief the column id of the result where this parameter is stored: diagrams.id
     399              :  */
     400              : static const int RESULT_FEATURE_DIAGRAM_ID_COLUMN = 5;
     401              : 
     402              : /*!
     403              :  *  \brief the column id of the result where this parameter is stored: diagrams.diagram_type
     404              :  */
     405              : static const int RESULT_FEATURE_DIAGRAM_TYPE_COLUMN = 6;
     406              : 
     407            1 : u8_error_t data_search_result_iterator_private_get_feature( data_search_result_iterator_t *this_,
     408              :                                                             data_search_result_t *out_search_result )
     409              : {
     410            1 :     U8_TRACE_BEGIN();
     411            1 :     assert( NULL != out_search_result );
     412            1 :     u8_error_t result = U8_ERROR_NONE;
     413              : 
     414            1 :     sqlite3_stmt *const prepared_statement = data_database_borrowed_stmt_get_statement( &((*this_).feature_statement) );
     415              : 
     416            1 :     data_search_result_init_feature( out_search_result,
     417            1 :                                      sqlite3_column_int64( prepared_statement, RESULT_FEATURE_ID_COLUMN ),
     418            1 :                                      sqlite3_column_int( prepared_statement, RESULT_FEATURE_MAIN_TYPE_COLUMN ),
     419            1 :                                      (const char*) sqlite3_column_text( prepared_statement, RESULT_FEATURE_KEY_COLUMN ),
     420            1 :                                      sqlite3_column_int64( prepared_statement, RESULT_FEATURE_CLASSIFIER_ID_COLUMN ),
     421            1 :                                      sqlite3_column_int64( prepared_statement, RESULT_FEATURE_DIAGRAM_ID_COLUMN )
     422              :                                    );
     423            1 :     const data_type_t current_type = data_search_result_get_match_type( out_search_result );
     424            1 :     const data_feature_type_t f_type = data_type_get_feature_type( &current_type );
     425            1 :     const data_classifier_type_t c_type = sqlite3_column_int( prepared_statement, RESULT_FEATURE_CLASSIFIER_MAIN_TYPE_COLUMN );
     426            1 :     const data_diagram_type_t d_type = sqlite3_column_int( prepared_statement, RESULT_FEATURE_DIAGRAM_TYPE_COLUMN );
     427            1 :     U8_TRACE_INFO_INT( "- c_type:", c_type );
     428            1 :     U8_TRACE_INFO_INT( "- d_type:", d_type );
     429              : 
     430            1 :     bool filter = false;
     431            1 :     const bool is_scenario_feat = data_rules_feature_is_scenario_cond( &((*this_).data_rules), f_type );
     432            1 :     if ( is_scenario_feat )
     433              :     {
     434              :         /* text search never returns lifelines, independant of data_rules_diagram_shows_scenario_features */
     435            0 :         filter = true;
     436              :     }
     437              :     else
     438              :     {
     439              :         /* evaluate diagram filter */
     440            1 :         filter = ! data_rules_diagram_shows_uncond_features ( &((*this_).data_rules), d_type );
     441              :     }
     442              : 
     443            1 :     if ( filter )
     444              :     {
     445              :         /* invalidate the out_search_result */
     446            0 :         data_search_result_init_void( out_search_result );
     447              :     }
     448              : 
     449            1 :     data_search_result_trace( out_search_result );
     450              : 
     451            1 :     U8_TRACE_END_ERR( result );
     452            1 :     return result;
     453              : }
     454              : 
     455              : 
     456              : /* ================================ RELATIONSHIP ================================ */
     457              : 
     458              : /*!
     459              :  *  \brief predefined search statement to find relationships by textfragment
     460              :  *
     461              :  *  note: relationships.name is needed for debugging only
     462              :  */
     463              : const char *const DATA_SEARCH_RESULT_ITERATOR_SELECT_RELATIONSHIP_BY_TEXTFRAGMENT =
     464              : "SELECT DISTINCT relationships.id,relationships.main_type,relationships.name,"
     465              : "relationships.from_classifier_id,relationships.to_classifier_id,"
     466              : "relationships.from_feature_id,relationships.to_feature_id,"
     467              : "source.focused_feature_id,dest.focused_feature_id,"  /* challenge: the group by clause may randomly select ids here */
     468              : "diagrams.id,diagrams.diagram_type "
     469              : "FROM relationships "
     470              : "INNER JOIN diagramelements AS source "
     471              : "ON source.classifier_id=relationships.from_classifier_id "
     472              : "INNER JOIN diagramelements AS dest "
     473              : "ON (dest.classifier_id=relationships.to_classifier_id)AND(dest.diagram_id==source.diagram_id) "
     474              : "INNER JOIN diagrams ON source.diagram_id=diagrams.id "
     475              : "WHERE relationships.name LIKE ? ESCAPE \"\\\" "
     476              : "OR relationships.stereotype LIKE ? ESCAPE \"\\\" "
     477              : "OR relationships.description LIKE ? ESCAPE \"\\\" "
     478              : //"GROUP BY relationships.id,diagrams.id "  /* good: no duplicates if a classifier is twice in a diagram / bad: randomly chosen source and dest --> use DISTINCT */
     479              : "ORDER BY relationships.id,( (source.focused_feature_id ISNULL) AND (dest.focused_feature_id ISNULL) ) ASC;";  /* start with interactions/scenarios */
     480              : 
     481              : /*!
     482              :  *  \brief the column id of the result where this parameter is stored: id
     483              :  */
     484              : static const int RESULT_RELATIONSHIP_ID_COLUMN = 0;
     485              : 
     486              : /*!
     487              :  *  \brief the column id of the result where this parameter is stored: main_type
     488              :  */
     489              : static const int RESULT_RELATIONSHIP_MAIN_TYPE_COLUMN = 1;
     490              : 
     491              : /*!
     492              :  *  \brief the column id of the result where this parameter is stored: name
     493              :  */
     494              : static const int RESULT_RELATIONSHIP_NAME_COLUMN = 2;
     495              : 
     496              : /*!
     497              :  *  \brief the column id of the result where this parameter is stored: from_classifier_id
     498              :  */
     499              : static const int RESULT_RELATIONSHIP_FROM_CLASSIFIER_ID_COLUMN = 3;
     500              : 
     501              : /*!
     502              :  *  \brief the column id of the result where this parameter is stored: to_classifier_id
     503              :  */
     504              : static const int RESULT_RELATIONSHIP_TO_CLASSIFIER_ID_COLUMN = 4;
     505              : 
     506              : /*!
     507              :  *  \brief the column id of the result where this parameter is stored: from_feature_id
     508              :  */
     509              : static const int RESULT_RELATIONSHIP_FROM_FEATURE_ID_COLUMN = 5;
     510              : 
     511              : /*!
     512              :  *  \brief the column id of the result where this parameter is stored: to_feature_id
     513              :  */
     514              : static const int RESULT_RELATIONSHIP_TO_FEATURE_ID_COLUMN = 6;
     515              : 
     516              : /*!
     517              :  *  \brief the column id of the result where this parameter is stored: source.focused_feature_id
     518              :  *
     519              :  *  In case of a GROUP BY clause, this id may not be related to the RESULT_RELATIONSHIP_FROM_FEATURE_ID_COLUMN due to random selection
     520              :  *  One may consider to remove the GROUP BY and accept more search results
     521              :  */
     522              : static const int RESULT_RELATIONSHIP_FROM_FOCUSED_ID_COLUMN = 7;
     523              : 
     524              : /*!
     525              :  *  \brief the column id of the result where this parameter is stored: dest.focused_feature_id
     526              :  *
     527              :  *  In case of a GROUP BY clause, this id may not be related to the RESULT_RELATIONSHIP_TO_FEATURE_ID_COLUMN due to random selection
     528              :  *  One may consider to remove the GROUP BY and accept more search results
     529              :  */
     530              : static const int RESULT_RELATIONSHIP_TO_FOCUSED_ID_COLUMN = 8;
     531              : 
     532              : /*!
     533              :  *  \brief the column id of the result where this parameter is stored: diagrams.id
     534              :  */
     535              : static const int RESULT_RELATIONSHIP_DIAGRAM_ID_COLUMN = 9;
     536              : 
     537              : /*!
     538              :  *  \brief the column id of the result where this parameter is stored: diagrams.diagram_type
     539              :  */
     540              : static const int RESULT_RELATIONSHIP_DIAGRAM_TYPE_COLUMN = 10;
     541              : 
     542            1 : u8_error_t data_search_result_iterator_private_get_relationship( data_search_result_iterator_t *this_,
     543              :                                                                  data_search_result_t *out_search_result )
     544              : {
     545            1 :     U8_TRACE_BEGIN();
     546            1 :     assert( NULL != out_search_result );
     547            1 :     u8_error_t result = U8_ERROR_NONE;
     548              : 
     549            1 :     sqlite3_stmt *const prepared_statement = data_database_borrowed_stmt_get_statement( &((*this_).relationship_statement) );
     550              : 
     551            1 :     data_search_result_init_relationship( out_search_result,
     552            1 :                                           sqlite3_column_int64( prepared_statement, RESULT_RELATIONSHIP_ID_COLUMN ),
     553            1 :                                           sqlite3_column_int( prepared_statement, RESULT_RELATIONSHIP_MAIN_TYPE_COLUMN ),
     554            1 :                                           (const char*) sqlite3_column_text( prepared_statement, RESULT_RELATIONSHIP_NAME_COLUMN ),
     555            1 :                                           sqlite3_column_int64( prepared_statement, RESULT_RELATIONSHIP_FROM_CLASSIFIER_ID_COLUMN ),
     556            1 :                                           sqlite3_column_int64( prepared_statement, RESULT_RELATIONSHIP_TO_CLASSIFIER_ID_COLUMN ),
     557            1 :                                           sqlite3_column_int64( prepared_statement, RESULT_RELATIONSHIP_DIAGRAM_ID_COLUMN )
     558              :                                         );
     559            0 :     const data_row_t from_feat
     560            1 :          = ( SQLITE_NULL != sqlite3_column_type( prepared_statement, RESULT_RELATIONSHIP_FROM_FEATURE_ID_COLUMN ) )
     561            1 :          ? sqlite3_column_int64( prepared_statement, RESULT_RELATIONSHIP_FROM_FEATURE_ID_COLUMN )
     562            1 :          : DATA_ROW_VOID;
     563            1 :          const data_row_t to_feat
     564            1 :          = ( SQLITE_NULL != sqlite3_column_type( prepared_statement, RESULT_RELATIONSHIP_TO_FEATURE_ID_COLUMN ) )
     565            0 :          ? sqlite3_column_int64( prepared_statement, RESULT_RELATIONSHIP_TO_FEATURE_ID_COLUMN )
     566            1 :          : DATA_ROW_VOID;
     567            1 :          const data_row_t from_focused
     568            1 :          = ( SQLITE_NULL != sqlite3_column_type( prepared_statement, RESULT_RELATIONSHIP_FROM_FOCUSED_ID_COLUMN ) )
     569            0 :          ? sqlite3_column_int64( prepared_statement, RESULT_RELATIONSHIP_FROM_FOCUSED_ID_COLUMN )
     570            1 :          : DATA_ROW_VOID;
     571            1 :          const data_row_t to_focused
     572            1 :          = ( SQLITE_NULL != sqlite3_column_type( prepared_statement, RESULT_RELATIONSHIP_TO_FOCUSED_ID_COLUMN ) )
     573            0 :          ? sqlite3_column_int64( prepared_statement, RESULT_RELATIONSHIP_TO_FOCUSED_ID_COLUMN )
     574            1 :          : DATA_ROW_VOID;
     575            1 :     const data_diagram_type_t d_type = sqlite3_column_int( prepared_statement, RESULT_RELATIONSHIP_DIAGRAM_TYPE_COLUMN );
     576            1 :     U8_TRACE_INFO_INT( "- from_feat:", from_feat );
     577            1 :     U8_TRACE_INFO_INT( "- to_feat:", to_feat );
     578            1 :     U8_TRACE_INFO_INT( "- d_type:", d_type );
     579            1 :     const data_row_t rel_row = data_id_get_row( data_search_result_get_match_id_const( out_search_result ) );
     580              : 
     581            1 :     bool filter = false;
     582            1 :     const bool is_scenario_diag = data_rules_diagram_is_scenario ( &((*this_).data_rules), d_type );
     583              :     /*const bool is_scenario_rel = data_rules_relationship_is_scenario_cond( &((*this_).data_rules), from_feature_type, to_feature_type);*/
     584            1 :     if ( is_scenario_diag )
     585              :     {
     586              :         /* in theory, we would need to know the from_feature_type and the to_feature_type to determine the visibility: */
     587              :         /*
     588              :          * const bool is_shown = data_rules_relationship_is_scenario_cond( const data_rules_t *this_,
     589              :          *                                                                 data_feature_type_t from_feature_type,
     590              :          *                                                                 data_feature_type_t to_feature_type
     591              :          *                                                               );
     592              :          */
     593              :         /* but we only have the data_relationship_type_t and the data_diagramelement_t here and we control the order of results: */
     594            0 :         const bool from_is_lifeline = ( DATA_ROW_VOID != from_feat )&&( from_focused == from_feat );
     595            0 :         const bool to_is_lifeline = ( DATA_ROW_VOID != to_feat )&&( to_focused == to_feat );
     596            0 :         const bool visible = from_is_lifeline && to_is_lifeline;
     597            0 :         if ( visible )
     598              :         {
     599            0 :             filter = false;
     600            0 :             (*this_).last_relationship_was_scenario = true;
     601            0 :             (*this_).last_relationship_id = rel_row;
     602            0 :             U8_TRACE_INFO_INT( "data_search_result_iterator: in scenario found relationship", rel_row );
     603              :         }
     604              :         else
     605              :         {
     606            0 :             filter = true;
     607            0 :             U8_TRACE_INFO_INT( "data_search_result_iterator: in scenario skipped invisible relationship", rel_row );
     608              :         }
     609              :     }
     610              :     else
     611              :     {
     612              :         /* in theory, we would need to know the from_feature_type and the to_feature_type to determine the visibility: */
     613              :         /*
     614              :          * const bool is_shown = data_rules_relationship_is_scenario_cond( const data_rules_t *this_,
     615              :          *                                                                 data_feature_type_t from_feature_type,
     616              :          *                                                                 data_feature_type_t to_feature_type
     617              :          *                                                               );
     618              :          */
     619              :         /* but we only have the data_relationship_type_t and the data_diagramelement_t here and we control the order of results: */
     620            1 :         const bool is_scenario = ( (*this_).last_relationship_id == rel_row )&&( (*this_).last_relationship_was_scenario );
     621            1 :         const bool vis_by_diagram = data_rules_diagram_shows_uncond_relationships ( &((*this_).data_rules), d_type );
     622            1 :         if ( vis_by_diagram && ( ! is_scenario ) )
     623              :         {
     624            1 :             filter = false;
     625            1 :             (*this_).last_relationship_was_scenario = false;
     626            1 :             (*this_).last_relationship_id = rel_row;
     627            1 :             U8_TRACE_INFO_INT( "data_search_result_iterator: non-scenario found relationship", rel_row );
     628              :         }
     629              :         else
     630              :         {
     631            0 :             filter = true;
     632            0 :             U8_TRACE_INFO_INT( "data_search_result_iterator: non-scenario skipped scenario-specific relationship", rel_row );
     633              :         }
     634              :     }
     635              : 
     636            1 :     if ( filter )
     637              :     {
     638              :         /* invalidate the out_search_result */
     639            0 :         data_search_result_init_void( out_search_result );
     640              :     }
     641              : 
     642            1 :     data_search_result_trace( out_search_result );
     643              : 
     644            1 :     U8_TRACE_END_ERR( result );
     645            1 :     return result;
     646              : }
     647              : 
     648              : 
     649              : /*
     650              : Copyright 2020-2026 Andreas Warnke
     651              : 
     652              : Licensed under the Apache License, Version 2.0 (the "License");
     653              : you may not use this file except in compliance with the License.
     654              : You may obtain a copy of the License at
     655              : 
     656              :     http://www.apache.org/licenses/LICENSE-2.0
     657              : 
     658              : Unless required by applicable law or agreed to in writing, software
     659              : distributed under the License is distributed on an "AS IS" BASIS,
     660              : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     661              : See the License for the specific language governing permissions and
     662              : limitations under the License.
     663              : */
        

Generated by: LCOV version 2.0-1