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

Generated by: LCOV version 2.0-1