/* * This file is a part of morm * and is distributed under the 2-Clause BSD licence. * Author: Tomasz Sowa */ /* * Copyright (c) 2018-2023, Tomasz Sowa * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ #ifndef headerfile_morm_src_finder #define headerfile_morm_src_finder #include #include #include #include "model.h" #include "utf8/utf8.h" #include "textstream/textstream.h" #include "dbconnector.h" #include "modelconnector.h" #include "cursor.h" #include "select.h" namespace morm { template class Finder { public: Finder() { initialize(); } Finder(pt::TextStream & out_stream) { initialize(); this->out_stream = &out_stream; } Finder(ModelConnector & model_connector) { initialize(); this->model_connector = &model_connector; set_out_stream(); } Finder(ModelConnector * model_connector) { initialize(); this->model_connector = model_connector; set_out_stream(); } Finder(pt::TextStream & out_stream, ModelConnector & model_connector) { initialize(); this->out_stream = &out_stream; this->model_connector = &model_connector; } Finder(pt::TextStream & out_stream, ModelConnector * model_connector) { initialize(); this->out_stream = &out_stream; this->model_connector = model_connector; } Finder & set_connector(ModelConnector * model_connector) { this->model_connector = model_connector; set_out_stream(); return *this; } Finder & set_connector(ModelConnector & model_connector) { this->model_connector = &model_connector; set_out_stream(); return *this; } Finder & set_stream(pt::TextStream * out_stream) { this->out_stream = out_stream; return *this; } Finder & set_stream(pt::TextStream & out_stream) { this->out_stream = out_stream; return *this; } Finder & set_model_data(ModelData * model_data) { this->model_data = model_data; return *this; } Finder & set_model_data(ModelData & model_data) { this->model_data = &model_data; return *this; } Finder & set_rows_counter_name(const wchar_t * rows_counter_name) { this->rows_counter_name = rows_counter_name; // may use a pt::TextStream? return *this; } Finder & set_rows_counter_name(const std::wstring & rows_counter_name) { this->rows_counter_name = rows_counter_name.c_str(); return *this; } Finder & declare_cursor(const char * cursor_name, bool scroll_cursor = false) { this->cursor_name.clear(); this->cursor_name << cursor_name; this->scroll_cursor = scroll_cursor; return *this; } Finder & declare_cursor(const wchar_t * cursor_name, bool scroll_cursor = false) { this->cursor_name.clear(); this->cursor_name << cursor_name; this->scroll_cursor = scroll_cursor; return *this; } bool was_error() { return was_query_error; } std::wstring get_error_msg() { return last_query_error; } Finder & select(const Select & select_flags = Select::default_type) { start_new_select(select_flags); if( !cursor_name.empty() ) { if( out_stream && db_expression ) { db_expression->prepare_declare_cursor_query(cursor_name, scroll_cursor, *out_stream); } } if( !select_flags.is_no_auto_generated_columns() ) { generate_standard_select(select_flags); } return *this; } /* * used if we are not using auto generated selects * * * a sample how to get the id field, assuming the table name is 'mymodel'. * mymodel = finder. * select(morm::Select::no_auto_generated_columns). * use_table_prefix(true). * raw("SELECT id AS \"mymodel.id\""). * raw("FROM mymodel"). * raw("WHERE id = 123"). * get(); * */ Finder & use_table_prefix(bool use_table_prefix_for_fetching) { this->use_table_prefix_for_fetching = use_table_prefix_for_fetching; return *this; } Finder & where() { if( out_stream && db_expression ) { (*out_stream) << " WHERE "; db_expression->prepare_to_where_clause(); } return *this; } Finder & group_or() { if( db_expression && out_stream ) { db_expression->group_or(*out_stream); } return *this; } Finder & group_and() { if( db_expression && out_stream ) { db_expression->group_and(*out_stream); } return *this; } Finder & group_end() { if( db_expression && out_stream ) { db_expression->group_end(*out_stream); } return *this; } template Finder & eq(const wchar_t * field_name, const FieldValue & field_value) { if( db_expression ) { db_expression->set_output_type(MORM_OUTPUT_TYPE_WHERE_EQ); db_expression->field_to_stream(*out_stream, field_name, field_value, FT::default_type, &model_env); } return *this; } template Finder & eq(const wchar_t * table_name, const wchar_t * field_name, const FieldValue & field_value) { if( db_expression ) { db_expression->set_output_type(MORM_OUTPUT_TYPE_WHERE_EQ); field_to_stream(table_name, 1, field_name, field_value); } return *this; } template Finder & eq(const wchar_t * table_name, int table_index, const wchar_t * field_name, const FieldValue & field_value) { if( db_expression ) { db_expression->set_output_type(MORM_OUTPUT_TYPE_WHERE_EQ); field_to_stream(table_name, table_index, field_name, field_value); } return *this; } template Finder & neq(const wchar_t * field_name, const FieldValue & field_value) { if( db_expression ) { db_expression->set_output_type(MORM_OUTPUT_TYPE_WHERE_NOT_EQ); db_expression->field_to_stream(*out_stream, field_name, field_value, FT::default_type, &model_env); } return *this; } template Finder & neq(const wchar_t * table_name, const wchar_t * field_name, const FieldValue & field_value) { if( db_expression ) { db_expression->set_output_type(MORM_OUTPUT_TYPE_WHERE_NOT_EQ); field_to_stream(table_name, 1, field_name, field_value); } return *this; } template Finder & neq(const wchar_t * table_name, int table_index, const wchar_t * field_name, const FieldValue & field_value) { if( db_expression ) { db_expression->set_output_type(MORM_OUTPUT_TYPE_WHERE_NOT_EQ); field_to_stream(table_name, table_index, field_name, field_value); } return *this; } template Finder & lt(const wchar_t * field_name, const FieldValue & field_value) { if( db_expression ) { db_expression->set_output_type(MORM_OUTPUT_TYPE_WHERE_LT); db_expression->field_to_stream(*out_stream, field_name, field_value, FT::default_type, &model_env); } return *this; } template Finder & lt(const wchar_t * table_name, const wchar_t * field_name, const FieldValue & field_value) { if( db_expression ) { db_expression->set_output_type(MORM_OUTPUT_TYPE_WHERE_LT); field_to_stream(table_name, 1, field_name, field_value); } return *this; } template Finder & lt(const wchar_t * table_name, int table_index, const wchar_t * field_name, const FieldValue & field_value) { if( db_expression ) { db_expression->set_output_type(MORM_OUTPUT_TYPE_WHERE_LT); field_to_stream(table_name, table_index, field_name, field_value); } return *this; } template Finder & gt(const wchar_t * field_name, const FieldValue & field_value) { if( db_expression ) { db_expression->set_output_type(MORM_OUTPUT_TYPE_WHERE_GT); db_expression->field_to_stream(*out_stream, field_name, field_value, FT::default_type, &model_env); } return *this; } template Finder & gt(const wchar_t * table_name, const wchar_t * field_name, const FieldValue & field_value) { if( db_expression ) { db_expression->set_output_type(MORM_OUTPUT_TYPE_WHERE_GT); field_to_stream(table_name, 1, field_name, field_value); } return *this; } template Finder & gt(const wchar_t * table_name, int table_index, const wchar_t * field_name, const FieldValue & field_value) { if( db_expression ) { db_expression->set_output_type(MORM_OUTPUT_TYPE_WHERE_GT); field_to_stream(table_name, table_index, field_name, field_value); } return *this; } template Finder & le(const wchar_t * field_name, const FieldValue & field_value) { if( db_expression ) { db_expression->set_output_type(MORM_OUTPUT_TYPE_WHERE_LE); db_expression->field_to_stream(*out_stream, field_name, field_value, FT::default_type, &model_env); } return *this; } template Finder & le(const wchar_t * table_name, const wchar_t * field_name, const FieldValue & field_value) { if( db_expression ) { db_expression->set_output_type(MORM_OUTPUT_TYPE_WHERE_LE); field_to_stream(table_name, 1, field_name, field_value); } return *this; } template Finder & le(const wchar_t * table_name, int table_index, const wchar_t * field_name, const FieldValue & field_value) { if( db_expression ) { db_expression->set_output_type(MORM_OUTPUT_TYPE_WHERE_LE); field_to_stream(table_name, table_index, field_name, field_value); } return *this; } template Finder & ge(const wchar_t * field_name, const FieldValue & field_value) { if( db_expression ) { db_expression->set_output_type(MORM_OUTPUT_TYPE_WHERE_GE); db_expression->field_to_stream(*out_stream, field_name, field_value, FT::default_type, &model_env); } return *this; } template Finder & ge(const wchar_t * table_name, const wchar_t * field_name, const FieldValue & field_value) { if( db_expression ) { db_expression->set_output_type(MORM_OUTPUT_TYPE_WHERE_GE); field_to_stream(table_name, 1, field_name, field_value); } return *this; } template Finder & ge(const wchar_t * table_name, int table_index, const wchar_t * field_name, const FieldValue & field_value) { if( db_expression ) { db_expression->set_output_type(MORM_OUTPUT_TYPE_WHERE_GE); field_to_stream(table_name, table_index, field_name, field_value); } return *this; } template Finder & in(const wchar_t * field_name, const std::set & container) { if( db_expression ) { db_expression->set_output_type(MORM_OUTPUT_TYPE_WHERE_IN); db_expression->field_in(*out_stream, field_name, container, &model_env); } return *this; } template Finder & in(const wchar_t * table_name, const wchar_t * field_name, const std::set & container) { if( db_expression ) { db_expression->set_output_type(MORM_OUTPUT_TYPE_WHERE_IN); field_in(table_name, 1, field_name, container); } return *this; } template Finder & in(const wchar_t * table_name, int table_index, const wchar_t * field_name, const std::set & container) { if( db_expression ) { db_expression->set_output_type(MORM_OUTPUT_TYPE_WHERE_IN); field_in(table_name, table_index, field_name, container); } return *this; } template Finder & in(const wchar_t * field_name, const std::list & container) { if( db_expression ) { db_expression->set_output_type(MORM_OUTPUT_TYPE_WHERE_IN); db_expression->field_in(*out_stream, field_name, container, &model_env); } return *this; } template Finder & in(const wchar_t * table_name, const wchar_t * field_name, const std::list & container) { if( db_expression ) { db_expression->set_output_type(MORM_OUTPUT_TYPE_WHERE_IN); field_in(table_name, 1, field_name, container); } return *this; } template Finder & in(const wchar_t * table_name, int table_index, const wchar_t * field_name, const std::list & container) { if( db_expression ) { db_expression->set_output_type(MORM_OUTPUT_TYPE_WHERE_IN); field_in(table_name, table_index, field_name, container); } return *this; } template Finder & in(const wchar_t * field_name, const std::vector & container) { if( db_expression ) { db_expression->set_output_type(MORM_OUTPUT_TYPE_WHERE_IN); db_expression->field_in(*out_stream, field_name, container, &model_env); } return *this; } template Finder & in(const wchar_t * table_name, const wchar_t * field_name, const std::vector & container) { if( db_expression ) { db_expression->set_output_type(MORM_OUTPUT_TYPE_WHERE_IN); field_in(table_name, 1, field_name, container); } return *this; } template Finder & in(const wchar_t * table_name, int table_index, const wchar_t * field_name, const std::vector & container) { if( db_expression ) { db_expression->set_output_type(MORM_OUTPUT_TYPE_WHERE_IN); field_in(table_name, table_index, field_name, container); } return *this; } Finder & is_null(const wchar_t * field_name) { if( db_expression ) { int ignored_value = 0; db_expression->set_output_type(MORM_OUTPUT_TYPE_WHERE_IS_NULL); db_expression->field_to_stream(*out_stream, field_name, ignored_value, FT::default_type, &model_env); } return *this; } Finder & is_null(const wchar_t * table_name, const wchar_t * field_name) { if( db_expression ) { int ignored_value = 0; db_expression->set_output_type(MORM_OUTPUT_TYPE_WHERE_IS_NULL); field_to_stream(table_name, 1, field_name, ignored_value); } return *this; } Finder & is_null(const wchar_t * table_name, int table_index, const wchar_t * field_name) { if( db_expression ) { int ignored_value = 0; db_expression->set_output_type(MORM_OUTPUT_TYPE_WHERE_IS_NULL); field_to_stream(table_name, table_index, field_name, ignored_value); } return *this; } Finder & is_not_null(const wchar_t * field_name) { if( db_expression ) { int ignored_value = 0; db_expression->set_output_type(MORM_OUTPUT_TYPE_WHERE_IS_NOT_NULL); db_expression->field_to_stream(*out_stream, field_name, ignored_value, FT::default_type, &model_env); } return *this; } Finder & is_not_null(const wchar_t * table_name, const wchar_t * field_name) { if( db_expression ) { int ignored_value = 0; db_expression->set_output_type(MORM_OUTPUT_TYPE_WHERE_IS_NOT_NULL); field_to_stream(table_name, 1, field_name, ignored_value); } return *this; } Finder & is_not_null(const wchar_t * table_name, int table_index, const wchar_t * field_name) { if( db_expression ) { int ignored_value = 0; db_expression->set_output_type(MORM_OUTPUT_TYPE_WHERE_IS_NOT_NULL); field_to_stream(table_name, table_index, field_name, ignored_value); } return *this; } /* * page_number start from zero (it's a number of a page, not an offset) */ Finder & page(size_t page_number, size_t page_size) { if( out_stream && db_expression ) { db_expression->page(*out_stream, page_number, page_size); } return *this; } Finder & raw(const char * sql, bool add_spaces = true) { return raw_generic(sql, add_spaces); } Finder & raw(const wchar_t * sql, bool add_spaces = true) { return raw_generic(sql, add_spaces); } Finder & raw(const std::string & sql, bool add_spaces = true) { return raw_generic(sql, add_spaces); } Finder & raw(const std::wstring & sql, bool add_spaces = true) { return raw_generic(sql, add_spaces); } Finder & raw(const pt::TextStream & sql, bool add_spaces = true) { return raw_generic(sql, add_spaces); } Finder & raw(const pt::WTextStream & sql, bool add_spaces = true) { return raw_generic(sql, add_spaces); } Finder & raw(long sql, bool add_spaces = true) { return raw_generic(sql, add_spaces); } Finder & raw(const pt::Date & date, bool add_spaces = true, const FT & field_type = morm::FT::default_type) { if( out_stream && db_expression ) { db_expression->esc(date, *out_stream, field_type); } return *this; } Finder & esc(const char * str, bool add_quotes = true, const FT & field_type = morm::FT::default_type) { if( out_stream && db_expression ) { db_expression->string_to_stream(*out_stream, str, field_type, add_quotes); } return *this; } Finder & esc(const wchar_t * str, bool add_quotes = true, const FT & field_type = morm::FT::default_type) { if( out_stream && db_expression ) { db_expression->string_to_stream(*out_stream, str, field_type, add_quotes); } return *this; } Finder & esc(const std::string & str, bool add_quotes = true, const FT & field_type = morm::FT::default_type) { if( out_stream && db_expression ) { db_expression->string_to_stream(*out_stream, str, field_type, add_quotes); } return *this; } Finder & esc(const std::wstring & str, bool add_quotes = true, const FT & field_type = morm::FT::default_type) { if( out_stream && db_expression ) { db_expression->string_to_stream(*out_stream, str, field_type, add_quotes); } return *this; } Finder & esc(const pt::TextStream & str, bool add_quotes = true, const FT & field_type = morm::FT::default_type) { if( out_stream && db_expression ) { db_expression->stream_to_stream(*out_stream, str, field_type, add_quotes); } return *this; } Finder & esc(const pt::WTextStream & str, bool add_quotes = true, const FT & field_type = morm::FT::default_type) { if( out_stream && db_expression ) { db_expression->stream_to_stream(*out_stream, str, field_type, add_quotes); } return *this; } Finder & esc(const pt::Date & date, bool add_spaces = true, const FT & field_type = morm::FT::default_type) { if( out_stream && db_expression ) { if( add_spaces ) (*out_stream) << ' '; db_expression->value_to_stream(*out_stream, date, field_type); if( add_spaces ) (*out_stream) << ' '; } return *this; } Finder & esc_like(const char * str, bool add_quotes = true, const FT & field_type = morm::FT::default_type) { if( out_stream && db_expression ) { model_env.use_escaping_for_like = true; db_expression->string_to_stream(*out_stream, str, field_type, add_quotes, &model_env); model_env.use_escaping_for_like = false; } return *this; } Finder & esc_like(const wchar_t * str, bool add_quotes = true, const FT & field_type = morm::FT::default_type) { if( out_stream && db_expression ) { model_env.use_escaping_for_like = true; db_expression->string_to_stream(*out_stream, str, field_type, add_quotes, &model_env); model_env.use_escaping_for_like = false; } return *this; } Finder & esc_like(const std::string & str, bool add_quotes = true, const FT & field_type = morm::FT::default_type) { if( out_stream && db_expression ) { model_env.use_escaping_for_like = true; db_expression->string_to_stream(*out_stream, str, field_type, add_quotes, &model_env); model_env.use_escaping_for_like = false; } return *this; } Finder & esc_like(const std::wstring & str, bool add_quotes = true, const FT & field_type = morm::FT::default_type) { if( out_stream && db_expression ) { model_env.use_escaping_for_like = true; db_expression->string_to_stream(*out_stream, str, field_type, add_quotes, &model_env); model_env.use_escaping_for_like = false; } return *this; } Finder & esc_like(const pt::TextStream & str, bool add_quotes = true, const FT & field_type = morm::FT::default_type) { if( out_stream && db_expression ) { model_env.use_escaping_for_like = true; db_expression->stream_to_stream(*out_stream, str, field_type, add_quotes, &model_env); model_env.use_escaping_for_like = false; } return *this; } Finder & esc_like(const pt::WTextStream & str, bool add_quotes = true, const FT & field_type = morm::FT::default_type) { if( out_stream && db_expression ) { model_env.use_escaping_for_like = true; db_expression->stream_to_stream(*out_stream, str, field_type, add_quotes, &model_env); model_env.use_escaping_for_like = false; } return *this; } /* * 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; cursor.set_model_data(model_data); cursor.set_has_autogenerated_select(model_env.has_autogenerated_select); cursor.use_table_prefix(use_table_prefix_for_fetching); cursor.set_select_flags(model_env.select_flags); cursor.set_cursor_name(cursor_name); cursor.set_scroll_cursor(scroll_cursor); if( model_env.select_flags.is_with_rows_counter() ) { if( model_env.rows_counter_column_name.empty() ) { generate_rows_counter_column_name(model_env); } cursor.set_rows_counter_column_name(model_env.rows_counter_column_name); } if( model_connector && out_stream ) { cursor.set_model_connector(model_connector); DbConnector * db_connector = model_connector->get_db_connector(); if( db_connector ) { QueryResult * query_result = db_connector->create_query_result(); cursor.set_query_result(query_result); query_result->references_count = 1; if( cursor_name.empty() ) { bool status = db_connector->query_select(*out_stream, *query_result); cursor.set_last_query_status(status); } else { bool status = db_connector->query_declare_cursor(*out_stream, *query_result); cursor.set_last_query_status(status); } } } if( !cursor_name.empty() ) cursor_name.clear(); return cursor; } bool get(ModelClass & result) { Cursor cursor = get_cursor(); bool status = cursor.get(result); model_env.rows_counter = cursor.get_rows_counter(); return status; } ModelClass get() { ModelClass model; get(model); return model; } bool get_list(std::list & result, bool clear_list = true) { Cursor cursor = get_cursor(); bool status = cursor.get_list(result, clear_list); model_env.rows_counter = cursor.get_rows_counter(); return status; } std::list get_list() { std::list result; get_list(result, false); return result; } bool get_vector(std::vector & result, bool clear_vector = true) { Cursor cursor = get_cursor(); bool status = cursor.get_vector(result, clear_vector); model_env.rows_counter = cursor.get_rows_counter(); return status; } std::vector get_vector() { std::vector result; get_vector(result, false); return result; } size_t get_rows_counter() { return model_env.rows_counter; } protected: virtual void start_new_select(const Select & select_flags = Select::default_type) { was_query_error = false; last_query_error.clear(); use_table_prefix_for_fetching = false; set_db_expression(); if( model_connector ) { if( out_stream ) { out_stream->clear(); } else { was_query_error = true; last_query_error = L"out stream object is required"; } } else { was_query_error = true; last_query_error = L"model connector object is required"; } model.set_connector(model_connector); finder_helper.clear(); model_env.clear(); model_env.select_flags = select_flags; model_env.has_autogenerated_select = false; model_env.model_data = model_data; model_env.finder_helper = &finder_helper; model_env.model = &model; if( rows_counter_name ) model_env.rows_counter_column_name = rows_counter_name; model.model_env = &model_env; model.table(); model.model_env->add_table_name_to_finder_helper(); } virtual void generate_standard_select(const Select & select_flags) { if( model_connector && out_stream && db_expression && model.model_env ) { model.model_env->has_autogenerated_select = true; (*out_stream) << "SELECT "; if( select_flags.is_distinct() ) { (*out_stream) << "DISTINCT "; } model.generate_select_columns(*out_stream); (*out_stream) << " FROM "; if( !model.model_env->schema_name.empty() ) { db_expression->schema_table_to_stream(*out_stream, model.model_env->schema_name, model.model_env->table_name); } else { db_expression->table_to_stream(*out_stream, model.model_env->table_name); } (*out_stream) << " AS "; db_expression->table_to_stream(*out_stream, model.model_env->table_name); if( !finder_helper.join_tables_str.empty() ) { (*out_stream) << " "; (*out_stream) << finder_helper.join_tables_str; } } } virtual void set_out_stream() { if( model_connector ) { this->out_stream = model_connector->get_stream(); } else { this->out_stream = nullptr; } } virtual void generate_rows_counter_column_name(ModelEnv & model_env, pt::TextStream & str) { if( model_env.has_autogenerated_select ) { /* * if the column name is empty put a short string which will not allocate dynamic memory * (special optimisation in std::string - a short static buffer) * * we need a non empty string for field(...) method to work correctly * (if the column name was empty then the field(...) would skip the column) * (we need the field(...) to correctly advance cursor_helper->current_column) */ str << L"morm"; } else { if( model_connector ) { DbConnector * db_connector = model_connector->get_db_connector(); if( db_connector ) { DbExpression * db_expression = db_connector->get_expression(); if( db_expression ) { db_expression->generate_rows_counter_column_name(model_env, str); } } } } } virtual void generate_rows_counter_column_name(ModelEnv & model_env) { pt::TextStream str; generate_rows_counter_column_name(model_env, str); str.to_str(model_env.rows_counter_column_name); } private: pt::TextStream * out_stream; ModelConnector * model_connector; DbExpression * db_expression; ModelClass model; bool was_query_error; std::wstring last_query_error; ModelEnv model_env; FinderHelper finder_helper; ModelData * model_data; bool use_table_prefix_for_fetching; const wchar_t * rows_counter_name; pt::TextStream cursor_name; bool scroll_cursor; void initialize() { out_stream = nullptr; model_connector = nullptr; db_expression = nullptr; was_query_error = false; model_data = nullptr; use_table_prefix_for_fetching = false; rows_counter_name = nullptr; scroll_cursor = false; } void set_db_expression() { if( model_connector ) { DbConnector * db_connector = model_connector->get_db_connector(); if( db_connector ) { db_expression = db_connector->get_expression(); if( db_expression ) { db_expression->clear(); db_expression->allow_to_use_prefix(true); } } } } template void field_to_stream(const wchar_t * table_name, int table_index, const wchar_t * field_name, const FieldValue & field_value) { if( db_expression ) { model_env.table2_name = table_name; model_env.table2_index = table_index; db_expression->field_to_stream(*out_stream, field_name, field_value, FT::default_type, &model_env); model_env.table2_name = nullptr; model_env.table2_index = 0; } } template void field_in(const wchar_t * table_name, int table_index, const wchar_t * field_name, const Container & container) { if( db_expression ) { model_env.table2_name = table_name; model_env.table2_index = table_index; db_expression->field_in(*out_stream, field_name, container, &model_env); model_env.table2_name = nullptr; model_env.table2_index = 0; } } template Finder & raw_generic(const FieldValue * sql, bool add_spaces = true) { if( out_stream ) { if( add_spaces ) (*out_stream) << ' '; (*out_stream) << sql; if( add_spaces ) (*out_stream) << ' '; } return *this; } template Finder & raw_generic(const FieldValue & sql, bool add_spaces = true) { if( out_stream ) { if( add_spaces ) (*out_stream) << ' '; (*out_stream) << sql; if( add_spaces ) (*out_stream) << ' '; } return *this; } }; } // namespace #endif