1 /*
2  * Copyright (c) 2014 Jerry Lundström <lundstrom.jerry@gmail.com>
3  * Copyright (c) 2014 .SE (The Internet Infrastructure Foundation).
4  * Copyright (c) 2014 OpenDNSSEC AB (svb)
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
20  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
22  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
24  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
25  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  *
28  */
29 
30 #include "db_object.h"
31 #include "db_error.h"
32 
33 
34 #include <stdlib.h>
35 
36 /* DB OBJECT FIELD */
37 
38 
39 
db_object_field_new(void)40 db_object_field_t* db_object_field_new(void) {
41     db_object_field_t* object_field =
42         (db_object_field_t*)calloc(1, sizeof(db_object_field_t));
43 
44     if (object_field) {
45         object_field->type = DB_TYPE_EMPTY;
46     }
47 
48     return object_field;
49 }
50 
51 /* TODO: unit test */
db_object_field_new_copy(const db_object_field_t * from_object_field)52 db_object_field_t* db_object_field_new_copy(const db_object_field_t* from_object_field) {
53     db_object_field_t* object_field;
54 
55     if (!from_object_field) {
56         return NULL;
57     }
58 
59     if (!(object_field = db_object_field_new())
60         || db_object_field_copy(object_field, from_object_field))
61     {
62         db_object_field_free(object_field);
63         return NULL;
64     }
65 
66     return object_field;
67 }
68 
db_object_field_free(db_object_field_t * object_field)69 void db_object_field_free(db_object_field_t* object_field) {
70     if (object_field) {
71         free(object_field);
72     }
73 }
74 
75 /* TODO: unit test */
db_object_field_copy(db_object_field_t * object_field,const db_object_field_t * from_object_field)76 int db_object_field_copy(db_object_field_t* object_field, const db_object_field_t* from_object_field) {
77     if (!object_field) {
78         return DB_ERROR_UNKNOWN;
79     }
80     if (!from_object_field) {
81         return DB_ERROR_UNKNOWN;
82     }
83     if (object_field->next) {
84         return DB_ERROR_UNKNOWN;
85     }
86 
87     object_field->name = from_object_field->name;
88     object_field->type = from_object_field->type;
89     object_field->enum_set = from_object_field->enum_set;
90 
91     return DB_OK;
92 }
93 
db_object_field_name(const db_object_field_t * object_field)94 const char* db_object_field_name(const db_object_field_t* object_field) {
95     if (!object_field) {
96         return NULL;
97     }
98 
99     return object_field->name;
100 }
101 
db_object_field_type(const db_object_field_t * object_field)102 db_type_t db_object_field_type(const db_object_field_t* object_field) {
103     if (!object_field) {
104         return DB_TYPE_EMPTY;
105     }
106 
107     return object_field->type;
108 }
109 
db_object_field_set_name(db_object_field_t * object_field,const char * name)110 int db_object_field_set_name(db_object_field_t* object_field, const char* name) {
111     if (!object_field) {
112         return DB_ERROR_UNKNOWN;
113     }
114     if (!name) {
115         return DB_ERROR_UNKNOWN;
116     }
117 
118     object_field->name = name;
119     return DB_OK;
120 }
121 
db_object_field_set_type(db_object_field_t * object_field,db_type_t type)122 int db_object_field_set_type(db_object_field_t* object_field, db_type_t type) {
123     if (!object_field) {
124         return DB_ERROR_UNKNOWN;
125     }
126     if (type == DB_TYPE_EMPTY) {
127         return DB_ERROR_UNKNOWN;
128     }
129 
130     object_field->type = type;
131     return DB_OK;
132 }
133 
db_object_field_set_enum_set(db_object_field_t * object_field,const db_enum_t * enum_set)134 int db_object_field_set_enum_set(db_object_field_t* object_field, const db_enum_t* enum_set) {
135     if (!object_field) {
136         return DB_ERROR_UNKNOWN;
137     }
138     if (object_field->type != DB_TYPE_ENUM) {
139         return DB_ERROR_UNKNOWN;
140     }
141 
142     object_field->enum_set = enum_set;
143     return DB_OK;
144 }
145 
db_object_field_not_empty(const db_object_field_t * object_field)146 int db_object_field_not_empty(const db_object_field_t* object_field) {
147     if (!object_field) {
148         return DB_ERROR_UNKNOWN;
149     }
150     if (!object_field->name) {
151         return DB_ERROR_UNKNOWN;
152     }
153     if (object_field->type == DB_TYPE_EMPTY) {
154         return DB_ERROR_UNKNOWN;
155     }
156     if (object_field->type == DB_TYPE_ENUM && !object_field->enum_set) {
157         return DB_ERROR_UNKNOWN;
158     }
159     return DB_OK;
160 }
161 
db_object_field_next(const db_object_field_t * object_field)162 const db_object_field_t* db_object_field_next(const db_object_field_t* object_field) {
163     if (!object_field) {
164         return NULL;
165     }
166 
167     return object_field->next;
168 }
169 
170 /* DB OBJECT FIELD LIST */
171 
172 
173 
db_object_field_list_new(void)174 db_object_field_list_t* db_object_field_list_new(void) {
175     db_object_field_list_t* object_field_list =
176         (db_object_field_list_t*)calloc(1, sizeof(db_object_field_list_t));
177 
178     return object_field_list;
179 }
180 
181 /* TODO: unit test */
db_object_field_list_new_copy(const db_object_field_list_t * from_object_field_list)182 db_object_field_list_t* db_object_field_list_new_copy(const db_object_field_list_t* from_object_field_list) {
183     db_object_field_list_t* object_field_list;
184 
185     if (!from_object_field_list) {
186         return NULL;
187     }
188 
189     if (!(object_field_list = db_object_field_list_new())
190         || db_object_field_list_copy(object_field_list, from_object_field_list))
191     {
192         db_object_field_list_free(object_field_list);
193         return NULL;
194     }
195 
196     return object_field_list;
197 }
198 
db_object_field_list_free(db_object_field_list_t * object_field_list)199 void db_object_field_list_free(db_object_field_list_t* object_field_list) {
200     if (object_field_list) {
201         if (object_field_list->begin) {
202             db_object_field_t* this = object_field_list->begin;
203             db_object_field_t* next = NULL;
204 
205             while (this) {
206                 next = this->next;
207                 db_object_field_free(this);
208                 this = next;
209             }
210         }
211         free(object_field_list);
212     }
213 }
214 
215 /* TODO: unit test */
db_object_field_list_copy(db_object_field_list_t * object_field_list,const db_object_field_list_t * from_object_field_list)216 int db_object_field_list_copy(db_object_field_list_t* object_field_list, const db_object_field_list_t* from_object_field_list) {
217     db_object_field_t* object_field;
218     db_object_field_t* object_field_copy;
219 
220     if (!object_field_list) {
221         return DB_ERROR_UNKNOWN;
222     }
223     /*
224      * TODO: Should we be able to copy into a object field list that already
225      * contains data?
226      */
227     if (object_field_list->begin) {
228         return DB_ERROR_UNKNOWN;
229     }
230     if (object_field_list->end) {
231         return DB_ERROR_UNKNOWN;
232     }
233     if (object_field_list->size) {
234         return DB_ERROR_UNKNOWN;
235     }
236     if (!from_object_field_list) {
237         return DB_ERROR_UNKNOWN;
238     }
239 
240     object_field = from_object_field_list->begin;
241     while (object_field) {
242         if (!(object_field_copy = db_object_field_new_copy(object_field))
243             || db_object_field_list_add(object_field_list, object_field_copy))
244         {
245             return DB_ERROR_UNKNOWN;
246         }
247 
248         object_field = object_field->next;
249     }
250 
251     return DB_OK;
252 }
253 
db_object_field_list_add(db_object_field_list_t * object_field_list,db_object_field_t * object_field)254 int db_object_field_list_add(db_object_field_list_t* object_field_list, db_object_field_t* object_field) {
255     if (!object_field_list) {
256         return DB_ERROR_UNKNOWN;
257     }
258     if (!object_field) {
259         return DB_ERROR_UNKNOWN;
260     }
261     if (db_object_field_not_empty(object_field)) {
262         return DB_ERROR_UNKNOWN;
263     }
264     if (object_field->next) {
265         return DB_ERROR_UNKNOWN;
266     }
267 
268     if (object_field_list->begin) {
269         if (!object_field_list->end) {
270             return DB_ERROR_UNKNOWN;
271         }
272         object_field_list->end->next = object_field;
273         object_field_list->end = object_field;
274     }
275     else {
276         object_field_list->begin = object_field;
277         object_field_list->end = object_field;
278     }
279     object_field_list->size++;
280 
281     return DB_OK;
282 }
283 
db_object_field_list_begin(const db_object_field_list_t * object_field_list)284 const db_object_field_t* db_object_field_list_begin(const db_object_field_list_t* object_field_list) {
285     if (!object_field_list) {
286         return NULL;
287     }
288 
289     return object_field_list->begin;
290 }
291 
db_object_field_list_size(const db_object_field_list_t * object_field_list)292 size_t db_object_field_list_size(const db_object_field_list_t* object_field_list) {
293     if (!object_field_list) {
294         return 0;
295     }
296 
297     return object_field_list->size;
298 }
299 
300 /* DB OBJECT */
301 
302 
303 
db_object_new(void)304 db_object_t* db_object_new(void) {
305     db_object_t* object =
306         (db_object_t*)calloc(1, sizeof(db_object_t));
307 
308     return object;
309 }
310 
db_object_free(db_object_t * object)311 void db_object_free(db_object_t* object) {
312     if (object) {
313         if (object->object_field_list) {
314             db_object_field_list_free(object->object_field_list);
315         }
316         free(object);
317     }
318 }
319 
db_object_connection(const db_object_t * object)320 const db_connection_t* db_object_connection(const db_object_t* object) {
321     if (!object) {
322         return NULL;
323     }
324     return object->connection;
325 }
326 
db_object_table(const db_object_t * object)327 const char* db_object_table(const db_object_t* object) {
328     if (!object) {
329         return NULL;
330     }
331     return object->table;
332 }
333 
db_object_object_field_list(const db_object_t * object)334 const db_object_field_list_t* db_object_object_field_list(const db_object_t* object) {
335     if (!object) {
336         return NULL;
337     }
338     return object->object_field_list;
339 }
340 
db_object_set_connection(db_object_t * object,const db_connection_t * connection)341 int db_object_set_connection(db_object_t* object, const db_connection_t* connection) {
342     if (!object) {
343         return DB_ERROR_UNKNOWN;
344     }
345     if (!connection) {
346         return DB_ERROR_UNKNOWN;
347     }
348     if (object->connection) {
349         return DB_ERROR_UNKNOWN;
350     }
351 
352     object->connection = connection;
353     return DB_OK;
354 }
355 
db_object_set_table(db_object_t * object,const char * table)356 int db_object_set_table(db_object_t* object, const char* table) {
357     if (!object) {
358         return DB_ERROR_UNKNOWN;
359     }
360     if (!table) {
361         return DB_ERROR_UNKNOWN;
362     }
363     if (object->table) {
364         return DB_ERROR_UNKNOWN;
365     }
366 
367     object->table = table;
368     return DB_OK;
369 }
370 
db_object_set_primary_key_name(db_object_t * object,const char * primary_key_name)371 int db_object_set_primary_key_name(db_object_t* object, const char* primary_key_name) {
372     if (!object) {
373         return DB_ERROR_UNKNOWN;
374     }
375     if (!primary_key_name) {
376         return DB_ERROR_UNKNOWN;
377     }
378     if (object->primary_key_name) {
379         return DB_ERROR_UNKNOWN;
380     }
381 
382     object->primary_key_name = primary_key_name;
383     return DB_OK;
384 }
385 
db_object_set_object_field_list(db_object_t * object,db_object_field_list_t * object_field_list)386 int db_object_set_object_field_list(db_object_t* object, db_object_field_list_t* object_field_list) {
387     if (!object) {
388         return DB_ERROR_UNKNOWN;
389     }
390     if (!object_field_list) {
391         return DB_ERROR_UNKNOWN;
392     }
393     if (object->object_field_list) {
394         return DB_ERROR_UNKNOWN;
395     }
396 
397     object->object_field_list = object_field_list;
398     return DB_OK;
399 }
400 
db_object_create(const db_object_t * object,const db_object_field_list_t * object_field_list,const db_value_set_t * value_set)401 int db_object_create(const db_object_t* object, const db_object_field_list_t* object_field_list, const db_value_set_t* value_set) {
402     if (!object) {
403         return DB_ERROR_UNKNOWN;
404     }
405     if (!value_set) {
406         return DB_ERROR_UNKNOWN;
407     }
408     if (!object->connection) {
409         return DB_ERROR_UNKNOWN;
410     }
411     if (!object->table) {
412         return DB_ERROR_UNKNOWN;
413     }
414     if (!object->primary_key_name) {
415         return DB_ERROR_UNKNOWN;
416     }
417 
418     if (object_field_list) {
419         return db_connection_create(object->connection, object, object_field_list, value_set);
420     }
421     return db_connection_create(object->connection, object, object->object_field_list, value_set);
422 }
423 
db_object_read(const db_object_t * object,const db_join_list_t * join_list,const db_clause_list_t * clause_list)424 db_result_list_t* db_object_read(const db_object_t* object, const db_join_list_t* join_list, const db_clause_list_t* clause_list) {
425     if (!object) {
426         return NULL;
427     }
428     if (!object->connection) {
429         return NULL;
430     }
431     if (!object->table) {
432         return NULL;
433     }
434     if (!object->primary_key_name) {
435         return NULL;
436     }
437 
438     return db_connection_read(object->connection, object, join_list, clause_list);
439 }
440 
db_object_update(const db_object_t * object,const db_object_field_list_t * object_field_list,const db_value_set_t * value_set,const db_clause_list_t * clause_list)441 int db_object_update(const db_object_t* object, const db_object_field_list_t* object_field_list, const db_value_set_t* value_set, const db_clause_list_t* clause_list) {
442     if (!object) {
443         return DB_ERROR_UNKNOWN;
444     }
445     if (!value_set) {
446         return DB_ERROR_UNKNOWN;
447     }
448     if (!object->connection) {
449         return DB_ERROR_UNKNOWN;
450     }
451     if (!object->table) {
452         return DB_ERROR_UNKNOWN;
453     }
454     if (!object->primary_key_name) {
455         return DB_ERROR_UNKNOWN;
456     }
457 
458     if (object_field_list) {
459         return db_connection_update(object->connection, object, object_field_list, value_set, clause_list);
460     }
461     return db_connection_update(object->connection, object, object->object_field_list, value_set, clause_list);
462 }
463 
db_object_delete(const db_object_t * object,const db_clause_list_t * clause_list)464 int db_object_delete(const db_object_t* object, const db_clause_list_t* clause_list) {
465     if (!object) {
466         return DB_ERROR_UNKNOWN;
467     }
468     if (!object->connection) {
469         return DB_ERROR_UNKNOWN;
470     }
471     if (!object->table) {
472         return DB_ERROR_UNKNOWN;
473     }
474     if (!object->primary_key_name) {
475         return DB_ERROR_UNKNOWN;
476     }
477 
478     return db_connection_delete(object->connection, object, clause_list);
479 }
480 
db_object_count(const db_object_t * object,const db_join_list_t * join_list,const db_clause_list_t * clause_list,size_t * count)481 int db_object_count(const db_object_t* object, const db_join_list_t* join_list, const db_clause_list_t* clause_list, size_t* count) {
482     if (!object) {
483         return DB_ERROR_UNKNOWN;
484     }
485     if (!count) {
486         return DB_ERROR_UNKNOWN;
487     }
488     if (!object->connection) {
489         return DB_ERROR_UNKNOWN;
490     }
491     if (!object->table) {
492         return DB_ERROR_UNKNOWN;
493     }
494     if (!object->primary_key_name) {
495         return DB_ERROR_UNKNOWN;
496     }
497 
498     return db_connection_count(object->connection, object, join_list, clause_list, count);
499 }
500