From d84ca900c3e3ff5f27815bc53edfa57b556c0b72 Mon Sep 17 00:00:00 2001 From: Tomasz Sowa Date: Fri, 23 Mar 2018 19:26:57 +0000 Subject: [PATCH] reorganizing class hierarchy git-svn-id: svn://ttmath.org/publicrep/morm/trunk@1075 e52654a7-88a9-db11-a3e9-0013d4bc506e --- src/Makefile.dep | 162 ++-- src/Makefile.o.dep | 2 +- src/baseexpression.cpp | 293 ++++++++ src/{expression.h => baseexpression.h} | 181 ++--- src/dbconnector.cpp | 184 +++++ src/dbconnector.h | 81 ++ src/dbexpression.cpp | 147 ++++ src/dbexpression.h | 120 +++ src/expression.cpp | 359 --------- src/{jsonescaper.cpp => flatconnector.cpp} | 73 +- src/flatconnector.h | 71 ++ src/{dbinterface.h => flatexpression.cpp} | 17 +- src/{jsonescaper.h => flatexpression.h} | 12 +- ...ostgresqlescaper.cpp => jsonconnector.cpp} | 22 +- src/{postgresqlescaper.h => jsonconnector.h} | 16 +- src/jsonexpression.cpp | 147 ++++ src/{baseescaper.cpp => jsonexpression.h} | 65 +- src/model.cpp | 39 +- src/model.h | 13 +- src/modelconnector.cpp | 230 ++---- src/modelconnector.h | 62 +- src/morm.h | 6 +- src/morm_types.h | 4 +- src/postgresqlconnector.cpp | 699 ++++++++++++++++++ src/postgresqlconnector.h | 111 +++ src/postgresqlexpression.cpp | 106 +++ src/{baseescaper.h => postgresqlexpression.h} | 32 +- 27 files changed, 2380 insertions(+), 874 deletions(-) create mode 100644 src/baseexpression.cpp rename src/{expression.h => baseexpression.h} (64%) create mode 100644 src/dbconnector.cpp create mode 100644 src/dbconnector.h create mode 100644 src/dbexpression.cpp create mode 100644 src/dbexpression.h delete mode 100644 src/expression.cpp rename src/{jsonescaper.cpp => flatconnector.cpp} (60%) create mode 100644 src/flatconnector.h rename src/{dbinterface.h => flatexpression.cpp} (92%) rename src/{jsonescaper.h => flatexpression.h} (88%) rename src/{postgresqlescaper.cpp => jsonconnector.cpp} (83%) rename src/{postgresqlescaper.h => jsonconnector.h} (88%) create mode 100644 src/jsonexpression.cpp rename src/{baseescaper.cpp => jsonexpression.h} (63%) create mode 100644 src/postgresqlconnector.cpp create mode 100644 src/postgresqlconnector.h create mode 100644 src/postgresqlexpression.cpp rename src/{baseescaper.h => postgresqlexpression.h} (74%) diff --git a/src/Makefile.dep b/src/Makefile.dep index 20a79a0..eff50e4 100644 --- a/src/Makefile.dep +++ b/src/Makefile.dep @@ -1,44 +1,98 @@ # DO NOT DELETE -baseescaper.o: baseescaper.h ../../pikotools/textstream/textstream.h -baseescaper.o: ../../pikotools/space/space.h -baseescaper.o: ../../pikotools/textstream/types.h ../../pikotools/date/date.h -baseescaper.o: ../../pikotools/convert/convert.h -baseescaper.o: ../../pikotools/convert/inttostr.h -baseescaper.o: ../../pikotools/convert/strtoint.h -baseescaper.o: ../../pikotools/convert/text.h ../../pikotools/convert/misc.h -baseescaper.o: ../../pikotools/membuffer/membuffer.h -baseescaper.o: ../../pikotools/textstream/types.h ../../pikotools/utf8/utf8.h -expression.o: expression.h ../../pikotools/textstream/textstream.h -expression.o: ../../pikotools/space/space.h -expression.o: ../../pikotools/textstream/types.h ../../pikotools/date/date.h -expression.o: ../../pikotools/convert/convert.h -expression.o: ../../pikotools/convert/inttostr.h -expression.o: ../../pikotools/convert/strtoint.h -expression.o: ../../pikotools/convert/text.h ../../pikotools/convert/misc.h -expression.o: ../../pikotools/membuffer/membuffer.h -expression.o: ../../pikotools/textstream/types.h morm_types.h baseescaper.h -expression.o: model.h modelconnector.h +baseexpression.o: baseexpression.h ../../pikotools/textstream/textstream.h +baseexpression.o: ../../pikotools/space/space.h +baseexpression.o: ../../pikotools/textstream/types.h +baseexpression.o: ../../pikotools/date/date.h +baseexpression.o: ../../pikotools/convert/convert.h +baseexpression.o: ../../pikotools/convert/inttostr.h +baseexpression.o: ../../pikotools/convert/strtoint.h +baseexpression.o: ../../pikotools/convert/text.h +baseexpression.o: ../../pikotools/convert/misc.h +baseexpression.o: ../../pikotools/membuffer/membuffer.h +baseexpression.o: ../../pikotools/textstream/types.h morm_types.h model.h +baseexpression.o: modelconnector.h ../../pikotools/utf8/utf8.h +dbconnector.o: dbconnector.h dbexpression.h baseexpression.h +dbconnector.o: ../../pikotools/textstream/textstream.h +dbconnector.o: ../../pikotools/space/space.h +dbconnector.o: ../../pikotools/textstream/types.h ../../pikotools/date/date.h +dbconnector.o: ../../pikotools/convert/convert.h +dbconnector.o: ../../pikotools/convert/inttostr.h +dbconnector.o: ../../pikotools/convert/strtoint.h +dbconnector.o: ../../pikotools/convert/text.h ../../pikotools/convert/misc.h +dbconnector.o: ../../pikotools/membuffer/membuffer.h +dbconnector.o: ../../pikotools/textstream/types.h morm_types.h model.h +dbconnector.o: modelconnector.h +dbexpression.o: dbexpression.h baseexpression.h +dbexpression.o: ../../pikotools/textstream/textstream.h +dbexpression.o: ../../pikotools/space/space.h +dbexpression.o: ../../pikotools/textstream/types.h +dbexpression.o: ../../pikotools/date/date.h ../../pikotools/convert/convert.h +dbexpression.o: ../../pikotools/convert/inttostr.h +dbexpression.o: ../../pikotools/convert/strtoint.h +dbexpression.o: ../../pikotools/convert/text.h ../../pikotools/convert/misc.h +dbexpression.o: ../../pikotools/membuffer/membuffer.h +dbexpression.o: ../../pikotools/textstream/types.h morm_types.h finder.o: finder.h -jsonescaper.o: jsonescaper.h baseescaper.h -jsonescaper.o: ../../pikotools/textstream/textstream.h -jsonescaper.o: ../../pikotools/space/space.h -jsonescaper.o: ../../pikotools/textstream/types.h ../../pikotools/date/date.h -jsonescaper.o: ../../pikotools/convert/convert.h -jsonescaper.o: ../../pikotools/convert/inttostr.h -jsonescaper.o: ../../pikotools/convert/strtoint.h -jsonescaper.o: ../../pikotools/convert/text.h ../../pikotools/convert/misc.h -jsonescaper.o: ../../pikotools/membuffer/membuffer.h -jsonescaper.o: ../../pikotools/textstream/types.h +flatconnector.o: flatconnector.h flatexpression.h baseexpression.h +flatconnector.o: ../../pikotools/textstream/textstream.h +flatconnector.o: ../../pikotools/space/space.h +flatconnector.o: ../../pikotools/textstream/types.h +flatconnector.o: ../../pikotools/date/date.h +flatconnector.o: ../../pikotools/convert/convert.h +flatconnector.o: ../../pikotools/convert/inttostr.h +flatconnector.o: ../../pikotools/convert/strtoint.h +flatconnector.o: ../../pikotools/convert/text.h +flatconnector.o: ../../pikotools/convert/misc.h +flatconnector.o: ../../pikotools/membuffer/membuffer.h +flatconnector.o: ../../pikotools/textstream/types.h morm_types.h model.h +flatconnector.o: modelconnector.h +flatexpression.o: flatexpression.h baseexpression.h +flatexpression.o: ../../pikotools/textstream/textstream.h +flatexpression.o: ../../pikotools/space/space.h +flatexpression.o: ../../pikotools/textstream/types.h +flatexpression.o: ../../pikotools/date/date.h +flatexpression.o: ../../pikotools/convert/convert.h +flatexpression.o: ../../pikotools/convert/inttostr.h +flatexpression.o: ../../pikotools/convert/strtoint.h +flatexpression.o: ../../pikotools/convert/text.h +flatexpression.o: ../../pikotools/convert/misc.h +flatexpression.o: ../../pikotools/membuffer/membuffer.h +flatexpression.o: ../../pikotools/textstream/types.h morm_types.h +jsonconnector.o: jsonconnector.h flatconnector.h flatexpression.h +jsonconnector.o: baseexpression.h ../../pikotools/textstream/textstream.h +jsonconnector.o: ../../pikotools/space/space.h +jsonconnector.o: ../../pikotools/textstream/types.h +jsonconnector.o: ../../pikotools/date/date.h +jsonconnector.o: ../../pikotools/convert/convert.h +jsonconnector.o: ../../pikotools/convert/inttostr.h +jsonconnector.o: ../../pikotools/convert/strtoint.h +jsonconnector.o: ../../pikotools/convert/text.h +jsonconnector.o: ../../pikotools/convert/misc.h +jsonconnector.o: ../../pikotools/membuffer/membuffer.h +jsonconnector.o: ../../pikotools/textstream/types.h morm_types.h +jsonconnector.o: jsonexpression.h +jsonexpression.o: jsonexpression.h flatexpression.h baseexpression.h +jsonexpression.o: ../../pikotools/textstream/textstream.h +jsonexpression.o: ../../pikotools/space/space.h +jsonexpression.o: ../../pikotools/textstream/types.h +jsonexpression.o: ../../pikotools/date/date.h +jsonexpression.o: ../../pikotools/convert/convert.h +jsonexpression.o: ../../pikotools/convert/inttostr.h +jsonexpression.o: ../../pikotools/convert/strtoint.h +jsonexpression.o: ../../pikotools/convert/text.h +jsonexpression.o: ../../pikotools/convert/misc.h +jsonexpression.o: ../../pikotools/membuffer/membuffer.h +jsonexpression.o: ../../pikotools/textstream/types.h morm_types.h model.o: model.h ../../pikotools/textstream/textstream.h model.o: ../../pikotools/space/space.h ../../pikotools/textstream/types.h model.o: ../../pikotools/date/date.h ../../pikotools/convert/convert.h model.o: ../../pikotools/convert/inttostr.h model.o: ../../pikotools/convert/strtoint.h ../../pikotools/convert/text.h model.o: ../../pikotools/convert/misc.h ../../pikotools/membuffer/membuffer.h -model.o: ../../pikotools/textstream/types.h modelconnector.h expression.h -model.o: morm_types.h baseescaper.h -modelconnector.o: modelconnector.h expression.h +model.o: ../../pikotools/textstream/types.h modelconnector.h baseexpression.h +model.o: morm_types.h +modelconnector.o: modelconnector.h baseexpression.h modelconnector.o: ../../pikotools/textstream/textstream.h modelconnector.o: ../../pikotools/space/space.h modelconnector.o: ../../pikotools/textstream/types.h @@ -49,17 +103,33 @@ modelconnector.o: ../../pikotools/convert/strtoint.h modelconnector.o: ../../pikotools/convert/text.h modelconnector.o: ../../pikotools/convert/misc.h modelconnector.o: ../../pikotools/membuffer/membuffer.h -modelconnector.o: ../../pikotools/textstream/types.h morm_types.h -modelconnector.o: baseescaper.h model.h jsonescaper.h postgresqlescaper.h -postgresqlescaper.o: postgresqlescaper.h baseescaper.h -postgresqlescaper.o: ../../pikotools/textstream/textstream.h -postgresqlescaper.o: ../../pikotools/space/space.h -postgresqlescaper.o: ../../pikotools/textstream/types.h -postgresqlescaper.o: ../../pikotools/date/date.h -postgresqlescaper.o: ../../pikotools/convert/convert.h -postgresqlescaper.o: ../../pikotools/convert/inttostr.h -postgresqlescaper.o: ../../pikotools/convert/strtoint.h -postgresqlescaper.o: ../../pikotools/convert/text.h -postgresqlescaper.o: ../../pikotools/convert/misc.h -postgresqlescaper.o: ../../pikotools/membuffer/membuffer.h -postgresqlescaper.o: ../../pikotools/textstream/types.h +modelconnector.o: ../../pikotools/textstream/types.h morm_types.h model.h +modelconnector.o: flatconnector.h flatexpression.h dbconnector.h +modelconnector.o: dbexpression.h +postgresqlconnector.o: postgresqlconnector.h dbconnector.h dbexpression.h +postgresqlconnector.o: baseexpression.h +postgresqlconnector.o: ../../pikotools/textstream/textstream.h +postgresqlconnector.o: ../../pikotools/space/space.h +postgresqlconnector.o: ../../pikotools/textstream/types.h +postgresqlconnector.o: ../../pikotools/date/date.h +postgresqlconnector.o: ../../pikotools/convert/convert.h +postgresqlconnector.o: ../../pikotools/convert/inttostr.h +postgresqlconnector.o: ../../pikotools/convert/strtoint.h +postgresqlconnector.o: ../../pikotools/convert/text.h +postgresqlconnector.o: ../../pikotools/convert/misc.h +postgresqlconnector.o: ../../pikotools/membuffer/membuffer.h +postgresqlconnector.o: ../../pikotools/textstream/types.h morm_types.h +postgresqlconnector.o: ../../pikotools/utf8/utf8.h postgresqlexpression.h +postgresqlexpression.o: postgresqlexpression.h dbexpression.h +postgresqlexpression.o: baseexpression.h +postgresqlexpression.o: ../../pikotools/textstream/textstream.h +postgresqlexpression.o: ../../pikotools/space/space.h +postgresqlexpression.o: ../../pikotools/textstream/types.h +postgresqlexpression.o: ../../pikotools/date/date.h +postgresqlexpression.o: ../../pikotools/convert/convert.h +postgresqlexpression.o: ../../pikotools/convert/inttostr.h +postgresqlexpression.o: ../../pikotools/convert/strtoint.h +postgresqlexpression.o: ../../pikotools/convert/text.h +postgresqlexpression.o: ../../pikotools/convert/misc.h +postgresqlexpression.o: ../../pikotools/membuffer/membuffer.h +postgresqlexpression.o: ../../pikotools/textstream/types.h morm_types.h diff --git a/src/Makefile.o.dep b/src/Makefile.o.dep index 0802eff..9bea281 100644 --- a/src/Makefile.o.dep +++ b/src/Makefile.o.dep @@ -1 +1 @@ -o = baseescaper.o expression.o finder.o jsonescaper.o model.o modelconnector.o postgresqlescaper.o \ No newline at end of file +o = baseexpression.o dbconnector.o dbexpression.o finder.o flatconnector.o flatexpression.o jsonconnector.o jsonexpression.o model.o modelconnector.o postgresqlconnector.o postgresqlexpression.o \ No newline at end of file diff --git a/src/baseexpression.cpp b/src/baseexpression.cpp new file mode 100644 index 0000000..1428b79 --- /dev/null +++ b/src/baseexpression.cpp @@ -0,0 +1,293 @@ +/* + * This file is a part of morm + * and is distributed under the 2-Clause BSD licence. + * Author: Tomasz Sowa + */ + +/* + * Copyright (c) 2018, 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 "baseexpression.h" +#include "morm_types.h" +#include "model.h" +#include "utf8/utf8.h" + + +namespace morm +{ + + +BaseExpression::BaseExpression() +{ + out_stream = nullptr; + is_first_field = false; + work_mode = 0; +} + +BaseExpression::~BaseExpression() +{ +} + + +void BaseExpression::set_work_mode(int work_mode) +{ + this->work_mode = work_mode; +} + + +void BaseExpression::generate_from_model(PT::TextStream & stream, Model & model) +{ + this->out_stream = &stream; + + before_generate_from_model(); + model.map_fields(); + after_generate_from_model(); +} + + +void BaseExpression::before_generate_from_model() +{ + is_first_field = true; +} + + +void BaseExpression::after_generate_from_model() +{ +} + + +bool BaseExpression::can_field_be_generated(bool insertable, bool updatable, bool is_primary_key) +{ + return true; +} + + +void BaseExpression::field_before() +{ + if( !is_first_field ) + { + // put a separator between fields + } +} + + +void BaseExpression::field_after() +{ + is_first_field = false; +} + + +void BaseExpression::put_field_name(const wchar_t * field_name) +{ + before_field_name(); + esc(field_name, *out_stream); + after_field_name(); +} + + +void BaseExpression::before_field_name() +{ +} + + +void BaseExpression::after_field_name() +{ +} + + +void BaseExpression::before_field_value(const std::wstring &) +{ +} + + +void BaseExpression::before_field_value(const std::string &) +{ +} + + +void BaseExpression::after_field_value(const std::wstring &) +{ +} + + +void BaseExpression::after_field_value(const std::string &) +{ +} + + +void BaseExpression::put_name_value_separator() +{ + (*out_stream) << ','; +} + + +void BaseExpression::esc(char val, PT::TextStream & stream) +{ + stream << val; +} + + +void BaseExpression::esc(unsigned char val, PT::TextStream & stream) +{ + esc(static_cast(val), stream); +} + + +void BaseExpression::esc(const std::wstring & val, PT::TextStream & stream) +{ + char utf8_buf[10]; + + for(size_t i = 0 ; i < val.size() ; ++i) + { + size_t utf8_len = PT::IntToUTF8((int)val[i], utf8_buf, sizeof(utf8_buf)); + + for(size_t a = 0 ; a < utf8_len ; ++a) + { + esc(utf8_buf[a], stream); + } + } +} + + +void BaseExpression::esc(const wchar_t * val, PT::TextStream & stream) +{ + char utf8_buf[10]; + + for(size_t i = 0 ; val[i] != 0 ; ++i) + { + size_t utf8_len = PT::IntToUTF8((int)val[i], utf8_buf, sizeof(utf8_buf)); + + for(size_t a = 0 ; a < utf8_len ; ++a) + { + esc(utf8_buf[a], stream); + } + } +} + + +void BaseExpression::esc(const std::string & val, PT::TextStream & stream) +{ + for(size_t i = 0 ; i < val.size() ; ++i) + { + esc(val[i], stream); + } +} + + +void BaseExpression::esc(const char * val, PT::TextStream & stream) +{ + for(size_t i = 0 ; val[i] != 0 ; ++i) + { + esc(val[i], stream); + } +} + + +void BaseExpression::esc(bool val, PT::TextStream & stream) +{ + stream << val; +} + + +void BaseExpression::esc(short val, PT::TextStream & stream) +{ + stream << val; +} + + +void BaseExpression::esc(unsigned short val, PT::TextStream & stream) +{ + stream << val; +} + + +void BaseExpression::esc(int val, PT::TextStream & stream) +{ + stream << val; +} + + +void BaseExpression::esc(unsigned int val, PT::TextStream & stream) +{ + stream << val; +} + + +void BaseExpression::esc(long val, PT::TextStream & stream) +{ + stream << val; +} + + +void BaseExpression::esc(unsigned long val, PT::TextStream & stream) +{ + stream << val; +} + + +void BaseExpression::esc(long long val, PT::TextStream & stream) +{ + // not implemented in PT::TextStream yet + //stream << val; +} + + +void BaseExpression::esc(unsigned long long val, PT::TextStream & stream) +{ + //stream << val; +} + + +void BaseExpression::esc(float val, PT::TextStream & stream) +{ + stream << val; +} + + +void BaseExpression::esc(double val, PT::TextStream & stream) +{ + stream << val; +} + + +void BaseExpression::esc(long double val, PT::TextStream & stream) +{ + //stream << val; +} + + +void BaseExpression::esc(void* val, PT::TextStream & stream) +{ + stream << val; +} + + + + +} + diff --git a/src/expression.h b/src/baseexpression.h similarity index 64% rename from src/expression.h rename to src/baseexpression.h index 4a2838f..c60c984 100644 --- a/src/expression.h +++ b/src/baseexpression.h @@ -32,13 +32,12 @@ * */ -#ifndef headerfile_morm_expression -#define headerfile_morm_expression +#ifndef headerfile_morm_baseexpression +#define headerfile_morm_baseexpression + #include "textstream/textstream.h" #include "morm_types.h" -#include "baseescaper.h" - namespace morm @@ -47,81 +46,29 @@ class Model; class ModelConnector; -class Expression +class BaseExpression { public: - Expression(); - virtual ~Expression(); - - virtual void set_json_escaper(BaseEscaper & json_escaper); - virtual void set_db_escaper(BaseEscaper & db_escaper); - - virtual void to_json(PT::TextStream & stream, Model & model); - virtual void insert(PT::TextStream & stream, Model & model, int db_type); - virtual void update(PT::TextStream & stream, Model & model, int db_type); + BaseExpression(); + virtual ~BaseExpression(); - Expression & eq(const wchar_t * field_name, const std::wstring & field_value) - { - //put_field_name(field_name); - return *this; - } - - Expression & eq(const wchar_t * field_name, const std::string & field_value) - { - - return *this; - } - - template - Expression & eq(const wchar_t * field_name, const FieldValue & field_value) - { - - return *this; - } - - /* - * - * - * - * - * - */ + virtual void set_work_mode(int work_mode); + virtual void generate_from_model(PT::TextStream & stream, Model & model); protected: - int work_mode; /* what to do: generating fields list, values list or fields-values list */ - int output_type; /* what the output string is: for json, for database */ - int db_type; /* what type of database we are using if generating a string for a database */ - bool is_first_field; // niech Stream bedzie jakims interfejsem z operatorami << dla standardowych typow + // albo w pikotoolsach dodać klase bazowa (intefejs) dla streamow + // i dodatkowo dodac loger ktory dziedziczy po niej i dodaje loglevel i endline + // jako metode bazowa dodac format("string", parametry,...) + // przyda sie do formatowania doubli PT::TextStream * out_stream; - Model * model; - - BaseEscaper * json_escaper; - BaseEscaper * db_escaper; - - -/* -ostream& operator<< (bool val); -ostream& operator<< (short val); -ostream& operator<< (unsigned short val); -ostream& operator<< (int val); -ostream& operator<< (unsigned int val); -ostream& operator<< (long val); -ostream& operator<< (unsigned long val); -ostream& operator<< (long long val); -ostream& operator<< (unsigned long long val); -ostream& operator<< (float val); -ostream& operator<< (double val); -ostream& operator<< (long double val); -ostream& operator<< (void* val); -*/ // virtual void map_fields(Model * model) // { @@ -133,8 +80,6 @@ ostream& operator<< (void* val); // generate_from_model(); // } - - virtual void generate_from_model(); virtual void before_generate_from_model(); virtual void after_generate_from_model(); virtual bool can_field_be_generated(bool insertable, bool updatable, bool is_primary_key); @@ -175,7 +120,7 @@ ostream& operator<< (void* val); void put_field_value(const FieldValue & field_value) { before_field_value(field_value); - field_value_raw(field_value); + esc(field_value, *out_stream); after_field_value(field_value); } @@ -183,9 +128,6 @@ ostream& operator<< (void* val); virtual void before_field_name(); virtual void after_field_name(); - virtual void before_field_value_string(); - virtual void after_field_value_string(); - virtual void before_field_value(const std::wstring &); virtual void after_field_value(const std::wstring &); @@ -202,27 +144,48 @@ ostream& operator<< (void* val); { } - virtual void field_name_raw(const wchar_t * field_name); - virtual void field_value_raw(const std::wstring & field_value); - virtual void field_value_raw(long field_value); + virtual void put_name_value_separator(); + + + + /* + template + void field_container(const wchar_t * field_name, Container container, bool insertable = true, bool updatable = true) + { + typename Container::value Value; // czy tu jest Container::value? sprawdzic + + if( !is_first_field ) + (*out_stream) << ","; + + if( work_mode == ORM_STREAM_MODE_CREATING_JSON ) + { + (*out_stream) << "["; + boolean is_first = true; + + for(Value v : container) + { + if( !is_first ) + (*out_stream) << ","; + + v.map_fields(this); + is_first = false; + } + + (*out_stream) << "]"; + } + // a co z bazą danych? + + + is_first_field = false; + } + */ - virtual void field_value_raw(int field_value); template void print_field_name_value(const wchar_t * field_name, const FieldValue & field_value) { put_field_name(field_name); - - if( output_type == MORM_OUTPUT_TYPE_JSON ) - { - (*out_stream) << ":"; - } - else - if( output_type == MORM_OUTPUT_TYPE_DB_PRIMARY_KEY ) - { - (*out_stream) << " = "; - } - + put_name_value_separator(); put_field_value(field_value); } @@ -260,36 +223,32 @@ ostream& operator<< (void* val); */ - template - void esc(const Field & val, PT::TextStream & stream) - { - if( output_type == MORM_OUTPUT_TYPE_JSON ) - { - if( json_escaper ) - { - json_escaper->esc(val, stream); - } - } - else - if( output_type == MORM_OUTPUT_TYPE_DB_INSERT || - output_type == MORM_OUTPUT_TYPE_DB_UPDATE || - output_type == MORM_OUTPUT_TYPE_DB_PRIMARY_KEY ) - { - if( db_escaper ) - { - db_escaper->esc(val, stream); - } - } - } + virtual void esc(char val, PT::TextStream & stream); + virtual void esc(unsigned char val, PT::TextStream & stream); + virtual void esc(const std::wstring & val, PT::TextStream & stream); + virtual void esc(const wchar_t * val, PT::TextStream & stream); + virtual void esc(const std::string & val, PT::TextStream & stream); + virtual void esc(const char * val, PT::TextStream & stream); + + virtual void esc(bool val, PT::TextStream & stream); + virtual void esc(short val, PT::TextStream & stream); + virtual void esc(unsigned short val, PT::TextStream & stream); + virtual void esc(int val, PT::TextStream & stream); + virtual void esc(unsigned int val, PT::TextStream & stream); + virtual void esc(long val, PT::TextStream & stream); + virtual void esc(unsigned long val, PT::TextStream & stream); + virtual void esc(long long val, PT::TextStream & stream); + virtual void esc(unsigned long long val, PT::TextStream & stream); + virtual void esc(float val, PT::TextStream & stream); + virtual void esc(double val, PT::TextStream & stream); + virtual void esc(long double val, PT::TextStream & stream); + virtual void esc(void* val, PT::TextStream & stream); friend ModelConnector; }; - - - -} // namespace +} #endif diff --git a/src/dbconnector.cpp b/src/dbconnector.cpp new file mode 100644 index 0000000..a55e036 --- /dev/null +++ b/src/dbconnector.cpp @@ -0,0 +1,184 @@ +/* + * This file is a part of morm + * and is distributed under the 2-Clause BSD licence. + * Author: Tomasz Sowa + */ + +/* + * Copyright (c) 2018, 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 "dbconnector.h" +#include "model.h" + + +namespace morm +{ + +DbConnector::DbConnector() +{ + db_expression = nullptr; + expression_allocated = false; +} + + +DbConnector::~DbConnector() +{ + deallocate_expression(); +} + + + +bool DbConnector::query(PT::TextStream & stream) +{ + return false; +} + + +bool DbConnector::query(const std::wstring & query) +{ + return false; +} + + +bool DbConnector::query(const std::string & query) +{ + return false; +} + + +bool DbConnector::query(const wchar_t * query) +{ + return false; +} + + +bool DbConnector::query(const char * query) +{ + // do query + return false; +} + + + + +DbExpression * DbConnector::get_expression() +{ + allocate_default_expression_if_needed(); + return db_expression; +} + + + +void DbConnector::generate_insert_query(PT::TextStream & stream, Model & model) +{ + allocate_default_expression_if_needed(); + + if( db_expression ) + { + db_expression->set_output_type(MORM_OUTPUT_TYPE_DB_UPDATE); + + stream << "insert into "; + model.table_name(stream); + stream << " ("; + db_expression->set_work_mode(MORM_WORK_MODE_MODEL_FIELDS); + db_expression->generate_from_model(stream, model); + + stream << ") values ("; + db_expression->set_work_mode(MORM_WORK_MODE_MODEL_VALUES); + db_expression->generate_from_model(stream, model); + stream << ")"; + } +} + + +void DbConnector::generate_update_query(PT::TextStream & stream, Model & model) +{ + allocate_default_expression_if_needed(); + + if( db_expression ) + { + db_expression->set_output_type(MORM_OUTPUT_TYPE_DB_UPDATE); + + stream << "update "; + model.table_name(stream); + stream << " set ("; + db_expression->set_work_mode(MORM_WORK_MODE_MODEL_FIELDS); + db_expression->generate_from_model(stream, model); + + stream << ") values ("; + db_expression->set_work_mode(MORM_WORK_MODE_MODEL_VALUES); + db_expression->generate_from_model(stream, model); + + stream << ") where "; + db_expression->set_work_mode(MORM_WORK_MODE_MODEL_FIELDS_VALUES); + db_expression->set_output_type(MORM_OUTPUT_TYPE_DB_PRIMARY_KEY); + db_expression->generate_from_model(stream, model); + } +} + + + +void DbConnector::insert(PT::TextStream & stream, Model & model) +{ + generate_insert_query(stream, model); + // do the real inserting + // query(stream); + // and get autogenerated columns +} + + +void DbConnector::update(PT::TextStream & stream, Model & model) +{ + generate_update_query(stream, model); + // do the real updating + // query(stream); + // and get autogenerated columns +} + + +void DbConnector::deallocate_expression() +{ + if( expression_allocated ) + { + delete db_expression; + db_expression = nullptr; + expression_allocated = false; + } +} + + + +void DbConnector::allocate_default_expression_if_needed() +{ + if( !db_expression ) + { + allocate_default_expression(); + } +} + +} diff --git a/src/dbconnector.h b/src/dbconnector.h new file mode 100644 index 0000000..1255974 --- /dev/null +++ b/src/dbconnector.h @@ -0,0 +1,81 @@ +/* + * This file is a part of morm + * and is distributed under the 2-Clause BSD licence. + * Author: Tomasz Sowa + */ + +/* + * Copyright (c) 2018, 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_dbconnector +#define headerfile_morm_dbconnector + +#include "dbexpression.h" +#include "textstream/textstream.h" + + +namespace morm +{ +class Model; + + +class DbConnector +{ + +public: + + DbConnector(); + virtual ~DbConnector(); + + DbExpression * get_expression(); + virtual void generate_insert_query(PT::TextStream & stream, Model & model); + virtual void generate_update_query(PT::TextStream & stream, Model & model); + + virtual void insert(PT::TextStream & stream, Model & model); + virtual void update(PT::TextStream & stream, Model & model); + + virtual bool query(PT::TextStream & stream); + virtual bool query(const std::wstring & query); + virtual bool query(const std::string & query); + virtual bool query(const wchar_t * query); + virtual bool query(const char * query); + +protected: + + DbExpression * db_expression; + bool expression_allocated; + + virtual void allocate_default_expression() = 0; + virtual void allocate_default_expression_if_needed(); + virtual void deallocate_expression(); + +}; + +} + +#endif diff --git a/src/dbexpression.cpp b/src/dbexpression.cpp new file mode 100644 index 0000000..d65672a --- /dev/null +++ b/src/dbexpression.cpp @@ -0,0 +1,147 @@ +/* + * This file is a part of morm + * and is distributed under the 2-Clause BSD licence. + * Author: Tomasz Sowa + */ + +/* + * Copyright (c) 2018, 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" + + +namespace morm +{ + + +DbExpression::DbExpression() +{ + output_type = 0; +} + + +DbExpression::~DbExpression() +{ +} + + +void DbExpression::set_output_type(int output_type) +{ + this->output_type = output_type; +} + + +bool DbExpression::can_field_be_generated(bool insertable, bool updatable, bool is_primary_key) +{ + if( output_type == MORM_OUTPUT_TYPE_DB_INSERT ) + { + return insertable; + } + else + if( output_type == MORM_OUTPUT_TYPE_DB_UPDATE ) + { + return updatable; + } + else + if( output_type == MORM_OUTPUT_TYPE_DB_PRIMARY_KEY ) + { + return 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 ) + { + (*out_stream) << ","; + } + else + if( output_type == MORM_OUTPUT_TYPE_DB_PRIMARY_KEY ) + { + (*out_stream) << " AND "; + } + } +} + + +void DbExpression::before_field_value_string() +{ + if( output_type == MORM_OUTPUT_TYPE_DB_INSERT || + output_type == MORM_OUTPUT_TYPE_DB_UPDATE || + output_type == MORM_OUTPUT_TYPE_DB_PRIMARY_KEY ) + { + (*out_stream) << "'"; + } +} + +void DbExpression::after_field_value_string() +{ + if( output_type == MORM_OUTPUT_TYPE_DB_INSERT || + output_type == MORM_OUTPUT_TYPE_DB_UPDATE || + output_type == MORM_OUTPUT_TYPE_DB_PRIMARY_KEY ) + { + (*out_stream) << "'"; + } +} + + +void DbExpression::before_field_value(const std::wstring &) +{ + before_field_value_string(); +} + +void DbExpression::before_field_value(const std::string &) +{ + before_field_value_string(); +} + +void DbExpression::after_field_value(const std::wstring &) +{ + after_field_value_string(); +} + +void DbExpression::after_field_value(const std::string &) +{ + after_field_value_string(); +} + + + + +} diff --git a/src/dbexpression.h b/src/dbexpression.h new file mode 100644 index 0000000..3114b1e --- /dev/null +++ b/src/dbexpression.h @@ -0,0 +1,120 @@ +/* + * This file is a part of morm + * and is distributed under the 2-Clause BSD licence. + * Author: Tomasz Sowa + */ + +/* + * Copyright (c) 2018, 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_dbexpression +#define headerfile_morm_dbexpression + +#include "baseexpression.h" +#include "morm_types.h" + + +namespace morm +{ + +class DbExpression : public BaseExpression +{ +public: + + DbExpression(); + virtual ~DbExpression(); + + virtual void set_output_type(int output_type); + + + +protected: + + int output_type; + + + + bool can_field_be_generated(bool insertable, bool updatable, bool is_primary_key); + + void field_before(); + void before_field_value(const std::wstring &); + void before_field_value(const std::string &); + void after_field_value(const std::wstring &); + void after_field_value(const std::string &); + + + + template + void print_field_name_value(const wchar_t * field_name, const FieldValue & field_value) + { + put_field_name(field_name); + + if( output_type == MORM_OUTPUT_TYPE_DB_PRIMARY_KEY ) + { + (*out_stream) << " = "; + } + + put_field_value(field_value); + } + + +private: + + void before_field_value_string(); + void after_field_value_string(); + + + + + +// DbExpression & eq(const wchar_t * field_name, const std::wstring & field_value) +// { +// //put_field_name(field_name); +// return *this; +// } +// +// DbExpression & eq(const wchar_t * field_name, const std::string & field_value) +// { +// +// return *this; +// } +// +// template +// DbExpression & eq(const wchar_t * field_name, const FieldValue & field_value) +// { +// return *this; +// } + + + + +}; + +} + +#endif diff --git a/src/expression.cpp b/src/expression.cpp deleted file mode 100644 index be97014..0000000 --- a/src/expression.cpp +++ /dev/null @@ -1,359 +0,0 @@ -/* - * This file is a part of morm - * and is distributed under the 2-Clause BSD licence. - * Author: Tomasz Sowa - */ - -/* - * Copyright (c) 2018, 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 "expression.h" -#include "model.h" - - -namespace morm -{ - -Expression::Expression() -{ - out_stream = nullptr; - model = nullptr; - json_escaper = nullptr; - db_escaper = nullptr; -} - -Expression::~Expression() -{ -} - -void Expression::set_json_escaper(BaseEscaper & json_escaper) -{ - this->json_escaper = &json_escaper; -} - -void Expression::set_db_escaper(BaseEscaper & db_escaper) -{ - this->db_escaper = &db_escaper; -} - - - -void Expression::generate_from_model() -{ - before_generate_from_model(); - model->map_fields(); - after_generate_from_model(); -} - - -void Expression::before_generate_from_model() -{ - is_first_field = true; - - if( work_mode == MORM_WORK_MODE_MODEL_FIELDS_VALUES ) - { - if( output_type == MORM_OUTPUT_TYPE_JSON ) - { - (*out_stream) << "{"; - } - } -} - - -void Expression::after_generate_from_model() -{ - if( work_mode == MORM_WORK_MODE_MODEL_FIELDS_VALUES ) - { - if( output_type == MORM_OUTPUT_TYPE_JSON ) - { - (*out_stream) << "}"; - } - } -} - - -bool Expression::can_field_be_generated(bool insertable, bool updatable, bool is_primary_key) -{ - if( output_type == MORM_OUTPUT_TYPE_DB_INSERT ) - { - return insertable; - } - else - if( output_type == MORM_OUTPUT_TYPE_DB_UPDATE ) - { - return updatable; - } - else - if( output_type == MORM_OUTPUT_TYPE_DB_PRIMARY_KEY ) - { - return is_primary_key; - } - else - { - return true; - } -} - - -void Expression::field_before() -{ - if( !is_first_field ) - { - if( output_type == MORM_OUTPUT_TYPE_JSON ) - { - (*out_stream) << ","; - } - else - if( output_type == MORM_OUTPUT_TYPE_DB_INSERT || - output_type == MORM_OUTPUT_TYPE_DB_UPDATE ) - { - (*out_stream) << ","; - } - else - if( output_type == MORM_OUTPUT_TYPE_DB_PRIMARY_KEY ) - { - (*out_stream) << " AND "; - } - } -} - - -void Expression::field_after() -{ - is_first_field = false; -} - - - -//void Expression::field(const wchar_t * field_name, Model & field, bool insertable = true, bool updatable = true) -//{ -// // IMPLEMENT ME -//} - -void Expression::put_field_name(const wchar_t * field_name) -{ - before_field_name(); - field_name_raw(field_name); - after_field_name(); -} - - -void Expression::before_field_name() -{ - if( output_type == MORM_OUTPUT_TYPE_JSON ) - { - (*out_stream) << "\""; - } -} - - -void Expression::after_field_name() -{ - if( output_type == MORM_OUTPUT_TYPE_JSON ) - { - (*out_stream) << "\""; - } -} - - -void Expression::before_field_value_string() -{ - if( output_type == MORM_OUTPUT_TYPE_JSON ) - { - (*out_stream) << "\""; - } - else - if( output_type == MORM_OUTPUT_TYPE_DB_INSERT || - output_type == MORM_OUTPUT_TYPE_DB_UPDATE || - output_type == MORM_OUTPUT_TYPE_DB_PRIMARY_KEY ) - { - if( db_type == MORM_DB_TYPE_POSTGRESQL ) - { - (*out_stream) << "E'"; - } - } -} - -void Expression::after_field_value_string() -{ - if( output_type == MORM_OUTPUT_TYPE_JSON ) - { - (*out_stream) << "\""; - } - else - if( output_type == MORM_OUTPUT_TYPE_DB_INSERT || - output_type == MORM_OUTPUT_TYPE_DB_UPDATE || - output_type == MORM_OUTPUT_TYPE_DB_PRIMARY_KEY ) - { - if( db_type == MORM_DB_TYPE_POSTGRESQL ) - { - (*out_stream) << "'"; - } - } -} - -void Expression::before_field_value(const std::wstring &) -{ - before_field_value_string(); -} - -void Expression::before_field_value(const std::string &) -{ - before_field_value_string(); -} - -void Expression::after_field_value(const std::wstring &) -{ - after_field_value_string(); -} - -void Expression::after_field_value(const std::string &) -{ - after_field_value_string(); -} - - -void Expression::field_name_raw(const wchar_t * field_name) -{ - // IMPROVE ME - // provide esc_field and esc_value methods - esc(field_name, *out_stream); -} - - -void Expression::field_value_raw(const std::wstring & field_value) -{ - // IMPROVE ME - // provide esc_field and esc_value methods - esc(field_value, *out_stream); -} - -void Expression::field_value_raw(long field_value) -{ - // may it should be moved to escaper? - (*out_stream) << field_value; -} - -void Expression::field_value_raw(int field_value) -{ - // may it should be moved to escaper? - (*out_stream) << field_value; -} - - -void Expression::to_json(PT::TextStream & stream, Model & model) -{ - work_mode = MORM_WORK_MODE_MODEL_FIELDS_VALUES; - output_type = MORM_OUTPUT_TYPE_JSON; - out_stream = &stream; - this->model = &model; - - generate_from_model(); -} - - -void Expression::insert(PT::TextStream & stream, Model & model, int db_type) -{ - out_stream = &stream; - output_type = MORM_OUTPUT_TYPE_DB_INSERT; - this->db_type = db_type; - this->model = &model; - - stream << "insert into "; - this->model->table_name(stream); - stream << " ("; - work_mode = MORM_WORK_MODE_MODEL_FIELDS; - generate_from_model(); - stream << ") values ("; - work_mode = MORM_WORK_MODE_MODEL_VALUES; - generate_from_model(); - stream << ")"; -} - - - - -void Expression::update(PT::TextStream & stream, Model & model, int db_type) -{ - out_stream = &stream; - this->db_type = db_type; - this->model = &model; - - stream << "update "; - this->model->table_name(stream); - stream << " set ("; - work_mode = MORM_WORK_MODE_MODEL_FIELDS; - output_type = MORM_OUTPUT_TYPE_DB_UPDATE; - generate_from_model(); - stream << ") values ("; - work_mode = MORM_WORK_MODE_MODEL_VALUES; - output_type = MORM_OUTPUT_TYPE_DB_UPDATE; - generate_from_model(); - stream << ") where "; - work_mode = MORM_WORK_MODE_MODEL_FIELDS_VALUES; - output_type = MORM_OUTPUT_TYPE_DB_PRIMARY_KEY; - generate_from_model(); -} - - -/* -template -void field_container(const wchar_t * field_name, Container container, bool insertable = true, bool updatable = true) -{ - typename Container::value Value; // czy tu jest Container::value? sprawdzic - - if( !is_first_field ) - (*out_stream) << ","; - - if( work_mode == ORM_STREAM_MODE_CREATING_JSON ) - { - (*out_stream) << "["; - boolean is_first = true; - - for(Value v : container) - { - if( !is_first ) - (*out_stream) << ","; - - v.map_fields(this); - is_first = false; - } - - (*out_stream) << "]"; - } - // a co z bazą danych? - - - is_first_field = false; -} -*/ - - - -} // namespace - diff --git a/src/jsonescaper.cpp b/src/flatconnector.cpp similarity index 60% rename from src/jsonescaper.cpp rename to src/flatconnector.cpp index 9c0652a..75b4f92 100644 --- a/src/jsonescaper.cpp +++ b/src/flatconnector.cpp @@ -32,27 +32,71 @@ * */ -#include "jsonescaper.h" - +#include "flatconnector.h" +#include "morm_types.h" +#include "model.h" namespace morm { -void JSONEscaper::esc(char val, PT::TextStream & stream) +FlatConnector::FlatConnector() { - switch( val ) + flat_expression = nullptr; + expression_allocated = false; +} + + +FlatConnector::~FlatConnector() +{ + deallocate_expression(); +} + + +void FlatConnector::set_expression(FlatExpression & expression) +{ + flat_expression = &expression; +} + + +FlatExpression * FlatConnector::get_expression() +{ + allocate_default_expression_if_needed(); + return flat_expression; +} + + + +void FlatConnector::to_text(PT::TextStream & stream, Model & model) +{ + allocate_default_expression_if_needed(); + + if( flat_expression ) { - case 0: stream << '\\'; stream << '0'; break; // may to skip this character is better? - case '\r': stream << '\\'; stream << 'r'; break; - case '\n': stream << '\\'; stream << 'n'; break; - case '\t': stream << '\\'; stream << 't'; break; - case 0x08: stream << '\\'; stream << 'b'; break; - case 0x0c: stream << '\\'; stream << 'f'; break; - case '\\': stream << '\\'; stream << '\\'; break; - case '"': stream << '\\'; stream << '\"'; break; - default: - stream << val; + flat_expression->set_work_mode(MORM_WORK_MODE_MODEL_FIELDS_VALUES); + flat_expression->generate_from_model(stream, model); + } +} + + + +void FlatConnector::deallocate_expression() +{ + if( expression_allocated ) + { + delete flat_expression; + flat_expression = nullptr; + expression_allocated = false; + } +} + + + +void FlatConnector::allocate_default_expression_if_needed() +{ + if( !flat_expression ) + { + allocate_default_expression(); } } @@ -60,4 +104,3 @@ void JSONEscaper::esc(char val, PT::TextStream & stream) } - diff --git a/src/flatconnector.h b/src/flatconnector.h new file mode 100644 index 0000000..a4ab8b1 --- /dev/null +++ b/src/flatconnector.h @@ -0,0 +1,71 @@ +/* + * This file is a part of morm + * and is distributed under the 2-Clause BSD licence. + * Author: Tomasz Sowa + */ + +/* + * Copyright (c) 2018, 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_flatconnector +#define headerfile_morm_flatconnector + +#include "flatexpression.h" +#include "textstream/textstream.h" + + +namespace morm +{ +class Model; + + +class FlatConnector +{ +public: + + FlatConnector(); + virtual ~FlatConnector(); + + virtual void to_text(PT::TextStream & stream, Model & model); + virtual void set_expression(FlatExpression & expression); + virtual FlatExpression * get_expression(); + +protected: + + FlatExpression * flat_expression; + bool expression_allocated; + + virtual void allocate_default_expression() = 0; + virtual void allocate_default_expression_if_needed(); + virtual void deallocate_expression(); + +}; + +} + +#endif diff --git a/src/dbinterface.h b/src/flatexpression.cpp similarity index 92% rename from src/dbinterface.h rename to src/flatexpression.cpp index d30a60c..8785c04 100644 --- a/src/dbinterface.h +++ b/src/flatexpression.cpp @@ -32,26 +32,13 @@ * */ -#ifndef headerfile_morm_dbinterface -#define headerfile_morm_dbinterface - -#include - +#include "flatexpression.h" +#include "morm_types.h" namespace morm { -class DbInterface -{ - - - - -}; - } - -#endif diff --git a/src/jsonescaper.h b/src/flatexpression.h similarity index 88% rename from src/jsonescaper.h rename to src/flatexpression.h index fbe8ad1..5374f6f 100644 --- a/src/jsonescaper.h +++ b/src/flatexpression.h @@ -32,27 +32,23 @@ * */ -#ifndef headerfile_morm_jsonescaper -#define headerfile_morm_jsonescaper - -#include "baseescaper.h" +#ifndef headerfile_morm_flatexpression +#define headerfile_morm_flatexpression +#include "baseexpression.h" namespace morm { -class JSONEscaper : public BaseEscaper +class FlatExpression : public BaseExpression { -public: - void esc(char val, PT::TextStream & stream); }; - } #endif diff --git a/src/postgresqlescaper.cpp b/src/jsonconnector.cpp similarity index 83% rename from src/postgresqlescaper.cpp rename to src/jsonconnector.cpp index 5b344c5..d1fede2 100644 --- a/src/postgresqlescaper.cpp +++ b/src/jsonconnector.cpp @@ -32,25 +32,21 @@ * */ -#include "postgresqlescaper.h" +#include "jsonconnector.h" +#include "jsonexpression.h" namespace morm { -void PostgreSQLEscaper::esc(char val, PT::TextStream & stream) +void JSONConnector::allocate_default_expression() { - switch( val ) - { - case '\\': stream << "\\\\"; break; - case '\'': stream << "\\\'"; break; // don't use "''" because we use the method for PQconnectdb too - default: - if( val != 0 ) - { - stream << val; - } - } -} + deallocate_expression(); + flat_expression = new JSONExpression(); + expression_allocated = true; } + + +} diff --git a/src/postgresqlescaper.h b/src/jsonconnector.h similarity index 88% rename from src/postgresqlescaper.h rename to src/jsonconnector.h index eaff473..116efc4 100644 --- a/src/postgresqlescaper.h +++ b/src/jsonconnector.h @@ -32,27 +32,29 @@ * */ -#ifndef headerfile_morm_postgresqlescaper -#define headerfile_morm_postgresqlescaper - -#include "baseescaper.h" +#ifndef headerfile_morm_jsonconnector +#define headerfile_morm_jsonconnector +#include "flatconnector.h" namespace morm { -class PostgreSQLEscaper : public BaseEscaper +class JSONConnector : public FlatConnector { + public: - void esc(char val, PT::TextStream & stream); +protected: + + + void allocate_default_expression(); }; - } #endif diff --git a/src/jsonexpression.cpp b/src/jsonexpression.cpp new file mode 100644 index 0000000..c4344a8 --- /dev/null +++ b/src/jsonexpression.cpp @@ -0,0 +1,147 @@ +/* + * This file is a part of morm + * and is distributed under the 2-Clause BSD licence. + * Author: Tomasz Sowa + */ + +/* + * Copyright (c) 2018, 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 "jsonexpression.h" +#include "morm_types.h" + + + +namespace morm +{ + + +void JSONExpression::before_generate_from_model() +{ + BaseExpression::before_generate_from_model(); + + if( work_mode == MORM_WORK_MODE_MODEL_FIELDS_VALUES ) + { + (*out_stream) << "{"; + } +} + + +void JSONExpression::after_generate_from_model() +{ + BaseExpression::after_generate_from_model(); + + if( work_mode == MORM_WORK_MODE_MODEL_FIELDS_VALUES ) + { + (*out_stream) << "}"; + } +} + + + +void JSONExpression::field_before() +{ + BaseExpression::field_before(); + + if( !is_first_field ) + { + (*out_stream) << ","; + } +} + + + +void JSONExpression::before_field_name() +{ + (*out_stream) << "\""; +} + + +void JSONExpression::after_field_name() +{ + (*out_stream) << "\""; +} + + +void JSONExpression::before_field_value_string() +{ + (*out_stream) << "\""; +} + +void JSONExpression::after_field_value_string() +{ + (*out_stream) << "\""; +} + + +void JSONExpression::before_field_value(const std::wstring &) +{ + before_field_value_string(); +} + +void JSONExpression::before_field_value(const std::string &) +{ + before_field_value_string(); +} + +void JSONExpression::after_field_value(const std::wstring &) +{ + after_field_value_string(); +} + +void JSONExpression::after_field_value(const std::string &) +{ + after_field_value_string(); +} + + +void JSONExpression::put_name_value_separator() +{ + (*out_stream) << ':'; +} + + +void JSONExpression::esc(char val, PT::TextStream & stream) +{ + switch( val ) + { + case 0: stream << '\\'; stream << '0'; break; // may to skip this character is better? + case '\r': stream << '\\'; stream << 'r'; break; + case '\n': stream << '\\'; stream << 'n'; break; + case '\t': stream << '\\'; stream << 't'; break; + case 0x08: stream << '\\'; stream << 'b'; break; + case 0x0c: stream << '\\'; stream << 'f'; break; + case '\\': stream << '\\'; stream << '\\'; break; + case '"': stream << '\\'; stream << '\"'; break; + default: + stream << val; + } +} + + +} diff --git a/src/baseescaper.cpp b/src/jsonexpression.h similarity index 63% rename from src/baseescaper.cpp rename to src/jsonexpression.h index 81398ac..892c29e 100644 --- a/src/baseescaper.cpp +++ b/src/jsonexpression.h @@ -32,60 +32,55 @@ * */ +#ifndef headerfile_morm_jsonexpression +#define headerfile_morm_jsonexpression + +#include "flatexpression.h" -#include "baseescaper.h" -#include "utf8/utf8.h" namespace morm { -BaseEscaper::~BaseEscaper() +class JSONExpression : public FlatExpression { -} + +protected: + + void before_generate_from_model(); + void after_generate_from_model(); -void BaseEscaper::esc(const std::wstring & val, PT::TextStream & stream) -{ - char utf8_buf[10]; - for(size_t i = 0 ; i < val.size() ; ++i) + void field_before(); + void before_field_name(); + void after_field_name(); + void before_field_value(const std::wstring &); + void before_field_value(const std::string &); + void after_field_value(const std::wstring &); + void after_field_value(const std::string &); + void put_name_value_separator(); + + template + void print_field_name_value(const wchar_t * field_name, const FieldValue & field_value) { - size_t utf8_len = PT::IntToUTF8((int)val[i], utf8_buf, sizeof(utf8_buf)); - - for(size_t a = 0 ; a < utf8_len ; ++a) - { - esc(utf8_buf[a], stream); - } + put_field_name(field_name); + (*out_stream) << ":"; + put_field_value(field_value); } -} -void BaseEscaper::esc(const wchar_t * val, PT::TextStream & stream) -{ - char utf8_buf[10]; - for(size_t i = 0 ; val[i] != 0 ; ++i) - { - size_t utf8_len = PT::IntToUTF8((int)val[i], utf8_buf, sizeof(utf8_buf)); - - for(size_t a = 0 ; a < utf8_len ; ++a) - { - esc(utf8_buf[a], stream); - } - } -} + void esc(char val, PT::TextStream & stream); -void BaseEscaper::esc(const std::string & val, PT::TextStream & stream) -{ - for(size_t i = 0 ; i < val.size() ; ++i) - { - esc(val[i], stream); - } -} +private: + void before_field_value_string(); + void after_field_value_string(); +}; } +#endif diff --git a/src/model.cpp b/src/model.cpp index 5dbdcd7..e7fb53f 100644 --- a/src/model.cpp +++ b/src/model.cpp @@ -58,49 +58,46 @@ void Model::set_connector(ModelConnector & connector) } -void Model::to_json(PT::TextStream & stream) +void Model::to_text(PT::TextStream & stream) { if( model_connector ) { - model_connector->to_json(stream, *this); + model_connector->to_text(stream, *this); } } -void Model::to_json(std::string & str) +void Model::to_text(std::string & str) { PT::TextStream stream; - to_json(stream); + to_text(stream); stream.to_string(str); } -std::string Model::to_json() +std::string Model::to_text() { std::string str; - to_json(str); + to_text(str); return str; } +std::string Model::to_string() +{ + return to_text(); +} -void Model::insert(PT::TextStream & stream, int orm_db_type) +void Model::generate_insert_query(PT::TextStream & stream) { if( model_connector ) { - model_connector->insert(stream, *this, orm_db_type); + model_connector->generate_insert_query(stream, *this); } } -void Model::insert(PT::TextStream & stream) -{ - if( model_connector ) - { - model_connector->insert(stream, *this); - } -} void Model::insert() { @@ -110,21 +107,15 @@ void Model::insert() } } -void Model::update(PT::TextStream & stream, int orm_db_type) + +void Model::generate_update_query(PT::TextStream & stream) { if( model_connector ) { - model_connector->update(stream, *this, orm_db_type); + model_connector->generate_update_query(stream, *this); } } -void Model::update(PT::TextStream & stream) -{ - if( model_connector ) - { - model_connector->update(stream, *this); - } -} void Model::update() { diff --git a/src/model.h b/src/model.h index fb55564..f2e5f8e 100644 --- a/src/model.h +++ b/src/model.h @@ -70,16 +70,15 @@ public: virtual void table_name(PT::TextStream & stream); - virtual void to_json(PT::TextStream & stream); - virtual void to_json(std::string & str); - virtual std::string to_json(); + virtual void to_text(PT::TextStream & stream); + virtual void to_text(std::string & str); + virtual std::string to_text(); + virtual std::string to_string(); - virtual void insert(PT::TextStream & stream, int orm_db_type); - virtual void insert(PT::TextStream & stream); + virtual void generate_insert_query(PT::TextStream & stream); virtual void insert(); - virtual void update(PT::TextStream & stream, int orm_db_type); - virtual void update(PT::TextStream & stream); + virtual void generate_update_query(PT::TextStream & stream); virtual void update(); diff --git a/src/modelconnector.cpp b/src/modelconnector.cpp index 779b11b..3d14fde 100644 --- a/src/modelconnector.cpp +++ b/src/modelconnector.cpp @@ -34,8 +34,8 @@ #include "modelconnector.h" #include "model.h" -#include "jsonescaper.h" -#include "postgresqlescaper.h" +#include "flatconnector.h" +#include "dbconnector.h" namespace morm @@ -43,42 +43,17 @@ namespace morm ModelConnector::ModelConnector() { - expression = nullptr; + flat_connector = nullptr; + db_connector = nullptr; + expression_callback = nullptr; + out_stream = nullptr; - json_escaper = nullptr; - postgresql_escaper = nullptr; - - expression_allocated = false; out_stream_allocated = false; - json_escaper_allocated = false; - postgresql_escaper_allocated = false; - - assigned_db_type = MORM_DB_TYPE_POSTGRESQL; } ModelConnector::~ModelConnector() { - deallocate_expression(); deallocate_stream(); - deallocate_json_escaper(); - deallocate_postgresql_escaper(); -} - -void ModelConnector::deallocate_expression() -{ - if( expression_allocated ) - { - delete expression; - expression = nullptr; - expression_allocated = false; - } -} - -void ModelConnector::allocate_default_expression() -{ - deallocate_expression(); - expression = new Expression(); - expression_allocated = true; } @@ -101,94 +76,22 @@ void ModelConnector::allocate_default_stream() } -void ModelConnector::deallocate_json_escaper() -{ - if( json_escaper_allocated ) - { - delete json_escaper; - json_escaper = nullptr; - json_escaper_allocated = false; - } -} - - -void ModelConnector::allocate_default_json_escaper() -{ - deallocate_json_escaper(); - json_escaper = new JSONEscaper(); - json_escaper_allocated = true; -} - - -void ModelConnector::deallocate_postgresql_escaper() -{ - if( postgresql_escaper_allocated ) - { - delete postgresql_escaper; - postgresql_escaper = nullptr; - postgresql_escaper_allocated = false; - } -} - - -void ModelConnector::allocate_default_postgresql_escaper() -{ - deallocate_postgresql_escaper(); - postgresql_escaper = new PostgreSQLEscaper(); - postgresql_escaper_allocated = true; -} - - void ModelConnector::allocate_default_stream_if_needed() { if( !out_stream ) - allocate_default_stream(); -} - -void ModelConnector::allocate_default_expression_if_needed() -{ - if( !expression ) - allocate_default_expression(); -} - -void ModelConnector::allocate_default_json_escaper_if_needed() -{ - if( !json_escaper ) - allocate_default_json_escaper(); -} - -void ModelConnector::allocate_default_postgresql_escaper_if_needed() -{ - if( !postgresql_escaper ) - allocate_default_postgresql_escaper(); -} - -void ModelConnector::allocate_default_db_escaper_if_needed() -{ - if( assigned_db_type == MORM_DB_TYPE_POSTGRESQL ) { - allocate_default_postgresql_escaper_if_needed(); + allocate_default_stream(); } } -void ModelConnector::set_expression(Expression & expression) -{ - deallocate_expression(); - this->expression = &expression; -} - void ModelConnector::set_stream(PT::TextStream & stream) { deallocate_stream(); this->out_stream = &stream; } -Expression * ModelConnector::get_expression() -{ - return expression; -} PT::TextStream * ModelConnector::get_stream() { @@ -197,115 +100,90 @@ PT::TextStream * ModelConnector::get_stream() -void ModelConnector::to_json(PT::TextStream & stream, Model & model) +void ModelConnector::set_flat_connector(FlatConnector & flat_connector) { - allocate_default_expression_if_needed(); - allocate_default_json_escaper_if_needed(); - - expression->set_json_escaper(*json_escaper); - expression->to_json(stream, model); + this->flat_connector = &flat_connector; } -void ModelConnector::insert(PT::TextStream & stream, Model & model, int db_type) +void ModelConnector::set_db_connector(DbConnector & db_connector) { - allocate_default_expression_if_needed(); - allocate_default_db_escaper_if_needed(); // FIX ME what about db_type parameter - - expression->set_db_escaper(*postgresql_escaper); //FIX ME select correct db escaper - expression->insert(stream, model, db_type); + this->db_connector = &db_connector; } -void ModelConnector::update(PT::TextStream & stream, Model & model, int db_type) +void ModelConnector::to_text(PT::TextStream & stream, Model & model) { - allocate_default_expression_if_needed(); - allocate_default_db_escaper_if_needed(); // FIX ME what about db_type parameter + if( flat_connector ) + { + expression_callback = flat_connector->get_expression(); - expression->set_db_escaper(*postgresql_escaper); //FIX ME select correct db escaper - expression->update(stream, model, db_type); -} + if( expression_callback ) + { + flat_connector->to_text(stream, model); + } - -void ModelConnector::insert(PT::TextStream & stream, Model & model) -{ - allocate_default_expression_if_needed(); - allocate_default_db_escaper_if_needed(); - - expression->set_db_escaper(*postgresql_escaper); //FIX ME select correct db escaper - expression->insert(stream, model, assigned_db_type); -} - - -void ModelConnector::update(PT::TextStream & stream, Model & model) -{ - allocate_default_expression_if_needed(); - allocate_default_db_escaper_if_needed(); - - expression->set_db_escaper(*postgresql_escaper); //FIX ME select correct db escaper - expression->update(stream, model, assigned_db_type); + expression_callback = nullptr; + } } -void ModelConnector::to_json(Model & model) +void ModelConnector::generate_insert_query(PT::TextStream & stream, Model & model) { - allocate_default_expression_if_needed(); - allocate_default_stream_if_needed(); - allocate_default_json_escaper_if_needed(); + if( db_connector ) + { + expression_callback = db_connector->get_expression(); - expression->set_json_escaper(*json_escaper); - expression->to_json(*out_stream, model); + if( expression_callback ) + { + db_connector->generate_insert_query(stream, model); + } + + expression_callback = nullptr; + } } -void ModelConnector::insert(Model & model, int db_type) +void ModelConnector::generate_update_query(PT::TextStream & stream, Model & model) { - allocate_default_expression_if_needed(); - allocate_default_stream_if_needed(); - allocate_default_db_escaper_if_needed(); // FIX ME what about db_type parameter? + if( db_connector ) + { + expression_callback = db_connector->get_expression(); - expression->set_db_escaper(*postgresql_escaper); //FIX ME select correct db escaper - expression->insert(*out_stream, model, db_type); + if( expression_callback ) + { + db_connector->generate_update_query(stream, model); + } + + expression_callback = nullptr; + } } -void ModelConnector::update(Model & model, int db_type) -{ - allocate_default_expression_if_needed(); - allocate_default_stream_if_needed(); - allocate_default_db_escaper_if_needed(); // FIX ME what about db_type parameter? - - expression->set_db_escaper(*postgresql_escaper); //FIX ME select correct db escaper - expression->update(*out_stream, model, db_type); -} - - - void ModelConnector::insert(Model & model) { - allocate_default_expression_if_needed(); allocate_default_stream_if_needed(); - allocate_default_db_escaper_if_needed(); - expression->set_db_escaper(*postgresql_escaper); //FIX ME select correct db escaper - expression->insert(*out_stream, model, assigned_db_type); + if( db_connector && out_stream ) + { + out_stream->clear(); + db_connector->insert(*out_stream, model); + } } void ModelConnector::update(Model & model) { - allocate_default_expression_if_needed(); allocate_default_stream_if_needed(); - allocate_default_db_escaper_if_needed(); - expression->set_db_escaper(*postgresql_escaper); //FIX ME select correct db escaper - expression->update(*out_stream, model, assigned_db_type); + if( db_connector && out_stream ) + { + out_stream->clear(); + db_connector->update(*out_stream, model); + } } - - - - } + diff --git a/src/modelconnector.h b/src/modelconnector.h index d88d227..5de34c4 100644 --- a/src/modelconnector.h +++ b/src/modelconnector.h @@ -35,13 +35,14 @@ #ifndef headerfile_morm_modelconnector #define headerfile_morm_modelconnector -#include "expression.h" - +#include "baseexpression.h" namespace morm { class Model; +class FlatConnector; +class DbConnector; class ModelConnector @@ -50,70 +51,49 @@ class ModelConnector public: ModelConnector(); - ~ModelConnector(); + virtual ~ModelConnector(); // FIX ME // add c-copy ctr (allocate a new stream and expression) - void set_expression(Expression & expression); - void set_stream(PT::TextStream & stream); + virtual void set_stream(PT::TextStream & stream); + virtual PT::TextStream * get_stream(); - Expression * get_expression(); - PT::TextStream * get_stream(); + virtual void set_flat_connector(FlatConnector & flat_connector); + virtual void set_db_connector(DbConnector & db_connector); - virtual void to_json(PT::TextStream & stream, Model & model); - virtual void insert(PT::TextStream & stream, Model & model, int db_type); - virtual void update(PT::TextStream & stream, Model & model, int db_type); + virtual void to_text(PT::TextStream & stream, Model & model); - virtual void insert(PT::TextStream & stream, Model & model); - virtual void update(PT::TextStream & stream, Model & model); - - virtual void to_json(Model & model); - virtual void insert(Model & model, int db_type); - virtual void update(Model & model, int db_type); + virtual void generate_insert_query(PT::TextStream & stream, Model & model); + virtual void generate_update_query(PT::TextStream & stream, Model & model); virtual void insert(Model & model); virtual void update(Model & model); + + + protected: - Expression * expression; + FlatConnector * flat_connector; + DbConnector * db_connector; + PT::TextStream * out_stream; // IMPROVE ME give here an interface to the base stream (implement him) - BaseEscaper * json_escaper; - BaseEscaper * postgresql_escaper; - - bool expression_allocated; bool out_stream_allocated; - bool json_escaper_allocated; - bool postgresql_escaper_allocated; - int assigned_db_type; - - void allocate_default_expression(); - void allocate_default_expression_if_needed(); - void deallocate_expression(); + BaseExpression * expression_callback; void allocate_default_stream(); void allocate_default_stream_if_needed(); void deallocate_stream(); - void allocate_default_json_escaper(); - void allocate_default_json_escaper_if_needed(); - void deallocate_json_escaper(); - - void allocate_default_postgresql_escaper(); - void allocate_default_postgresql_escaper_if_needed(); - void deallocate_postgresql_escaper(); - - void allocate_default_db_escaper_if_needed(); - template - void field(const wchar_t * field_name, const FieldValue & field_value, bool insertable, bool updatable, bool is_primary_key) + void field(const wchar_t * field_name, FieldValue & field_value, bool insertable, bool updatable, bool is_primary_key) { - if( expression ) + if( expression_callback ) { - expression->field(field_name, field_value, insertable, updatable, is_primary_key); + expression_callback->field(field_name, field_value, insertable, updatable, is_primary_key); } } diff --git a/src/morm.h b/src/morm.h index b2f9fc6..9f7d7b7 100644 --- a/src/morm.h +++ b/src/morm.h @@ -38,8 +38,12 @@ #include "morm_types.h" #include "model.h" -#include "expression.h" #include "finder.h" +#include "jsonconnector.h" +#include "postgresqlconnector.h" +#include "jsonexpression.h" +#include "postgresqlexpression.h" +#include "modelconnector.h" namespace morm diff --git a/src/morm_types.h b/src/morm_types.h index fa0e1d8..f5b2bb5 100644 --- a/src/morm_types.h +++ b/src/morm_types.h @@ -40,12 +40,12 @@ #define MORM_WORK_MODE_MODEL_VALUES 2 #define MORM_WORK_MODE_MODEL_FIELDS_VALUES 3 -#define MORM_OUTPUT_TYPE_JSON 1 +//#define MORM_OUTPUT_TYPE_JSON 1 #define MORM_OUTPUT_TYPE_DB_INSERT 2 #define MORM_OUTPUT_TYPE_DB_UPDATE 3 #define MORM_OUTPUT_TYPE_DB_PRIMARY_KEY 4 -#define MORM_DB_TYPE_POSTGRESQL 1 +//#define MORM_DB_TYPE_POSTGRESQL 1 namespace morm diff --git a/src/postgresqlconnector.cpp b/src/postgresqlconnector.cpp new file mode 100644 index 0000000..4de7d3e --- /dev/null +++ b/src/postgresqlconnector.cpp @@ -0,0 +1,699 @@ +/* + * This file is a part of morm + * and is distributed under the 2-Clause BSD licence. + * Author: Tomasz Sowa + */ + +/* + * Copyright (c) 2018, 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 "postgresqlconnector.h" +#include "utf8/utf8.h" +#include "postgresqlexpression.h" + + +namespace morm +{ + +PostgreSQLConnector::PostgreSQLConnector() +{ + pg_conn = nullptr; + log_queries = false; + last_status = PGRES_EMPTY_QUERY; + last_result = nullptr; +} + +PostgreSQLConnector::~PostgreSQLConnector() +{ +} + + +void PostgreSQLConnector::allocate_default_expression() +{ + deallocate_expression(); + db_expression = new PostgreSQLExpression(); + expression_allocated = true; +} + + + +void PostgreSQLConnector::set_log_queries(bool log_queries) +{ + this->log_queries = log_queries; +} + + +bool PostgreSQLConnector::query(const char * query_str) +{ +// if( log_queries ) +// log << log1 << "Db: executing query: " << q << logend; + + last_status = PGRES_EMPTY_QUERY; + last_result = PQexec(pg_conn, query_str); + + if( !last_result ) + { + if( PQstatus(pg_conn) != CONNECTION_OK ) + { + //AssertConnection(); + last_result = PQexec(pg_conn, query_str); + } + } + + if( last_result ) + { + last_status = PQresultStatus(last_result); + } + else + { +// log << log1 << "Db: Problem with this query: \"" << q << '\"' << logend; +// log << log1 << "Db: " << PQerrorMessage(db_conn->GetPgConn()) << logend; + } + +return last_result != nullptr; +} + + +bool PostgreSQLConnector::query_select(const char * query_str) +{ + return (query(query_str) && last_status == PGRES_TUPLES_OK); +} + +bool PostgreSQLConnector::query_update(const char * query_str) +{ + return (query(query_str) && last_status == PGRES_COMMAND_OK); +} + +bool PostgreSQLConnector::query_insert(const char * query_str) +{ + return (query(query_str) && last_status == PGRES_COMMAND_OK); +} + + +//Error PostgreSQLConnector::DoCommand(const char * command) +//{ +// PGresult * r = 0; +// Error status = WINIX_ERR_OK; +// +// try +// { +// r = AssertQuery(command); +// AssertResult(r, PGRES_COMMAND_OK); +// } +// catch(const Error & e) +// { +// status = e; +// } +// +// ClearResult(r); +// +//return status; +//} + + + + +bool PostgreSQLConnector::is_last_result(ExecStatusType t) +{ + return (last_result && PQresultStatus(last_result) == t); +} + + + +int PostgreSQLConnector::get_column_index(const char * column_name) +{ + int c = PQfnumber(last_result, column_name); + // returns -1 if there is no such a column + +return c; +} + + + +const char * PostgreSQLConnector::get_value(int row, int col) +{ + const char * res = PQgetvalue(last_result, row, col); + // can return a null pointer if there is no such an item in the last result + +return res; +} + + +bool PostgreSQLConnector::get_value(int row, int col, std::string & result, bool clear_string) +{ + if( clear_string ) + result.clear(); + + const char * raw_result = get_value(row, col); + + if( raw_result ) + { + result += raw_result; + } + + return raw_result != nullptr; +} + + +bool PostgreSQLConnector::get_value(int row, int col, std::wstring & result, bool clear_string) +{ + if( clear_string ) + result.clear(); + + const char * raw_result = get_value(row, col); + + if( raw_result ) + { + PT::UTF8ToWide(raw_result, result); + } + + return raw_result != nullptr; +} + + + +//void PostgreSQLConnector::get_value_bin(int row, int col, std::string & result, bool clear_string) +//{ +// if( clear_string ) +// result.clear(); +// +// const char * raw_result = get_value(row, col); +// +// if( raw_result ) +// { +// int len = PQgetlength(last_result, row, col); +// +// if( len > 0 ) +// { +// unescape_bin(raw_result, len, result); +// } +// } +//} + + + +//long PostgreSQLConnector::AssertValueLong(PGresult * r, int row, int col) +//{ +// return strtol( AssertValue(r, row, col), 0, 10 ); +//} +// +// +//int PostgreSQLConnector::AssertValueInt(PGresult * r, int row, int col) +//{ +// return (int)strtol( AssertValue(r, row, col), 0, 10 ); +//} +// +// +//bool PostgreSQLConnector::AssertValueBool(PGresult * r, int row, int col) +//{ +// const char * s = AssertValue(r, row, col); +// return (s[0]=='t' || s[0]=='y' || s[0]=='1'); +//} +// +// +//unsigned long PostgreSQLConnector::AssertValueULong(PGresult * r, int row, int col) +//{ +// return strtoul( AssertValue(r, row, col), 0, 10 ); +//} +// +// +//unsigned int PostgreSQLConnector::AssertValueUInt(PGresult * r, int row, int col) +//{ +// return (unsigned int)strtoul( AssertValue(r, row, col), 0, 10 ); +//} +// +// +// +//PT::Date PostgreSQLConnector::AssertValueDate(PGresult * r, int row, int col) +//{ +// PT::Date date = AssertValue(r, row, col); +// +//return date; +//} +// +// +//bool PostgreSQLConnector::AssertValueSpace(PGresult * r, int row, int col, PT::Space & space) +//{ +// const char * res = AssertValue(r, row, col); +// +// conf_parser.SetSpace(space); +// space.Clear(); +// +// PT::SpaceParser::Status status = conf_parser.ParseString(res); +// +// if( status != PT::SpaceParser::ok ) +// { +// log << log1 << "Db: a problem with parsing a PT::Space"; +// +// if( status == PT::SpaceParser::syntax_error ) +// log << ", syntax error at line: " << conf_parser.line; +// +// log << logend; +// +// space.Clear(); +// return false; +// } +// +//return true; +//} +// +// + + + +void PostgreSQLConnector::clear_result() +{ + if( last_result ) + { + PQclear(last_result); + last_result = nullptr; + } +} + + +bool PostgreSQLConnector::is_null(int row, int col) +{ + if( last_result ) + { + return PQgetisnull(last_result, row, col) == 1; + } + + return true; +} + + +//int PostgreSQLConnector::Rows(PGresult * r) +//{ +// // PQntuples - Returns the number of rows (tuples) in the query result. Because it returns +// // an integer result, large result sets might overflow the return value on 32-bit operating systems. +// return PQntuples(r); +//} + + +//int PostgreSQLConnector::Cols(PGresult * r) +//{ +// // PQnfields - Returns the number of columns (fields) in each row of the query result. +// return PQnfields(r); +//} + + +//long PostgreSQLConnector::AffectedRows(PGresult * r) +//{ +// // PQcmdTuples - This function returns a string containing the number of rows affected by the SQL +// // statement that generated the PGresult. This function can only be used following the execution +// // of an INSERT, UPDATE, DELETE, MOVE, FETCH, or COPY statement, or [...] +// char * rows_str = PQcmdTuples(r); // can be an empty string +// long rows = 0; +// +// if( rows_str ) +// { +// rows = strtol(rows_str, 0, 10); +// // strtol - If an overflow or underflow occurs, errno is set to ERANGE +// // and the function return value is clamped according to the following table: +// // Function underflow overflow +// // strtol() LONG_MIN LONG_MAX +// +// if( rows < 0 ) +// rows = 0; +// } +// +//return rows; +//} + + +//long PostgreSQLConnector::AssertCurrval(const char * table) +//{ +// PGresult * r; +// +// bquery.Clear(); +// bquery << R("select currval(") +// << table +// << R(");"); +// +// r = AssertQuery(bquery); +// AssertResult(r, PGRES_TUPLES_OK); +// +// if( Rows(r) != 1 ) +// { +// log << log1 << "Db: error (currval) for table: " << table << ", " << PQerrorMessage(db_conn->GetPgConn()) << logend; +// throw Error(WINIX_ERR_DB_ERR_CURRVAL); +// } +// +//return AssertValueLong(r, 0, 0); +//} +// + + + + + + + + +//void PostgreSQLConnector::CreateIdList(const std::vector & id_tab, std::wstring & list, bool add_parentheses) +//{ +//wchar_t buffer[50]; +//size_t buffer_len = sizeof(buffer) / sizeof(wchar_t); +// +// list.clear(); +// +// if( add_parentheses ) +// list += '('; +// +// for(size_t i=0 ; i='0' && c<='7'; +} + +// moves 'i' at least once +// return -1 if there is en error +int PostgreSQLConnector::UnescapeBin(const char * str, size_t & i, size_t len) +{ + if( str[i] != '\\' ) + return str[i++]; + + i += 1; + + if( i >= len ) + return -1; + + if( str[i] == '\\' ) + return str[i++]; + + if( i+2 >= len ) + { + i = len; + return -1; + } + + if( !IsCorrectOctalDigit(str[i]) || + !IsCorrectOctalDigit(str[i+1]) || + !IsCorrectOctalDigit(str[i+2]) ) + { + i += 3; + return -1; + } + + int c = 8*8*CharToInt(str[i]) + 8*CharToInt(str[i+1]) + CharToInt(str[i+2]); + + i += 3; + + if( c<0 || c>255 ) + return -1; + +return c; +} + +void PostgreSQLConnector::UnescapeBin(const char * str, size_t len, std::string & out, bool clear_out) +{ +int c; +size_t i = 0; + + if( clear_out ) + out.clear(); + + while( i < len ) + { + c = UnescapeBin(str, i, len); + + if( c != -1 ) + out += c; + } +} +*/ + + + + + +/* + converting from a bytea + the new way (hex format) +*/ + + +//char PostgreSQLConnector::UnescapeBinHexToDigit(char hex) +//{ +// if( hex>='0' && hex<='9' ) +// return hex - '0'; +// +// if( hex>='a' && hex<='z' ) +// return hex - 'a' + 10; +// +// if( hex>='A' && hex<='Z' ) +// return hex - 'A' + 10; +// +//return 0; +//} +// +// +//void PostgreSQLConnector::UnescapeBin(const char * str, size_t len, std::string & out, bool clear_out) +//{ +// if( clear_out ) +// out.clear(); +// +// if( len < 2 || str[0]!='\\' || str[1]!='x' ) +// { +// log << log1 << "Db: unsupported binary format (skipping)" << logend; +// return; +// } +// +// for(size_t i=2 ; i + 1 < len ; i+=2 ) +// { +// int c1 = UnescapeBinHexToDigit(str[i]); +// int c2 = UnescapeBinHexToDigit(str[i+1]); +// +// out += ((c1 << 4) | c2); +// } +//} + + + +//void PostgreSQLConnector::SetConnParam(const std::wstring & database_name, const std::wstring & user, const std::wstring & pass) +//{ +// db_database = database_name; +// db_user = user; +// db_pass = pass; +//} +// +// +// +//void PostgreSQLConnector::Connect() +//{ +// Close(); +// +// conn_info.Clear(); +// conn_info.SetExtented(false); +// +// conn_info << R("dbname=") << db_database +// << R(" user=") << db_user +// << R(" password=") << db_pass; +// +// pg_conn = PQconnectdb(conn_info.CStr()); +// +// // warning! pg_conn can be not null but there cannnot be a connection established +// // use PQstatus(pg_conn) to check whether the connection works fine +//} +// +// +// +//void PostgreSQLConnector::LogConnectionSocket() +//{ +// log << log2 << "Db: connection to the database works fine" << logend; +// log << log3 << "Db: connection socket: " << PQsocket(pg_conn) << logend; +//} +// +// +// +//void PostgreSQLConnector::WaitForConnection() +//{ +// if( !pg_conn || PQstatus(pg_conn) != CONNECTION_OK ) +// { +// log << log3 << "Db: waiting for the db to be ready...." << logend << logsave; +// +// while( !AssertConnection(false, false) ) +// sleep(5); +// +// LogConnectionSocket(); +// } +//} +// +// +// +//void PostgreSQLConnector::Close() +//{ +// if( pg_conn ) +// { +// PQfinish(pg_conn); +// pg_conn = 0; +// } +//} +// +// +// +//bool PostgreSQLConnector::AssertConnection(bool put_log, bool throw_if_no_connection) +//{ +//bool was_connection = true; +// +// +// if( !pg_conn ) +// { +// was_connection = false; +// Connect(); +// } +// else +// if( PQstatus(pg_conn) != CONNECTION_OK ) +// { +// if( put_log ) +// log << log2 << "Db: connection to the database is lost, trying to recover" << logend; +// +// was_connection = false; +// PQreset(pg_conn); +// } +// +// +// if( pg_conn && PQstatus(pg_conn) == CONNECTION_OK ) +// { +// if( !was_connection ) +// { +// if( put_log ) +// LogConnectionSocket(); +// +// SetDbParameters(); +// } +// +// return true; +// } +// else +// { +// if( put_log ) +// log << log1 << "Db: connection to db server cannot be established" << logend; +// +// if( throw_if_no_connection ) +// throw Error(WINIX_ERR_DB_FATAL_ERROR_DURING_CONNECTING); +// +// return false; +// } +//} +// +// +// +//void PostgreSQLConnector::SetDbParameters() +//{ +// if( PQsetClientEncoding(pg_conn, "UTF8") == -1 ) +// log << log1 << "Db: Can't set the proper client encoding" << logend; +//} + + +} diff --git a/src/postgresqlconnector.h b/src/postgresqlconnector.h new file mode 100644 index 0000000..65734bc --- /dev/null +++ b/src/postgresqlconnector.h @@ -0,0 +1,111 @@ +/* + * This file is a part of morm + * and is distributed under the 2-Clause BSD licence. + * Author: Tomasz Sowa + */ + +/* + * Copyright (c) 2018, 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_postgresqlconnector +#define headerfile_morm_postgresqlconnector + +#include "dbconnector.h" +#include +#include + + + +namespace morm +{ + +class PostgreSQLConnector : public DbConnector +{ +public: + PostgreSQLConnector(); + virtual ~PostgreSQLConnector(); + + void set_log_queries(bool log_queries); + + bool query(const char * query_str); + bool query_select(const char * query_str); + bool query_update(const char * query_str); + bool query_insert(const char * query_str); + + bool is_last_result(ExecStatusType t); + + /* + * get column index from the last query (select) + * returns -1 if there is no such a column + * + */ + int get_column_index(const char * column_name); + + bool is_null(int row, int col); + + /* + * return an item from the last query + * can return a null pointer if there is no such an item in the last result + * + */ + const char * get_value(int row, int col); + + bool get_value(int row, int col, std::string & result, bool clear_string = true); + bool get_value(int row, int col, std::wstring & result, bool clear_string = true); + void get_value_bin(int row, int col, std::string & result, bool clear_string = true); + + void clear_result(); + + //void SetConnParam(const std::wstring & database, const std::wstring & user, const std::wstring & pass); + //void Connect(); + //void WaitForConnection(); + //void Close(); + //bool AssertConnection(bool put_log = true, bool throw_if_no_connection = true); + //void SetDbParameters(); + //PGconn * GetPgConn(); + + +protected: + + PGconn * pg_conn; + PGresult * last_result; // can be null + ExecStatusType last_status; + bool log_queries; + + std::wstring db_database; + std::wstring db_user; + std::wstring db_pass; + + + void allocate_default_expression(); + +}; + +} + +#endif diff --git a/src/postgresqlexpression.cpp b/src/postgresqlexpression.cpp new file mode 100644 index 0000000..574dda8 --- /dev/null +++ b/src/postgresqlexpression.cpp @@ -0,0 +1,106 @@ +/* + * This file is a part of morm + * and is distributed under the 2-Clause BSD licence. + * Author: Tomasz Sowa + */ + +/* + * Copyright (c) 2018, 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 "postgresqlexpression.h" + + +namespace morm +{ + + +void PostgreSQLExpression::before_field_value_string() +{ + if( output_type == MORM_OUTPUT_TYPE_DB_INSERT || + output_type == MORM_OUTPUT_TYPE_DB_UPDATE || + output_type == MORM_OUTPUT_TYPE_DB_PRIMARY_KEY ) + { + (*out_stream) << "E'"; + } +} + +void PostgreSQLExpression::after_field_value_string() +{ + if( output_type == MORM_OUTPUT_TYPE_DB_INSERT || + output_type == MORM_OUTPUT_TYPE_DB_UPDATE || + output_type == MORM_OUTPUT_TYPE_DB_PRIMARY_KEY ) + { + (*out_stream) << "'"; + } +} + + +void PostgreSQLExpression::before_field_value(const std::wstring &) +{ + before_field_value_string(); +} + +void PostgreSQLExpression::before_field_value(const std::string &) +{ + before_field_value_string(); +} + +void PostgreSQLExpression::after_field_value(const std::wstring &) +{ + after_field_value_string(); +} + +void PostgreSQLExpression::after_field_value(const std::string &) +{ + after_field_value_string(); +} + +void PostgreSQLExpression::put_name_value_separator() +{ + (*out_stream) << '='; +} + + +void PostgreSQLExpression::esc(char val, PT::TextStream & stream) +{ + switch( val ) + { + case '\\': stream << "\\\\"; break; + case '\'': stream << "\\\'"; break; // don't use "''" because we use the method for PQconnectdb too + default: + if( val != 0 ) + { + stream << val; + } + } +} + + + + +} diff --git a/src/baseescaper.h b/src/postgresqlexpression.h similarity index 74% rename from src/baseescaper.h rename to src/postgresqlexpression.h index 43cd644..6f7da9f 100644 --- a/src/baseescaper.h +++ b/src/postgresqlexpression.h @@ -32,32 +32,38 @@ * */ -#ifndef headerfile_morm_baseescaper -#define headerfile_morm_baseescaper - -#include -#include "textstream/textstream.h" +#ifndef headerfile_morm_postgresqlexpression +#define headerfile_morm_postgresqlexpression +#include "dbexpression.h" namespace morm { -class BaseEscaper +class PostgreSQLExpression : public DbExpression { -public: - virtual void esc(char val, PT::TextStream & stream) = 0; - virtual ~BaseEscaper(); - void esc(const std::wstring & val, PT::TextStream & stream); - void esc(const wchar_t * val, PT::TextStream & stream); - void esc(const std::string & val, PT::TextStream & stream); +protected: + + void before_field_value(const std::wstring &); + void before_field_value(const std::string &); + void after_field_value(const std::wstring &); + void after_field_value(const std::string &); + void put_name_value_separator(); + +private: + + void before_field_value_string(); + void after_field_value_string(); + + + void esc(char val, PT::TextStream & stream); }; - } #endif