LCOV - code coverage report
Current view: top level - data/source/storage - data_database_iterator_classifiers.c (source / functions) Hit Total Coverage
Test: crystal-facet-uml_v1.61.0_covts Lines: 81 94 86.2 %
Date: 2024-10-26 21:44:38 Functions: 6 6 100.0 %

          Line data    Source code
       1             : /* File: data_database_iterator_classifiers.c; Copyright and License: see below */
       2             : 
       3             : #include "storage/data_database_iterator_classifiers.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 search statement to iterate over all classifiers sorted by number of parent-containers
      13             :  *
      14             :  *  The "order by cnt" is important to ensure parent objects are iterated first, e.g. for xmi export
      15             :  *  The "order by id" is important to get reproducable results
      16             :  */
      17             : static const char DATA_DATABASE_ITERATOR_CLASSIFIERS_SELECT_ALL_HIERARCHICAL[] =
      18             :     "SELECT id,main_type,stereotype,name,description,x_order,y_order,list_order,uuid,"
      19             :         "(SELECT count(*) FROM relationships "
      20             :         "WHERE (relationships.to_classifier_id=classifiers.id) AND (relationships.to_feature_id IS NULL) "
      21             :         "AND (relationships.main_type=300)) AS cnt "
      22             :     "FROM classifiers "
      23             :     "ORDER BY cnt ASC,id ASC;";
      24             : 
      25             : /*!
      26             :  *  \brief search statement to iterate over all classifiers
      27             :  *
      28             :  *  The "order by id" is important to get reproducable results, e.g. for json export
      29             :  */
      30             : static const char DATA_DATABASE_ITERATOR_CLASSIFIERS_SELECT_ALL[] =
      31             :     "SELECT id,main_type,stereotype,name,description,x_order,y_order,list_order,uuid,-1 "
      32             :     "FROM classifiers "
      33             :     "ORDER BY id ASC;";
      34             : 
      35             : /*!
      36             :  *  \brief the column id of the result where this parameter is stored: id
      37             :  */
      38             : static const int RESULT_CLASSIFIER_ID_COLUMN = 0;
      39             : 
      40             : /*!
      41             :  *  \brief the column id of the result where this parameter is stored: main_type
      42             :  */
      43             : static const int RESULT_CLASSIFIER_MAIN_TYPE_COLUMN = 1;
      44             : 
      45             : /*!
      46             :  *  \brief the column id of the result where this parameter is stored: stereotype
      47             :  */
      48             : static const int RESULT_CLASSIFIER_STEREOTYPE_COLUMN = 2;
      49             : 
      50             : /*!
      51             :  *  \brief the column id of the result where this parameter is stored: name
      52             :  */
      53             : static const int RESULT_CLASSIFIER_NAME_COLUMN = 3;
      54             : 
      55             : /*!
      56             :  *  \brief the column id of the result where this parameter is stored: description
      57             :  */
      58             : static const int RESULT_CLASSIFIER_DESCRIPTION_COLUMN = 4;
      59             : 
      60             : /*!
      61             :  *  \brief the column id of the result where this parameter is stored: x_order
      62             :  */
      63             : static const int RESULT_CLASSIFIER_X_ORDER_COLUMN = 5;
      64             : 
      65             : /*!
      66             :  *  \brief the column id of the result where this parameter is stored: y_order
      67             :  */
      68             : static const int RESULT_CLASSIFIER_Y_ORDER_COLUMN = 6;
      69             : 
      70             : /*!
      71             :  *  \brief the column id of the result where this parameter is stored: list_order
      72             :  */
      73             : static const int RESULT_CLASSIFIER_LIST_ORDER_COLUMN = 7;
      74             : 
      75             : /*!
      76             :  *  \brief the column id of the result where this parameter is stored: uuid
      77             :  */
      78             : static const int RESULT_CLASSIFIER_UUID_COLUMN = 8;
      79             : 
      80             : /*!
      81             :  *  \brief the column id of the result where this parameter is stored: count of containment parents
      82             :  */
      83             : static const int RESULT_CLASSIFIER_CONTAINMENT_PARENTS_COLUMN = 9;
      84             : 
      85           1 : u8_error_t data_database_iterator_classifiers_init_empty ( data_database_iterator_classifiers_t *this_ )
      86             : {
      87           1 :     U8_TRACE_BEGIN();
      88           1 :     u8_error_t result = U8_ERROR_NONE;
      89             : 
      90           1 :     (*this_).is_valid = false;
      91           1 :     (*this_).database = NULL;
      92           1 :     (*this_).statement_all_classifiers = NULL;
      93           1 :     (*this_).is_at_end = true;
      94             : 
      95           1 :     U8_TRACE_END_ERR(result);
      96           1 :     return result;
      97             : }
      98             : 
      99           1 : u8_error_t data_database_iterator_classifiers_reinit ( data_database_iterator_classifiers_t *this_,
     100             :                                                        data_database_t *database,
     101             :                                                        bool hierarchical )
     102             : {
     103           1 :     U8_TRACE_BEGIN();
     104           1 :     assert( NULL != database );
     105           1 :     u8_error_t result = U8_ERROR_NONE;
     106             : 
     107             :     /* destroy old state */
     108           1 :     result = data_database_iterator_classifiers_destroy( this_ );
     109           1 :     (*this_).statement_all_classifiers = NULL;
     110             : 
     111             :     /* init new state */
     112           1 :     (*this_).is_valid = true;
     113           1 :     (*this_).database = database;
     114             :     {
     115           1 :         const char *const string_statement
     116             :             = hierarchical
     117             :             ? DATA_DATABASE_ITERATOR_CLASSIFIERS_SELECT_ALL_HIERARCHICAL
     118           1 :             : DATA_DATABASE_ITERATOR_CLASSIFIERS_SELECT_ALL;
     119           1 :         const size_t string_size
     120             :             = hierarchical
     121             :             ? sizeof( DATA_DATABASE_ITERATOR_CLASSIFIERS_SELECT_ALL_HIERARCHICAL )
     122           1 :             : sizeof( DATA_DATABASE_ITERATOR_CLASSIFIERS_SELECT_ALL );
     123           1 :         sqlite3 *db = data_database_get_database_ptr ( (*this_).database );
     124             :         const char *first_unused_statement_char;
     125           1 :         U8_TRACE_INFO_STR( "sqlite3_prepare_v2():", string_statement );
     126           1 :         const int sqlite_err = sqlite3_prepare_v2( db,
     127             :                                                    string_statement,
     128             :                                                    string_size,
     129             :                                                    &((*this_).statement_all_classifiers),
     130             :                                                    &first_unused_statement_char
     131             :                                                  );
     132           1 :         if (( SQLITE_OK != sqlite_err )
     133           1 :             || ( first_unused_statement_char != &(string_statement[string_size-1]) ))
     134             :         {
     135           0 :             U8_LOG_ERROR_STR( "sqlite3_prepare_v2() failed:", string_statement );
     136           0 :             U8_LOG_ERROR_INT( "sqlite3_prepare_v2() failed:", sqlite_err );
     137           0 :             U8_LOG_ERROR_STR( "sqlite3_prepare_v2() failed:", sqlite3_errmsg( db ) );
     138           0 :             result |= U8_ERROR_AT_DB;
     139             :         }
     140             :     }
     141           1 :     result |= data_database_iterator_private_step_to_next( this_ );
     142             : 
     143           1 :     U8_TRACE_END_ERR(result);
     144           1 :     return result;
     145             : }
     146             : 
     147           2 : u8_error_t data_database_iterator_classifiers_destroy ( data_database_iterator_classifiers_t *this_ )
     148             : {
     149           2 :     U8_TRACE_BEGIN();
     150           2 :     u8_error_t result = U8_ERROR_NONE;
     151             : 
     152           2 :     if ( (*this_).is_valid )
     153             :     {
     154           1 :         assert( NULL != (*this_).statement_all_classifiers );
     155           1 :         U8_TRACE_INFO_STR( "sqlite3_finalize():", sqlite3_sql( (*this_).statement_all_classifiers ) );
     156           1 :         const int sqlite_err = sqlite3_finalize( (*this_).statement_all_classifiers );
     157           1 :         if ( SQLITE_OK != sqlite_err )
     158             :         {
     159           0 :             U8_LOG_ERROR_STR( "sqlite3_finalize() failed:", sqlite3_sql( (*this_).statement_all_classifiers ) );
     160           0 :             U8_LOG_ERROR_INT( "sqlite3_finalize() failed:", sqlite_err );
     161           0 :             result = U8_ERROR_AT_DB;
     162             :         }
     163             :     }
     164             : 
     165           2 :     (*this_).is_valid = false;
     166           2 :     (*this_).database = NULL;
     167           2 :     (*this_).statement_all_classifiers = NULL;
     168           2 :     (*this_).is_at_end = true;
     169             : 
     170           2 :     U8_TRACE_END_ERR(result);
     171           2 :     return result;
     172             : }
     173             : 
     174           3 : bool data_database_iterator_classifiers_has_next ( const data_database_iterator_classifiers_t *this_ )
     175             : {
     176           3 :     return ( ! (*this_).is_at_end );
     177             : }
     178             : 
     179           3 : u8_error_t data_database_iterator_classifiers_next ( data_database_iterator_classifiers_t *this_, data_classifier_t *out_classifier )
     180             : {
     181           3 :     U8_TRACE_BEGIN();
     182           3 :     assert( NULL != out_classifier );
     183           3 :     u8_error_t result = U8_ERROR_NONE;
     184             : 
     185           3 :     if ( (*this_).is_valid )
     186             :     {
     187           3 :         if ( ! (*this_).is_at_end )
     188             :         {
     189           2 :             sqlite3_stmt *const sql_statement = (*this_).statement_all_classifiers;
     190           2 :             data_row_id_t classifier_id = sqlite3_column_int64( sql_statement, RESULT_CLASSIFIER_ID_COLUMN );
     191           4 :             result |= data_classifier_reinit( out_classifier,
     192             :                                               classifier_id,
     193           2 :                                               sqlite3_column_int( sql_statement, RESULT_CLASSIFIER_MAIN_TYPE_COLUMN ),
     194           2 :                                               (const char*) sqlite3_column_text( sql_statement, RESULT_CLASSIFIER_STEREOTYPE_COLUMN ),
     195           2 :                                               (const char*) sqlite3_column_text( sql_statement, RESULT_CLASSIFIER_NAME_COLUMN ),
     196           2 :                                               (const char*) sqlite3_column_text( sql_statement, RESULT_CLASSIFIER_DESCRIPTION_COLUMN ),
     197             :                                               sqlite3_column_int( sql_statement, RESULT_CLASSIFIER_X_ORDER_COLUMN ),
     198             :                                               sqlite3_column_int( sql_statement, RESULT_CLASSIFIER_Y_ORDER_COLUMN ),
     199             :                                               sqlite3_column_int( sql_statement, RESULT_CLASSIFIER_LIST_ORDER_COLUMN ),
     200           2 :                                               (const char*) sqlite3_column_text( sql_statement, RESULT_CLASSIFIER_UUID_COLUMN )
     201             :                                             );
     202           2 :             data_classifier_trace( out_classifier );
     203           2 :             U8_TRACE_INFO_INT( "count of containment parents:", sqlite3_column_int( sql_statement, RESULT_CLASSIFIER_CONTAINMENT_PARENTS_COLUMN ));
     204             : 
     205             :             /* step to next */
     206           2 :             result |= data_database_iterator_private_step_to_next( this_ );
     207             :         }
     208             :         else
     209             :         {
     210           1 :             U8_TRACE_INFO( "iterator already at end" );
     211           1 :             (*this_).is_at_end = true;
     212           1 :             result |= U8_ERROR_INVALID_REQUEST;
     213             :         }
     214             :     }
     215             :     else
     216             :     {
     217           0 :         result |= U8_ERROR_NO_DB;
     218           0 :         U8_TRACE_INFO( "No valid sql statement, cannot request data." );
     219             :     }
     220             : 
     221           3 :     U8_TRACE_END_ERR( result );
     222           3 :     return result;
     223             : }
     224             : 
     225           3 : u8_error_t data_database_iterator_private_step_to_next ( data_database_iterator_classifiers_t *this_ )
     226             : {
     227           3 :     U8_TRACE_BEGIN();
     228           3 :     assert( (*this_).is_valid );
     229           3 :     assert( NULL != (*this_).statement_all_classifiers );
     230           3 :     u8_error_t result = U8_ERROR_NONE;
     231             : 
     232             :     /* do one step, check if is_at_end */
     233             :     {
     234             :         int sqlite_err;
     235           3 :         U8_TRACE_INFO( "sqlite3_step()" );
     236           3 :         sqlite_err = sqlite3_step( (*this_).statement_all_classifiers );
     237           3 :         if ( SQLITE_DONE == sqlite_err )
     238             :         {
     239           1 :             U8_TRACE_INFO( "sqlite3_step finished: SQLITE_DONE" );
     240           1 :             (*this_).is_at_end = true;
     241             :         }
     242           2 :         else if ( SQLITE_ROW == sqlite_err )
     243             :         {
     244           2 :             (*this_).is_at_end = false;
     245             :         }
     246             :         else
     247             :         {
     248           0 :             U8_LOG_ERROR_INT( "sqlite3_step failed:", sqlite_err );
     249           0 :             (*this_).is_at_end = true;
     250           0 :             result |= data_database_iterator_classifiers_destroy( this_ );
     251           0 :             result |= U8_ERROR_AT_DB;
     252             :         }
     253             :     }
     254             : 
     255           3 :     U8_TRACE_END_ERR(result);
     256           3 :     return result;
     257             : }
     258             : 
     259             : 
     260             : /*
     261             : Copyright 2020-2024 Andreas Warnke
     262             : 
     263             : Licensed under the Apache License, Version 2.0 (the "License");
     264             : you may not use this file except in compliance with the License.
     265             : You may obtain a copy of the License at
     266             : 
     267             :     http://www.apache.org/licenses/LICENSE-2.0
     268             : 
     269             : Unless required by applicable law or agreed to in writing, software
     270             : distributed under the License is distributed on an "AS IS" BASIS,
     271             : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     272             : See the License for the specific language governing permissions and
     273             : limitations under the License.
     274             : */

Generated by: LCOV version 1.16