61ff9ca03cd97c3089d64ff55ebff983566572a3
[framework/web/wrt-commons.git] / modules / db / include / dpl / db / orm_generator.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_generator.h
18  * @author      Bartosz Janiak (b.janiak@samsung.com)
19  * @version     1.0
20  * @brief       Macro definitions for generating the DPL-ORM table definitions from database definitions.
21  */
22
23 #ifndef ORM_GENERATOR_DATABASE_NAME
24 #error You need to define database name in ORM_GENERATOR_DATABASE_NAME define before you include orm_generator.h file
25 #endif
26
27 #include <dpl/db/orm_interface.h>
28
29 #define ORM_GENERATOR_DATABASE_NAME_LOCAL <ORM_GENERATOR_DATABASE_NAME>
30
31 #ifdef DPL_ORM_GENERATOR_H
32 #warning orm_generator.h is included multiply times. Make sure it has different ORM_GENERATOR_DATABASE_NAME set.
33 #endif
34
35 #define DPL_ORM_GENERATOR_H
36
37
38 #include <dpl/string.h>
39 #include <dpl/optional.h>
40 #include <dpl/type_list.h>
41 #include <dpl/db/sql_connection.h>
42 #include <dpl/db/orm.h>
43 #include <dpl/assert.h>
44 #include <string>
45
46 /*
47
48 This is true only when exactly one db is available.
49
50 #if (defined DECLARE_COLUMN) || (defined INT) || (defined TINYINT) ||               \
51     (defined INTEGER) || (defined BIGINT) || defined(VARCHAR) || defined(TEXT) ||   \
52     (defined SQL) || (defined TABLE_CONSTRAINTS) || (defined OPTIONAL) ||           \
53     (defined DATABASE_START) || (defined DATABASE_END) || (defined CREATE_TABLE) || \
54     (defined COLUMN) || (defined COLUMN_NOT_NULL) || (defined CREATE_TABLE_END)
55
56 #error  This file temporarily defines many macros with generic names. To avoid name clash please include \
57         this file as early as possible. If this is not possible please report this problem to DPL developers.
58
59 #endif
60 */
61
62 namespace DPL {
63 namespace DB {
64 namespace ORM {
65
66 // Global macros
67
68 #define STRINGIFY(s) _str(s)
69 #define _str(s) #s
70 #define DECLARE_COLUMN(FIELD, TYPE) \
71     struct FIELD { \
72         typedef TYPE ColumnType; \
73         static const char* GetColumnName() { return STRINGIFY(FIELD); } \
74         static void SetRowField(Row& row, const TYPE& value) { row.Set_##FIELD(value);} \
75     };
76
77 #define INT         int
78 #define TINYINT     int
79 #define INTEGER     int  //TODO: should be long long?
80 #define BIGINT      int  //TODO: should be long long?
81 #define VARCHAR(x)  DPL::String
82 #define TEXT        DPL::String
83
84 #define SQL(args...)
85 #define TABLE_CONSTRAINTS(args...)
86 #define OPTIONAL(type) DPL::Optional< type >
87 #define DATABASE_START(db_name)                                 \
88     namespace db_name                                           \
89     {                                                           \
90         class ScopedTransaction                                 \
91         {                                                       \
92             bool m_commited;                                    \
93             IOrmInterface *m_interface;                         \
94                                                                 \
95         public:                                                 \
96             ScopedTransaction(IOrmInterface *interface) :       \
97                 m_commited(false),                              \
98                 m_interface(interface)                          \
99             {                                                   \
100                 Assert(interface != NULL);                      \
101                 m_interface->TransactionBegin();                \
102             }                                                   \
103                                                                 \
104             ~ScopedTransaction()                                \
105             {                                                   \
106                 if (!m_commited)                                \
107                     m_interface->TransactionRollback();         \
108             }                                                   \
109                                                                 \
110             void Commit()                                       \
111             {                                                   \
112                 m_interface->TransactionCommit();               \
113                 m_commited = true;                              \
114             }                                                   \
115         };
116
117 #define DATABASE_END() }
118
119 // RowBase ostream operator<< declaration
120
121 #define CREATE_TABLE(name) \
122     namespace name {                                                            \
123         class RowBase;                                                          \
124         inline std::ostream& operator<<(std::ostream& ostr, const RowBase& row); \
125     }
126 #define COLUMN_NOT_NULL(name, type, args...)
127 #define COLUMN(name, type, args...)
128 #define CREATE_TABLE_END()
129
130 #include ORM_GENERATOR_DATABASE_NAME_LOCAL
131
132 #undef CREATE_TABLE
133 #undef COLUMN_NOT_NULL
134 #undef COLUMN
135 #undef CREATE_TABLE_END
136
137 #undef DATABASE_START
138 #define DATABASE_START(db_name) namespace db_name {
139
140 // RowBase class
141
142 #define CREATE_TABLE(name) namespace name { class RowBase {                 \
143    public: friend std::ostream& operator<<(std::ostream&, const RowBase&);
144 #define COLUMN_NOT_NULL(name, type, args...)                                \
145         protected: type name; bool m_##name##_set;                          \
146         public:  void Set_##name(const type& value) {                       \
147                      m_##name##_set = true;                                 \
148                      this->name = value;                                     \
149         }                                                                   \
150         public:  type Get_##name() const {                                  \
151                      if ( !m_##name##_set ) {                               \
152                         ThrowMsg(Exception::RowFieldNotInitialized,         \
153                         "You tried to read a row field that hasn't been set yet."); \
154                      }                                                      \
155                      return name;                                           \
156         }
157
158 #define COLUMN(name, type, args...)                                         \
159         protected: OPTIONAL(type) name; bool m_##name##_set;                \
160         public:  void Set_##name(const OPTIONAL(type)& value) {             \
161                      m_##name##_set = true;                                 \
162                      this->name = value;                                     \
163         }                                                                   \
164         public:  OPTIONAL(type) Get_##name() const {                        \
165                      if ( !m_##name##_set ) {                               \
166                         ThrowMsg(Exception::RowFieldNotInitialized,         \
167                         "You tried to read a row field that hasn't been set yet."); \
168                      }                                                      \
169                      return name;                                           \
170         }
171 #define CREATE_TABLE_END() }; }
172
173 #include ORM_GENERATOR_DATABASE_NAME_LOCAL
174
175 #undef CREATE_TABLE
176 #undef COLUMN_NOT_NULL
177 #undef COLUMN
178 #undef CREATE_TABLE_END
179
180 // RowBase ostream operator<<
181
182 #define CREATE_TABLE(name) std::ostream& name::operator<<(std::ostream& ostr, const RowBase& row) { using ::operator<< ; ostr << STRINGIFY(name) << " (";
183 #define COLUMN_NOT_NULL(name, type, args...) ostr << " '" << row.name << "'" ;
184 #define COLUMN(name, type, args...)          ostr << " '" << row.name << "'" ;
185 #define CREATE_TABLE_END() ostr << " )" ; return ostr; }
186
187 #include ORM_GENERATOR_DATABASE_NAME_LOCAL
188
189 #undef CREATE_TABLE
190 #undef COLUMN_NOT_NULL
191 #undef COLUMN
192 #undef CREATE_TABLE_END
193
194 // RowBase2 class (== RowBase + operator==)
195
196 #define CREATE_TABLE(name) namespace name { class RowBase2 : public RowBase { \
197     public: bool operator==(const RowBase2& row) const { return true
198 #define COLUMN_NOT_NULL(name, type, args...) && (this->name == row.name)
199 #define COLUMN(name, type, args...)          && (this->name == row.name)
200 #define CREATE_TABLE_END() ; } }; }
201
202 #include ORM_GENERATOR_DATABASE_NAME_LOCAL
203
204 #undef CREATE_TABLE
205 #undef COLUMN_NOT_NULL
206 #undef COLUMN
207 #undef CREATE_TABLE_END
208
209 // RowBase3 class (== RowBase2 + operator<)
210
211 #define CREATE_TABLE(name) namespace name { class RowBase3 : public RowBase2 { \
212     public: bool operator<(const RowBase3& row) const {
213 #define COLUMN_NOT_NULL(name, type, args...) if (this->name < row.name) { return true; } if (this->name > row.name) { return false; }
214 #define COLUMN(name, type, args...)          if (this->name < row.name) { return true; } if (this->name > row.name) { return false; }
215 #define CREATE_TABLE_END() return false; } }; }
216
217 #include ORM_GENERATOR_DATABASE_NAME_LOCAL
218
219 #undef CREATE_TABLE
220 #undef COLUMN_NOT_NULL
221 #undef COLUMN
222 #undef CREATE_TABLE_END
223
224 // RowBase4 class (== RowBase3 + IsSignatureMatching )
225
226 #define CREATE_TABLE(name) namespace name { class RowBase4 : public RowBase3 { \
227     public: bool IsSignatureMatching(const RowBase4& row) const { return true
228 #define COLUMN_NOT_NULL(name, type, args...) && (this->m_##name##_set == row.m_##name##_set)
229 #define COLUMN(name, type, args...)          && (this->m_##name##_set == row.m_##name##_set)
230 #define CREATE_TABLE_END() ; } }; }
231
232 #include ORM_GENERATOR_DATABASE_NAME_LOCAL
233
234 #undef CREATE_TABLE
235 #undef COLUMN_NOT_NULL
236 #undef COLUMN
237 #undef CREATE_TABLE_END
238
239 // RowBase5 class (== RowBase4 + default constructor)
240
241 #define CREATE_TABLE(name) namespace name { class RowBase5 : public RowBase4 { \
242     public: RowBase5() {
243 #define COLUMN_NOT_NULL(name, type, args...) m_##name##_set = false;
244 #define COLUMN(name, type, args...)          m_##name##_set = false;
245 #define CREATE_TABLE_END() } }; }
246
247 #include ORM_GENERATOR_DATABASE_NAME_LOCAL
248
249 #undef CREATE_TABLE
250 #undef COLUMN_NOT_NULL
251 #undef COLUMN
252 #undef CREATE_TABLE_END
253
254 // Row class (== RowBase5 + ForEachColumn )
255
256 #define CREATE_TABLE(name) namespace name { class Row : public RowBase5 { \
257     public: template<typename Visitor>                                    \
258     void VisitColumns(Visitor& visitor) const {
259 #define COLUMN_NOT_NULL(name, type, args...) visitor.Visit(STRINGIFY(name), this->name, this->m_##name##_set);
260 #define COLUMN(name, type, args...)          visitor.Visit(STRINGIFY(name), this->name, this->m_##name##_set);
261 #define CREATE_TABLE_END() } }; }
262
263 #include ORM_GENERATOR_DATABASE_NAME_LOCAL
264
265 #undef CREATE_TABLE
266 #undef COLUMN_NOT_NULL
267 #undef COLUMN
268 #undef CREATE_TABLE_END
269
270 // Field structure declarations
271
272 #define CREATE_TABLE(name) namespace name {
273 #define COLUMN_NOT_NULL(name, type, args...) DECLARE_COLUMN(name, type)
274 #define COLUMN(name, type, args...) DECLARE_COLUMN(name, OPTIONAL(type))
275 #define CREATE_TABLE_END() }
276
277 #include ORM_GENERATOR_DATABASE_NAME_LOCAL
278
279 #undef CREATE_TABLE
280 #undef COLUMN_NOT_NULL
281 #undef COLUMN
282 #undef CREATE_TABLE_END
283
284 // ColumnList typedef
285
286 #define CREATE_TABLE(name) namespace name { typedef DPL::TypeListDecl<
287 #define COLUMN_NOT_NULL(name, type, args...) name,
288 #define COLUMN(name, type, args...) name,
289 #define CREATE_TABLE_END() DPL::TypeListGuard>::Type ColumnList; }
290
291 #include ORM_GENERATOR_DATABASE_NAME_LOCAL
292
293 #undef CREATE_TABLE
294 #undef COLUMN_NOT_NULL
295 #undef COLUMN
296 #undef CREATE_TABLE_END
297
298 // TableDefinition struct
299
300 #define CREATE_TABLE(table_name)                                            \
301     namespace table_name {                                                  \
302         struct TableDefinition {                                            \
303             typedef table_name::ColumnList ColumnList;                      \
304             typedef table_name::Row Row;                                    \
305             static const char* GetName() { return STRINGIFY(table_name); }  \
306             static DPL::DB::SqlConnection::DataCommand *AllocTableDataCommand( \
307                 const std::string &statement,                               \
308                 IOrmInterface *interface)                                   \
309             {                                                               \
310                 Assert(interface != NULL);                                  \
311                 return interface->AllocDataCommand(statement);              \
312             }                                                               \
313             static void FreeTableDataCommand(                               \
314                 DPL::DB::SqlConnection::DataCommand *command,               \
315                 IOrmInterface *interface)                                   \
316             {                                                               \
317                 Assert(interface != NULL);                                  \
318                 interface->FreeDataCommand(command);                        \
319             }                                                               \
320             static DPL::DB::SqlConnection::RowID GetLastInsertRowID(        \
321                 IOrmInterface *interface)                                   \
322             {                                                               \
323                 Assert(interface != NULL);                                  \
324                 return interface->GetLastInsertRowID();                     \
325             }                                                               \
326         };                                                                  \
327     }
328
329 #define COLUMN_NOT_NULL(name, type, args...)
330 #define COLUMN(name, type, args...)
331 #define CREATE_TABLE_END()
332
333 #include ORM_GENERATOR_DATABASE_NAME_LOCAL
334
335 #undef CREATE_TABLE
336 #undef COLUMN_NOT_NULL
337 #undef COLUMN
338 #undef CREATE_TABLE_END
339
340 // Query typedefs
341
342 #define CREATE_TABLE(name) \
343     namespace name { \
344         typedef Select<TableDefinition> Select; \
345         typedef Insert<TableDefinition> Insert; \
346         typedef Delete<TableDefinition> Delete; \
347         typedef Update<TableDefinition> Update; \
348     }
349 #define COLUMN_NOT_NULL(name, type, args...)
350 #define COLUMN(name, type, args...)
351 #define CREATE_TABLE_END()
352
353 #include ORM_GENERATOR_DATABASE_NAME_LOCAL
354
355 #undef CREATE_TABLE
356 #undef COLUMN_NOT_NULL
357 #undef COLUMN
358 #undef CREATE_TABLE_END
359
360
361 // Global undefs
362 #undef INT
363 #undef TINYINT
364 #undef INTEGER
365 #undef BIGINT
366 #undef VARCHAR
367 #undef TEXT
368
369 #undef SQL
370 #undef TABLE_CONSTRAINTS
371 #undef OPTIONAL
372 #undef DATABASE_START
373 #undef DATABASE_END
374
375 } //namespace ORM
376 } //namespace DB
377 } //namespace DPL
378
379 #undef ORM_GENERATOR_DATABASE_NAME
380 #undef ORM_GENERATOR_DATABASE_NAME_LOCAL