LCOV - code coverage report
Current view: top level - data/source/storage - data_search_result_iterator.c (source / functions) Hit Total Coverage
Test: crystal-facet-uml_v1.65.6_covts Lines: 220 250 88.0 %
Date: 2025-09-25 21:07:53 Functions: 10 10 100.0 %

          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           1 :     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 1.16