2018-03-13 23:22:17 +01:00
/*
* This file is a part of morm
* and is distributed under the 2 - Clause BSD licence .
* Author : Tomasz Sowa < t . sowa @ ttmath . org >
*/
/*
2023-01-11 23:06:27 +01:00
* Copyright ( c ) 2018 - 2023 , Tomasz Sowa
2018-03-13 23:22:17 +01:00
* All rights reserved .
*
* Redistribution and use in source and binary forms , with or without
* modification , are permitted provided that the following conditions are met :
*
* 1. Redistributions of source code must retain the above copyright notice ,
* this list of conditions and the following disclaimer .
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice , this list of conditions and the following disclaimer in the
* documentation and / or other materials provided with the distribution .
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS " AS IS "
* AND ANY EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED . IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT , INDIRECT , INCIDENTAL , SPECIAL , EXEMPLARY , OR
* CONSEQUENTIAL DAMAGES ( INCLUDING , BUT NOT LIMITED TO , PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES ; LOSS OF USE , DATA , OR PROFITS ; OR BUSINESS
* INTERRUPTION ) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY , WHETHER IN
* CONTRACT , STRICT LIABILITY , OR TORT ( INCLUDING NEGLIGENCE OR OTHERWISE )
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE , EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE .
*
*/
2022-06-30 13:28:38 +02:00
# ifndef headerfile_morm_src_baseexpression
# define headerfile_morm_src_baseexpression
2018-03-23 20:26:57 +01:00
2018-04-17 00:46:25 +02:00
# include <list>
2018-04-18 19:52:09 +02:00
# include <set>
2022-05-16 13:42:51 +02:00
# include <type_traits>
2018-03-13 23:22:17 +01:00
# include "textstream/textstream.h"
2018-04-12 18:05:14 +02:00
# include "date/date.h"
2019-03-26 19:34:07 +01:00
# include "morm_types.h"
2019-05-13 19:59:28 +02:00
# include "modelenv.h"
2021-03-10 16:20:11 +01:00
# include "ft.h"
2021-05-31 18:40:28 +02:00
# include "convert/text.h"
2021-06-01 19:34:34 +02:00
# ifdef MORM_HAS_EZC_LIBRARY
2021-05-31 18:40:28 +02:00
# include "funinfo.h"
2021-06-01 19:34:34 +02:00
# endif
2018-03-13 23:22:17 +01:00
namespace morm
{
class Model ;
class ModelConnector ;
2018-03-23 20:26:57 +01:00
class BaseExpression
2018-03-13 23:22:17 +01:00
{
public :
2018-03-23 20:26:57 +01:00
BaseExpression ( ) ;
virtual ~ BaseExpression ( ) ;
2018-03-13 23:22:17 +01:00
2022-05-31 01:45:27 +02:00
BaseExpression ( const BaseExpression & ) = delete ;
BaseExpression ( BaseExpression & & ) = delete ;
2018-03-23 20:26:57 +01:00
virtual void set_work_mode ( int work_mode ) ;
2019-03-26 19:34:07 +01:00
virtual int get_work_mode ( ) ;
2021-05-20 16:25:01 +02:00
virtual pt : : TextStream * get_text_stream ( ) ;
virtual void set_text_stream ( pt : : TextStream * out_stream ) ;
2021-05-12 00:27:35 +02:00
2019-05-31 20:28:09 +02:00
virtual void clear ( ) ;
2018-05-02 01:22:32 +02:00
2021-05-20 16:25:01 +02:00
virtual void generate_from_model ( pt : : TextStream & stream , Model & model ) ;
2018-03-13 23:22:17 +01:00
2021-05-20 16:25:01 +02:00
virtual pt : : TextStream * get_current_stream ( ) ;
2018-07-16 00:36:04 +02:00
2019-03-31 22:21:12 +02:00
// rename me
virtual void allow_to_use_prefix ( bool use_prefix ) ;
2019-05-21 19:24:12 +02:00
virtual bool get_allow_to_use_prefix ( ) ;
2018-07-16 00:36:04 +02:00
2018-03-30 21:34:45 +02:00
template < typename FieldValue >
2021-05-12 04:53:23 +02:00
void field ( const wchar_t * field_name , const FieldValue & field_value , const FT & field_type , ModelEnv * model_env )
2021-06-20 17:49:54 +02:00
{
field_generic ( field_name , field_value , nullptr , field_type , model_env ) ;
}
virtual void field ( const wchar_t * field_name , void ( Model : : * getter_method ) ( pt : : Stream & ) , const FT & field_type , ModelEnv * model_env )
{
int tmp_object = 0 ;
field_generic ( field_name , tmp_object , getter_method , field_type , model_env ) ;
}
template < typename FieldValue >
void field_generic ( const wchar_t * field_name , const FieldValue & field_value , void ( Model : : * getter_method ) ( pt : : Stream & ) , const FT & field_type , ModelEnv * model_env )
2018-03-30 21:34:45 +02:00
{
2021-03-10 16:20:11 +01:00
if ( out_stream & & can_field_be_generated ( field_type ) )
2018-03-30 21:34:45 +02:00
{
field_before ( ) ;
if ( work_mode = = MORM_WORK_MODE_MODEL_FIELDS )
{
2021-05-13 00:19:22 +02:00
put_field_name_and_table_if_needed ( field_name , field_type , model_env ) ;
2019-03-26 19:34:07 +01:00
}
else
if ( work_mode = = MORM_WORK_MODE_MODEL_SAVE_FIELDS )
{
2021-04-12 18:53:55 +02:00
save_foreign_key ( field_name , field_type , model_env ) ;
2018-03-30 21:34:45 +02:00
}
else
if ( work_mode = = MORM_WORK_MODE_MODEL_VALUES )
{
2021-06-20 17:49:54 +02:00
put_field_value_or_null ( field_value , getter_method , field_type , model_env ) ;
2018-03-30 21:34:45 +02:00
}
else
if ( work_mode = = MORM_WORK_MODE_MODEL_FIELDS_VALUES )
{
2019-09-04 18:02:18 +02:00
if ( model_env & & model_env - > set_field_name_helper )
{
if ( ( size_t ) model_env - > field_index < model_env - > set_field_name_helper - > size ( ) )
{
2021-05-13 00:19:22 +02:00
put_field_name_and_table_if_needed ( ( * model_env - > set_field_name_helper ) [ model_env - > field_index ] , field_type , model_env ) ;
2019-09-04 18:02:18 +02:00
put_name_value_separator ( ) ;
2021-06-20 17:49:54 +02:00
put_field_value_or_null ( field_value , getter_method , field_type , model_env ) ;
2019-09-04 18:02:18 +02:00
}
model_env - > field_index + = 1 ;
}
else
{
2021-05-13 00:19:22 +02:00
put_field_name_and_table_if_needed ( field_name , field_type , model_env ) ;
2019-09-04 18:02:18 +02:00
put_name_value_separator ( ) ;
2021-06-20 17:49:54 +02:00
put_field_value_or_null ( field_value , getter_method , field_type , model_env ) ;
2019-09-04 18:02:18 +02:00
}
2018-03-30 21:34:45 +02:00
}
2022-12-16 02:48:07 +01:00
else
if ( work_mode = = MORM_WORK_MODE_MODEL_FIELDS_VALUES_FIELDS )
{
( * out_stream ) < < ' \n ' ;
put_field_name_and_table_if_needed ( field_name , field_type , model_env ) ;
put_name_value_separator ( ) ;
put_field_value_or_null ( field_value , getter_method , field_type , model_env ) ;
put_name_value_separator ( ) ;
/*
* IMPROVEME currently only used in XML serializer so we put / directly here
* we need some virtual methods for it
*/
before_field_name ( ) ; // here should be a different method such as before_closing_field_name()
if ( out_stream )
{
( * out_stream ) < < ' / ' ;
}
esc ( field_name , * out_stream , FT : : default_type , nullptr ) ; /* do not use provided field_type here - it would use e.g. binary mode if it was set, similar don't use model_env */
after_field_name ( ) ; // here too, e.g. after_closing_field_name()
/*
*
*/
}
2021-05-31 18:40:28 +02:00
field_after ( ) ;
}
}
2021-04-30 01:23:22 +02:00
2021-03-09 18:10:34 +01:00
template < typename FieldValue >
2021-06-20 17:49:54 +02:00
void put_field_value_or_null ( const FieldValue & field_value , void ( Model : : * getter_method ) ( pt : : Stream & ) , const FT & field_type , ModelEnv * model_env )
2021-03-09 18:10:34 +01:00
{
2021-06-20 17:49:54 +02:00
if ( getter_method )
2021-03-09 18:10:34 +01:00
{
2021-06-20 17:49:54 +02:00
put_field_value ( getter_method , field_type , model_env ) ;
2021-03-09 18:10:34 +01:00
}
else
{
2021-06-20 17:49:54 +02:00
if ( field_type . is_primary_key ( ) )
{
if ( model_env & & model_env - > has_primary_key_set )
2022-12-05 06:36:13 +01:00
put_field_value ( field_value , field_type , model_env ) ;
2021-06-20 17:49:54 +02:00
else
put_null_value ( ) ;
}
else
{
2022-12-05 06:36:13 +01:00
put_field_value ( field_value , field_type , model_env ) ;
2021-06-20 17:49:54 +02:00
}
2021-03-09 18:10:34 +01:00
}
}
2021-05-31 18:40:28 +02:00
2018-04-22 23:04:50 +02:00
template < typename FieldValue >
2021-05-20 16:25:01 +02:00
void field_in ( pt : : TextStream & stream , const wchar_t * field_name , const std : : set < FieldValue > & container , ModelEnv * model_env )
2018-04-22 23:04:50 +02:00
{
2019-05-31 20:28:09 +02:00
field_in_generic < FieldValue , std : : set < FieldValue > > ( stream , field_name , container , model_env ) ;
2018-04-22 23:04:50 +02:00
}
2018-03-30 21:34:45 +02:00
2018-04-18 19:52:09 +02:00
template < typename FieldValue >
2021-05-20 16:25:01 +02:00
void field_in ( pt : : TextStream & stream , const wchar_t * field_name , const std : : list < FieldValue > & container , ModelEnv * model_env )
2018-04-18 19:52:09 +02:00
{
2019-05-31 20:28:09 +02:00
field_in_generic < FieldValue , std : : list < FieldValue > > ( stream , field_name , container , model_env ) ;
2018-04-18 19:52:09 +02:00
}
2019-05-31 20:28:09 +02:00
2018-04-18 19:52:09 +02:00
template < typename FieldValue >
2021-05-20 16:25:01 +02:00
void field_in ( pt : : TextStream & stream , const wchar_t * field_name , const std : : vector < FieldValue > & container , ModelEnv * model_env )
2018-04-18 19:52:09 +02:00
{
2019-05-31 20:28:09 +02:00
field_in_generic < FieldValue , std : : vector < FieldValue > > ( stream , field_name , container , model_env ) ;
2018-04-18 19:52:09 +02:00
}
2019-05-31 20:28:09 +02:00
2021-06-17 21:31:58 +02:00
template < typename ModelContainer , typename ModelContainerType , typename IsContainerByValueRenameMe >
void field_list ( const wchar_t * field_name , ModelContainer & field_value , ModelContainerType * model_container_type ,
const FT & field_type , ModelConnector * model_connector , ModelEnv * model_env , IsContainerByValueRenameMe * foo )
2018-04-17 00:46:25 +02:00
{
2021-03-10 16:20:11 +01:00
if ( out_stream & & can_field_be_generated ( field_type ) )
2018-04-17 00:46:25 +02:00
{
field_before ( ) ;
2019-03-26 19:34:07 +01:00
// if( work_mode == MORM_WORK_MODE_MODEL_FIELDS )
// {
2021-05-13 00:19:22 +02:00
// put_field_name_and_table_if_needed(field_name);
2019-03-26 19:34:07 +01:00
// }
// else
2018-04-17 00:46:25 +02:00
if ( work_mode = = MORM_WORK_MODE_MODEL_FIELDS_VALUES )
{
2021-05-13 00:19:22 +02:00
put_field_name_and_table_if_needed ( field_name , field_type , model_env ) ;
2018-04-17 00:46:25 +02:00
put_name_value_separator ( ) ;
2021-06-17 21:31:58 +02:00
put_field_value_list ( field_value , model_container_type , model_connector , model_env , foo ) ;
2018-04-17 00:46:25 +02:00
}
2022-12-16 02:48:07 +01:00
else
if ( work_mode = = MORM_WORK_MODE_MODEL_FIELDS_VALUES_FIELDS )
{
( * out_stream ) < < ' \n ' ;
put_field_name_and_table_if_needed ( field_name , field_type , model_env ) ;
put_name_value_separator ( ) ;
put_field_value_list ( field_value , model_container_type , model_connector , model_env , foo ) ;
put_name_value_separator ( ) ;
/*
* IMPROVEME currently only used in XML serializer so we put / directly here
* we need some virtual methods for it
*/
before_field_name ( ) ; // here should be a different method such as before_closing_field_name()
if ( out_stream )
{
( * out_stream ) < < ' / ' ;
}
esc ( field_name , * out_stream , FT : : default_type , nullptr ) ; /* do not use provided field_type here - it would use e.g. binary mode if it was set, similar don't use model_env */
after_field_name ( ) ; // here too, e.g. after_closing_field_name()
/*
*
*/
}
2018-04-17 00:46:25 +02:00
field_after ( ) ;
}
}
2018-04-26 20:58:31 +02:00
template < typename ModelClass >
2021-05-12 04:53:23 +02:00
void field_model ( const wchar_t * field_name , ModelClass & field_model , const FT & field_type , ModelEnv * model_env )
2018-04-26 20:58:31 +02:00
{
2021-03-10 16:20:11 +01:00
if ( out_stream & & can_field_be_generated ( field_type ) )
2018-04-26 20:58:31 +02:00
{
field_before ( ) ;
2018-07-05 13:15:16 +02:00
if ( work_mode = = MORM_WORK_MODE_MODEL_FIELDS )
{
2021-05-13 00:19:22 +02:00
put_field_name_and_table_if_needed ( field_name , field_type , model_env ) ;
2018-07-05 13:15:16 +02:00
}
else
if ( work_mode = = MORM_WORK_MODE_MODEL_VALUES )
{
generate_from_model ( field_model ) ; // is it ok as a value?
}
else
2018-04-26 20:58:31 +02:00
if ( work_mode = = MORM_WORK_MODE_MODEL_FIELDS_VALUES )
{
2021-05-13 00:19:22 +02:00
put_field_name_and_table_if_needed ( field_name , field_type , model_env ) ;
2018-04-26 20:58:31 +02:00
put_name_value_separator ( ) ;
generate_from_model ( field_model ) ;
}
2022-12-16 02:48:07 +01:00
else
if ( work_mode = = MORM_WORK_MODE_MODEL_FIELDS_VALUES_FIELDS )
{
( * out_stream ) < < ' \n ' ;
put_field_name_and_table_if_needed ( field_name , field_type , model_env ) ;
put_name_value_separator ( ) ;
generate_from_model ( field_model ) ;
put_name_value_separator ( ) ;
/*
* IMPROVEME currently only used in XML serializer so we put / directly here
* we need some virtual methods for it
*/
before_field_name ( ) ; // here should be a different method such as before_closing_field_name()
if ( out_stream )
{
( * out_stream ) < < ' / ' ;
}
esc ( field_name , * out_stream , FT : : default_type , nullptr ) ; /* do not use provided field_type here - it would use e.g. binary mode if it was set, similar don't use model_env */
after_field_name ( ) ; // here too, e.g. after_closing_field_name()
( * out_stream ) < < ' \n ' ;
/*
*
*/
}
2018-04-26 20:58:31 +02:00
field_after ( ) ;
}
}
2018-04-18 19:52:09 +02:00
2018-04-16 01:00:17 +02:00
template < typename FieldValue >
2021-05-20 16:25:01 +02:00
void field_to_stream ( pt : : TextStream & stream , const wchar_t * field_name , const FieldValue & field_value , const FT & field_type , ModelEnv * model_env )
2018-04-16 01:00:17 +02:00
{
this - > out_stream = & stream ;
2021-03-10 16:20:11 +01:00
field ( field_name , field_value , field_type , model_env ) ;
2018-04-16 01:00:17 +02:00
this - > out_stream = nullptr ;
}
2021-05-12 00:27:35 +02:00
virtual void put_schema_table ( const wchar_t * schema_name , const wchar_t * table_name ) ;
2021-05-20 16:25:01 +02:00
virtual void put_schema_table ( const pt : : WTextStream & schema_name , const pt : : WTextStream & table_name ) ;
2021-05-12 00:27:35 +02:00
virtual void put_table ( const wchar_t * table_name ) ;
2021-05-20 16:25:01 +02:00
virtual void put_table ( const pt : : WTextStream & table_name ) ;
2021-05-12 00:27:35 +02:00
virtual void put_table_with_index ( const wchar_t * table_name , int index ) ;
2021-05-20 16:25:01 +02:00
virtual void put_table_with_index ( const pt : : WTextStream & table_name , int index ) ;
2021-05-12 00:27:35 +02:00
virtual void put_table_with_index_and_field ( const wchar_t * table_name , int index , const wchar_t * field_name , const FT & field_type ) ;
2021-05-20 16:25:01 +02:00
virtual void put_table_with_index_and_field ( const pt : : WTextStream & table_name , int index , const wchar_t * field_name , const FT & field_type ) ;
2021-05-13 00:19:22 +02:00
virtual void put_table_and_field ( const wchar_t * table_name , const wchar_t * field_name , const FT & field_type ) ;
2021-05-20 16:25:01 +02:00
virtual void put_table_and_field ( const pt : : WTextStream & table_name , const wchar_t * field_name , const FT & field_type ) ;
2021-04-30 01:23:22 +02:00
2022-12-02 11:45:19 +01:00
virtual void put_string ( const char * str , const FT & field_type , bool add_quotes = false ) ;
virtual void put_string ( const wchar_t * str , const FT & field_type , bool add_quotes = false ) ;
virtual void put_string ( const std : : string & str , const FT & field_type , bool add_quotes = false ) ;
virtual void put_string ( const std : : wstring & str , const FT & field_type , bool add_quotes = false ) ;
2022-12-02 13:26:30 +01:00
virtual void put_stream ( const pt : : TextStream & str , const FT & field_type , bool add_quotes = false ) ;
virtual void put_stream ( const pt : : WTextStream & str , const FT & field_type , bool add_quotes = false ) ;
2022-12-02 11:45:19 +01:00
2021-05-20 16:25:01 +02:00
virtual void schema_table_to_stream ( pt : : TextStream & stream , const wchar_t * schema_name , const wchar_t * table_name ) ;
virtual void schema_table_to_stream ( pt : : TextStream & stream , const pt : : WTextStream & schema_name , const pt : : WTextStream & table_name ) ;
virtual void table_to_stream ( pt : : TextStream & stream , const wchar_t * table_name ) ;
virtual void table_to_stream ( pt : : TextStream & stream , const pt : : WTextStream & table_name ) ;
virtual void table_with_index_to_stream ( pt : : TextStream & stream , const wchar_t * table_name , int index ) ;
virtual void table_with_index_to_stream ( pt : : TextStream & stream , const pt : : WTextStream & table_name , int index ) ;
virtual void table_with_index_and_field_to_stream ( pt : : TextStream & stream , const wchar_t * table_name , int index , const wchar_t * field_name , const FT & field_type ) ;
virtual void table_with_index_and_field_to_stream ( pt : : TextStream & stream , const pt : : WTextStream & table_name , int index , const wchar_t * field_name , const FT & field_type ) ;
virtual void table_and_field_to_stream ( pt : : TextStream & stream , const wchar_t * table_name , const wchar_t * field_name , const FT & field_type ) ;
virtual void table_and_field_to_stream ( pt : : TextStream & stream , const pt : : WTextStream & table_name , const wchar_t * field_name , const FT & field_type ) ;
2021-04-30 01:23:22 +02:00
2022-12-02 11:45:19 +01:00
virtual void string_to_stream ( pt : : TextStream & stream , const char * str , const FT & field_type , bool add_quotes = false ) ;
virtual void string_to_stream ( pt : : TextStream & stream , const wchar_t * str , const FT & field_type , bool add_quotes = false ) ;
virtual void string_to_stream ( pt : : TextStream & stream , const std : : string & str , const FT & field_type , bool add_quotes = false ) ;
virtual void string_to_stream ( pt : : TextStream & stream , const std : : wstring & str , const FT & field_type , bool add_quotes = false ) ;
2022-12-02 13:26:30 +01:00
virtual void stream_to_stream ( pt : : TextStream & stream_out , const pt : : TextStream & stream_in , const FT & field_type , bool add_quotes = false ) ;
virtual void stream_to_stream ( pt : : TextStream & stream_out , const pt : : WTextStream & stream_in , const FT & field_type , bool add_quotes = false ) ;
2022-12-02 11:45:19 +01:00
template < typename StringType >
2022-12-05 06:36:13 +01:00
void put_string_generic ( const StringType * str , const FT & field_type , bool add_quotes , ModelEnv * model_env = nullptr )
2022-12-02 11:45:19 +01:00
{
if ( out_stream )
{
if ( add_quotes )
{
2022-12-05 06:36:13 +01:00
before_field_value_string ( field_type , model_env ) ;
2022-12-02 11:45:19 +01:00
}
2022-12-05 06:36:13 +01:00
esc ( str , * out_stream , field_type , model_env ) ;
2022-12-02 11:45:19 +01:00
if ( add_quotes )
{
2022-12-05 06:36:13 +01:00
after_field_value_string ( field_type , model_env ) ;
2022-12-02 11:45:19 +01:00
}
}
}
2022-12-02 13:26:30 +01:00
template < typename StringOrStreamType >
2022-12-05 06:36:13 +01:00
void put_string_generic ( const StringOrStreamType & str , const FT & field_type , bool add_quotes , ModelEnv * model_env = nullptr )
2022-12-02 11:45:19 +01:00
{
if ( out_stream )
{
if ( add_quotes )
{
2022-12-05 06:36:13 +01:00
before_field_value_string ( field_type , model_env ) ;
2022-12-02 11:45:19 +01:00
}
2022-12-05 06:36:13 +01:00
esc ( str , * out_stream , field_type , model_env ) ;
2022-12-02 11:45:19 +01:00
if ( add_quotes )
{
2022-12-05 06:36:13 +01:00
after_field_value_string ( field_type , model_env ) ;
2022-12-02 11:45:19 +01:00
}
}
}
2021-04-30 01:23:22 +02:00
2019-09-25 19:21:12 +02:00
/*
* IMPLEMENT ME
* esc for : signed char , wchar_t , char16_t , char32_t
*
*/
2022-12-05 06:36:13 +01:00
virtual bool esc_char ( char val , pt : : TextStream & stream , const FT & field_type = FT : : default_type , ModelEnv * model_env = nullptr ) ;
virtual bool esc_char ( wchar_t val , pt : : TextStream & stream , const FT & field_type = FT : : default_type , ModelEnv * model_env = nullptr ) ;
2022-02-08 12:47:34 +01:00
2022-12-05 06:36:13 +01:00
virtual void esc ( char val , pt : : TextStream & stream , const FT & field_type = FT : : default_type , ModelEnv * model_env = nullptr ) ;
virtual void esc ( unsigned char val , pt : : TextStream & stream , const FT & field_type = FT : : default_type , ModelEnv * model_env = nullptr ) ;
virtual void esc ( wchar_t val , pt : : TextStream & stream , const FT & field_type = FT : : default_type , ModelEnv * model_env = nullptr ) ;
2021-05-12 04:53:23 +02:00
2022-12-05 06:36:13 +01:00
virtual void esc ( const std : : wstring & val , pt : : TextStream & stream , const FT & field_type = FT : : default_type , ModelEnv * model_env = nullptr ) ;
virtual void esc ( const wchar_t * val , pt : : TextStream & stream , const FT & field_type = FT : : default_type , ModelEnv * model_env = nullptr ) ;
2021-05-12 04:53:23 +02:00
2022-12-05 06:36:13 +01:00
virtual void esc ( const std : : string & val , pt : : TextStream & stream , const FT & field_type = FT : : default_type , ModelEnv * model_env = nullptr ) ;
virtual void esc ( const char * val , pt : : TextStream & stream , const FT & field_type = FT : : default_type , ModelEnv * model_env = nullptr ) ;
2021-05-12 04:53:23 +02:00
2022-12-05 06:36:13 +01:00
virtual void esc ( bool val , pt : : TextStream & stream , const FT & field_type = FT : : default_type , ModelEnv * model_env = nullptr ) ;
virtual void esc ( short val , pt : : TextStream & stream , const FT & field_type = FT : : default_type , ModelEnv * model_env = nullptr ) ;
virtual void esc ( unsigned short val , pt : : TextStream & stream , const FT & field_type = FT : : default_type , ModelEnv * model_env = nullptr ) ;
virtual void esc ( int val , pt : : TextStream & stream , const FT & field_type = FT : : default_type , ModelEnv * model_env = nullptr ) ;
virtual void esc ( unsigned int val , pt : : TextStream & stream , const FT & field_type = FT : : default_type , ModelEnv * model_env = nullptr ) ;
virtual void esc ( long val , pt : : TextStream & stream , const FT & field_type = FT : : default_type , ModelEnv * model_env = nullptr ) ;
virtual void esc ( unsigned long val , pt : : TextStream & stream , const FT & field_type = FT : : default_type , ModelEnv * model_env = nullptr ) ;
virtual void esc ( long long val , pt : : TextStream & stream , const FT & field_type = FT : : default_type , ModelEnv * model_env = nullptr ) ;
virtual void esc ( unsigned long long val , pt : : TextStream & stream , const FT & field_type = FT : : default_type , ModelEnv * model_env = nullptr ) ;
virtual void esc ( float val , pt : : TextStream & stream , const FT & field_type = FT : : default_type , ModelEnv * model_env = nullptr ) ;
virtual void esc ( double val , pt : : TextStream & stream , const FT & field_type = FT : : default_type , ModelEnv * model_env = nullptr ) ;
virtual void esc ( long double val , pt : : TextStream & stream , const FT & field_type = FT : : default_type , ModelEnv * model_env = nullptr ) ;
2018-04-16 01:00:17 +02:00
2022-12-05 06:36:13 +01:00
virtual void esc ( const pt : : Date & date , pt : : TextStream & stream , const FT & field_type = FT : : default_type , ModelEnv * model_env = nullptr ) ;
virtual void esc ( const pt : : TextStream & val , pt : : TextStream & stream , const FT & field_type = FT : : default_type , ModelEnv * model_env = nullptr ) ;
virtual void esc ( const pt : : WTextStream & val , pt : : TextStream & stream , const FT & field_type = FT : : default_type , ModelEnv * model_env = nullptr ) ;
virtual void esc ( const pt : : Space & space , pt : : TextStream & stream , const FT & field_type = FT : : default_type , ModelEnv * model_env = nullptr ) ;
2018-03-30 21:34:45 +02:00
2019-05-31 20:28:09 +02:00
2018-07-03 18:55:06 +02:00
2018-03-13 23:22:17 +01:00
protected :
int work_mode ; /* what to do: generating fields list, values list or fields-values list */
bool is_first_field ;
2021-05-20 16:25:01 +02:00
pt : : TextStream * out_stream ;
2019-03-31 22:21:12 +02:00
bool use_prefix ;
2022-05-31 01:45:27 +02:00
pt : : TextStream scratch_buffer_local ;
pt : : TextStream * scratch_buffer ;
2018-05-02 01:22:32 +02:00
2018-04-17 00:46:25 +02:00
virtual void generate_from_model ( Model & model ) ;
2018-03-13 23:22:17 +01:00
virtual void before_generate_from_model ( ) ;
virtual void after_generate_from_model ( ) ;
2021-05-12 04:53:23 +02:00
virtual bool can_field_be_generated ( const FT & ) ;
2018-03-13 23:22:17 +01:00
virtual void field_before ( ) ;
virtual void field_after ( ) ;
2021-05-13 00:19:22 +02:00
virtual void put_field_name_and_table_if_needed ( const wchar_t * field_name , const FT & field_type , ModelEnv * model_env ) ;
2021-05-12 04:53:23 +02:00
virtual void put_field_name ( const wchar_t * field_name , const FT & field_type , ModelEnv * model_env ) ;
2021-05-12 00:27:35 +02:00
2021-05-12 04:53:23 +02:00
virtual void save_foreign_key ( const wchar_t * field_name , const FT & field_type , ModelEnv * model_env ) ;
2019-09-13 20:17:02 +02:00
virtual void dump_additional_info ( Model & model ) ;
2022-07-11 17:48:13 +02:00
virtual void add_additional_columns ( Model & model ) ;
2018-03-13 23:22:17 +01:00
template < typename FieldValue >
2022-12-05 06:36:13 +01:00
void put_field_value ( const FieldValue & field_value , const FT & field_type , ModelEnv * model_env = nullptr )
2018-03-13 23:22:17 +01:00
{
2018-04-18 19:52:09 +02:00
if ( out_stream )
{
2022-12-05 06:36:13 +01:00
before_field_value ( field_value , field_type , model_env ) ;
esc ( field_value , * out_stream , field_type , model_env ) ;
after_field_value ( field_value , field_type , model_env ) ;
2018-04-18 19:52:09 +02:00
}
2018-03-13 23:22:17 +01:00
}
2022-12-05 06:36:13 +01:00
void put_field_value ( void ( Model : : * getter_method ) ( pt : : Stream & ) , const FT & field_type , ModelEnv * model_env = nullptr )
2021-06-20 17:49:54 +02:00
{
if ( out_stream & & model_env & & model_env - > model & & getter_method )
{
2022-12-05 06:36:13 +01:00
before_field_value_string ( field_type , model_env ) ;
2022-05-31 01:45:27 +02:00
if ( scratch_buffer )
{
scratch_buffer - > clear ( ) ;
( model_env - > model - > * getter_method ) ( * scratch_buffer ) ;
2022-12-05 06:36:13 +01:00
esc ( * scratch_buffer , * out_stream , field_type , model_env ) ;
2022-05-31 01:45:27 +02:00
scratch_buffer - > clear ( ) ;
}
2022-12-05 06:36:13 +01:00
after_field_value_string ( field_type , model_env ) ;
2021-06-20 17:49:54 +02:00
}
}
2019-05-21 17:51:13 +02:00
2021-03-09 18:10:34 +01:00
virtual void put_null_value ( )
{
( * out_stream ) < < " null " ;
}
2019-05-21 17:51:13 +02:00
virtual void before_field_value_list ( )
{
}
virtual void after_field_value_list ( )
{
}
virtual void field_value_list_separator ( )
{
( * out_stream ) < < " , " ;
}
2019-05-31 20:28:09 +02:00
virtual void put_statement_in_starts ( )
{
( * out_stream ) < < " ( " ;
}
virtual void put_statement_in_ends ( )
{
( * out_stream ) < < " ) " ;
}
2019-05-21 17:51:13 +02:00
2019-08-20 17:49:37 +02:00
2021-06-17 21:31:58 +02:00
template < typename ModelContainer , typename ModelContainerType , typename IsContainerByValueRenameMe >
void put_field_value_list ( ModelContainer & field_value , ModelContainerType * model_container_type , ModelConnector * model_connector ,
ModelEnv * model_env , IsContainerByValueRenameMe * foo )
2019-08-20 17:49:37 +02:00
{
2021-06-17 21:31:58 +02:00
if constexpr ( std : : is_base_of < Model , ModelContainerType > ( ) )
{
if constexpr ( std : : is_base_of < Model , IsContainerByValueRenameMe > ( ) )
{
put_field_value_list_model_by_value ( field_value , model_container_type , model_connector , model_env ) ;
}
else
{
put_field_value_list_model_by_pointer ( field_value , model_container_type , model_connector , model_env ) ;
}
}
else
{
put_field_value_list_non_model ( field_value , model_connector ) ;
}
}
template < typename ModelContainer , typename ModelContainerType >
void put_field_value_list_model_by_value ( ModelContainer & field_value , ModelContainerType * model_container_type , ModelConnector * model_connector ,
ModelEnv * model_env )
{
if ( model_connector & & model_env & & out_stream )
2019-08-20 17:49:37 +02:00
{
bool is_first = true ;
before_field_value_list ( ) ;
2021-06-17 21:31:58 +02:00
for ( auto & child_model_item : field_value )
2019-08-20 17:49:37 +02:00
{
if ( ! is_first )
{
field_value_list_separator ( ) ;
}
2021-06-17 21:31:58 +02:00
put_field_value_list_model ( child_model_item , model_connector , model_env ) ;
2019-08-20 17:49:37 +02:00
is_first = false ;
}
after_field_value_list ( ) ;
}
}
2021-06-17 21:31:58 +02:00
template < typename ModelContainer , typename ModelContainerType >
void put_field_value_list_model_by_pointer ( ModelContainer & field_value , ModelContainerType * model_container_type , ModelConnector * model_connector ,
ModelEnv * model_env )
2018-04-17 00:46:25 +02:00
{
2019-05-21 17:51:13 +02:00
if ( model_connector & & model_env & & out_stream )
2018-04-17 00:46:25 +02:00
{
2019-05-21 17:51:13 +02:00
bool is_first = true ;
before_field_value_list ( ) ;
2018-04-17 00:46:25 +02:00
2021-06-17 21:31:58 +02:00
for ( auto * child_model_item : field_value )
2018-04-17 00:46:25 +02:00
{
if ( ! is_first )
{
2019-05-21 17:51:13 +02:00
field_value_list_separator ( ) ;
2018-04-17 00:46:25 +02:00
}
2021-06-17 21:31:58 +02:00
put_field_value_list_model ( * child_model_item , model_connector , model_env ) ;
2018-04-17 00:46:25 +02:00
is_first = false ;
}
2019-05-21 17:51:13 +02:00
after_field_value_list ( ) ;
2018-04-17 00:46:25 +02:00
}
}
2018-03-13 23:22:17 +01:00
2018-04-18 19:52:09 +02:00
2021-06-17 21:31:58 +02:00
template < typename ModelContainerType >
void put_field_value_list_model ( ModelContainerType & child_model , ModelConnector * model_connector , ModelEnv * model_env )
2019-08-20 17:49:37 +02:00
{
2021-06-17 21:31:58 +02:00
ModelEnv model_env_local ( * model_env ) ;
child_model . model_env = & model_env_local ;
child_model . model_env - > has_primary_key_set = child_model . get_has_primary_key_set ( ) ;
2021-07-01 22:39:50 +02:00
child_model . model_env - > model = & child_model ;
2021-06-17 21:31:58 +02:00
child_model . set_connector ( model_connector ) ;
2019-08-20 17:49:37 +02:00
2021-06-17 21:31:58 +02:00
generate_from_model ( child_model ) ;
2019-08-20 17:49:37 +02:00
2021-06-17 21:31:58 +02:00
child_model . model_env = nullptr ;
2019-08-20 17:49:37 +02:00
}
2021-06-17 21:31:58 +02:00
template < typename ModelContainer >
void put_field_value_list_non_model ( ModelContainer & field_value , ModelConnector * model_connector )
2019-08-20 17:49:37 +02:00
{
2021-06-17 21:31:58 +02:00
if ( model_connector & & out_stream )
{
bool is_first = true ;
before_field_value_list ( ) ;
2019-08-20 17:49:37 +02:00
2021-06-17 21:31:58 +02:00
for ( const auto & m : field_value )
{
if ( ! is_first )
{
field_value_list_separator ( ) ;
}
2019-08-20 17:49:37 +02:00
2021-06-17 21:31:58 +02:00
put_field_value ( m , FT : : default_type ) ;
is_first = false ;
}
2019-08-20 17:49:37 +02:00
2021-06-17 21:31:58 +02:00
after_field_value_list ( ) ;
}
2019-08-20 17:49:37 +02:00
}
2018-04-18 19:52:09 +02:00
// used in 'in()' statements, may should be renamed?
template < typename FieldValue , typename Container >
2021-05-20 16:25:01 +02:00
void field_in_generic ( pt : : TextStream & stream , const wchar_t * field_name , const Container & container , ModelEnv * model_env )
2018-04-18 19:52:09 +02:00
{
// IMPROVE ME
// what about if container is empty?
// only 'in()' statement would be generated
this - > out_stream = & stream ;
field_before ( ) ;
2021-05-13 00:19:22 +02:00
put_field_name_and_table_if_needed ( field_name , FT : : default_type , model_env ) ;
2018-04-18 19:52:09 +02:00
put_name_value_separator ( ) ;
bool is_first = true ;
2019-05-31 20:28:09 +02:00
put_statement_in_starts ( ) ;
2018-04-18 19:52:09 +02:00
for ( const FieldValue & v : container )
{
if ( ! is_first )
{
2019-05-31 20:28:09 +02:00
field_value_list_separator ( ) ;
2018-04-18 19:52:09 +02:00
}
2022-12-05 06:36:13 +01:00
put_field_value ( v , FT : : default_type , model_env ) ;
2018-04-18 19:52:09 +02:00
is_first = false ;
}
2019-05-31 20:28:09 +02:00
put_statement_in_ends ( ) ;
2018-04-18 19:52:09 +02:00
field_after ( ) ;
this - > out_stream = nullptr ;
}
2021-05-13 02:32:03 +02:00
virtual void schema_table_separator ( ) ;
virtual void table_field_separator ( ) ;
virtual void before_schema_name ( ) ;
virtual void after_schema_name ( ) ;
virtual void before_table_name ( ) ;
virtual void after_table_name ( ) ;
virtual void before_field_name ( ) ;
virtual void after_field_name ( ) ;
2021-02-24 01:15:17 +01:00
2022-12-05 06:36:13 +01:00
virtual void before_field_value ( const std : : wstring & , const FT & field_type , ModelEnv * model_env ) ;
virtual void after_field_value ( const std : : wstring & , const FT & field_type , ModelEnv * model_env ) ;
2018-03-13 23:22:17 +01:00
2022-12-05 06:36:13 +01:00
virtual void before_field_value ( const std : : string & , const FT & field_type , ModelEnv * model_env ) ;
virtual void after_field_value ( const std : : string & , const FT & field_type , ModelEnv * model_env ) ;
2018-03-13 23:22:17 +01:00
2022-12-05 06:36:13 +01:00
virtual void before_field_value ( const wchar_t * , const FT & field_type , ModelEnv * model_env ) ;
virtual void after_field_value ( const wchar_t * , const FT & field_type , ModelEnv * model_env ) ;
2018-03-30 21:34:45 +02:00
2022-12-05 06:36:13 +01:00
virtual void before_field_value ( const char * , const FT & field_type , ModelEnv * model_env ) ;
virtual void after_field_value ( const char * , const FT & field_type , ModelEnv * model_env ) ;
2018-03-30 21:34:45 +02:00
2022-12-05 06:36:13 +01:00
virtual void before_field_value ( wchar_t , const FT & field_type , ModelEnv * model_env ) ;
virtual void after_field_value ( wchar_t , const FT & field_type , ModelEnv * model_env ) ;
2018-04-17 00:46:25 +02:00
2022-12-05 06:36:13 +01:00
virtual void before_field_value ( char , const FT & field_type , ModelEnv * model_env ) ;
virtual void after_field_value ( char , const FT & field_type , ModelEnv * model_env ) ;
2021-05-11 22:11:31 +02:00
2022-12-05 06:36:13 +01:00
virtual void before_field_value ( const pt : : Date & , const FT & field_type , ModelEnv * model_env ) ;
virtual void after_field_value ( const pt : : Date & , const FT & field_type , ModelEnv * model_env ) ;
2021-05-11 22:11:31 +02:00
2022-12-05 06:36:13 +01:00
virtual void before_field_value ( const pt : : Space & , const FT & field_type , ModelEnv * model_env ) ;
virtual void after_field_value ( const pt : : Space & , const FT & field_type , ModelEnv * model_env ) ;
2018-03-30 21:34:45 +02:00
2018-03-13 23:22:17 +01:00
template < typename FieldValue >
2022-12-05 06:36:13 +01:00
void before_field_value ( const FieldValue & , const FT & field_type , ModelEnv * model_env )
2018-03-13 23:22:17 +01:00
{
}
template < typename FieldValue >
2022-12-05 06:36:13 +01:00
void after_field_value ( const FieldValue & , const FT & field_type , ModelEnv * model_env )
2018-03-13 23:22:17 +01:00
{
}
2018-03-23 20:26:57 +01:00
virtual void put_name_value_separator ( ) ;
2018-03-13 23:22:17 +01:00
2019-09-25 19:21:12 +02:00
/*
* IMPLEMENT ME
* put_type for : signed char , wchar_t , char16_t , char32_t
*
*/
2021-05-20 16:25:01 +02:00
// virtual void put_type(char val, pt::TextStream & stream);
// virtual void put_type(unsigned char val, pt::TextStream & stream);
2021-03-11 18:40:32 +01:00
//
2021-05-20 16:25:01 +02:00
// virtual void put_type(const std::wstring & val, pt::TextStream & stream);
// virtual void put_type(const wchar_t * val, pt::TextStream & stream);
2021-03-11 18:40:32 +01:00
//
2021-05-20 16:25:01 +02:00
// virtual void put_type(const std::string & val, pt::TextStream & stream);
// virtual void put_type(const char * val, pt::TextStream & stream);
2021-03-11 18:40:32 +01:00
//
2021-05-20 16:25:01 +02:00
// virtual void put_type(bool val, pt::TextStream & stream);
// virtual void put_type(short val, pt::TextStream & stream);
// virtual void put_type(unsigned short val, pt::TextStream & stream);
// virtual void put_type(int val, pt::TextStream & stream);
// virtual void put_type(unsigned int val, pt::TextStream & stream);
// virtual void put_type(long val, pt::TextStream & stream);
// virtual void put_type(unsigned long val, pt::TextStream & stream);
// virtual void put_type(long long val, pt::TextStream & stream);
// virtual void put_type(unsigned long long val, pt::TextStream & stream);
// virtual void put_type(float val, pt::TextStream & stream);
// virtual void put_type(double val, pt::TextStream & stream);
// virtual void put_type(long double val, pt::TextStream & stream);
//virtual void put_type(void* val, pt::TextStream & stream);
// virtual void put_type(const pt::Date & date, pt::TextStream & stream);
// virtual void put_type(const Model & model, pt::TextStream & stream);
2021-03-11 18:40:32 +01:00
//
// template<typename ListType>
2021-05-20 16:25:01 +02:00
// void put_type(const std::list<ListType> & model, pt::TextStream & stream)
2021-03-11 18:40:32 +01:00
// {
// stream << "table"; // may just use std::list?
// }
//
// template<typename ListType>
2021-05-20 16:25:01 +02:00
// void put_type(const std::vector<ListType> & model, pt::TextStream & stream)
2021-03-11 18:40:32 +01:00
// {
// stream << "table"; // may just just std::vector?
// }
2022-12-05 06:36:13 +01:00
virtual void before_field_value_string ( const FT & field_type , ModelEnv * model_env ) ;
virtual void after_field_value_string ( const FT & field_type , ModelEnv * model_env ) ;
2018-07-16 00:36:04 +02:00
2021-05-11 22:11:31 +02:00
char char_to_hex_part ( char c ) ;
2021-05-20 16:25:01 +02:00
void char_to_hex ( char c , pt : : TextStream & stream ) ;
2022-02-08 12:47:34 +01:00
void char_to_hex ( wchar_t c , pt : : TextStream & stream ) ;
2019-08-20 17:49:37 +02:00
2022-12-05 06:36:13 +01:00
void esc ( const wchar_t * val , bool has_known_length , size_t len , pt : : TextStream & stream , const FT & field_type , ModelEnv * model_env ) ;
void esc ( const char * val , bool has_known_length , size_t len , pt : : TextStream & stream , const FT & field_type , ModelEnv * model_env ) ;
2018-03-23 20:26:57 +01:00
2021-05-13 02:32:03 +02:00
bool is_empty_field ( const wchar_t * value ) ;
2022-05-16 13:42:51 +02:00
template < typename CharType >
2022-12-05 06:36:13 +01:00
void esc_normal_string ( CharType * val , bool has_known_length , size_t len , pt : : TextStream & stream , const FT & field_type , ModelEnv * model_env )
2022-05-16 13:42:51 +02:00
{
for ( size_t i = 0 ; has_known_length ? ( i < len ) : val [ i ] ! = 0 ; + + i )
{
2022-12-05 06:36:13 +01:00
esc ( val [ i ] , stream , field_type , model_env ) ;
2022-05-16 13:42:51 +02:00
}
}
template < typename CharType >
2022-12-05 06:36:13 +01:00
void esc_numeric_string ( CharType * val , bool has_known_length , size_t len , pt : : TextStream & stream , const FT & field_type , ModelEnv * model_env )
2022-05-16 13:42:51 +02:00
{
bool was_comma = false ;
bool was_something_printed = false ;
2023-01-11 23:06:27 +01:00
bool was_digit_printed = false ;
2022-05-16 13:42:51 +02:00
for ( size_t i = 0 ; has_known_length ? ( i < len ) : val [ i ] ! = 0 ; + + i )
{
typename std : : remove_const < CharType > : : type c = val [ i ] ;
if ( c = = ' , ' )
c = ' . ' ;
2023-01-11 23:06:27 +01:00
if ( ( c = = ' . ' & & ! was_comma ) | | ( c > = ' 0 ' & & c < = ' 9 ' ) | | ( c = = ' - ' & & ! was_something_printed ) )
2022-05-16 13:42:51 +02:00
{
2023-01-11 23:06:27 +01:00
if ( c = = ' . ' )
{
if ( ! was_digit_printed )
{
esc ( static_cast < CharType > ( ' 0 ' ) , stream , field_type , model_env ) ;
was_digit_printed = true ;
}
was_comma = true ;
}
2022-12-05 06:36:13 +01:00
esc ( c , stream , field_type , model_env ) ;
2022-05-16 13:42:51 +02:00
was_something_printed = true ;
2023-01-11 23:06:27 +01:00
if ( c > = ' 0 ' & & c < = ' 9 ' )
{
was_digit_printed = true ;
}
2022-05-16 13:42:51 +02:00
}
}
2023-01-11 23:06:27 +01:00
if ( ! was_digit_printed )
2022-05-16 13:42:51 +02:00
{
2022-12-05 06:36:13 +01:00
esc ( static_cast < CharType > ( ' 0 ' ) , stream , field_type , model_env ) ;
2022-05-16 13:42:51 +02:00
}
}
2018-03-13 23:22:17 +01:00
} ;
2018-03-23 20:26:57 +01:00
}
2018-03-13 23:22:17 +01:00
# endif