From a4a1acebeb31fae6831a90aaa488761977fc646c Mon Sep 17 00:00:00 2001 From: Tomasz Sowa Date: Mon, 5 Dec 2022 06:36:13 +0100 Subject: [PATCH] add Finder::like(...) and ilike(...) methods --- src/baseexpression.cpp | 156 +++++++------- src/baseexpression.h | 142 ++++++------- src/dbexpression.cpp | 30 ++- src/dbexpression.h | 4 +- src/finder.h | 380 +++++++++++++++++++++++++++++++++++ src/jsonexpression.cpp | 18 +- src/jsonexpression.h | 16 +- src/modelenv.h | 9 + src/morm_types.h | 2 + src/postgresqlexpression.cpp | 33 ++- src/postgresqlexpression.h | 6 +- 11 files changed, 616 insertions(+), 180 deletions(-) diff --git a/src/baseexpression.cpp b/src/baseexpression.cpp index 2838309..d28bff0 100644 --- a/src/baseexpression.cpp +++ b/src/baseexpression.cpp @@ -210,7 +210,7 @@ void BaseExpression::put_field_name(const wchar_t * field_name, const FT & field else { before_field_name(); - esc(field_name, *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(); } } @@ -277,95 +277,95 @@ void BaseExpression::after_field_name() } -void BaseExpression::before_field_value(const std::wstring &, const FT & field_type) +void BaseExpression::before_field_value(const std::wstring &, const FT & field_type, ModelEnv * model_env) { - before_field_value_string(field_type); + before_field_value_string(field_type, model_env); } -void BaseExpression::before_field_value(const std::string &, const FT & field_type) +void BaseExpression::before_field_value(const std::string &, const FT & field_type, ModelEnv * model_env) { - before_field_value_string(field_type); + before_field_value_string(field_type, model_env); } -void BaseExpression::after_field_value(const std::wstring &, const FT & field_type) +void BaseExpression::after_field_value(const std::wstring &, const FT & field_type, ModelEnv * model_env) { - after_field_value_string(field_type); + after_field_value_string(field_type, model_env); } -void BaseExpression::after_field_value(const std::string &, const FT & field_type) +void BaseExpression::after_field_value(const std::string &, const FT & field_type, ModelEnv * model_env) { - after_field_value_string(field_type); + after_field_value_string(field_type, model_env); } -void BaseExpression::before_field_value(const wchar_t *, const FT & field_type) +void BaseExpression::before_field_value(const wchar_t *, const FT & field_type, ModelEnv * model_env) { - before_field_value_string(field_type); + before_field_value_string(field_type, model_env); } -void BaseExpression::after_field_value(const wchar_t *, const FT & field_type) +void BaseExpression::after_field_value(const wchar_t *, const FT & field_type, ModelEnv * model_env) { - after_field_value_string(field_type); + after_field_value_string(field_type, model_env); } -void BaseExpression::before_field_value(const char *, const FT & field_type) +void BaseExpression::before_field_value(const char *, const FT & field_type, ModelEnv * model_env) { - before_field_value_string(field_type); + before_field_value_string(field_type, model_env); } -void BaseExpression::after_field_value(const char *, const FT & field_type) +void BaseExpression::after_field_value(const char *, const FT & field_type, ModelEnv * model_env) { - after_field_value_string(field_type); + after_field_value_string(field_type, model_env); } -void BaseExpression::before_field_value(wchar_t, const FT & field_type) +void BaseExpression::before_field_value(wchar_t, const FT & field_type, ModelEnv * model_env) { - before_field_value_string(field_type); + before_field_value_string(field_type, model_env); } -void BaseExpression::after_field_value(wchar_t, const FT & field_type) +void BaseExpression::after_field_value(wchar_t, const FT & field_type, ModelEnv * model_env) { - after_field_value_string(field_type); + after_field_value_string(field_type, model_env); } -void BaseExpression::before_field_value(char, const FT & field_type) +void BaseExpression::before_field_value(char, const FT & field_type, ModelEnv * model_env) { - before_field_value_string(field_type); + before_field_value_string(field_type, model_env); } -void BaseExpression::after_field_value(char, const FT & field_type) +void BaseExpression::after_field_value(char, const FT & field_type, ModelEnv * model_env) { - after_field_value_string(field_type); + after_field_value_string(field_type, model_env); } -void BaseExpression::before_field_value(const pt::Date &, const FT & field_type) +void BaseExpression::before_field_value(const pt::Date &, const FT & field_type, ModelEnv * model_env) { - before_field_value_string(field_type); + before_field_value_string(field_type, model_env); } -void BaseExpression::after_field_value(const pt::Date &, const FT & field_type) +void BaseExpression::after_field_value(const pt::Date &, const FT & field_type, ModelEnv * model_env) { - after_field_value_string(field_type); + after_field_value_string(field_type, model_env); } -void BaseExpression::before_field_value(const pt::Space &, const FT & field_type) +void BaseExpression::before_field_value(const pt::Space &, const FT & field_type, ModelEnv * model_env) { - before_field_value_string(field_type); + before_field_value_string(field_type, model_env); } -void BaseExpression::after_field_value(const pt::Space &, const FT & field_type) +void BaseExpression::after_field_value(const pt::Space &, const FT & field_type, ModelEnv * model_env) { - after_field_value_string(field_type); + after_field_value_string(field_type, model_env); } @@ -407,9 +407,9 @@ void BaseExpression::char_to_hex(wchar_t c, pt::TextStream & stream) * return true if the val character was escaped and put (or ignored) to the stream * */ -bool BaseExpression::esc_char(char val, pt::TextStream & stream) +bool BaseExpression::esc_char(char val, pt::TextStream & stream, const FT & field_type, ModelEnv * model_env) { - return esc_char((wchar_t)(unsigned char)val, stream); + return esc_char((wchar_t)(unsigned char)val, stream, field_type, model_env); } @@ -419,13 +419,13 @@ bool BaseExpression::esc_char(char val, pt::TextStream & stream) * in most caces you have to provide your own esc_char(wchar_t val, pt::TextStream & stream) method * */ -bool BaseExpression::esc_char(wchar_t val, pt::TextStream & stream) +bool BaseExpression::esc_char(wchar_t val, pt::TextStream & stream, const FT & field_type, ModelEnv * model_env) { return false; } -void BaseExpression::esc(char val, pt::TextStream & stream, const FT & field_type) +void BaseExpression::esc(char val, pt::TextStream & stream, const FT & field_type, ModelEnv * model_env) { if( field_type.is_binary() || field_type.is_hexadecimal() ) { @@ -433,7 +433,7 @@ void BaseExpression::esc(char val, pt::TextStream & stream, const FT & field_typ } else { - if( !esc_char(val, stream) ) + if( !esc_char(val, stream, field_type, model_env) ) { stream << val; } @@ -441,13 +441,13 @@ void BaseExpression::esc(char val, pt::TextStream & stream, const FT & field_typ } -void BaseExpression::esc(unsigned char val, pt::TextStream & stream, const FT & field_type) +void BaseExpression::esc(unsigned char val, pt::TextStream & stream, const FT & field_type, ModelEnv * model_env) { - esc(static_cast(val), stream, field_type); + esc(static_cast(val), stream, field_type, model_env); } -void BaseExpression::esc(wchar_t val, pt::TextStream & stream, const FT & field_type) +void BaseExpression::esc(wchar_t val, pt::TextStream & stream, const FT & field_type, ModelEnv * model_env) { if( field_type.is_binary() || field_type.is_hexadecimal() ) { @@ -457,7 +457,7 @@ void BaseExpression::esc(wchar_t val, pt::TextStream & stream, const FT & field_ { if( field_type.use_utf8() ) { - if( !esc_char(val, stream) ) + if( !esc_char(val, stream, field_type, model_env) ) { stream << val; } @@ -466,7 +466,7 @@ void BaseExpression::esc(wchar_t val, pt::TextStream & stream, const FT & field_ { char val_char = (char)(unsigned char)val; - if( !esc_char(val_char, stream) ) + if( !esc_char(val_char, stream, field_type, model_env) ) { stream << val_char; } @@ -475,57 +475,57 @@ void BaseExpression::esc(wchar_t val, pt::TextStream & stream, const FT & field_ } -void BaseExpression::esc(const wchar_t * val, bool has_known_length, size_t len, pt::TextStream & stream, const FT & field_type) +void BaseExpression::esc(const wchar_t * val, bool has_known_length, size_t len, pt::TextStream & stream, const FT & field_type, ModelEnv * model_env) { if( field_type.is_numeric() ) { - esc_numeric_string(val, has_known_length, len, stream, field_type); + esc_numeric_string(val, has_known_length, len, stream, field_type, model_env); } else { - esc_normal_string(val, has_known_length, len, stream, field_type); + esc_normal_string(val, has_known_length, len, stream, field_type, model_env); } } -void BaseExpression::esc(const char * val, bool has_known_length, size_t len, pt::TextStream & stream, const FT & field_type) +void BaseExpression::esc(const char * val, bool has_known_length, size_t len, pt::TextStream & stream, const FT & field_type, ModelEnv * model_env) { if( field_type.is_numeric() ) { - esc_numeric_string(val, has_known_length, len, stream, field_type); + esc_numeric_string(val, has_known_length, len, stream, field_type, model_env); } else { - esc_normal_string(val, has_known_length, len, stream, field_type); + esc_normal_string(val, has_known_length, len, stream, field_type, model_env); } } -void BaseExpression::esc(const std::wstring & val, pt::TextStream & stream, const FT & field_type) +void BaseExpression::esc(const std::wstring & val, pt::TextStream & stream, const FT & field_type, ModelEnv * model_env) { - esc(val.c_str(), true, val.size(), stream, field_type); + esc(val.c_str(), true, val.size(), stream, field_type, model_env); } -void BaseExpression::esc(const wchar_t * val, pt::TextStream & stream, const FT & field_type) +void BaseExpression::esc(const wchar_t * val, pt::TextStream & stream, const FT & field_type, ModelEnv * model_env) { - esc(val, false, 0, stream, field_type); + esc(val, false, 0, stream, field_type, model_env); } -void BaseExpression::esc(const std::string & val, pt::TextStream & stream, const FT & field_type) +void BaseExpression::esc(const std::string & val, pt::TextStream & stream, const FT & field_type, ModelEnv * model_env) { - esc(val.c_str(), true, val.size(), stream, field_type); + esc(val.c_str(), true, val.size(), stream, field_type, model_env); } -void BaseExpression::esc(const char * val, pt::TextStream & stream, const FT & field_type) +void BaseExpression::esc(const char * val, pt::TextStream & stream, const FT & field_type, ModelEnv * model_env) { - esc(val, false, 0, stream, field_type); + esc(val, false, 0, stream, field_type, model_env); } -void BaseExpression::esc(bool val, pt::TextStream & stream, const FT & field_type) +void BaseExpression::esc(bool val, pt::TextStream & stream, const FT & field_type, ModelEnv * model_env) { if( val ) stream << "true"; @@ -534,73 +534,73 @@ void BaseExpression::esc(bool val, pt::TextStream & stream, const FT & field_typ } -void BaseExpression::esc(short val, pt::TextStream & stream, const FT & field_type) +void BaseExpression::esc(short val, pt::TextStream & stream, const FT & field_type, ModelEnv * model_env) { stream << val; } -void BaseExpression::esc(unsigned short val, pt::TextStream & stream, const FT & field_type) +void BaseExpression::esc(unsigned short val, pt::TextStream & stream, const FT & field_type, ModelEnv * model_env) { stream << val; } -void BaseExpression::esc(int val, pt::TextStream & stream, const FT & field_type) +void BaseExpression::esc(int val, pt::TextStream & stream, const FT & field_type, ModelEnv * model_env) { stream << val; } -void BaseExpression::esc(unsigned int val, pt::TextStream & stream, const FT & field_type) +void BaseExpression::esc(unsigned int val, pt::TextStream & stream, const FT & field_type, ModelEnv * model_env) { stream << val; } -void BaseExpression::esc(long val, pt::TextStream & stream, const FT & field_type) +void BaseExpression::esc(long val, pt::TextStream & stream, const FT & field_type, ModelEnv * model_env) { stream << val; } -void BaseExpression::esc(unsigned long val, pt::TextStream & stream, const FT & field_type) +void BaseExpression::esc(unsigned long val, pt::TextStream & stream, const FT & field_type, ModelEnv * model_env) { stream << val; } -void BaseExpression::esc(long long val, pt::TextStream & stream, const FT & field_type) +void BaseExpression::esc(long long val, pt::TextStream & stream, const FT & field_type, ModelEnv * model_env) { stream << val; } -void BaseExpression::esc(unsigned long long val, pt::TextStream & stream, const FT & field_type) +void BaseExpression::esc(unsigned long long val, pt::TextStream & stream, const FT & field_type, ModelEnv * model_env) { stream << val; } -void BaseExpression::esc(float val, pt::TextStream & stream, const FT & field_type) +void BaseExpression::esc(float val, pt::TextStream & stream, const FT & field_type, ModelEnv * model_env) { stream << val; } -void BaseExpression::esc(double val, pt::TextStream & stream, const FT & field_type) +void BaseExpression::esc(double val, pt::TextStream & stream, const FT & field_type, ModelEnv * model_env) { stream << val; } -void BaseExpression::esc(long double val, pt::TextStream & stream, const FT & field_type) +void BaseExpression::esc(long double val, pt::TextStream & stream, const FT & field_type, ModelEnv * model_env) { stream << val; } -void BaseExpression::esc(const pt::Date & date, pt::TextStream & stream, const FT & field_type) +void BaseExpression::esc(const pt::Date & date, pt::TextStream & stream, const FT & field_type, ModelEnv * model_env) { if( field_type.is_date_only() ) { @@ -625,29 +625,29 @@ void BaseExpression::esc(const pt::Date & date, pt::TextStream & stream, const F } -void BaseExpression::esc(const pt::TextStream & val, pt::TextStream & stream, const FT & field_type) +void BaseExpression::esc(const pt::TextStream & val, pt::TextStream & stream, const FT & field_type, ModelEnv * model_env) { pt::TextStream::const_iterator i = val.begin(); for(; i != val.end() ; ++i) { - esc(*i, stream, field_type); + esc(*i, stream, field_type, model_env); } } -void BaseExpression::esc(const pt::WTextStream & val, pt::TextStream & stream, const FT & field_type) +void BaseExpression::esc(const pt::WTextStream & val, pt::TextStream & stream, const FT & field_type, ModelEnv * model_env) { pt::WTextStream::const_iterator i = val.begin(); for(; i != val.end() ; ++i) { - esc(*i, stream, field_type); + esc(*i, stream, field_type, model_env); } } -void BaseExpression::esc(const pt::Space & space, pt::TextStream & stream, const FT & field_type) +void BaseExpression::esc(const pt::Space & space, pt::TextStream & stream, const FT & field_type, ModelEnv * model_env) { pt::WTextStream tmp_stream; bool pretty_print = field_type.is_pretty_print(); @@ -657,7 +657,7 @@ void BaseExpression::esc(const pt::Space & space, pt::TextStream & stream, const else space.serialize_to_json_stream(tmp_stream, pretty_print); - esc(tmp_stream, stream, field_type); + esc(tmp_stream, stream, field_type, model_env); } @@ -770,11 +770,11 @@ void BaseExpression::esc(const pt::Space & space, pt::TextStream & stream, const //} -void BaseExpression::before_field_value_string(const FT & field_type) +void BaseExpression::before_field_value_string(const FT & field_type, ModelEnv * model_env) { } -void BaseExpression::after_field_value_string(const FT & field_type) +void BaseExpression::after_field_value_string(const FT & field_type, ModelEnv * model_env) { } diff --git a/src/baseexpression.h b/src/baseexpression.h index bdd839c..753c5db 100644 --- a/src/baseexpression.h +++ b/src/baseexpression.h @@ -157,13 +157,13 @@ public: if( field_type.is_primary_key() ) { if( model_env && model_env->has_primary_key_set ) - put_field_value(field_value, field_type); + put_field_value(field_value, field_type, model_env); else put_null_value(); } else { - put_field_value(field_value, field_type); + put_field_value(field_value, field_type, model_env); } } } @@ -290,39 +290,39 @@ public: template - void put_string_generic(const StringType * str, const FT & field_type, bool add_quotes) + void put_string_generic(const StringType * str, const FT & field_type, bool add_quotes, ModelEnv * model_env = nullptr) { if( out_stream ) { if( add_quotes ) { - before_field_value_string(field_type); + before_field_value_string(field_type, model_env); } - esc(str, *out_stream, field_type); + esc(str, *out_stream, field_type, model_env); if( add_quotes ) { - after_field_value_string(field_type); + after_field_value_string(field_type, model_env); } } } template - void put_string_generic(const StringOrStreamType & str, const FT & field_type, bool add_quotes) + void put_string_generic(const StringOrStreamType & str, const FT & field_type, bool add_quotes, ModelEnv * model_env = nullptr) { if( out_stream ) { if( add_quotes ) { - before_field_value_string(field_type); + before_field_value_string(field_type, model_env); } - esc(str, *out_stream, field_type); + esc(str, *out_stream, field_type, model_env); if( add_quotes ) { - after_field_value_string(field_type); + after_field_value_string(field_type, model_env); } } } @@ -332,36 +332,36 @@ public: * esc for: signed char, wchar_t, char16_t, char32_t * */ - virtual bool esc_char(char val, pt::TextStream & stream); - virtual bool esc_char(wchar_t val, pt::TextStream & stream); + 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); - virtual void esc(char val, pt::TextStream & stream, const FT & field_type = FT::default_type); - virtual void esc(unsigned char val, pt::TextStream & stream, const FT & field_type = FT::default_type); - virtual void esc(wchar_t val, pt::TextStream & stream, const FT & field_type = FT::default_type); + 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); - virtual void esc(const std::wstring & val, pt::TextStream & stream, const FT & field_type = FT::default_type); - virtual void esc(const wchar_t * val, pt::TextStream & stream, const FT & field_type = FT::default_type); + 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); - virtual void esc(const std::string & val, pt::TextStream & stream, const FT & field_type = FT::default_type); - virtual void esc(const char * val, pt::TextStream & stream, const FT & field_type = FT::default_type); + 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); - virtual void esc(bool val, pt::TextStream & stream, const FT & field_type = FT::default_type); - virtual void esc(short val, pt::TextStream & stream, const FT & field_type = FT::default_type); - virtual void esc(unsigned short val, pt::TextStream & stream, const FT & field_type = FT::default_type); - virtual void esc(int val, pt::TextStream & stream, const FT & field_type = FT::default_type); - virtual void esc(unsigned int val, pt::TextStream & stream, const FT & field_type = FT::default_type); - virtual void esc(long val, pt::TextStream & stream, const FT & field_type = FT::default_type); - virtual void esc(unsigned long val, pt::TextStream & stream, const FT & field_type = FT::default_type); - virtual void esc(long long val, pt::TextStream & stream, const FT & field_type = FT::default_type); - virtual void esc(unsigned long long val, pt::TextStream & stream, const FT & field_type = FT::default_type); - virtual void esc(float val, pt::TextStream & stream, const FT & field_type = FT::default_type); - virtual void esc(double val, pt::TextStream & stream, const FT & field_type = FT::default_type); - virtual void esc(long double val, pt::TextStream & stream, const FT & field_type = FT::default_type); + 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); - virtual void esc(const pt::Date & date, pt::TextStream & stream, const FT & field_type = FT::default_type); - virtual void esc(const pt::TextStream & val,pt::TextStream & stream, const FT & field_type = FT::default_type); - virtual void esc(const pt::WTextStream & val,pt::TextStream & stream, const FT & field_type = FT::default_type); - virtual void esc(const pt::Space & space, pt::TextStream & stream, const FT & field_type = FT::default_type); + 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); @@ -390,31 +390,31 @@ protected: virtual void add_additional_columns(Model & model); template - void put_field_value(const FieldValue & field_value, const FT & field_type) + void put_field_value(const FieldValue & field_value, const FT & field_type, ModelEnv * model_env = nullptr) { if( out_stream ) { - before_field_value(field_value, field_type); - esc(field_value, *out_stream, field_type); - after_field_value(field_value, field_type); + 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); } } - void put_field_value(void (Model::*getter_method)(pt::Stream &), const FT & field_type, ModelEnv * model_env) + void put_field_value(void (Model::*getter_method)(pt::Stream &), const FT & field_type, ModelEnv * model_env = nullptr) { if( out_stream && model_env && model_env->model && getter_method ) { - before_field_value_string(field_type); + before_field_value_string(field_type, model_env); if( scratch_buffer ) { scratch_buffer->clear(); (model_env->model->*getter_method)(*scratch_buffer); - esc(*scratch_buffer, *out_stream, field_type); + esc(*scratch_buffer, *out_stream, field_type, model_env); scratch_buffer->clear(); } - after_field_value_string(field_type); + after_field_value_string(field_type, model_env); } } @@ -585,7 +585,7 @@ protected: field_value_list_separator(); } - put_field_value(v, FT::default_type); + put_field_value(v, FT::default_type, model_env); is_first = false; } @@ -608,37 +608,37 @@ protected: virtual void after_field_name(); - virtual void before_field_value(const std::wstring &, const FT & field_type); - virtual void after_field_value(const std::wstring &, const FT & field_type); + 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); - virtual void before_field_value(const std::string &, const FT & field_type); - virtual void after_field_value(const std::string &, const FT & field_type); + 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); - virtual void before_field_value(const wchar_t *, const FT & field_type); - virtual void after_field_value(const wchar_t *, const FT & field_type); + 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); - virtual void before_field_value(const char *, const FT & field_type); - virtual void after_field_value(const char *, const FT & field_type); + 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); - virtual void before_field_value(wchar_t, const FT & field_type); - virtual void after_field_value(wchar_t, const FT & field_type); + 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); - virtual void before_field_value(char, const FT & field_type); - virtual void after_field_value(char, const FT & field_type); + 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); - virtual void before_field_value(const pt::Date &, const FT & field_type); - virtual void after_field_value(const pt::Date &, const FT & field_type); + 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); - virtual void before_field_value(const pt::Space &, const FT & field_type); - virtual void after_field_value(const pt::Space &, const FT & field_type); + 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); template - void before_field_value(const FieldValue &, const FT & field_type) + void before_field_value(const FieldValue &, const FT & field_type, ModelEnv * model_env) { } template - void after_field_value(const FieldValue &, const FT & field_type) + void after_field_value(const FieldValue &, const FT & field_type, ModelEnv * model_env) { } @@ -690,32 +690,32 @@ protected: - virtual void before_field_value_string(const FT & field_type); - virtual void after_field_value_string(const FT & field_type); + 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); char char_to_hex_part(char c); void char_to_hex(char c, pt::TextStream & stream); void char_to_hex(wchar_t c, pt::TextStream & stream); - void esc(const wchar_t * val, bool has_known_length, size_t len, pt::TextStream & stream, const FT & field_type); - void esc(const char * val, bool has_known_length, size_t len, pt::TextStream & stream, const FT & field_type); + 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); bool is_empty_field(const wchar_t * value); template - void esc_normal_string(CharType * val, bool has_known_length, size_t len, pt::TextStream & stream, const FT & field_type) + void esc_normal_string(CharType * val, bool has_known_length, size_t len, pt::TextStream & stream, const FT & field_type, ModelEnv * model_env) { for(size_t i = 0 ; has_known_length ? (i < len) : val[i] != 0 ; ++i) { - esc(val[i], stream, field_type); + esc(val[i], stream, field_type, model_env); } } template - void esc_numeric_string(CharType * val, bool has_known_length, size_t len, pt::TextStream & stream, const FT & field_type) + void esc_numeric_string(CharType * val, bool has_known_length, size_t len, pt::TextStream & stream, const FT & field_type, ModelEnv * model_env) { bool was_comma = false; bool was_something_printed = false; @@ -729,7 +729,7 @@ protected: if( (c=='.' && !was_comma) || (c>='0' && c<='9') ) { - esc(c, stream, field_type); + esc(c, stream, field_type, model_env); was_something_printed = true; if( c == '.' ) @@ -739,7 +739,7 @@ protected: if( !was_something_printed ) { - esc(static_cast('0'), stream, field_type); + esc(static_cast('0'), stream, field_type, model_env); } } diff --git a/src/dbexpression.cpp b/src/dbexpression.cpp index 1891b75..c88769c 100644 --- a/src/dbexpression.cpp +++ b/src/dbexpression.cpp @@ -120,7 +120,9 @@ void DbExpression::field_before() output_type == MORM_OUTPUT_TYPE_WHERE_LE || output_type == MORM_OUTPUT_TYPE_WHERE_LT || output_type == MORM_OUTPUT_TYPE_WHERE_NOT_EQ || - output_type == MORM_OUTPUT_TYPE_WHERE_IN ) + output_type == MORM_OUTPUT_TYPE_WHERE_IN || + output_type == MORM_OUTPUT_TYPE_WHERE_LIKE || + output_type == MORM_OUTPUT_TYPE_WHERE_ILIKE ) { int conjunction = MORM_CONJUNCTION_AND; @@ -180,7 +182,17 @@ void DbExpression::put_name_value_separator() else if( output_type == MORM_OUTPUT_TYPE_WHERE_IN ) { - (*out_stream) << " in "; + (*out_stream) << " IN "; + } + else + if( output_type == MORM_OUTPUT_TYPE_WHERE_LIKE ) + { + (*out_stream) << " LIKE "; + } + else + if( output_type == MORM_OUTPUT_TYPE_WHERE_ILIKE ) + { + (*out_stream) << " ILIKE "; } } @@ -234,14 +246,20 @@ void DbExpression::after_field_name() -void DbExpression::before_field_value_string(const FT & field_type) +void DbExpression::before_field_value_string(const FT & field_type, ModelEnv * model_env) { (*out_stream) << "'"; + + if( model_env && model_env->use_escaping_for_like && model_env->add_prefix_percent ) + (*out_stream) << '%'; } -void DbExpression::after_field_value_string(const FT & field_type) +void DbExpression::after_field_value_string(const FT & field_type, ModelEnv * model_env) { + if( model_env && model_env->use_escaping_for_like && model_env->add_postfix_percent ) + (*out_stream) << '%'; + (*out_stream) << "'"; } @@ -350,4 +368,8 @@ void DbExpression::add_rows_counter_column(Model & model) } + + + + } diff --git a/src/dbexpression.h b/src/dbexpression.h index 55e3d6f..ada8773 100644 --- a/src/dbexpression.h +++ b/src/dbexpression.h @@ -107,8 +107,8 @@ protected: void add_additional_columns(Model & model); - void before_field_value_string(const FT & field_type); - void after_field_value_string(const FT & field_type); + void before_field_value_string(const FT & field_type, ModelEnv * model_env); + void after_field_value_string(const FT & field_type, ModelEnv * model_env); virtual void add_rows_counter_column(Model & model); diff --git a/src/finder.h b/src/finder.h index 2201431..624b0fa 100644 --- a/src/finder.h +++ b/src/finder.h @@ -711,6 +711,386 @@ public: } + /* + * like + */ + Finder & like(const wchar_t * field_name, const char * pattern, + bool escape_pattern = true, bool add_prefix_percent = true, bool add_postfix_percent = true) + { + return like_generic(field_name, pattern, escape_pattern, add_prefix_percent, add_postfix_percent); + } + + + Finder & like(const wchar_t * table_name, const wchar_t * field_name, const char * pattern, + bool escape_pattern = true, bool add_prefix_percent = true, bool add_postfix_percent = true) + { + return like_generic(table_name, field_name, pattern, escape_pattern, add_prefix_percent, add_postfix_percent); + } + + + Finder & like(const wchar_t * table_name, int table_index, const wchar_t * field_name, const char * pattern, + bool escape_pattern = true, bool add_prefix_percent = true, bool add_postfix_percent = true) + { + return like_generic(table_name, table_index, field_name, pattern, escape_pattern, add_prefix_percent, add_postfix_percent); + } + + + Finder & like(const wchar_t * field_name, const wchar_t * pattern, + bool escape_pattern = true, bool add_prefix_percent = true, bool add_postfix_percent = true) + { + return like_generic(field_name, pattern, escape_pattern, add_prefix_percent, add_postfix_percent); + } + + + Finder & like(const wchar_t * table_name, const wchar_t * field_name, const wchar_t * pattern, + bool escape_pattern = true, bool add_prefix_percent = true, bool add_postfix_percent = true) + { + return like_generic(table_name, field_name, pattern, escape_pattern, add_prefix_percent, add_postfix_percent); + } + + + Finder & like(const wchar_t * table_name, int table_index, const wchar_t * field_name, const wchar_t * pattern, + bool escape_pattern = true, bool add_prefix_percent = true, bool add_postfix_percent = true) + { + return like_generic(table_name, table_index, field_name, pattern, escape_pattern, add_prefix_percent, add_postfix_percent); + } + + + Finder & like(const wchar_t * field_name, const std::string & pattern, + bool escape_pattern = true, bool add_prefix_percent = true, bool add_postfix_percent = true) + { + return like_generic(field_name, pattern, escape_pattern, add_prefix_percent, add_postfix_percent); + } + + + Finder & like(const wchar_t * table_name, const wchar_t * field_name, const std::string & pattern, + bool escape_pattern = true, bool add_prefix_percent = true, bool add_postfix_percent = true) + { + return like_generic(table_name, field_name, pattern, escape_pattern, add_prefix_percent, add_postfix_percent); + } + + + Finder & like(const wchar_t * table_name, int table_index, const wchar_t * field_name, const std::string & pattern, + bool escape_pattern = true, bool add_prefix_percent = true, bool add_postfix_percent = true) + { + return like_generic(table_name, table_index, field_name, pattern, escape_pattern, add_prefix_percent, add_postfix_percent); + } + + + Finder & like(const wchar_t * field_name, const std::wstring & pattern, + bool escape_pattern = true, bool add_prefix_percent = true, bool add_postfix_percent = true) + { + return like_generic(field_name, pattern, escape_pattern, add_prefix_percent, add_postfix_percent); + } + + + Finder & like(const wchar_t * table_name, const wchar_t * field_name, const std::wstring & pattern, + bool escape_pattern = true, bool add_prefix_percent = true, bool add_postfix_percent = true) + { + return like_generic(table_name, field_name, pattern, escape_pattern, add_prefix_percent, add_postfix_percent); + } + + + Finder & like(const wchar_t * table_name, int table_index, const wchar_t * field_name, const std::wstring & pattern, + bool escape_pattern = true, bool add_prefix_percent = true, bool add_postfix_percent = true) + { + return like_generic(table_name, table_index, field_name, pattern, escape_pattern, add_prefix_percent, add_postfix_percent); + } + + + Finder & like(const wchar_t * field_name, const pt::TextStream & pattern, + bool escape_pattern = true, bool add_prefix_percent = true, bool add_postfix_percent = true) + { + return like_generic(field_name, pattern, escape_pattern, add_prefix_percent, add_postfix_percent); + } + + + Finder & like(const wchar_t * table_name, const wchar_t * field_name, const pt::TextStream & pattern, + bool escape_pattern = true, bool add_prefix_percent = true, bool add_postfix_percent = true) + { + return like_generic(table_name, field_name, pattern, escape_pattern, add_prefix_percent, add_postfix_percent); + } + + + Finder & like(const wchar_t * table_name, int table_index, const wchar_t * field_name, const pt::TextStream & pattern, + bool escape_pattern = true, bool add_prefix_percent = true, bool add_postfix_percent = true) + { + return like_generic(table_name, table_index, field_name, pattern, escape_pattern, add_prefix_percent, add_postfix_percent); + } + + + Finder & like(const wchar_t * field_name, const pt::WTextStream & pattern, + bool escape_pattern = true, bool add_prefix_percent = true, bool add_postfix_percent = true) + { + return like_generic(field_name, pattern, escape_pattern, add_prefix_percent, add_postfix_percent); + } + + + Finder & like(const wchar_t * table_name, const wchar_t * field_name, const pt::WTextStream & pattern, + bool escape_pattern = true, bool add_prefix_percent = true, bool add_postfix_percent = true) + { + return like_generic(table_name, field_name, pattern, escape_pattern, add_prefix_percent, add_postfix_percent); + } + + + Finder & like(const wchar_t * table_name, int table_index, const wchar_t * field_name, const pt::WTextStream & pattern, + bool escape_pattern = true, bool add_prefix_percent = true, bool add_postfix_percent = true) + { + return like_generic(table_name, table_index, field_name, pattern, escape_pattern, add_prefix_percent, add_postfix_percent); + } + + + /* + * ilike + */ + Finder & ilike(const wchar_t * field_name, const char * pattern, + bool escape_pattern = true, bool add_prefix_percent = true, bool add_postfix_percent = true) + { + return ilike_generic(field_name, pattern, escape_pattern, add_prefix_percent, add_postfix_percent); + } + + + Finder & ilike(const wchar_t * table_name, const wchar_t * field_name, const char * pattern, + bool escape_pattern = true, bool add_prefix_percent = true, bool add_postfix_percent = true) + { + return ilike_generic(table_name, field_name, pattern, escape_pattern, add_prefix_percent, add_postfix_percent); + } + + + Finder & ilike(const wchar_t * table_name, int table_index, const wchar_t * field_name, const char * pattern, + bool escape_pattern = true, bool add_prefix_percent = true, bool add_postfix_percent = true) + { + return ilike_generic(table_name, table_index, field_name, pattern, escape_pattern, add_prefix_percent, add_postfix_percent); + } + + + Finder & ilike(const wchar_t * field_name, const wchar_t * pattern, + bool escape_pattern = true, bool add_prefix_percent = true, bool add_postfix_percent = true) + { + return ilike_generic(field_name, pattern, escape_pattern, add_prefix_percent, add_postfix_percent); + } + + + Finder & ilike(const wchar_t * table_name, const wchar_t * field_name, const wchar_t * pattern, + bool escape_pattern = true, bool add_prefix_percent = true, bool add_postfix_percent = true) + { + return ilike_generic(table_name, field_name, pattern, escape_pattern, add_prefix_percent, add_postfix_percent); + } + + + Finder & ilike(const wchar_t * table_name, int table_index, const wchar_t * field_name, const wchar_t * pattern, + bool escape_pattern = true, bool add_prefix_percent = true, bool add_postfix_percent = true) + { + return ilike_generic(table_name, table_index, field_name, pattern, escape_pattern, add_prefix_percent, add_postfix_percent); + } + + + Finder & ilike(const wchar_t * field_name, const std::string & pattern, + bool escape_pattern = true, bool add_prefix_percent = true, bool add_postfix_percent = true) + { + return ilike_generic(field_name, pattern, escape_pattern, add_prefix_percent, add_postfix_percent); + } + + + Finder & ilike(const wchar_t * table_name, const wchar_t * field_name, const std::string & pattern, + bool escape_pattern = true, bool add_prefix_percent = true, bool add_postfix_percent = true) + { + return ilike_generic(table_name, field_name, pattern, escape_pattern, add_prefix_percent, add_postfix_percent); + } + + + Finder & ilike(const wchar_t * table_name, int table_index, const wchar_t * field_name, const std::string & pattern, + bool escape_pattern = true, bool add_prefix_percent = true, bool add_postfix_percent = true) + { + return ilike_generic(table_name, table_index, field_name, pattern, escape_pattern, add_prefix_percent, add_postfix_percent); + } + + + Finder & ilike(const wchar_t * field_name, const std::wstring & pattern, + bool escape_pattern = true, bool add_prefix_percent = true, bool add_postfix_percent = true) + { + return ilike_generic(field_name, pattern, escape_pattern, add_prefix_percent, add_postfix_percent); + } + + + Finder & ilike(const wchar_t * table_name, const wchar_t * field_name, const std::wstring & pattern, + bool escape_pattern = true, bool add_prefix_percent = true, bool add_postfix_percent = true) + { + return ilike_generic(table_name, field_name, pattern, escape_pattern, add_prefix_percent, add_postfix_percent); + } + + + Finder & ilike(const wchar_t * table_name, int table_index, const wchar_t * field_name, const std::wstring & pattern, + bool escape_pattern = true, bool add_prefix_percent = true, bool add_postfix_percent = true) + { + return ilike_generic(table_name, table_index, field_name, pattern, escape_pattern, add_prefix_percent, add_postfix_percent); + } + + + Finder & ilike(const wchar_t * field_name, const pt::TextStream & pattern, + bool escape_pattern = true, bool add_prefix_percent = true, bool add_postfix_percent = true) + { + return ilike_generic(field_name, pattern, escape_pattern, add_prefix_percent, add_postfix_percent); + } + + + Finder & ilike(const wchar_t * table_name, const wchar_t * field_name, const pt::TextStream & pattern, + bool escape_pattern = true, bool add_prefix_percent = true, bool add_postfix_percent = true) + { + return ilike_generic(table_name, field_name, pattern, escape_pattern, add_prefix_percent, add_postfix_percent); + } + + + Finder & ilike(const wchar_t * table_name, int table_index, const wchar_t * field_name, const pt::TextStream & pattern, + bool escape_pattern = true, bool add_prefix_percent = true, bool add_postfix_percent = true) + { + return ilike_generic(table_name, table_index, field_name, pattern, escape_pattern, add_prefix_percent, add_postfix_percent); + } + + + Finder & ilike(const wchar_t * field_name, const pt::WTextStream & pattern, + bool escape_pattern = true, bool add_prefix_percent = true, bool add_postfix_percent = true) + { + return ilike_generic(field_name, pattern, escape_pattern, add_prefix_percent, add_postfix_percent); + } + + + Finder & ilike(const wchar_t * table_name, const wchar_t * field_name, const pt::WTextStream & pattern, + bool escape_pattern = true, bool add_prefix_percent = true, bool add_postfix_percent = true) + { + return ilike_generic(table_name, field_name, pattern, escape_pattern, add_prefix_percent, add_postfix_percent); + } + + + Finder & ilike(const wchar_t * table_name, int table_index, const wchar_t * field_name, const pt::WTextStream & pattern, + bool escape_pattern = true, bool add_prefix_percent = true, bool add_postfix_percent = true) + { + return ilike_generic(table_name, table_index, field_name, pattern, escape_pattern, add_prefix_percent, add_postfix_percent); + } + + + + template + Finder & like_generic(const wchar_t * field_name, const PatternValue & pattern, + bool escape_pattern, bool add_prefix_percent, bool add_postfix_percent) + { + if( db_expression ) + { + model_env.use_escaping_for_like = escape_pattern; + model_env.add_prefix_percent = add_prefix_percent; + model_env.add_postfix_percent = add_postfix_percent; + db_expression->set_output_type(MORM_OUTPUT_TYPE_WHERE_LIKE); + db_expression->field_to_stream(*out_stream, field_name, pattern, FT::default_type, &model_env); + model_env.use_escaping_for_like = false; + model_env.add_prefix_percent = false; + model_env.add_postfix_percent = false; + } + + return *this; + } + + + template + Finder & like_generic(const wchar_t * table_name, const wchar_t * field_name, const PatternValue & pattern, + bool escape_pattern, bool add_prefix_percent, bool add_postfix_percent) + { + if( db_expression ) + { + model_env.use_escaping_for_like = escape_pattern; + model_env.add_prefix_percent = add_prefix_percent; + model_env.add_postfix_percent = add_postfix_percent; + db_expression->set_output_type(MORM_OUTPUT_TYPE_WHERE_LIKE); + field_to_stream(table_name, 1, field_name, pattern); + model_env.use_escaping_for_like = false; + model_env.add_prefix_percent = false; + model_env.add_postfix_percent = false; + } + + return *this; + } + + + template + Finder & like_generic(const wchar_t * table_name, int table_index, const wchar_t * field_name, const PatternValue & pattern, + bool escape_pattern, bool add_prefix_percent, bool add_postfix_percent) + { + if( db_expression ) + { + model_env.use_escaping_for_like = escape_pattern; + model_env.add_prefix_percent = add_prefix_percent; + model_env.add_postfix_percent = add_postfix_percent; + db_expression->set_output_type(MORM_OUTPUT_TYPE_WHERE_LIKE); + field_to_stream(table_name, table_index, field_name, pattern); + model_env.use_escaping_for_like = false; + model_env.add_prefix_percent = false; + model_env.add_postfix_percent = false; + } + + return *this; + } + + + template + Finder & ilike_generic(const wchar_t * field_name, const PatternValue & pattern, + bool escape_pattern, bool add_prefix_percent, bool add_postfix_percent) + { + if( db_expression ) + { + model_env.use_escaping_for_like = escape_pattern; + model_env.add_prefix_percent = add_prefix_percent; + model_env.add_postfix_percent = add_postfix_percent; + db_expression->set_output_type(MORM_OUTPUT_TYPE_WHERE_ILIKE); + db_expression->field_to_stream(*out_stream, field_name, pattern, FT::default_type, &model_env); + model_env.use_escaping_for_like = false; + model_env.add_prefix_percent = false; + model_env.add_postfix_percent = false; + } + + return *this; + } + + + template + Finder & ilike_generic(const wchar_t * table_name, const wchar_t * field_name, const PatternValue & pattern, + bool escape_pattern, bool add_prefix_percent, bool add_postfix_percent) + { + if( db_expression ) + { + model_env.use_escaping_for_like = escape_pattern; + model_env.add_prefix_percent = add_prefix_percent; + model_env.add_postfix_percent = add_postfix_percent; + db_expression->set_output_type(MORM_OUTPUT_TYPE_WHERE_ILIKE); + field_to_stream(table_name, 1, field_name, pattern); + model_env.use_escaping_for_like = false; + model_env.add_prefix_percent = false; + model_env.add_postfix_percent = false; + } + + return *this; + } + + + template + Finder & ilike_generic(const wchar_t * table_name, int table_index, const wchar_t * field_name, const PatternValue & pattern, + bool escape_pattern, bool add_prefix_percent, bool add_postfix_percent) + { + if( db_expression ) + { + model_env.use_escaping_for_like = escape_pattern; + model_env.add_prefix_percent = add_prefix_percent; + model_env.add_postfix_percent = add_postfix_percent; + db_expression->set_output_type(MORM_OUTPUT_TYPE_WHERE_ILIKE); + field_to_stream(table_name, table_index, field_name, pattern); + model_env.use_escaping_for_like = false; + model_env.add_prefix_percent = false; + model_env.add_postfix_percent = false; + } + + return *this; + } + + + Cursor get_cursor() { Cursor cursor; diff --git a/src/jsonexpression.cpp b/src/jsonexpression.cpp index bdc278d..8bfd16e 100644 --- a/src/jsonexpression.cpp +++ b/src/jsonexpression.cpp @@ -88,30 +88,30 @@ void JSONExpression::after_field_name() -void JSONExpression::before_field_value_string(const FT & field_type) +void JSONExpression::before_field_value_string(const FT & field_type, ModelEnv * model_env) { (*out_stream) << "\""; } -void JSONExpression::after_field_value_string(const FT & field_type) +void JSONExpression::after_field_value_string(const FT & field_type, ModelEnv * model_env) { (*out_stream) << "\""; } -void JSONExpression::before_field_value(const pt::Space &, const FT & field_type) +void JSONExpression::before_field_value(const pt::Space &, const FT & field_type, ModelEnv * model_env) { if( field_type.is_space() ) { - before_field_value_string(field_type); + before_field_value_string(field_type, model_env); } } -void JSONExpression::after_field_value(const pt::Space &, const FT & field_type) +void JSONExpression::after_field_value(const pt::Space &, const FT & field_type, ModelEnv * model_env) { if( field_type.is_space() ) { - after_field_value_string(field_type); + after_field_value_string(field_type, model_env); } } @@ -135,14 +135,14 @@ void JSONExpression::after_field_value_list() } -bool JSONExpression::esc_char(wchar_t val, pt::TextStream & stream) +bool JSONExpression::esc_char(wchar_t val, pt::TextStream & stream, const FT & field_type, ModelEnv * model_env) { return pt::try_esc_to_json(val, stream); } -void JSONExpression::esc(const pt::Space & space, pt::TextStream & stream, const FT & field_type) +void JSONExpression::esc(const pt::Space & space, pt::TextStream & stream, const FT & field_type, ModelEnv * model_env) { bool pretty_print = field_type.is_pretty_print(); @@ -150,7 +150,7 @@ void JSONExpression::esc(const pt::Space & space, pt::TextStream & stream, const { pt::WTextStream tmp_stream; space.serialize_to_space_stream(tmp_stream, pretty_print); - BaseExpression::esc(tmp_stream, stream, field_type); + BaseExpression::esc(tmp_stream, stream, field_type, model_env); } else { diff --git a/src/jsonexpression.h b/src/jsonexpression.h index 61e4886..921c04d 100644 --- a/src/jsonexpression.h +++ b/src/jsonexpression.h @@ -62,21 +62,17 @@ protected: void before_field_value_list(); void after_field_value_list(); - // using FlatExpression::esc to suppress clang warning: - // 'morm::JSONExpression::esc' hides overloaded virtual function [-Woverloaded-virtual] - using FlatExpression::esc; - - bool esc_char(wchar_t val, pt::TextStream & stream); + bool esc_char(wchar_t val, pt::TextStream & stream, const FT & field_type, ModelEnv * model_env); + void esc(const pt::Space & space, pt::TextStream & stream, const FT & field_type, ModelEnv * model_env); private: - void before_field_value_string(const FT & field_type); - void after_field_value_string(const FT & field_type); - void before_field_value(const pt::Space &, const FT & field_type); - void after_field_value(const pt::Space &, const FT & field_type); + void before_field_value_string(const FT & field_type, ModelEnv * model_env); + void after_field_value_string(const FT & field_type, ModelEnv * model_env); + void before_field_value(const pt::Space &, const FT & field_type, ModelEnv * model_env); + void after_field_value(const pt::Space &, const FT & field_type, ModelEnv * model_env); - void esc(const pt::Space & space, pt::TextStream & stream, const FT & field_type); }; diff --git a/src/modelenv.h b/src/modelenv.h index 4139c0d..f40aad1 100644 --- a/src/modelenv.h +++ b/src/modelenv.h @@ -111,6 +111,9 @@ public: Select select_flags; size_t rows_counter; std::wstring rows_counter_column_name; + bool use_escaping_for_like; // escaping % and _ characters for LIKE or ILIKE statements + bool add_prefix_percent; // add a percent sign before a string value (used mainly in LIKE or ILIKE) + bool add_postfix_percent; // add a percent sign after a string value (used mainly in LIKE or ILIKE) @@ -152,6 +155,9 @@ public: select_flags = e.select_flags; rows_counter = e.rows_counter; rows_counter_column_name = e.rows_counter_column_name; + use_escaping_for_like = e.use_escaping_for_like; + add_prefix_percent = e.add_prefix_percent; + add_postfix_percent = e.add_postfix_percent; #ifdef MORM_HAS_EZC_LIBRARY ezc_fun_info = e.ezc_fun_info; @@ -208,6 +214,9 @@ public: select_flags = Select::default_type; rows_counter = 0; rows_counter_column_name.clear(); + use_escaping_for_like = false; + add_prefix_percent = false; + add_postfix_percent = false; #ifdef MORM_HAS_EZC_LIBRARY ezc_fun_info = nullptr; diff --git a/src/morm_types.h b/src/morm_types.h index a374a5a..f013ada 100644 --- a/src/morm_types.h +++ b/src/morm_types.h @@ -98,6 +98,8 @@ #define MORM_OUTPUT_TYPE_WHERE_GE 24 #define MORM_OUTPUT_TYPE_WHERE_IN 25 #define MORM_OUTPUT_TYPE_WHERE_NOT_EQ 26 +#define MORM_OUTPUT_TYPE_WHERE_LIKE 27 +#define MORM_OUTPUT_TYPE_WHERE_ILIKE 28 #define MORM_CONJUNCTION_AND 1 diff --git a/src/postgresqlexpression.cpp b/src/postgresqlexpression.cpp index 9e32897..a839d4b 100644 --- a/src/postgresqlexpression.cpp +++ b/src/postgresqlexpression.cpp @@ -40,7 +40,7 @@ namespace morm -void PostgreSQLExpression::before_field_value_string(const FT & field_type) +void PostgreSQLExpression::before_field_value_string(const FT & field_type, ModelEnv * model_env) { if( field_type.is_binary() ) { @@ -59,17 +59,44 @@ void PostgreSQLExpression::before_field_value_string(const FT & field_type) else { (*out_stream) << "E'"; + + if( model_env && model_env->add_prefix_percent ) + (*out_stream) << '%'; } } -void PostgreSQLExpression::after_field_value_string(const FT & field_type) +void PostgreSQLExpression::after_field_value_string(const FT & field_type, ModelEnv * model_env) { + if( model_env && model_env->add_postfix_percent ) + (*out_stream) << '%'; + (*out_stream) << "'"; } -bool PostgreSQLExpression::esc_char(wchar_t val, pt::TextStream & stream) +bool PostgreSQLExpression::esc_char(wchar_t val, pt::TextStream & stream, const FT & field_type, ModelEnv * model_env) { + if( model_env && model_env->use_escaping_for_like ) + { + if( val == '%' ) + { + stream << "\\\\%"; // gives: "\\%" (we are using a string form with E so we need to double backslashes here) + return true; + } + else + if( val == '_' ) + { + stream << "\\\\_"; // gives: "\\_" + return true; + } + else + if( val == '\\' ) + { + stream << "\\\\\\\\"; // gives: "\\\\" + return true; + } + } + if( val == '\\' ) { stream << "\\\\"; diff --git a/src/postgresqlexpression.h b/src/postgresqlexpression.h index 4f0b348..0fa3a36 100644 --- a/src/postgresqlexpression.h +++ b/src/postgresqlexpression.h @@ -55,10 +55,10 @@ protected: private: - void before_field_value_string(const FT & field_type); - void after_field_value_string(const FT & field_type); + void before_field_value_string(const FT & field_type, ModelEnv * model_env); + void after_field_value_string(const FT & field_type, ModelEnv * model_env); - bool esc_char(wchar_t val, pt::TextStream & stream); + bool esc_char(wchar_t val, pt::TextStream & stream, const FT & field_type, ModelEnv * model_env); };