LCOV - code coverage report
Current view: top level - data/source/storage - data_feature_iterator.c (source / functions) Coverage Total Hit
Test: crystal-facet-uml_v1.70.5_covts Lines: 93.9 % 66 62
Test Date: 2026-05-28 21:31:40 Functions: 100.0 % 6 6

            Line data    Source code
       1              : /* File: data_feature_iterator.c; Copyright and License: see below */
       2              : 
       3              : #include "storage/data_feature_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              : /*!
      12              :  *  \brief predefined search statement to find features by diagram-id
      13              :  */
      14              : const char *const DATA_FEATURE_ITERATOR_SELECT_FEATURES_BY_DIAGRAM_ID =
      15              :     "SELECT features.id,features.main_type,features.classifier_id,"
      16              :     "features.key,features.value,features.description,features.list_order,features.uuid,"
      17              :     "diagramelements.id " /* diagramelements.id needed only for debugging */
      18              :     "FROM features INNER JOIN diagramelements ON diagramelements.classifier_id=features.classifier_id "
      19              :     /* "WHERE diagramelements.diagram_id=? " */
      20              :     "WHERE diagramelements.diagram_id=? AND ( diagramelements.focused_feature_id=features.id OR features.main_type<>3 ) "
      21              :     "GROUP BY features.id "
      22              :     "ORDER BY features.list_order ASC,features.id ASC;";   /* ensure always the same order */
      23              :     /* Note: 3 == DATA_FEATURE_TYPE_LIFELINE */
      24              : 
      25              :     /* if you ignore the type, "non-scenario features" of "classifiers that have a lifeline" would be skipped: */
      26              :     /* "WHERE diagramelements.diagram_id=? AND ( (diagramelements.focused_feature_id=features.id) OR (diagramelements.focused_feature_id ISNULL) ) " */
      27              :     /* but we want to skip only lifelines and only if these belong to foreign diagrams */
      28              : 
      29              : /*!
      30              :  *  \brief predefined search statement to find features by classifier-id
      31              :  *
      32              :  *  Order by id to ensure a defined, non-changeing order of relationships in json export
      33              :  */
      34              : const char *const DATA_FEATURE_ITERATOR_SELECT_FEATURES_BY_CLASSIFIER_ID =
      35              :     "SELECT id,main_type,classifier_id,key,value,description,list_order,uuid,-1 "
      36              :     "FROM features "
      37              :     "WHERE classifier_id=? ORDER BY id ASC;";   /* ensure always the same order */
      38              : 
      39              : /*!
      40              :  *  \brief the column id of the result where this parameter is stored: id
      41              :  */
      42              : static const int RESULT_FEATURE_ID_COLUMN = 0;
      43              : 
      44              : /*!
      45              :  *  \brief the column id of the result where this parameter is stored: main_type
      46              :  */
      47              : static const int RESULT_FEATURE_MAIN_TYPE_COLUMN = 1;
      48              : 
      49              : /*!
      50              :  *  \brief the column id of the result where this parameter is stored: classifier_id
      51              :  */
      52              : static const int RESULT_FEATURE_CLASSIFIER_ID_COLUMN = 2;
      53              : 
      54              : /*!
      55              :  *  \brief the column id of the result where this parameter is stored: key
      56              :  */
      57              : static const int RESULT_FEATURE_KEY_COLUMN = 3;
      58              : 
      59              : /*!
      60              :  *  \brief the column id of the result where this parameter is stored: value
      61              :  */
      62              : static const int RESULT_FEATURE_VALUE_COLUMN = 4;
      63              : 
      64              : /*!
      65              :  *  \brief the column id of the result where this parameter is stored: description
      66              :  */
      67              : static const int RESULT_FEATURE_DESCRIPTION_COLUMN = 5;
      68              : 
      69              : /*!
      70              :  *  \brief the column id of the result where this parameter is stored: list_order
      71              :  */
      72              : static const int RESULT_FEATURE_LIST_ORDER_COLUMN = 6;
      73              : 
      74              : /*!
      75              :  *  \brief the column id of the result where this parameter is stored: uuid
      76              :  */
      77              : static const int RESULT_FEATURE_LIST_UUID_COLUMN = 7;
      78              : 
      79              : /*!
      80              :  *  \brief the column id of the result where this parameter is stored: diagramelements.id
      81              :  */
      82              : static const int RESULT_FEATURE_DIAGRAMELEMENTS_ID_COLUMN = 8;
      83              : 
      84           33 : void data_feature_iterator_init_empty ( data_feature_iterator_t *this_ )
      85              : {
      86           33 :     U8_TRACE_BEGIN();
      87              : 
      88           33 :     data_database_borrowed_stmt_init_void( &((*this_).statement) );
      89           33 :     (*this_).is_at_end = true;
      90              : 
      91           33 :     U8_TRACE_END();
      92           33 : }
      93              : 
      94           33 : u8_error_t data_feature_iterator_reinit ( data_feature_iterator_t *this_,
      95              :                                              data_database_borrowed_stmt_t statement )
      96              : {
      97           33 :     U8_TRACE_BEGIN();
      98           33 :     assert( data_database_borrowed_stmt_is_valid( &statement ) );
      99           33 :     u8_error_t result = U8_ERROR_NONE;
     100              : 
     101              :     /* destroy old state */
     102           33 :     result = data_feature_iterator_destroy( this_ );
     103              : 
     104              :     /* init new state */
     105           33 :     (*this_).statement = statement;
     106           33 :     (*this_).is_at_end = false;
     107           33 :     result |= data_feature_iterator_private_step_to_next( this_ );
     108              : 
     109           33 :     U8_TRACE_END_ERR(result);
     110           33 :     return result;
     111              : }
     112              : 
     113           66 : u8_error_t data_feature_iterator_destroy ( data_feature_iterator_t *this_ )
     114              : {
     115           66 :     U8_TRACE_BEGIN();
     116           66 :     u8_error_t result = U8_ERROR_NONE;
     117              : 
     118           66 :     result |= data_database_borrowed_stmt_destroy( &((*this_).statement) );
     119           66 :     (*this_).is_at_end = true;
     120              : 
     121           66 :     U8_TRACE_END_ERR(result);
     122           66 :     return result;
     123              : }
     124              : 
     125          302 : bool data_feature_iterator_has_next ( const data_feature_iterator_t *this_ )
     126              : {
     127          302 :     return ( ! (*this_).is_at_end );
     128              : }
     129              : 
     130          282 : u8_error_t data_feature_iterator_next ( data_feature_iterator_t *this_, data_feature_t *out_feature )
     131              : {
     132          282 :     U8_TRACE_BEGIN();
     133          282 :     assert( NULL != out_feature );
     134          282 :     assert( data_database_borrowed_stmt_is_valid( &((*this_).statement) ) );
     135          282 :     u8_error_t result = U8_ERROR_NONE;
     136              : 
     137          282 :     if ( ! (*this_).is_at_end )
     138              :     {
     139          280 :         sqlite3_stmt *const sql_statement = data_database_borrowed_stmt_get_statement( &((*this_).statement) );
     140              : 
     141          280 :         result |= data_feature_init( out_feature,
     142          280 :                                      sqlite3_column_int64( sql_statement, RESULT_FEATURE_ID_COLUMN ),
     143          280 :                                      sqlite3_column_int( sql_statement, RESULT_FEATURE_MAIN_TYPE_COLUMN ),
     144          280 :                                      sqlite3_column_int64( sql_statement, RESULT_FEATURE_CLASSIFIER_ID_COLUMN ),
     145          280 :                                      (const char*) sqlite3_column_text( sql_statement, RESULT_FEATURE_KEY_COLUMN ),
     146          280 :                                      (const char*) sqlite3_column_text( sql_statement, RESULT_FEATURE_VALUE_COLUMN ),
     147          280 :                                      (const char*) sqlite3_column_text( sql_statement, RESULT_FEATURE_DESCRIPTION_COLUMN ),
     148          280 :                                      sqlite3_column_int( sql_statement, RESULT_FEATURE_LIST_ORDER_COLUMN ),
     149          280 :                                      (const char*) sqlite3_column_text( sql_statement, RESULT_FEATURE_LIST_UUID_COLUMN )
     150              :                                    );
     151          280 :         U8_TRACE_INFO_INT( "diagramelements.id:", sqlite3_column_int64( sql_statement, RESULT_FEATURE_DIAGRAMELEMENTS_ID_COLUMN ) );
     152          280 :         data_feature_trace( out_feature );
     153              : 
     154              :         /* step to next */
     155          280 :         result |= data_feature_iterator_private_step_to_next( this_ );
     156              :     }
     157              :     else
     158              :     {
     159            2 :         U8_TRACE_INFO( "iterator already at end" );
     160            2 :         (*this_).is_at_end = true;
     161            2 :         result |= U8_ERROR_INVALID_REQUEST;
     162              :     }
     163              : 
     164          282 :     U8_TRACE_END_ERR( result );
     165          282 :     return result;
     166              : }
     167              : 
     168          313 : u8_error_t data_feature_iterator_private_step_to_next ( data_feature_iterator_t *this_ )
     169              : {
     170          313 :     U8_TRACE_BEGIN();
     171          313 :     assert( data_database_borrowed_stmt_is_valid( &((*this_).statement) ) );
     172          313 :     u8_error_t result = U8_ERROR_NONE;
     173              : 
     174              :     /* do one step, check if is_at_end */
     175              :     {
     176              :         int sqlite_err;
     177          313 :         U8_TRACE_INFO( "sqlite3_step()" );
     178          313 :         sqlite_err = sqlite3_step( data_database_borrowed_stmt_get_statement( &((*this_).statement) ) );
     179          313 :         if ( SQLITE_DONE == sqlite_err )
     180              :         {
     181           32 :             U8_TRACE_INFO( "sqlite3_step finished: SQLITE_DONE" );
     182           32 :             (*this_).is_at_end = true;
     183              :         }
     184          281 :         else if ( SQLITE_ROW == sqlite_err )
     185              :         {
     186          281 :             (*this_).is_at_end = false;
     187              :         }
     188              :         else
     189              :         {
     190            0 :             U8_LOG_ERROR_INT( "sqlite3_step failed:", sqlite_err );
     191            0 :             (*this_).is_at_end = true;
     192            0 :             result |= data_feature_iterator_destroy( this_ );
     193            0 :             result |= U8_ERROR_AT_DB;
     194              :         }
     195              :     }
     196              : 
     197          313 :     U8_TRACE_END_ERR(result);
     198          313 :     return result;
     199              : }
     200              : 
     201              : 
     202              : /*
     203              : Copyright 2024-2026 Andreas Warnke
     204              : 
     205              : Licensed under the Apache License, Version 2.0 (the "License");
     206              : you may not use this file except in compliance with the License.
     207              : You may obtain a copy of the License at
     208              : 
     209              :     http://www.apache.org/licenses/LICENSE-2.0
     210              : 
     211              : Unless required by applicable law or agreed to in writing, software
     212              : distributed under the License is distributed on an "AS IS" BASIS,
     213              : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     214              : See the License for the specific language governing permissions and
     215              : limitations under the License.
     216              : */
        

Generated by: LCOV version 2.0-1