LCOV - code coverage report
Current view: top level - data/source/storage - data_feature_iterator.c (source / functions) Hit Total Coverage
Test: crystal-facet-uml_v1.65.6_covts Lines: 62 66 93.9 %
Date: 2025-09-25 21:07:53 Functions: 6 6 100.0 %

          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          21 : u8_error_t data_feature_iterator_init_empty ( data_feature_iterator_t *this_ )
      85             : {
      86          21 :     U8_TRACE_BEGIN();
      87          21 :     u8_error_t result = U8_ERROR_NONE;
      88             : 
      89          21 :     data_database_borrowed_stmt_init_void( &((*this_).statement) );
      90          21 :     (*this_).is_at_end = true;
      91             : 
      92          21 :     U8_TRACE_END_ERR(result);
      93          21 :     return result;
      94             : }
      95             : 
      96          21 : u8_error_t data_feature_iterator_reinit ( data_feature_iterator_t *this_,
      97             :                                              data_database_borrowed_stmt_t statement )
      98             : {
      99          21 :     U8_TRACE_BEGIN();
     100          21 :     assert( data_database_borrowed_stmt_is_valid( &statement ) );
     101          21 :     u8_error_t result = U8_ERROR_NONE;
     102             : 
     103             :     /* destroy old state */
     104          21 :     result = data_feature_iterator_destroy( this_ );
     105             : 
     106             :     /* init new state */
     107          21 :     (*this_).statement = statement;
     108          21 :     (*this_).is_at_end = false;
     109          21 :     result |= data_feature_iterator_private_step_to_next( this_ );
     110             : 
     111          21 :     U8_TRACE_END_ERR(result);
     112          21 :     return result;
     113             : }
     114             : 
     115          42 : u8_error_t data_feature_iterator_destroy ( data_feature_iterator_t *this_ )
     116             : {
     117          42 :     U8_TRACE_BEGIN();
     118          42 :     u8_error_t result = U8_ERROR_NONE;
     119             : 
     120          42 :     result |= data_database_borrowed_stmt_destroy( &((*this_).statement) );
     121          42 :     (*this_).is_at_end = true;
     122             : 
     123          42 :     U8_TRACE_END_ERR(result);
     124          42 :     return result;
     125             : }
     126             : 
     127         281 : bool data_feature_iterator_has_next ( const data_feature_iterator_t *this_ )
     128             : {
     129         281 :     return ( ! (*this_).is_at_end );
     130             : }
     131             : 
     132         273 : u8_error_t data_feature_iterator_next ( data_feature_iterator_t *this_, data_feature_t *out_feature )
     133             : {
     134         273 :     U8_TRACE_BEGIN();
     135         273 :     assert( NULL != out_feature );
     136         273 :     assert( data_database_borrowed_stmt_is_valid( &((*this_).statement) ) );
     137         273 :     u8_error_t result = U8_ERROR_NONE;
     138             : 
     139         273 :     if ( ! (*this_).is_at_end )
     140             :     {
     141         271 :         sqlite3_stmt *const sql_statement = data_database_borrowed_stmt_get_statement( &((*this_).statement) );
     142             : 
     143         542 :         result |= data_feature_init( out_feature,
     144         271 :                                      sqlite3_column_int64( sql_statement, RESULT_FEATURE_ID_COLUMN ),
     145         271 :                                      sqlite3_column_int( sql_statement, RESULT_FEATURE_MAIN_TYPE_COLUMN ),
     146         271 :                                      sqlite3_column_int64( sql_statement, RESULT_FEATURE_CLASSIFIER_ID_COLUMN ),
     147         271 :                                      (const char*) sqlite3_column_text( sql_statement, RESULT_FEATURE_KEY_COLUMN ),
     148         271 :                                      (const char*) sqlite3_column_text( sql_statement, RESULT_FEATURE_VALUE_COLUMN ),
     149         271 :                                      (const char*) sqlite3_column_text( sql_statement, RESULT_FEATURE_DESCRIPTION_COLUMN ),
     150             :                                      sqlite3_column_int( sql_statement, RESULT_FEATURE_LIST_ORDER_COLUMN ),
     151         271 :                                      (const char*) sqlite3_column_text( sql_statement, RESULT_FEATURE_LIST_UUID_COLUMN )
     152             :                                    );
     153         271 :         U8_TRACE_INFO_INT( "diagramelements.id:", sqlite3_column_int64( sql_statement, RESULT_FEATURE_DIAGRAMELEMENTS_ID_COLUMN ) );
     154         271 :         data_feature_trace( out_feature );
     155             : 
     156             :         /* step to next */
     157         271 :         result |= data_feature_iterator_private_step_to_next( this_ );
     158             :     }
     159             :     else
     160             :     {
     161           2 :         U8_TRACE_INFO( "iterator already at end" );
     162           2 :         (*this_).is_at_end = true;
     163           2 :         result |= U8_ERROR_INVALID_REQUEST;
     164             :     }
     165             : 
     166         273 :     U8_TRACE_END_ERR( result );
     167         273 :     return result;
     168             : }
     169             : 
     170         292 : u8_error_t data_feature_iterator_private_step_to_next ( data_feature_iterator_t *this_ )
     171             : {
     172         292 :     U8_TRACE_BEGIN();
     173         292 :     assert( data_database_borrowed_stmt_is_valid( &((*this_).statement) ) );
     174         292 :     u8_error_t result = U8_ERROR_NONE;
     175             : 
     176             :     /* do one step, check if is_at_end */
     177             :     {
     178             :         int sqlite_err;
     179         292 :         U8_TRACE_INFO( "sqlite3_step()" );
     180         292 :         sqlite_err = sqlite3_step( data_database_borrowed_stmt_get_statement( &((*this_).statement) ) );
     181         292 :         if ( SQLITE_DONE == sqlite_err )
     182             :         {
     183          20 :             U8_TRACE_INFO( "sqlite3_step finished: SQLITE_DONE" );
     184          20 :             (*this_).is_at_end = true;
     185             :         }
     186         272 :         else if ( SQLITE_ROW == sqlite_err )
     187             :         {
     188         272 :             (*this_).is_at_end = false;
     189             :         }
     190             :         else
     191             :         {
     192           0 :             U8_LOG_ERROR_INT( "sqlite3_step failed:", sqlite_err );
     193           0 :             (*this_).is_at_end = true;
     194           0 :             result |= data_feature_iterator_destroy( this_ );
     195           0 :             result |= U8_ERROR_AT_DB;
     196             :         }
     197             :     }
     198             : 
     199         292 :     U8_TRACE_END_ERR(result);
     200         292 :     return result;
     201             : }
     202             : 
     203             : 
     204             : /*
     205             : Copyright 2024-2025 Andreas Warnke
     206             : 
     207             : Licensed under the Apache License, Version 2.0 (the "License");
     208             : you may not use this file except in compliance with the License.
     209             : You may obtain a copy of the License at
     210             : 
     211             :     http://www.apache.org/licenses/LICENSE-2.0
     212             : 
     213             : Unless required by applicable law or agreed to in writing, software
     214             : distributed under the License is distributed on an "AS IS" BASIS,
     215             : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     216             : See the License for the specific language governing permissions and
     217             : limitations under the License.
     218             : */

Generated by: LCOV version 1.16