add Finder::like(...) and ilike(...) methods

This commit is contained in:
Tomasz Sowa 2022-12-05 06:36:13 +01:00
parent dfc631dd06
commit a4a1acebeb
11 changed files with 616 additions and 180 deletions

View File

@ -210,7 +210,7 @@ void BaseExpression::put_field_name(const wchar_t * field_name, const FT & field
else else
{ {
before_field_name(); 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(); 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 * 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 * 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; 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() ) 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 else
{ {
if( !esc_char(val, stream) ) if( !esc_char(val, stream, field_type, model_env) )
{ {
stream << val; 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<char>(val), stream, field_type); esc(static_cast<char>(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() ) 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( field_type.use_utf8() )
{ {
if( !esc_char(val, stream) ) if( !esc_char(val, stream, field_type, model_env) )
{ {
stream << val; 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; 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; 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() ) 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 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() ) 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 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 ) if( val )
stream << "true"; 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; 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; 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; 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; 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; 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; 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; 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; 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; 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; 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; 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() ) 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(); pt::TextStream::const_iterator i = val.begin();
for(; i != val.end() ; ++i) 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(); pt::WTextStream::const_iterator i = val.begin();
for(; i != val.end() ; ++i) 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; pt::WTextStream tmp_stream;
bool pretty_print = field_type.is_pretty_print(); bool pretty_print = field_type.is_pretty_print();
@ -657,7 +657,7 @@ void BaseExpression::esc(const pt::Space & space, pt::TextStream & stream, const
else else
space.serialize_to_json_stream(tmp_stream, pretty_print); 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)
{ {
} }

View File

@ -157,13 +157,13 @@ public:
if( field_type.is_primary_key() ) if( field_type.is_primary_key() )
{ {
if( model_env && model_env->has_primary_key_set ) 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 else
put_null_value(); put_null_value();
} }
else else
{ {
put_field_value(field_value, field_type); put_field_value(field_value, field_type, model_env);
} }
} }
} }
@ -290,39 +290,39 @@ public:
template<typename StringType> template<typename StringType>
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( out_stream )
{ {
if( add_quotes ) 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 ) if( add_quotes )
{ {
after_field_value_string(field_type); after_field_value_string(field_type, model_env);
} }
} }
} }
template<typename StringOrStreamType> template<typename StringOrStreamType>
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( out_stream )
{ {
if( add_quotes ) 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 ) 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 * esc for: signed char, wchar_t, char16_t, char32_t
* *
*/ */
virtual bool esc_char(char 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); 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(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); 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); 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 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); 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 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); 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(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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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::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); 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); 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); 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); virtual void add_additional_columns(Model & model);
template<typename FieldValue> template<typename FieldValue>
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 ) if( out_stream )
{ {
before_field_value(field_value, field_type); before_field_value(field_value, field_type, model_env);
esc(field_value, *out_stream, field_type); esc(field_value, *out_stream, field_type, model_env);
after_field_value(field_value, field_type); 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 ) 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 ) if( scratch_buffer )
{ {
scratch_buffer->clear(); scratch_buffer->clear();
(model_env->model->*getter_method)(*scratch_buffer); (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(); 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(); field_value_list_separator();
} }
put_field_value(v, FT::default_type); put_field_value(v, FT::default_type, model_env);
is_first = false; is_first = false;
} }
@ -608,37 +608,37 @@ protected:
virtual void after_field_name(); virtual void after_field_name();
virtual void before_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); 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 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); 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 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); 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 before_field_value(const char *, const FT & field_type, ModelEnv * model_env);
virtual void after_field_value(const char *, const FT & field_type); 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 before_field_value(wchar_t, const FT & field_type, ModelEnv * model_env);
virtual void after_field_value(wchar_t, const FT & field_type); 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 before_field_value(char, const FT & field_type, ModelEnv * model_env);
virtual void after_field_value(char, const FT & field_type); 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 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); 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 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); virtual void after_field_value(const pt::Space &, const FT & field_type, ModelEnv * model_env);
template<typename FieldValue> template<typename FieldValue>
void before_field_value(const FieldValue &, const FT & field_type) void before_field_value(const FieldValue &, const FT & field_type, ModelEnv * model_env)
{ {
} }
template<typename FieldValue> template<typename FieldValue>
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 before_field_value_string(const FT & field_type, ModelEnv * model_env);
virtual void after_field_value_string(const FT & field_type); virtual void after_field_value_string(const FT & field_type, ModelEnv * model_env);
char char_to_hex_part(char c); char char_to_hex_part(char c);
void char_to_hex(char c, pt::TextStream & stream); void char_to_hex(char c, pt::TextStream & stream);
void char_to_hex(wchar_t 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 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); 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); bool is_empty_field(const wchar_t * value);
template<typename CharType> template<typename CharType>
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) 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<typename CharType> template<typename CharType>
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_comma = false;
bool was_something_printed = false; bool was_something_printed = false;
@ -729,7 +729,7 @@ protected:
if( (c=='.' && !was_comma) || (c>='0' && c<='9') ) if( (c=='.' && !was_comma) || (c>='0' && c<='9') )
{ {
esc(c, stream, field_type); esc(c, stream, field_type, model_env);
was_something_printed = true; was_something_printed = true;
if( c == '.' ) if( c == '.' )
@ -739,7 +739,7 @@ protected:
if( !was_something_printed ) if( !was_something_printed )
{ {
esc(static_cast<CharType>('0'), stream, field_type); esc(static_cast<CharType>('0'), stream, field_type, model_env);
} }
} }

View File

@ -120,7 +120,9 @@ void DbExpression::field_before()
output_type == MORM_OUTPUT_TYPE_WHERE_LE || output_type == MORM_OUTPUT_TYPE_WHERE_LE ||
output_type == MORM_OUTPUT_TYPE_WHERE_LT || output_type == MORM_OUTPUT_TYPE_WHERE_LT ||
output_type == MORM_OUTPUT_TYPE_WHERE_NOT_EQ || 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; int conjunction = MORM_CONJUNCTION_AND;
@ -180,7 +182,17 @@ void DbExpression::put_name_value_separator()
else else
if( output_type == MORM_OUTPUT_TYPE_WHERE_IN ) 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) << "'"; (*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) << "'"; (*out_stream) << "'";
} }
@ -350,4 +368,8 @@ void DbExpression::add_rows_counter_column(Model & model)
} }
} }

View File

@ -107,8 +107,8 @@ protected:
void add_additional_columns(Model & model); void add_additional_columns(Model & model);
void before_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); void after_field_value_string(const FT & field_type, ModelEnv * model_env);
virtual void add_rows_counter_column(Model & model); virtual void add_rows_counter_column(Model & model);

View File

@ -711,6 +711,386 @@ public:
} }
/*
* like
*/
Finder<ModelClass> & 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<ModelClass> & 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<ModelClass> & 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<ModelClass> & 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<ModelClass> & 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<ModelClass> & 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<ModelClass> & 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<ModelClass> & 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<ModelClass> & 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<ModelClass> & 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<ModelClass> & 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<ModelClass> & 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<ModelClass> & 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<ModelClass> & 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<ModelClass> & 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<ModelClass> & 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<ModelClass> & 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<ModelClass> & 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<ModelClass> & 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<ModelClass> & 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<ModelClass> & 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<ModelClass> & 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<ModelClass> & 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<ModelClass> & 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<ModelClass> & 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<ModelClass> & 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<ModelClass> & 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<ModelClass> & 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<ModelClass> & 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<ModelClass> & 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<ModelClass> & 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<ModelClass> & 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<ModelClass> & 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<ModelClass> & 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<ModelClass> & 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<ModelClass> & 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<typename PatternValue>
Finder<ModelClass> & 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<typename PatternValue>
Finder<ModelClass> & 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<typename PatternValue>
Finder<ModelClass> & 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<typename PatternValue>
Finder<ModelClass> & 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<typename PatternValue>
Finder<ModelClass> & 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<typename PatternValue>
Finder<ModelClass> & 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<ModelClass> get_cursor() Cursor<ModelClass> get_cursor()
{ {
Cursor<ModelClass> cursor; Cursor<ModelClass> cursor;

View File

@ -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) << "\""; (*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) << "\""; (*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() ) 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() ) 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); 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(); 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; pt::WTextStream tmp_stream;
space.serialize_to_space_stream(tmp_stream, pretty_print); 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 else
{ {

View File

@ -62,21 +62,17 @@ protected:
void before_field_value_list(); void before_field_value_list();
void after_field_value_list(); void after_field_value_list();
// using FlatExpression::esc to suppress clang warning: bool esc_char(wchar_t val, pt::TextStream & stream, const FT & field_type, ModelEnv * model_env);
// 'morm::JSONExpression::esc' hides overloaded virtual function [-Woverloaded-virtual] void esc(const pt::Space & space, pt::TextStream & stream, const FT & field_type, ModelEnv * model_env);
using FlatExpression::esc;
bool esc_char(wchar_t val, pt::TextStream & stream);
private: private:
void before_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); void after_field_value_string(const FT & field_type, ModelEnv * model_env);
void before_field_value(const pt::Space &, const FT & field_type); 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); 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);
}; };

View File

@ -111,6 +111,9 @@ public:
Select select_flags; Select select_flags;
size_t rows_counter; size_t rows_counter;
std::wstring rows_counter_column_name; 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; select_flags = e.select_flags;
rows_counter = e.rows_counter; rows_counter = e.rows_counter;
rows_counter_column_name = e.rows_counter_column_name; 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 #ifdef MORM_HAS_EZC_LIBRARY
ezc_fun_info = e.ezc_fun_info; ezc_fun_info = e.ezc_fun_info;
@ -208,6 +214,9 @@ public:
select_flags = Select::default_type; select_flags = Select::default_type;
rows_counter = 0; rows_counter = 0;
rows_counter_column_name.clear(); rows_counter_column_name.clear();
use_escaping_for_like = false;
add_prefix_percent = false;
add_postfix_percent = false;
#ifdef MORM_HAS_EZC_LIBRARY #ifdef MORM_HAS_EZC_LIBRARY
ezc_fun_info = nullptr; ezc_fun_info = nullptr;

View File

@ -98,6 +98,8 @@
#define MORM_OUTPUT_TYPE_WHERE_GE 24 #define MORM_OUTPUT_TYPE_WHERE_GE 24
#define MORM_OUTPUT_TYPE_WHERE_IN 25 #define MORM_OUTPUT_TYPE_WHERE_IN 25
#define MORM_OUTPUT_TYPE_WHERE_NOT_EQ 26 #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 #define MORM_CONJUNCTION_AND 1

View File

@ -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() ) if( field_type.is_binary() )
{ {
@ -59,17 +59,44 @@ void PostgreSQLExpression::before_field_value_string(const FT & field_type)
else else
{ {
(*out_stream) << "E'"; (*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) << "'"; (*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 == '\\' ) if( val == '\\' )
{ {
stream << "\\\\"; stream << "\\\\";

View File

@ -55,10 +55,10 @@ protected:
private: private:
void before_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); 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);
}; };