Initialize Tizen 2.3
[framework/web/wrt-commons.git] / modules_mobile / db / include / dpl / db / orm.h
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *    Licensed under the Apache License, Version 2.0 (the "License");
5  *    you may not use this file except in compliance with the License.
6  *    You may obtain a copy of the License at
7  *
8  *        http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *    Unless required by applicable law or agreed to in writing, software
11  *    distributed under the License is distributed on an "AS IS" BASIS,
12  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *    See the License for the specific language governing permissions and
14  *    limitations under the License.
15  */
16 /*
17  * @file        orm.h
18  * @author      Bartosz Janiak (b.janiak@samsung.com)
19  * @version     1.0
20  * @brief       DPL-ORM: Object-relational mapping for sqlite database, written on top of DPL.
21  */
22
23 #include <cstdlib>
24 #include <cstdio>
25 #include <string>
26 #include <typeinfo>
27 #include <utility>
28 #include <set>
29 #include <memory>
30
31 #include <dpl/db/sql_connection.h>
32 #include <dpl/db/orm_interface.h>
33 #include <dpl/string.h>
34 #include <dpl/optional.h>
35 #include <dpl/type_list.h>
36 #include <dpl/assert.h>
37 #include <dpl/foreach.h>
38
39 #ifndef DPL_ORM_H
40 #define DPL_ORM_H
41
42 namespace DPL {
43 namespace DB {
44 namespace ORM {
45
46 //TODO move to type utils
47 #define DPL_CHECK_TYPE_INSTANTIABILITY(type) \
48     { \
49         type _ignored_; \
50         (void)_ignored_; \
51     }
52
53 #define DECLARE_COLUMN_TYPE_LIST() typedef DPL::TypeListDecl<
54 #define SELECTED_COLUMN(table_name, column_name) table_name::column_name,
55 #define DECLARE_COLUMN_TYPE_LIST_END(name) DPL::TypeListGuard>::Type name;
56
57 typedef size_t ColumnIndex;
58 typedef size_t ArgumentIndex;
59 typedef DPL::Optional<DPL::String> OptionalString;
60 typedef DPL::Optional<int> OptionalInteger;
61 typedef DPL::DB::SqlConnection::DataCommand DataCommand;
62
63 namespace RelationTypes {
64     extern const char Equal[];
65     extern const char LessThan[];
66     extern const char And[];
67     extern const char Or[];
68     extern const char Is[];
69     extern const char In[];
70     //TODO define more relation types
71 }
72
73 namespace DataCommandUtils {
74     //TODO move to DPL::DataCommand?
75     void BindArgument(DataCommand *command, ArgumentIndex index, int argument);
76     void BindArgument(DataCommand *command, ArgumentIndex index, const OptionalInteger& argument);
77     void BindArgument(DataCommand *command, ArgumentIndex index, const DPL::String& argument);
78     void BindArgument(DataCommand *command, ArgumentIndex index, const OptionalString& argument);
79 }
80 class __attribute__ ((visibility("hidden"))) Expression {
81 public:
82     virtual ~Expression() {}
83     virtual std::string GetString() const = 0;
84     virtual ArgumentIndex BindTo(DataCommand *command, ArgumentIndex index) = 0;
85 };
86
87 typedef std::shared_ptr<Expression> ExpressionPtr;
88
89 namespace OrderingUtils {
90
91 template<typename CompoundType> inline std::string OrderByInternal()
92 {
93     std::string order = OrderByInternal<typename CompoundType::Tail>();
94     if(!order.empty()) return CompoundType::Head::GetString() + ", " + order;
95     else return CompoundType::Head::GetString();
96 }
97
98 template<> inline std::string OrderByInternal<TypeListGuard>()
99 {
100     return std::string();
101 }
102
103 }
104
105 template<typename ColumnType>
106 class __attribute__ ((visibility("hidden"))) OrderingExpression {
107 protected:
108     static std::string GetSchemaAndName()
109     {
110         std::string statement;
111         statement += ColumnType::GetTableName();
112         statement += ".";
113         statement += ColumnType::GetColumnName();
114         statement += " ";
115         return statement;
116     }
117 public:
118     virtual ~OrderingExpression() {}
119 };
120
121 template<const char* Operator, typename LeftExpression, typename RightExpression>
122 class __attribute__ ((visibility("hidden"))) BinaryExpression : public Expression {
123 protected:
124     LeftExpression  m_leftExpression;
125     RightExpression m_rightExpression;
126     bool            m_outerParenthesis;
127 public:
128     BinaryExpression(const LeftExpression& leftExpression, const RightExpression& rightExpression, bool outerParenthesis = true) :
129         m_leftExpression(leftExpression),
130         m_rightExpression(rightExpression),
131         m_outerParenthesis(outerParenthesis)
132     {}
133
134     virtual std::string GetString() const
135     {
136         return  (m_outerParenthesis ? "( " : " " ) +
137                  m_leftExpression.GetString() + " " + Operator + " " + m_rightExpression.GetString() +
138                 (m_outerParenthesis ? " )" : " " ) ;
139     }
140
141     virtual ArgumentIndex BindTo(DataCommand *command, ArgumentIndex index)
142     {
143         index = m_leftExpression.BindTo(command, index);
144         return  m_rightExpression.BindTo(command, index);
145     }
146
147     template<typename TableDefinition>
148     struct ValidForTable {
149         typedef std::pair<typename LeftExpression ::template ValidForTable<TableDefinition>::Yes ,
150                           typename RightExpression::template ValidForTable<TableDefinition>::Yes >
151                 Yes;
152     };
153 };
154
155 template<typename LeftExpression, typename RightExpression>
156 BinaryExpression<RelationTypes::And, LeftExpression, RightExpression>
157     And(const LeftExpression& leftExpression, const RightExpression& rightExpression)
158 {
159     return BinaryExpression<RelationTypes::And, LeftExpression, RightExpression>
160             (leftExpression, rightExpression);
161 }
162
163 template<typename LeftExpression, typename RightExpression>
164 BinaryExpression<RelationTypes::Or, LeftExpression, RightExpression>
165     Or(const LeftExpression& leftExpression, const RightExpression& rightExpression)
166 {
167     return BinaryExpression<RelationTypes::Or, LeftExpression, RightExpression>
168             (leftExpression, rightExpression);
169 }
170
171 template<typename ArgumentType>
172 class __attribute__ ((visibility("hidden"))) ExpressionWithArgument : public Expression {
173 protected:
174     ArgumentType argument;
175
176 public:
177     explicit ExpressionWithArgument(const ArgumentType& _argument) : argument(_argument) {}
178
179     virtual ArgumentIndex BindTo(DataCommand *command, ArgumentIndex index)
180     {
181         DataCommandUtils::BindArgument(command, index, argument);
182         return index + 1;
183     }
184 };
185
186 template<typename ColumnData, const char* Relation>
187 class __attribute__ ((visibility("hidden"))) Compare : public ExpressionWithArgument<typename ColumnData::ColumnType> {
188 public:
189     explicit Compare(typename ColumnData::ColumnType column) :
190         ExpressionWithArgument<typename ColumnData::ColumnType>(column)
191     {}
192
193     virtual std::string GetString() const
194     {
195         std::string statement;
196         statement += ColumnData::GetTableName();
197         statement += ".";
198         statement += ColumnData::GetColumnName();
199         statement += " ";
200         statement += Relation;
201         statement += " ?";
202         return statement;
203     }
204
205     template<typename TableDefinition>
206     struct ValidForTable {
207         typedef typename TableDefinition::ColumnList::template Contains<ColumnData> Yes;
208     };
209 };
210 #define ORM_DEFINE_COMPARE_EXPRESSION(name, relationType)                      \
211     template<typename ColumnData>                                              \
212     class __attribute__ ((visibility("hidden"))) name : public Compare<ColumnData, RelationTypes::relationType> {     \
213     public:                                                                    \
214         name(typename ColumnData::ColumnType column) :                         \
215             Compare<ColumnData, RelationTypes::relationType>(column)           \
216         {}                                                                     \
217     };
218
219 ORM_DEFINE_COMPARE_EXPRESSION(Equals, Equal)
220 ORM_DEFINE_COMPARE_EXPRESSION(Is, Is)
221
222 #define ORM_DEFINE_ORDERING_EXPRESSION(name, value)                                     \
223     template<typename ColumnType>                                                       \
224     class __attribute__ ((visibility("hidden"))) name                                   \
225         : OrderingExpression<ColumnType> {                                              \
226     public:                                                                             \
227         static std::string GetString()                                                  \
228         {                                                                               \
229             std::string statement = OrderingExpression<ColumnType>::GetSchemaAndName(); \
230             statement += value;                                                         \
231             return statement;                                                           \
232         }                                                                               \
233     };
234
235 ORM_DEFINE_ORDERING_EXPRESSION(OrderingAscending, "ASC")
236 ORM_DEFINE_ORDERING_EXPRESSION(OrderingDescending, "DESC")
237
238 template<typename ColumnData1, typename ColumnData2>
239 class __attribute__ ((visibility("hidden"))) CompareBinaryColumn {
240 private:
241     std::string m_relation;
242 public:
243     CompareBinaryColumn(const char* Relation) :
244       m_relation(Relation)
245     {}
246
247     virtual ~CompareBinaryColumn() {}
248
249     virtual std::string GetString() const
250     {
251         std::string statement;
252         statement += ColumnData1::GetTableName();
253         statement += ".";
254         statement += ColumnData1::GetColumnName();
255         statement += " ";
256         statement += m_relation;
257         statement += " ";
258         statement += ColumnData2::GetTableName();
259         statement += ".";
260         statement += ColumnData2::GetColumnName();
261
262         return statement;
263     }
264 };
265
266 template<typename ColumnData1, typename ColumnData2>
267 CompareBinaryColumn<ColumnData1, ColumnData2>
268     Equal()
269 {
270     return CompareBinaryColumn<ColumnData1, ColumnData2>(RelationTypes::Equal);
271 }
272
273 template<typename ColumnData, const char* Relation>
274 class __attribute__ ((visibility("hidden"))) NumerousArguments : public Expression {
275 protected:
276     std::set<typename ColumnData::ColumnType> m_argumentList;
277 public:
278     NumerousArguments(const std::set<typename ColumnData::ColumnType>& argumentList) : m_argumentList(argumentList) {}
279
280     virtual std::string GetString() const
281     {
282         std::string statement;
283         statement += ColumnData::GetColumnName();
284         statement += " ";
285         statement += Relation;
286         statement += " ( ";
287
288         int argumentCount = m_argumentList.size();
289         while(argumentCount)
290         {
291             statement += "?";
292             argumentCount--;
293             if (argumentCount)
294             {
295                 statement += ", ";
296             }
297         }
298
299         statement += " )";
300
301         return statement;
302     }
303
304     virtual ArgumentIndex BindTo(DataCommand *command, ArgumentIndex index)
305     {
306         ArgumentIndex argumentIndex = index;
307         FOREACH(argumentIt, m_argumentList)
308         {
309             DataCommandUtils::BindArgument(command, argumentIndex, *argumentIt);
310             argumentIndex++;
311         }
312         return  argumentIndex + 1;
313     }
314
315     template<typename TableDefinition>
316     struct ValidForTable {
317         typedef typename TableDefinition::ColumnList::template Contains<ColumnData> Yes;
318     };
319 };
320
321 #define ORM_DEFINE_COMPARE_EXPRESSION_NUMEROUS_ARGUMENTS(name, relationType)                      \
322     template<typename ColumnData>                                              \
323     class __attribute__ ((visibility("hidden"))) name : public NumerousArguments<ColumnData, RelationTypes::relationType> {     \
324     public:                                                                    \
325         name(std::set<typename ColumnData::ColumnType> column) :                         \
326             NumerousArguments<ColumnData, RelationTypes::relationType>(column)           \
327         {}                                                                     \
328     };
329
330 ORM_DEFINE_COMPARE_EXPRESSION_NUMEROUS_ARGUMENTS(In, In)
331
332 template<typename ColumnType>
333 ColumnType GetColumnFromCommand(ColumnIndex columnIndex, DataCommand *command);
334
335 class __attribute__ ((visibility("hidden"))) CustomColumnBase {
336 public:
337     CustomColumnBase() {}
338     virtual ~CustomColumnBase() {}
339 };
340
341 template<typename ColumnType>
342 class __attribute__ ((visibility("hidden"))) CustomColumn : public CustomColumnBase {
343 private:
344     ColumnType m_columnData;
345
346 public:
347     CustomColumn() {}
348     CustomColumn(ColumnType data)
349     {
350         m_columnData = data;
351     }
352
353     void SetColumnData(ColumnType data)
354     {
355         m_columnData = data;
356     }
357
358     ColumnType GetColumnData() const
359     {
360         return m_columnData;
361     }
362 };
363
364 template<typename ColumnList>
365 class __attribute__ ((visibility("hidden"))) CustomRowUtil {
366 public:
367     static void MakeColumnList(std::vector<CustomColumnBase*>& columnList)
368     {
369         typedef CustomColumn<typename ColumnList::Head::ColumnType> Type;
370         Type* pColumn = new Type();
371         columnList.push_back(pColumn);
372         CustomRowUtil<typename ColumnList::Tail>::MakeColumnList(columnList);
373     }
374
375     static void CopyColumnList(const std::vector<CustomColumnBase*>& srcList, std::vector<CustomColumnBase*>& dstList)
376     {
377         CopyColumnList(srcList, dstList, 0);
378     }
379
380     static ColumnIndex GetColumnIndex(const std::string& columnName)
381     {
382         return GetColumnIndex(columnName, 0);
383     }
384
385 private:
386     static void CopyColumnList(const std::vector<CustomColumnBase*>& srcList, std::vector<CustomColumnBase*>& dstList, ColumnIndex index)
387     {
388         typedef CustomColumn<typename ColumnList::Head::ColumnType> Type;
389         Type* pColumn = new Type(((Type*)(srcList.at(index)))->GetColumnData());
390         dstList.push_back(pColumn);
391         CustomRowUtil<typename ColumnList::Tail>::CopyColumnList(srcList, dstList, index + 1);
392     }
393
394     static ColumnIndex GetColumnIndex(const std::string& columnName, ColumnIndex index)
395     {
396         if (ColumnList::Head::GetColumnName() == columnName)
397             return index;
398
399         return CustomRowUtil<typename ColumnList::Tail>::GetColumnIndex(columnName, index + 1);
400     }
401
402 template<typename Other>
403 friend class CustomRowUtil;
404 };
405
406 template<>
407 class __attribute__ ((visibility("hidden"))) CustomRowUtil<DPL::TypeListGuard> {
408 public:
409     static void MakeColumnList(std::vector<CustomColumnBase*>&) {}
410 private:
411     static void CopyColumnList(const std::vector<CustomColumnBase*>&, std::vector<CustomColumnBase*>&, ColumnIndex) {}
412     static ColumnIndex GetColumnIndex(const std::string&, ColumnIndex) { return -1; }
413
414 template<typename Other>
415 friend class CustomRowUtil;
416 };
417
418 template<typename ColumnList>
419 class __attribute__ ((visibility("hidden"))) CustomRow {
420 private:
421     std::vector<CustomColumnBase*> m_columns;
422
423 public:
424     CustomRow()
425     {
426         CustomRowUtil<ColumnList>::MakeColumnList(m_columns);
427     }
428
429     CustomRow(const CustomRow& r)
430     {
431         CustomRowUtil<ColumnList>::CopyColumnList(r.m_columns, m_columns);
432     }
433
434     virtual ~CustomRow()
435     {
436         while (!m_columns.empty())
437         {
438             CustomColumnBase* pCustomColumn = m_columns.back();
439             m_columns.pop_back();
440             if (pCustomColumn)
441                 delete pCustomColumn;
442         }
443     }
444
445     template<typename ColumnType>
446     void SetColumnData(ColumnIndex columnIndex, ColumnType data)
447     {
448         typedef CustomColumn<ColumnType> Type;
449         Assert(columnIndex < m_columns.size());
450         Type* pColumn = dynamic_cast<Type*>(m_columns.at(columnIndex));
451         Assert(pColumn);
452         pColumn->SetColumnData(data);
453     }
454
455     template<typename ColumnData>
456     typename ColumnData::ColumnType GetColumnData()
457     {
458         typedef CustomColumn<typename ColumnData::ColumnType> Type;
459         ColumnIndex index = CustomRowUtil<ColumnList>::GetColumnIndex(ColumnData::GetColumnName());
460         Assert(index < m_columns.size());
461         Type* pColumn = dynamic_cast<Type*>(m_columns.at(index));
462         Assert(pColumn);
463         return pColumn->GetColumnData();
464     }
465 };
466
467 template<typename CustomRow, typename ColumnType>
468 void SetColumnData(CustomRow& row, ColumnType columnData, ColumnIndex columnIndex)
469 {
470     row.SetColumnData<ColumnType>(columnIndex, columnData);
471 }
472
473 template<typename ColumnList, typename CustomRow>
474 class  __attribute__ ((visibility("hidden"))) FillCustomRowUtil {
475 public:
476     static void FillCustomRow(CustomRow& row, DataCommand* command)
477     {
478         FillCustomRow(row, 0, command);
479     }
480
481 private:
482     static void FillCustomRow(CustomRow& row, ColumnIndex columnIndex, DataCommand* command)
483     {
484         typename ColumnList::Head::ColumnType columnData;
485         columnData = GetColumnFromCommand<typename ColumnList::Head::ColumnType>(columnIndex, command);
486         SetColumnData<CustomRow, typename ColumnList::Head::ColumnType>(row, columnData, columnIndex);
487         FillCustomRowUtil<typename ColumnList::Tail, CustomRow>::FillCustomRow(row, columnIndex + 1, command);
488     }
489
490 template<typename Other, typename OtherRow>
491 friend class FillCustomRowUtil;
492 };
493
494 template<typename CustomRow>
495 class  __attribute__ ((visibility("hidden"))) FillCustomRowUtil<DPL::TypeListGuard, CustomRow> {
496 private:
497     static void FillCustomRow(CustomRow&, ColumnIndex, DataCommand *)
498     { /* do nothing, we're past the last element of column list */ }
499
500 template<typename Other, typename OtherRow>
501 friend class FillCustomRowUtil;
502 };
503
504 template<typename ColumnList, typename Row>
505 class  __attribute__ ((visibility("hidden"))) FillRowUtil {
506 public:
507     static void FillRow(Row& row, DataCommand *command)
508     {
509         FillRow(row, 0, command);
510     }
511
512 private:
513     static void FillRow(Row& row, ColumnIndex columnIndex, DataCommand *command)
514     {
515         typename ColumnList::Head::ColumnType rowField;
516         rowField = GetColumnFromCommand<typename ColumnList::Head::ColumnType>(columnIndex, command);
517         ColumnList::Head::SetRowField(row, rowField);
518         FillRowUtil<typename ColumnList::Tail, Row>::FillRow(row, columnIndex + 1, command);
519     }
520
521 template<typename Other, typename OtherRow>
522 friend class FillRowUtil;
523 };
524
525 template<typename Row>
526 class  __attribute__ ((visibility("hidden"))) FillRowUtil<DPL::TypeListGuard, Row> {
527 private:
528     static void FillRow(Row&, ColumnIndex, DataCommand *)
529     { /* do nothing, we're past the last element of column list */ }
530
531 template<typename Other, typename OtherRow>
532 friend class FillRowUtil;
533 };
534
535 template<typename ColumnList>
536 class  __attribute__ ((visibility("hidden"))) JoinUtil {
537 public:
538     static std::string GetColumnNames()
539     {
540         std::string result;
541         result = ColumnList::Head::GetTableName();
542         result += ".";
543         result += ColumnList::Head::GetColumnName();
544         if (ColumnList::Tail::Size > 0)
545             result += ", ";
546
547         return result += JoinUtil<typename ColumnList::Tail>::GetColumnNames();
548     }
549
550     static std::string GetJoinTableName(const std::string& tableName)
551     {
552         std::string joinTableName = ColumnList::Head::GetTableName();
553         if (tableName.find(joinTableName) == std::string::npos)
554             return joinTableName;
555
556         return JoinUtil<typename ColumnList::Tail>::GetJoinTableName(tableName);
557     }
558 };
559
560 template<>
561 class  __attribute__ ((visibility("hidden"))) JoinUtil<DPL::TypeListGuard> {
562 public:
563     static std::string GetColumnNames() { return ""; }
564     static std::string GetJoinTableName(std::string) { return ""; }
565 };
566
567 class Exception {
568 public:
569     DECLARE_EXCEPTION_TYPE(DPL::Exception, Base)
570     DECLARE_EXCEPTION_TYPE(Base, SelectReuseWithDifferentQuerySignature)
571     DECLARE_EXCEPTION_TYPE(Base, RowFieldNotInitialized)
572     DECLARE_EXCEPTION_TYPE(Base, EmptyUpdateStatement)
573 };
574
575 template<typename TableDefinition>
576 class  __attribute__ ((visibility("hidden"))) Query
577 {
578 protected:
579     explicit Query(IOrmInterface* interface) :
580         m_interface(interface),
581         m_command(NULL)
582     {
583     }
584
585     virtual ~Query()
586     {
587         if (m_command == NULL)
588             return;
589
590         TableDefinition::FreeTableDataCommand(m_command, m_interface);
591     }
592
593     IOrmInterface* m_interface;
594     DataCommand *m_command;
595     std::string m_commandString;
596     ArgumentIndex m_bindArgumentIndex;
597 };
598
599 template<typename TableDefinition>
600 class  __attribute__ ((visibility("hidden"))) QueryWithWhereClause : public Query<TableDefinition>
601 {
602 protected:
603     ExpressionPtr m_whereExpression;
604
605     void Prepare()
606     {
607         if ( !!m_whereExpression )
608         {
609             this->m_commandString += " WHERE ";
610             this->m_commandString += m_whereExpression->GetString();
611         }
612     }
613
614     void Bind()
615     {
616         if ( !!m_whereExpression )
617         {
618             this->m_bindArgumentIndex = m_whereExpression->BindTo(
619                 this->m_command, this->m_bindArgumentIndex);
620         }
621     }
622
623 public:
624     explicit QueryWithWhereClause(IOrmInterface* interface) :
625         Query<TableDefinition>(interface)
626     {
627     }
628
629     template<typename Expression>
630     void Where(const Expression& expression)
631     {
632         DPL_CHECK_TYPE_INSTANTIABILITY(typename Expression::template ValidForTable<TableDefinition>::Yes);
633         if ( !!m_whereExpression && ( typeid(Expression) != typeid(*m_whereExpression) ) )
634         {
635             std::ostringstream str;
636             str << "Current ORM implementation doesn't allow to reuse Select"
637                     " instance with different query signature (particularly "
638                     "WHERE on different column).\n";
639             str << "Query: ";
640             str << this->m_commandString;
641             ThrowMsg(Exception::SelectReuseWithDifferentQuerySignature,
642                 str.str());
643         }
644         //TODO maybe don't make a copy here but just generate the string part of the query.
645         m_whereExpression.reset(new Expression(expression));
646     }
647
648 };
649
650 template<typename TableDefinition>
651 class  __attribute__ ((visibility("hidden"))) Delete : public QueryWithWhereClause<TableDefinition>
652 {
653 protected:
654     void Prepare()
655     {
656         if ( !this->m_command)
657         {
658             this->m_commandString  = "DELETE FROM ";
659             this->m_commandString += TableDefinition::GetName();
660
661             QueryWithWhereClause<TableDefinition>::Prepare();
662
663             this->m_command = TableDefinition::AllocTableDataCommand(
664                     this->m_commandString.c_str(),
665                     Query<TableDefinition>::m_interface);
666             LogPedantic("Prepared SQL command " << this->m_commandString);
667         }
668     }
669
670     void Bind()
671     {
672         this->m_bindArgumentIndex = 1;
673         QueryWithWhereClause<TableDefinition>::Bind();
674     }
675
676 public:
677     explicit Delete(IOrmInterface *interface = NULL) :
678         QueryWithWhereClause<TableDefinition>(interface)
679     {
680     }
681
682     void Execute()
683     {
684         Prepare();
685         Bind();
686         this->m_command->Step();
687         this->m_command->Reset();
688     }
689 };
690
691 namespace {
692 class BindVisitor {
693 private:
694     DataCommand *m_command;
695 public:
696     ArgumentIndex m_bindArgumentIndex;
697
698     BindVisitor(DataCommand *command) :
699         m_command(command),
700         m_bindArgumentIndex(1)
701     {}
702
703     template<typename ColumnType>
704     void Visit(const char*, const ColumnType& value, bool isSet)
705     {
706         if ( isSet )
707         {
708             DataCommandUtils::BindArgument(m_command, m_bindArgumentIndex, value);
709             m_bindArgumentIndex++;
710         }
711     }
712 };
713 } //anonymous namespace
714 template<typename TableDefinition>
715 class __attribute__ ((visibility("hidden"))) Insert : public Query<TableDefinition>
716 {
717 public:
718     typedef typename TableDefinition::Row Row;
719     typedef DPL::DB::SqlConnection::RowID RowID;
720
721 protected:
722     DPL::Optional<std::string> m_orClause;
723     Row m_row;
724
725     class PrepareVisitor {
726     public:
727         std::string m_columnNames;
728         std::string m_values;
729
730         template<typename ColumnType>
731         void Visit(const char* name, const ColumnType&, bool isSet)
732         {
733             if ( isSet )
734             {
735                 if ( !m_columnNames.empty() )
736                 {
737                     m_columnNames += ", ";
738                     m_values += ", ";
739                 }
740                 m_columnNames += name;
741                 m_values += "?";
742             }
743         }
744     };
745
746     void Prepare()
747     {
748         if ( !this->m_command )
749         {
750             this->m_commandString = "INSERT ";
751             if ( !!m_orClause )
752             {
753                 this->m_commandString += " OR " + *m_orClause + " ";
754             }
755             this->m_commandString += "INTO ";
756             this->m_commandString += TableDefinition::GetName();
757
758             PrepareVisitor visitor;
759             m_row.VisitColumns(visitor);
760
761             this->m_commandString += " ( " + visitor.m_columnNames + " ) ";
762             this->m_commandString += "VALUES ( " + visitor.m_values + " )";
763
764             LogPedantic("Prepared SQL command " << this->m_commandString);
765             this->m_command = TableDefinition::AllocTableDataCommand(
766                 this->m_commandString.c_str(),
767                 Query<TableDefinition>::m_interface);
768         }
769     }
770
771     void Bind()
772     {
773         BindVisitor visitor(this->m_command);
774         m_row.VisitColumns(visitor);
775     }
776
777 public:
778     explicit Insert(
779             IOrmInterface* interface = NULL,
780             const DPL::Optional<std::string>& orClause = DPL::Optional<std::string>::Null) :
781         Query<TableDefinition>(interface),
782         m_orClause(orClause)
783     {
784     }
785
786     void Values(const Row& row)
787     {
788         if ( this->m_command )
789         {
790             if ( !row.IsSignatureMatching(m_row) )
791             {
792                 ThrowMsg(Exception::SelectReuseWithDifferentQuerySignature,
793                     "Current ORM implementation doesn't allow to reuse Insert instance "
794                     "with different query signature.");
795             }
796         }
797         m_row = row;
798     }
799
800     RowID Execute()
801     {
802         Prepare();
803         Bind();
804         this->m_command->Step();
805
806         RowID result = TableDefinition::GetLastInsertRowID(
807             Query<TableDefinition>::m_interface);
808
809         this->m_command->Reset();
810         return result;
811     }
812 };
813
814 template<typename TableDefinition>
815 class __attribute__ ((visibility("hidden"))) Select : public QueryWithWhereClause<TableDefinition>
816 {
817 public:
818     typedef typename TableDefinition::ColumnList       ColumnList;
819     typedef typename TableDefinition::Row              Row;
820
821     typedef std::list<Row>                             RowList;
822 protected:
823     DPL::Optional<std::string> m_orderBy;
824     std::string m_JoinClause;
825     bool                       m_distinctResults;
826
827     void Prepare(const char* selectColumnName)
828     {
829         if ( !this->m_command )
830         {
831             this->m_commandString  = "SELECT ";
832             if (m_distinctResults)
833                 this->m_commandString += "DISTINCT ";
834             this->m_commandString += selectColumnName;
835             this->m_commandString += " FROM ";
836             this->m_commandString += TableDefinition::GetName();
837
838             this->m_commandString += m_JoinClause;
839
840             QueryWithWhereClause<TableDefinition>::Prepare();
841
842             if ( !m_orderBy.IsNull() )
843             {
844                 this->m_commandString += " ORDER BY " + *m_orderBy;
845             }
846
847             this->m_command = TableDefinition::AllocTableDataCommand(
848                 this->m_commandString.c_str(),
849                 Query<TableDefinition>::m_interface);
850
851             LogPedantic("Prepared SQL command " << this->m_commandString);
852         }
853     }
854
855     void Bind()
856     {
857         this->m_bindArgumentIndex = 1;
858         QueryWithWhereClause<TableDefinition>::Bind();
859     }
860
861     template<typename ColumnType>
862     ColumnType GetColumn(ColumnIndex columnIndex)
863     {
864         return GetColumnFromCommand<ColumnType>(columnIndex, this->m_command);
865     }
866
867     Row GetRow()
868     {
869         Row row;
870         FillRowUtil<ColumnList, Row>::FillRow(row, this->m_command);
871         return row;
872     }
873
874     template<typename ColumnList, typename CustomRow>
875     CustomRow GetCustomRow()
876     {
877         CustomRow row;
878         FillCustomRowUtil<ColumnList, CustomRow>::FillCustomRow(row, this->m_command);
879         return row;
880     }
881
882 public:
883
884     explicit Select(IOrmInterface *interface = NULL) :
885         QueryWithWhereClause<TableDefinition>(interface),
886         m_distinctResults(false)
887     {
888     }
889
890     void Distinct()
891     {
892         m_distinctResults = true;
893     }
894
895     template<typename CompoundType>
896     void OrderBy(const CompoundType&)
897     {
898         m_orderBy = OrderingUtils::OrderByInternal<typename CompoundType::Type>();
899     }
900
901     void OrderBy(const std::string & orderBy) //backward compatibility
902     {
903         m_orderBy = orderBy;
904     }
905
906     void OrderBy(const char * orderBy) //backward compatibility
907     {
908         m_orderBy = std::string(orderBy);
909     }
910
911     template<typename ColumnList, typename Expression>
912     void Join(const Expression& expression) {
913         std::string usedTableNames = TableDefinition::GetName();
914         if (!m_JoinClause.empty())
915             usedTableNames += m_JoinClause;
916
917         this->m_JoinClause += " JOIN ";
918         this->m_JoinClause += JoinUtil<ColumnList>::GetJoinTableName(usedTableNames);
919         this->m_JoinClause += " ON ";
920         this->m_JoinClause += expression.GetString();
921     }
922
923     template<typename ColumnData>
924     typename ColumnData::ColumnType GetSingleValue()
925     {
926         Prepare(ColumnData::GetColumnName());
927         Bind();
928         this->m_command->Step();
929
930         typename ColumnData::ColumnType result =
931             GetColumn<typename ColumnData::ColumnType>(0);
932
933         this->m_command->Reset();
934         return result;
935     }
936
937     //TODO return range - pair of custom iterators
938     template<typename ColumnData>
939     std::list<typename ColumnData::ColumnType> GetValueList()
940     {
941         Prepare(ColumnData::GetColumnName());
942         Bind();
943
944         std::list<typename ColumnData::ColumnType> resultList;
945
946         while (this->m_command->Step())
947             resultList.push_back(GetColumn<typename ColumnData::ColumnType>(0));
948
949         this->m_command->Reset();
950         return resultList;
951     }
952
953     Row GetSingleRow()
954     {
955         Prepare("*");
956         Bind();
957         this->m_command->Step();
958
959         Row result = GetRow();
960
961         this->m_command->Reset();
962         return result;
963     }
964
965     //TODO return range - pair of custom iterators
966     RowList GetRowList()
967     {
968         Prepare("*");
969         Bind();
970
971         RowList resultList;
972
973         while (this->m_command->Step())
974             resultList.push_back(GetRow());
975
976         this->m_command->Reset();
977         return resultList;
978     }
979
980     template<typename ColumnList, typename CustomRow>
981     CustomRow GetCustomSingleRow()
982     {
983         Prepare(JoinUtil<ColumnList>::GetColumnNames().c_str());
984         Bind();
985         this->m_command->Step();
986
987         CustomRow result = GetCustomRow<ColumnList, CustomRow>();
988
989         this->m_command->Reset();
990         return result;
991     }
992
993     template<typename ColumnList, typename CustomRow>
994     std::list<CustomRow> GetCustomRowList()
995     {
996         Prepare(JoinUtil<ColumnList>::GetColumnNames().c_str());
997         Bind();
998
999         std::list<CustomRow> resultList;
1000
1001         while (this->m_command->Step())
1002             resultList.push_back(GetCustomRow<ColumnList, CustomRow>());
1003
1004         this->m_command->Reset();
1005         return resultList;
1006     }
1007 };
1008
1009 template<typename TableDefinition>
1010 class __attribute__ ((visibility("hidden"))) Update : public QueryWithWhereClause<TableDefinition> {
1011 public:
1012     typedef typename TableDefinition::Row Row;
1013
1014 protected:
1015     DPL::Optional<std::string> m_orClause;
1016     Row m_row;
1017
1018     class PrepareVisitor {
1019     public:
1020         std::string m_setExpressions;
1021
1022         template<typename ColumnType>
1023         void Visit(const char* name, const ColumnType&, bool isSet)
1024         {
1025             if ( isSet )
1026             {
1027                 if ( !m_setExpressions.empty() )
1028                 {
1029                     m_setExpressions += ", ";
1030                 }
1031                 m_setExpressions += name;
1032                 m_setExpressions += " = ";
1033                 m_setExpressions += "?";
1034             }
1035         }
1036     };
1037
1038     void Prepare()
1039     {
1040         if ( !this->m_command )
1041         {
1042             this->m_commandString = "UPDATE ";
1043             if ( !!m_orClause )
1044             {
1045                 this->m_commandString += " OR " + *m_orClause + " ";
1046             }
1047             this->m_commandString += TableDefinition::GetName();
1048             this->m_commandString += " SET ";
1049
1050             // got through row columns and values
1051             PrepareVisitor visitor;
1052             m_row.VisitColumns(visitor);
1053
1054             if(visitor.m_setExpressions.empty())
1055             {
1056                 ThrowMsg(Exception::EmptyUpdateStatement, "No SET expressions in update statement");
1057             }
1058
1059             this->m_commandString += visitor.m_setExpressions;
1060
1061             // where
1062             QueryWithWhereClause<TableDefinition>::Prepare();
1063
1064             this->m_command = TableDefinition::AllocTableDataCommand(
1065                     this->m_commandString.c_str(),
1066                     Query<TableDefinition>::m_interface);
1067             LogPedantic("Prepared SQL command " << this->m_commandString);
1068         }
1069     }
1070
1071     void Bind()
1072     {
1073         BindVisitor visitor(this->m_command);
1074         m_row.VisitColumns(visitor);
1075
1076         this->m_bindArgumentIndex = visitor.m_bindArgumentIndex;
1077         QueryWithWhereClause<TableDefinition>::Bind();
1078     }
1079
1080
1081 public:
1082     explicit Update(IOrmInterface *interface = NULL,
1083                     const DPL::Optional<std::string>& orClause = DPL::Optional<std::string>::Null) :
1084         QueryWithWhereClause<TableDefinition>(interface),
1085         m_orClause(orClause)
1086     {
1087     }
1088
1089     void Values(const Row& row)
1090     {
1091         if ( this->m_command )
1092         {
1093             if ( !row.IsSignatureMatching(m_row) )
1094             {
1095                 ThrowMsg(Exception::SelectReuseWithDifferentQuerySignature,
1096                     "Current ORM implementation doesn't allow to reuse Update instance "
1097                     "with different query signature.");
1098             }
1099         }
1100         m_row = row;
1101     }
1102
1103     void Execute()
1104     {
1105         Prepare();
1106         Bind();
1107         this->m_command->Step();
1108         this->m_command->Reset();
1109     }
1110 };
1111
1112 } //namespace ORM
1113 } //namespace DB
1114 } //namespace DPL
1115
1116 #endif // DPL_ORM_H