/* * This file is a part of morm * and is distributed under the 2-Clause BSD licence. * Author: Tomasz Sowa */ /* * Copyright (c) 2018-2022, 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. * */ #include "dbexpression.h" #include "model.h" namespace morm { DbExpression::DbExpression() { output_type = 0; } DbExpression::~DbExpression() { } void DbExpression::set_output_type(int output_type) { this->output_type = output_type; } int DbExpression::get_output_type() { return output_type; } bool DbExpression::can_field_be_generated(const FT & field_type) { if( output_type == MORM_OUTPUT_TYPE_DB_INSERT ) { return field_type.is_insertable(); } else if( output_type == MORM_OUTPUT_TYPE_DB_UPDATE ) { return field_type.is_updatable(); } else if( output_type == MORM_OUTPUT_TYPE_DB_PRIMARY_KEY || output_type == MORM_OUTPUT_TYPE_JOIN_TABLES || output_type == MORM_OUTPUT_TYPE_DB_INSERT_PRIMARY_KEY || output_type == MORM_OUTPUT_TYPE_DB_UPDATE_PRIMARY_KEY ) { return field_type.is_primary_key(); } else { return true; } } void DbExpression::field_before() { BaseExpression::field_before(); if( !is_first_field ) { if( output_type == MORM_OUTPUT_TYPE_DB_INSERT || output_type == MORM_OUTPUT_TYPE_DB_UPDATE || output_type == MORM_OUTPUT_TYPE_SELECT_COLUMNS ) { (*out_stream) << ", "; } else if( output_type == MORM_OUTPUT_TYPE_DB_PRIMARY_KEY ) { (*out_stream) << " AND "; } else if( output_type == MORM_OUTPUT_TYPE_DB_INSERT_PRIMARY_KEY || output_type == MORM_OUTPUT_TYPE_DB_UPDATE_PRIMARY_KEY ) { (*out_stream) << ", "; } else if( output_type == MORM_OUTPUT_TYPE_WHERE_EQ || output_type == MORM_OUTPUT_TYPE_WHERE_GE || output_type == MORM_OUTPUT_TYPE_WHERE_GT || output_type == MORM_OUTPUT_TYPE_WHERE_LE || output_type == MORM_OUTPUT_TYPE_WHERE_LT || output_type == MORM_OUTPUT_TYPE_WHERE_NOT_EQ || output_type == MORM_OUTPUT_TYPE_WHERE_IN ) { int conjunction = MORM_CONJUNCTION_AND; if( !conjunctions.empty() ) { conjunction = conjunctions.back(); } if( conjunction == MORM_CONJUNCTION_AND ) { (*out_stream) << " AND "; } else if( conjunction == MORM_CONJUNCTION_OR ) { (*out_stream) << " OR "; } } } } void DbExpression::put_name_value_separator() { if( output_type == MORM_OUTPUT_TYPE_DB_PRIMARY_KEY || output_type == MORM_OUTPUT_TYPE_WHERE_EQ || output_type == MORM_OUTPUT_TYPE_DB_UPDATE || output_type == MORM_OUTPUT_TYPE_DB_INSERT_PRIMARY_KEY || output_type == MORM_OUTPUT_TYPE_DB_UPDATE_PRIMARY_KEY ) { (*out_stream) << "="; } else if( output_type == MORM_OUTPUT_TYPE_WHERE_NOT_EQ ) { (*out_stream) << "<>"; } else if( output_type == MORM_OUTPUT_TYPE_WHERE_LT ) { (*out_stream) << "<"; } else if( output_type == MORM_OUTPUT_TYPE_WHERE_GT ) { (*out_stream) << ">"; } else if( output_type == MORM_OUTPUT_TYPE_WHERE_LE ) { (*out_stream) << "<="; } else if( output_type == MORM_OUTPUT_TYPE_WHERE_GE ) { (*out_stream) << ">="; } else if( output_type == MORM_OUTPUT_TYPE_WHERE_IN ) { (*out_stream) << " in "; } } void DbExpression::schema_table_separator() { (*out_stream) << '.'; } void DbExpression::table_field_separator() { (*out_stream) << '.'; } void DbExpression::before_schema_name() { (*out_stream) << '"'; } void DbExpression::after_schema_name() { (*out_stream) << '"'; } void DbExpression::before_table_name() { (*out_stream) << '"'; } void DbExpression::after_table_name() { (*out_stream) << '"'; } void DbExpression::before_field_name() { (*out_stream) << '"'; } void DbExpression::after_field_name() { (*out_stream) << '"'; } void DbExpression::before_field_value_string(const FT & field_type) { (*out_stream) << "'"; } void DbExpression::after_field_value_string(const FT & field_type) { (*out_stream) << "'"; } void DbExpression::prepare_to_where_clause() { work_mode = MORM_WORK_MODE_MODEL_FIELDS_VALUES; conjunctions.clear(); is_first_field = true; } DbExpression & DbExpression::group_or(pt::TextStream & stream) { out_stream = &stream; field_before(); (*out_stream) << "("; is_first_field = true; conjunctions.push_back(MORM_CONJUNCTION_OR); out_stream = nullptr; return *this; } DbExpression & DbExpression::group_and(pt::TextStream & stream) { out_stream = &stream; field_before(); (*out_stream) << "("; is_first_field = true; conjunctions.push_back(MORM_CONJUNCTION_AND); out_stream = nullptr; return *this; } DbExpression & DbExpression::group_end(pt::TextStream & stream) { out_stream = &stream; if( !conjunctions.empty() ) { conjunctions.pop_back(); (*out_stream) << ")"; field_after(); } out_stream = nullptr; return *this; } DbExpression & DbExpression::page(pt::TextStream & stream, size_t page_number, size_t page_size) { stream << " LIMIT " << (page_number*page_size) << "," << page_size << " "; return *this; } void DbExpression::generate_rows_counter_column_name(ModelEnv & model_env, pt::TextStream & str) { str << model_env.table_name; if( model_env.table_index > 1 ) { str << model_env.table_index; } str << DbExpression::COLUMN_ROWS_COUNTER_POSTFIX; } void DbExpression::add_additional_columns(Model & model) { if( model.model_env ) { if( model.model_env->select_flags.is_with_rows_counter() ) { add_rows_counter_column(model); } } } void DbExpression::add_rows_counter_column(Model & model) { if( out_stream && model.model_env ) { field_before(); (*out_stream) << "COUNT(*) OVER() AS "; pt::TextStream str; generate_rows_counter_column_name(*model.model_env, str); if( !model.model_env->has_autogenerated_select ) { str.to_str(model.model_env->rows_counter_column_name); } before_field_name(); esc(str, *out_stream); after_field_name(); field_after(); } } }