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 "key_state.h"
31 #include "db_error.h"
32 
33 
34 #include <string.h>
35 
36 const db_enum_t key_state_enum_set_type[] = {
37     { "DS", (key_state_type_t)KEY_STATE_TYPE_DS },
38     { "RRSIG", (key_state_type_t)KEY_STATE_TYPE_RRSIG },
39     { "DNSKEY", (key_state_type_t)KEY_STATE_TYPE_DNSKEY },
40     { "RRSIGDNSKEY", (key_state_type_t)KEY_STATE_TYPE_RRSIGDNSKEY },
41     { NULL, 0 }
42 };
43 
44 const db_enum_t key_state_enum_set_state[] = {
45     { "hidden", (key_state_state_t)KEY_STATE_STATE_HIDDEN },
46     { "rumoured", (key_state_state_t)KEY_STATE_STATE_RUMOURED },
47     { "omnipresent", (key_state_state_t)KEY_STATE_STATE_OMNIPRESENT },
48     { "unretentive", (key_state_state_t)KEY_STATE_STATE_UNRETENTIVE },
49     { "NA", (key_state_state_t)KEY_STATE_STATE_NA },
50     { NULL, 0 }
51 };
52 
53 /**
54  * Create a new key state object.
55  * \param[in] connection a db_connection_t pointer.
56  * \return a key_state_t pointer or NULL on error.
57  */
__key_state_new_object(const db_connection_t * connection)58 static db_object_t* __key_state_new_object(const db_connection_t* connection) {
59     db_object_field_list_t* object_field_list;
60     db_object_field_t* object_field;
61     db_object_t* object;
62 
63     if (!(object = db_object_new())
64         || db_object_set_connection(object, connection)
65         || db_object_set_table(object, "keyState")
66         || db_object_set_primary_key_name(object, "id")
67         || !(object_field_list = db_object_field_list_new()))
68     {
69         db_object_free(object);
70         return NULL;
71     }
72 
73     if (!(object_field = db_object_field_new())
74         || db_object_field_set_name(object_field, "id")
75         || db_object_field_set_type(object_field, DB_TYPE_PRIMARY_KEY)
76         || db_object_field_list_add(object_field_list, object_field))
77     {
78         db_object_field_free(object_field);
79         db_object_field_list_free(object_field_list);
80         db_object_free(object);
81         return NULL;
82     }
83 
84     if (!(object_field = db_object_field_new())
85         || db_object_field_set_name(object_field, "rev")
86         || db_object_field_set_type(object_field, DB_TYPE_REVISION)
87         || db_object_field_list_add(object_field_list, object_field))
88     {
89         db_object_field_free(object_field);
90         db_object_field_list_free(object_field_list);
91         db_object_free(object);
92         return NULL;
93     }
94 
95     if (!(object_field = db_object_field_new())
96         || db_object_field_set_name(object_field, "keyDataId")
97         || db_object_field_set_type(object_field, DB_TYPE_ANY)
98         || db_object_field_list_add(object_field_list, object_field))
99     {
100         db_object_field_free(object_field);
101         db_object_field_list_free(object_field_list);
102         db_object_free(object);
103         return NULL;
104     }
105 
106     if (!(object_field = db_object_field_new())
107         || db_object_field_set_name(object_field, "type")
108         || db_object_field_set_type(object_field, DB_TYPE_ENUM)
109         || db_object_field_set_enum_set(object_field, key_state_enum_set_type)
110         || db_object_field_list_add(object_field_list, object_field))
111     {
112         db_object_field_free(object_field);
113         db_object_field_list_free(object_field_list);
114         db_object_free(object);
115         return NULL;
116     }
117 
118     if (!(object_field = db_object_field_new())
119         || db_object_field_set_name(object_field, "state")
120         || db_object_field_set_type(object_field, DB_TYPE_ENUM)
121         || db_object_field_set_enum_set(object_field, key_state_enum_set_state)
122         || db_object_field_list_add(object_field_list, object_field))
123     {
124         db_object_field_free(object_field);
125         db_object_field_list_free(object_field_list);
126         db_object_free(object);
127         return NULL;
128     }
129 
130     if (!(object_field = db_object_field_new())
131         || db_object_field_set_name(object_field, "lastChange")
132         || db_object_field_set_type(object_field, DB_TYPE_UINT32)
133         || db_object_field_list_add(object_field_list, object_field))
134     {
135         db_object_field_free(object_field);
136         db_object_field_list_free(object_field_list);
137         db_object_free(object);
138         return NULL;
139     }
140 
141     if (!(object_field = db_object_field_new())
142         || db_object_field_set_name(object_field, "minimize")
143         || db_object_field_set_type(object_field, DB_TYPE_UINT32)
144         || db_object_field_list_add(object_field_list, object_field))
145     {
146         db_object_field_free(object_field);
147         db_object_field_list_free(object_field_list);
148         db_object_free(object);
149         return NULL;
150     }
151 
152     if (!(object_field = db_object_field_new())
153         || db_object_field_set_name(object_field, "ttl")
154         || db_object_field_set_type(object_field, DB_TYPE_UINT32)
155         || db_object_field_list_add(object_field_list, object_field))
156     {
157         db_object_field_free(object_field);
158         db_object_field_list_free(object_field_list);
159         db_object_free(object);
160         return NULL;
161     }
162 
163     if (db_object_set_object_field_list(object, object_field_list)) {
164         db_object_field_list_free(object_field_list);
165         db_object_free(object);
166         return NULL;
167     }
168 
169     return object;
170 }
171 
172 /* KEY STATE */
173 
174 
175 
key_state_new(const db_connection_t * connection)176 key_state_t* key_state_new(const db_connection_t* connection) {
177     key_state_t* key_state =
178         (key_state_t*)calloc(1, sizeof(key_state_t));
179 
180     if (key_state) {
181         if (!(key_state->dbo = __key_state_new_object(connection))) {
182             free(key_state);
183             return NULL;
184         }
185         db_value_reset(&(key_state->id));
186         db_value_reset(&(key_state->rev));
187         db_value_reset(&(key_state->key_data_id));
188         key_state->type = KEY_STATE_TYPE_INVALID;
189         key_state->state = KEY_STATE_STATE_HIDDEN;
190     }
191 
192     return key_state;
193 }
194 
key_state_new_copy(const key_state_t * key_state)195 key_state_t* key_state_new_copy(const key_state_t* key_state) {
196     key_state_t* new_key_state;
197 
198     if (!key_state) {
199         return NULL;
200     }
201     if (!key_state->dbo) {
202         return NULL;
203     }
204 
205     if (!(new_key_state = key_state_new(db_object_connection(key_state->dbo)))
206         || key_state_copy(new_key_state, key_state))
207     {
208         key_state_free(new_key_state);
209         return NULL;
210     }
211     return new_key_state;
212 }
213 
key_state_free(key_state_t * key_state)214 void key_state_free(key_state_t* key_state) {
215     if (key_state) {
216         if (key_state->dbo) {
217             db_object_free(key_state->dbo);
218         }
219         db_value_reset(&(key_state->id));
220         db_value_reset(&(key_state->rev));
221         db_value_reset(&(key_state->key_data_id));
222         if (key_state->private_key_data_id) {
223             key_data_free(key_state->private_key_data_id);
224         }
225         free(key_state);
226     }
227 }
228 
key_state_copy(key_state_t * key_state,const key_state_t * key_state_copy)229 int key_state_copy(key_state_t* key_state, const key_state_t* key_state_copy) {
230     if (!key_state) {
231         return DB_ERROR_UNKNOWN;
232     }
233     if (!key_state_copy) {
234         return DB_ERROR_UNKNOWN;
235     }
236 
237     if (db_value_copy(&(key_state->id), &(key_state_copy->id))) {
238         return DB_ERROR_UNKNOWN;
239     }
240     if (db_value_copy(&(key_state->rev), &(key_state_copy->rev))) {
241         return DB_ERROR_UNKNOWN;
242     }
243     if (db_value_copy(&(key_state->key_data_id), &(key_state_copy->key_data_id))) {
244         return DB_ERROR_UNKNOWN;
245     }
246     if (key_state->private_key_data_id) {
247         key_data_free(key_state->private_key_data_id);
248         key_state->private_key_data_id = NULL;
249     }
250     if (key_state_copy->private_key_data_id
251         && !(key_state->private_key_data_id = key_data_new_copy(key_state_copy->private_key_data_id)))
252     {
253         return DB_ERROR_UNKNOWN;
254     }
255     key_state->associated_key_data_id = NULL;
256     if (!key_state_copy->private_key_data_id
257         && key_state_copy->associated_key_data_id
258         && !(key_state->private_key_data_id = key_data_new_copy(key_state_copy->associated_key_data_id)))
259     {
260         return DB_ERROR_UNKNOWN;
261     }
262     key_state->type = key_state_copy->type;
263     key_state->state = key_state_copy->state;
264     key_state->last_change = key_state_copy->last_change;
265     key_state->minimize = key_state_copy->minimize;
266     key_state->ttl = key_state_copy->ttl;
267     return DB_OK;
268 }
269 
key_state_from_result(key_state_t * key_state,const db_result_t * result)270 int key_state_from_result(key_state_t* key_state, const db_result_t* result) {
271     const db_value_set_t* value_set;
272     int type;
273     int state;
274 
275     if (!key_state) {
276         return DB_ERROR_UNKNOWN;
277     }
278     if (!result) {
279         return DB_ERROR_UNKNOWN;
280     }
281 
282     db_value_reset(&(key_state->id));
283     db_value_reset(&(key_state->rev));
284     db_value_reset(&(key_state->key_data_id));
285     if (!(value_set = db_result_value_set(result))
286         || db_value_set_size(value_set) != 8
287         || db_value_copy(&(key_state->id), db_value_set_at(value_set, 0))
288         || db_value_copy(&(key_state->rev), db_value_set_at(value_set, 1))
289         || db_value_copy(&(key_state->key_data_id), db_value_set_at(value_set, 2))
290         || db_value_to_enum_value(db_value_set_at(value_set, 3), &type, key_state_enum_set_type)
291         || db_value_to_enum_value(db_value_set_at(value_set, 4), &state, key_state_enum_set_state)
292         || db_value_to_uint32(db_value_set_at(value_set, 5), &(key_state->last_change))
293         || db_value_to_uint32(db_value_set_at(value_set, 6), &(key_state->minimize))
294         || db_value_to_uint32(db_value_set_at(value_set, 7), &(key_state->ttl)))
295     {
296         return DB_ERROR_UNKNOWN;
297     }
298 
299     if (type == (key_state_type_t)KEY_STATE_TYPE_DS) {
300         key_state->type = KEY_STATE_TYPE_DS;
301     }
302     else if (type == (key_state_type_t)KEY_STATE_TYPE_RRSIG) {
303         key_state->type = KEY_STATE_TYPE_RRSIG;
304     }
305     else if (type == (key_state_type_t)KEY_STATE_TYPE_DNSKEY) {
306         key_state->type = KEY_STATE_TYPE_DNSKEY;
307     }
308     else if (type == (key_state_type_t)KEY_STATE_TYPE_RRSIGDNSKEY) {
309         key_state->type = KEY_STATE_TYPE_RRSIGDNSKEY;
310     }
311     else {
312         return DB_ERROR_UNKNOWN;
313     }
314 
315     if (state == (key_state_state_t)KEY_STATE_STATE_HIDDEN) {
316         key_state->state = KEY_STATE_STATE_HIDDEN;
317     }
318     else if (state == (key_state_state_t)KEY_STATE_STATE_RUMOURED) {
319         key_state->state = KEY_STATE_STATE_RUMOURED;
320     }
321     else if (state == (key_state_state_t)KEY_STATE_STATE_OMNIPRESENT) {
322         key_state->state = KEY_STATE_STATE_OMNIPRESENT;
323     }
324     else if (state == (key_state_state_t)KEY_STATE_STATE_UNRETENTIVE) {
325         key_state->state = KEY_STATE_STATE_UNRETENTIVE;
326     }
327     else if (state == (key_state_state_t)KEY_STATE_STATE_NA) {
328         key_state->state = KEY_STATE_STATE_NA;
329     }
330     else {
331         return DB_ERROR_UNKNOWN;
332     }
333 
334     return DB_OK;
335 }
336 
key_state_key_data_id(const key_state_t * key_state)337 const db_value_t* key_state_key_data_id(const key_state_t* key_state) {
338     if (!key_state) {
339         return NULL;
340     }
341 
342     return &(key_state->key_data_id);
343 }
344 
key_state_type(const key_state_t * key_state)345 key_state_type_t key_state_type(const key_state_t* key_state) {
346     if (!key_state) {
347         return KEY_STATE_TYPE_INVALID;
348     }
349 
350     return key_state->type;
351 }
352 
key_state_type_text(const key_state_t * key_state)353 const char* key_state_type_text(const key_state_t* key_state) {
354     const db_enum_t* enum_set = key_state_enum_set_type;
355 
356     if (!key_state) {
357         return NULL;
358     }
359 
360     while (enum_set->text) {
361         if (enum_set->value == key_state->type) {
362             return enum_set->text;
363         }
364         enum_set++;
365     }
366     return NULL;
367 }
368 
key_state_state(const key_state_t * key_state)369 key_state_state_t key_state_state(const key_state_t* key_state) {
370     if (!key_state) {
371         return KEY_STATE_STATE_INVALID;
372     }
373 
374     return key_state->state;
375 }
376 
key_state_state_text(const key_state_t * key_state)377 const char* key_state_state_text(const key_state_t* key_state) {
378     const db_enum_t* enum_set = key_state_enum_set_state;
379 
380     if (!key_state) {
381         return NULL;
382     }
383 
384     while (enum_set->text) {
385         if (enum_set->value == key_state->state) {
386             return enum_set->text;
387         }
388         enum_set++;
389     }
390     return NULL;
391 }
392 
key_state_last_change(const key_state_t * key_state)393 unsigned int key_state_last_change(const key_state_t* key_state) {
394     if (!key_state) {
395         return 0;
396     }
397 
398     return key_state->last_change;
399 }
400 
key_state_minimize(const key_state_t * key_state)401 unsigned int key_state_minimize(const key_state_t* key_state) {
402     if (!key_state) {
403         return 0;
404     }
405 
406     return key_state->minimize;
407 }
408 
key_state_ttl(const key_state_t * key_state)409 unsigned int key_state_ttl(const key_state_t* key_state) {
410     if (!key_state) {
411         return 0;
412     }
413 
414     return key_state->ttl;
415 }
416 
key_state_set_key_data_id(key_state_t * key_state,const db_value_t * key_data_id)417 int key_state_set_key_data_id(key_state_t* key_state, const db_value_t* key_data_id) {
418     if (!key_state) {
419         return DB_ERROR_UNKNOWN;
420     }
421     if (!key_data_id) {
422         return DB_ERROR_UNKNOWN;
423     }
424     if (db_value_not_empty(key_data_id)) {
425         return DB_ERROR_UNKNOWN;
426     }
427 
428     db_value_reset(&(key_state->key_data_id));
429     if (db_value_copy(&(key_state->key_data_id), key_data_id)) {
430         return DB_ERROR_UNKNOWN;
431     }
432 
433     return DB_OK;
434 }
435 
key_state_set_type(key_state_t * key_state,key_state_type_t type)436 int key_state_set_type(key_state_t* key_state, key_state_type_t type) {
437     if (!key_state) {
438         return DB_ERROR_UNKNOWN;
439     }
440     if (type == KEY_STATE_TYPE_INVALID) {
441         return DB_ERROR_UNKNOWN;
442     }
443 
444     key_state->type = type;
445 
446     return DB_OK;
447 }
448 
key_state_set_state(key_state_t * key_state,key_state_state_t state)449 int key_state_set_state(key_state_t* key_state, key_state_state_t state) {
450     if (!key_state) {
451         return DB_ERROR_UNKNOWN;
452     }
453     if (state == KEY_STATE_STATE_INVALID) {
454         return DB_ERROR_UNKNOWN;
455     }
456 
457     key_state->state = state;
458 
459     return DB_OK;
460 }
461 
key_state_set_last_change(key_state_t * key_state,unsigned int last_change)462 int key_state_set_last_change(key_state_t* key_state, unsigned int last_change) {
463     if (!key_state) {
464         return DB_ERROR_UNKNOWN;
465     }
466 
467     key_state->last_change = last_change;
468 
469     return DB_OK;
470 }
471 
key_state_set_minimize(key_state_t * key_state,unsigned int minimize)472 int key_state_set_minimize(key_state_t* key_state, unsigned int minimize) {
473     if (!key_state) {
474         return DB_ERROR_UNKNOWN;
475     }
476 
477     key_state->minimize = minimize;
478 
479     return DB_OK;
480 }
481 
key_state_set_ttl(key_state_t * key_state,unsigned int ttl)482 int key_state_set_ttl(key_state_t* key_state, unsigned int ttl) {
483     if (!key_state) {
484         return DB_ERROR_UNKNOWN;
485     }
486 
487     key_state->ttl = ttl;
488 
489     return DB_OK;
490 }
491 
key_state_key_data_id_clause(db_clause_list_t * clause_list,const db_value_t * key_data_id)492 db_clause_t* key_state_key_data_id_clause(db_clause_list_t* clause_list, const db_value_t* key_data_id) {
493     db_clause_t* clause;
494 
495     if (!clause_list) {
496         return NULL;
497     }
498     if (!key_data_id) {
499         return NULL;
500     }
501     if (db_value_not_empty(key_data_id)) {
502         return NULL;
503     }
504 
505     if (!(clause = db_clause_new())
506         || db_clause_set_field(clause, "keyDataId")
507         || db_clause_set_type(clause, DB_CLAUSE_EQUAL)
508         || db_clause_set_operator(clause, DB_CLAUSE_OPERATOR_AND)
509         || db_value_copy(db_clause_get_value(clause), key_data_id)
510         || db_clause_list_add(clause_list, clause))
511     {
512         db_clause_free(clause);
513         return NULL;
514     }
515 
516     return clause;
517 }
518 
key_state_create(key_state_t * key_state)519 int key_state_create(key_state_t* key_state) {
520     db_object_field_list_t* object_field_list;
521     db_object_field_t* object_field;
522     db_value_set_t* value_set;
523     int ret;
524 
525     if (!key_state) {
526         return DB_ERROR_UNKNOWN;
527     }
528     if (!key_state->dbo) {
529         return DB_ERROR_UNKNOWN;
530     }
531     if (!db_value_not_empty(&(key_state->id))) {
532         return DB_ERROR_UNKNOWN;
533     }
534     if (!db_value_not_empty(&(key_state->rev))) {
535         return DB_ERROR_UNKNOWN;
536     }
537     if (db_value_not_empty(&(key_state->key_data_id))) {
538         return DB_ERROR_UNKNOWN;
539     }
540     /* TODO: validate content more */
541 
542     if (!(object_field_list = db_object_field_list_new())) {
543         return DB_ERROR_UNKNOWN;
544     }
545 
546     if (!(object_field = db_object_field_new())
547         || db_object_field_set_name(object_field, "keyDataId")
548         || db_object_field_set_type(object_field, DB_TYPE_ANY)
549         || db_object_field_list_add(object_field_list, object_field))
550     {
551         db_object_field_free(object_field);
552         db_object_field_list_free(object_field_list);
553         return DB_ERROR_UNKNOWN;
554     }
555 
556     if (!(object_field = db_object_field_new())
557         || db_object_field_set_name(object_field, "type")
558         || db_object_field_set_type(object_field, DB_TYPE_ENUM)
559         || db_object_field_set_enum_set(object_field, key_state_enum_set_type)
560         || db_object_field_list_add(object_field_list, object_field))
561     {
562         db_object_field_free(object_field);
563         db_object_field_list_free(object_field_list);
564         return DB_ERROR_UNKNOWN;
565     }
566 
567     if (!(object_field = db_object_field_new())
568         || db_object_field_set_name(object_field, "state")
569         || db_object_field_set_type(object_field, DB_TYPE_ENUM)
570         || db_object_field_set_enum_set(object_field, key_state_enum_set_state)
571         || db_object_field_list_add(object_field_list, object_field))
572     {
573         db_object_field_free(object_field);
574         db_object_field_list_free(object_field_list);
575         return DB_ERROR_UNKNOWN;
576     }
577 
578     if (!(object_field = db_object_field_new())
579         || db_object_field_set_name(object_field, "lastChange")
580         || db_object_field_set_type(object_field, DB_TYPE_UINT32)
581         || db_object_field_list_add(object_field_list, object_field))
582     {
583         db_object_field_free(object_field);
584         db_object_field_list_free(object_field_list);
585         return DB_ERROR_UNKNOWN;
586     }
587 
588     if (!(object_field = db_object_field_new())
589         || db_object_field_set_name(object_field, "minimize")
590         || db_object_field_set_type(object_field, DB_TYPE_UINT32)
591         || db_object_field_list_add(object_field_list, object_field))
592     {
593         db_object_field_free(object_field);
594         db_object_field_list_free(object_field_list);
595         return DB_ERROR_UNKNOWN;
596     }
597 
598     if (!(object_field = db_object_field_new())
599         || db_object_field_set_name(object_field, "ttl")
600         || db_object_field_set_type(object_field, DB_TYPE_UINT32)
601         || db_object_field_list_add(object_field_list, object_field))
602     {
603         db_object_field_free(object_field);
604         db_object_field_list_free(object_field_list);
605         return DB_ERROR_UNKNOWN;
606     }
607 
608     if (!(value_set = db_value_set_new(6))) {
609         db_object_field_list_free(object_field_list);
610         return DB_ERROR_UNKNOWN;
611     }
612 
613     if (db_value_copy(db_value_set_get(value_set, 0), &(key_state->key_data_id))
614         || db_value_from_enum_value(db_value_set_get(value_set, 1), key_state->type, key_state_enum_set_type)
615         || db_value_from_enum_value(db_value_set_get(value_set, 2), key_state->state, key_state_enum_set_state)
616         || db_value_from_uint32(db_value_set_get(value_set, 3), key_state->last_change)
617         || db_value_from_uint32(db_value_set_get(value_set, 4), key_state->minimize)
618         || db_value_from_uint32(db_value_set_get(value_set, 5), key_state->ttl))
619     {
620         db_value_set_free(value_set);
621         db_object_field_list_free(object_field_list);
622         return DB_ERROR_UNKNOWN;
623     }
624 
625     ret = db_object_create(key_state->dbo, object_field_list, value_set);
626     db_value_set_free(value_set);
627     db_object_field_list_free(object_field_list);
628     return ret;
629 }
630 
key_state_get_by_id(key_state_t * key_state,const db_value_t * id)631 int key_state_get_by_id(key_state_t* key_state, const db_value_t* id) {
632     db_clause_list_t* clause_list;
633     db_clause_t* clause;
634     db_result_list_t* result_list;
635     const db_result_t* result;
636 
637     if (!key_state) {
638         return DB_ERROR_UNKNOWN;
639     }
640     if (!key_state->dbo) {
641         return DB_ERROR_UNKNOWN;
642     }
643     if (!id) {
644         return DB_ERROR_UNKNOWN;
645     }
646     if (db_value_not_empty(id)) {
647         return DB_ERROR_UNKNOWN;
648     }
649 
650     if (!(clause_list = db_clause_list_new())) {
651         return DB_ERROR_UNKNOWN;
652     }
653     if (!(clause = db_clause_new())
654         || db_clause_set_field(clause, "id")
655         || db_clause_set_type(clause, DB_CLAUSE_EQUAL)
656         || db_value_copy(db_clause_get_value(clause), id)
657         || db_clause_list_add(clause_list, clause))
658     {
659         db_clause_free(clause);
660         db_clause_list_free(clause_list);
661         return DB_ERROR_UNKNOWN;
662     }
663 
664     result_list = db_object_read(key_state->dbo, NULL, clause_list);
665     db_clause_list_free(clause_list);
666 
667     if (result_list) {
668         result = db_result_list_next(result_list);
669         if (result) {
670             if (key_state_from_result(key_state, result)) {
671                 db_result_list_free(result_list);
672                 return DB_ERROR_UNKNOWN;
673             }
674 
675             db_result_list_free(result_list);
676             return DB_OK;
677         }
678     }
679 
680     db_result_list_free(result_list);
681     return DB_ERROR_UNKNOWN;
682 }
683 
key_state_update(key_state_t * key_state)684 int key_state_update(key_state_t* key_state) {
685     db_object_field_list_t* object_field_list;
686     db_object_field_t* object_field;
687     db_value_set_t* value_set;
688     db_clause_list_t* clause_list;
689     db_clause_t* clause;
690     int ret;
691 
692     if (!key_state) {
693         return DB_ERROR_UNKNOWN;
694     }
695     if (!key_state->dbo) {
696         return DB_ERROR_UNKNOWN;
697     }
698     if (db_value_not_empty(&(key_state->id))) {
699         return DB_ERROR_UNKNOWN;
700     }
701     if (db_value_not_empty(&(key_state->rev))) {
702         return DB_ERROR_UNKNOWN;
703     }
704     if (db_value_not_empty(&(key_state->key_data_id))) {
705         return DB_ERROR_UNKNOWN;
706     }
707     /* TODO: validate content more */
708 
709     if (!(object_field_list = db_object_field_list_new())) {
710         return DB_ERROR_UNKNOWN;
711     }
712 
713     if (!(object_field = db_object_field_new())
714         || db_object_field_set_name(object_field, "keyDataId")
715         || db_object_field_set_type(object_field, DB_TYPE_ANY)
716         || db_object_field_list_add(object_field_list, object_field))
717     {
718         db_object_field_free(object_field);
719         db_object_field_list_free(object_field_list);
720         return DB_ERROR_UNKNOWN;
721     }
722 
723     if (!(object_field = db_object_field_new())
724         || db_object_field_set_name(object_field, "type")
725         || db_object_field_set_type(object_field, DB_TYPE_ENUM)
726         || db_object_field_set_enum_set(object_field, key_state_enum_set_type)
727         || db_object_field_list_add(object_field_list, object_field))
728     {
729         db_object_field_free(object_field);
730         db_object_field_list_free(object_field_list);
731         return DB_ERROR_UNKNOWN;
732     }
733 
734     if (!(object_field = db_object_field_new())
735         || db_object_field_set_name(object_field, "state")
736         || db_object_field_set_type(object_field, DB_TYPE_ENUM)
737         || db_object_field_set_enum_set(object_field, key_state_enum_set_state)
738         || db_object_field_list_add(object_field_list, object_field))
739     {
740         db_object_field_free(object_field);
741         db_object_field_list_free(object_field_list);
742         return DB_ERROR_UNKNOWN;
743     }
744 
745     if (!(object_field = db_object_field_new())
746         || db_object_field_set_name(object_field, "lastChange")
747         || db_object_field_set_type(object_field, DB_TYPE_UINT32)
748         || db_object_field_list_add(object_field_list, object_field))
749     {
750         db_object_field_free(object_field);
751         db_object_field_list_free(object_field_list);
752         return DB_ERROR_UNKNOWN;
753     }
754 
755     if (!(object_field = db_object_field_new())
756         || db_object_field_set_name(object_field, "minimize")
757         || db_object_field_set_type(object_field, DB_TYPE_UINT32)
758         || db_object_field_list_add(object_field_list, object_field))
759     {
760         db_object_field_free(object_field);
761         db_object_field_list_free(object_field_list);
762         return DB_ERROR_UNKNOWN;
763     }
764 
765     if (!(object_field = db_object_field_new())
766         || db_object_field_set_name(object_field, "ttl")
767         || db_object_field_set_type(object_field, DB_TYPE_UINT32)
768         || db_object_field_list_add(object_field_list, object_field))
769     {
770         db_object_field_free(object_field);
771         db_object_field_list_free(object_field_list);
772         return DB_ERROR_UNKNOWN;
773     }
774 
775     if (!(value_set = db_value_set_new(6))) {
776         db_object_field_list_free(object_field_list);
777         return DB_ERROR_UNKNOWN;
778     }
779 
780     if (db_value_copy(db_value_set_get(value_set, 0), &(key_state->key_data_id))
781         || db_value_from_enum_value(db_value_set_get(value_set, 1), key_state->type, key_state_enum_set_type)
782         || db_value_from_enum_value(db_value_set_get(value_set, 2), key_state->state, key_state_enum_set_state)
783         || db_value_from_uint32(db_value_set_get(value_set, 3), key_state->last_change)
784         || db_value_from_uint32(db_value_set_get(value_set, 4), key_state->minimize)
785         || db_value_from_uint32(db_value_set_get(value_set, 5), key_state->ttl))
786     {
787         db_value_set_free(value_set);
788         db_object_field_list_free(object_field_list);
789         return DB_ERROR_UNKNOWN;
790     }
791 
792     if (!(clause_list = db_clause_list_new())) {
793         db_value_set_free(value_set);
794         db_object_field_list_free(object_field_list);
795         return DB_ERROR_UNKNOWN;
796     }
797 
798     if (!(clause = db_clause_new())
799         || db_clause_set_field(clause, "id")
800         || db_clause_set_type(clause, DB_CLAUSE_EQUAL)
801         || db_value_copy(db_clause_get_value(clause), &(key_state->id))
802         || db_clause_list_add(clause_list, clause))
803     {
804         db_clause_free(clause);
805         db_clause_list_free(clause_list);
806         db_value_set_free(value_set);
807         db_object_field_list_free(object_field_list);
808         return DB_ERROR_UNKNOWN;
809     }
810 
811     if (!(clause = db_clause_new())
812         || db_clause_set_field(clause, "rev")
813         || db_clause_set_type(clause, DB_CLAUSE_EQUAL)
814         || db_value_copy(db_clause_get_value(clause), &(key_state->rev))
815         || db_clause_list_add(clause_list, clause))
816     {
817         db_clause_free(clause);
818         db_clause_list_free(clause_list);
819         db_value_set_free(value_set);
820         db_object_field_list_free(object_field_list);
821         return DB_ERROR_UNKNOWN;
822     }
823 
824     ret = db_object_update(key_state->dbo, object_field_list, value_set, clause_list);
825     db_value_set_free(value_set);
826     db_object_field_list_free(object_field_list);
827     db_clause_list_free(clause_list);
828     return ret;
829 }
830 
key_state_delete(const key_state_t * key_state)831 int key_state_delete(const key_state_t* key_state) {
832     db_clause_list_t* clause_list;
833     db_clause_t* clause;
834     int ret;
835 
836     if (!key_state) {
837         return DB_ERROR_UNKNOWN;
838     }
839     if (!key_state->dbo) {
840         return DB_ERROR_UNKNOWN;
841     }
842     if (db_value_not_empty(&(key_state->id))) {
843         return DB_ERROR_UNKNOWN;
844     }
845 
846     if (!(clause_list = db_clause_list_new())) {
847         return DB_ERROR_UNKNOWN;
848     }
849 
850     if (!(clause = db_clause_new())
851         || db_clause_set_field(clause, "id")
852         || db_clause_set_type(clause, DB_CLAUSE_EQUAL)
853         || db_value_copy(db_clause_get_value(clause), &(key_state->id))
854         || db_clause_list_add(clause_list, clause))
855     {
856         db_clause_free(clause);
857         db_clause_list_free(clause_list);
858         return DB_ERROR_UNKNOWN;
859     }
860 
861     if (!(clause = db_clause_new())
862         || db_clause_set_field(clause, "rev")
863         || db_clause_set_type(clause, DB_CLAUSE_EQUAL)
864         || db_value_copy(db_clause_get_value(clause), &(key_state->rev))
865         || db_clause_list_add(clause_list, clause))
866     {
867         db_clause_free(clause);
868         db_clause_list_free(clause_list);
869         return DB_ERROR_UNKNOWN;
870     }
871 
872     ret = db_object_delete(key_state->dbo, clause_list);
873     db_clause_list_free(clause_list);
874     return ret;
875 }
876 
877 /* KEY STATE LIST */
878 
879 
880 
key_state_list_new(const db_connection_t * connection)881 key_state_list_t* key_state_list_new(const db_connection_t* connection) {
882     key_state_list_t* key_state_list =
883         (key_state_list_t*)calloc(1, sizeof(key_state_list_t));
884 
885     if (key_state_list) {
886         if (!(key_state_list->dbo = __key_state_new_object(connection))) {
887             free(key_state_list);
888             return NULL;
889         }
890     }
891 
892     return key_state_list;
893 }
894 
key_state_list_new_copy(const key_state_list_t * from_key_state_list)895 key_state_list_t* key_state_list_new_copy(const key_state_list_t* from_key_state_list) {
896     key_state_list_t* key_state_list;
897 
898     if (!from_key_state_list) {
899         return NULL;
900     }
901     if (!from_key_state_list->dbo) {
902         return NULL;
903     }
904 
905     if (!(key_state_list = key_state_list_new(db_object_connection(from_key_state_list->dbo)))
906         || key_state_list_copy(key_state_list, from_key_state_list))
907     {
908         key_state_list_free(key_state_list);
909         return NULL;
910     }
911     return key_state_list;
912 }
913 
key_state_list_object_store(key_state_list_t * key_state_list)914 int key_state_list_object_store(key_state_list_t* key_state_list) {
915     if (!key_state_list) {
916         return DB_ERROR_UNKNOWN;
917     }
918 
919     key_state_list->object_store = 1;
920 
921     return DB_OK;
922 }
923 
key_state_list_free(key_state_list_t * key_state_list)924 void key_state_list_free(key_state_list_t* key_state_list) {
925     size_t i;
926 
927     if (key_state_list) {
928         if (key_state_list->dbo) {
929             db_object_free(key_state_list->dbo);
930         }
931         if (key_state_list->result_list) {
932             db_result_list_free(key_state_list->result_list);
933         }
934         if (key_state_list->key_state) {
935             key_state_free(key_state_list->key_state);
936         }
937         for (i = 0; i < key_state_list->object_list_size; i++) {
938             if (key_state_list->object_list[i]) {
939                 key_state_free(key_state_list->object_list[i]);
940             }
941         }
942         if (key_state_list->object_list) {
943             free(key_state_list->object_list);
944         }
945         if (key_state_list->key_data_id_list) {
946             key_data_list_free(key_state_list->key_data_id_list);
947         }
948         free(key_state_list);
949     }
950 }
951 
key_state_list_copy(key_state_list_t * key_state_list,const key_state_list_t * from_key_state_list)952 int key_state_list_copy(key_state_list_t* key_state_list, const key_state_list_t* from_key_state_list) {
953     size_t i;
954 
955     if (!key_state_list) {
956         return DB_ERROR_UNKNOWN;
957     }
958     if (!from_key_state_list) {
959         return DB_ERROR_UNKNOWN;
960     }
961     if (from_key_state_list->object_list && !from_key_state_list->object_list_size) {
962         return DB_ERROR_UNKNOWN;
963     }
964 
965     if (key_state_list->result_list) {
966         db_result_list_free(key_state_list->result_list);
967         key_state_list->result_list = NULL;
968     }
969     if (from_key_state_list->result_list
970         && !(key_state_list->result_list = db_result_list_new_copy(from_key_state_list->result_list)))
971     {
972         return DB_ERROR_UNKNOWN;
973     }
974 
975     key_state_list->object_store = from_key_state_list->object_store;
976     for (i = 0; i < key_state_list->object_list_size; i++) {
977         if (key_state_list->object_list[i]) {
978             key_state_free(key_state_list->object_list[i]);
979         }
980     }
981     key_state_list->object_list_size = 0;
982     if (key_state_list->object_list) {
983         free(key_state_list->object_list);
984         key_state_list->object_list = NULL;
985     }
986     if (from_key_state_list->object_list) {
987         if (!(key_state_list->object_list = (key_state_t**)calloc(from_key_state_list->object_list_size, sizeof(key_state_t*)))) {
988             return DB_ERROR_UNKNOWN;
989         }
990         key_state_list->object_list_size = from_key_state_list->object_list_size;
991         for (i = 0; i < from_key_state_list->object_list_size; i++) {
992             if (!from_key_state_list->object_list[i]) {
993                 continue;
994             }
995             if (!(key_state_list->object_list[i] = key_state_new_copy(from_key_state_list->object_list[i]))) {
996                 return DB_ERROR_UNKNOWN;
997             }
998         }
999     }
1000     key_state_list->object_list_position = 0;;
1001     key_state_list->object_list_first = 1;
1002     key_state_list->associated_fetch = from_key_state_list->associated_fetch;
1003 
1004     if (from_key_state_list->key_data_id_list
1005         && !(key_state_list->key_data_id_list = key_data_list_new_copy(from_key_state_list->key_data_id_list)))
1006     {
1007         return DB_ERROR_UNKNOWN;
1008     }
1009 
1010     return DB_OK;
1011 }
1012 
key_state_list_get_associated(key_state_list_t * key_state_list)1013 static int key_state_list_get_associated(key_state_list_t* key_state_list) {
1014     const db_clause_t* clause_walk;
1015     const key_data_t* key_data_key_data_id;
1016     int cmp;
1017     size_t i;
1018     db_clause_list_t* clause_list;
1019     db_clause_t* clause;
1020     const key_state_t* key_state;
1021 
1022     if (!key_state_list) {
1023         return DB_ERROR_UNKNOWN;
1024     }
1025     if (!key_state_list->dbo) {
1026         return DB_ERROR_UNKNOWN;
1027     }
1028     if (!key_state_list->associated_fetch) {
1029         return DB_ERROR_UNKNOWN;
1030     }
1031     if (!key_state_list->result_list) {
1032         return DB_ERROR_UNKNOWN;
1033     }
1034     if (key_state_list->object_list) {
1035         return DB_ERROR_UNKNOWN;
1036     }
1037 
1038     if (key_state_list->key_data_id_list) {
1039         key_data_list_free(key_state_list->key_data_id_list);
1040         key_state_list->key_data_id_list = NULL;
1041     }
1042 
1043     if (!(clause_list = db_clause_list_new())) {
1044         return DB_ERROR_UNKNOWN;
1045     }
1046     key_state = key_state_list_begin(key_state_list);
1047     while (key_state) {
1048         cmp = 1;
1049         clause_walk = db_clause_list_begin(clause_list);
1050         while (clause_walk) {
1051             if (db_value_cmp(db_clause_value(clause_walk), key_state_key_data_id(key_state), &cmp)) {
1052                 db_clause_list_free(clause_list);
1053                 return DB_ERROR_UNKNOWN;
1054             }
1055             if (!cmp) {
1056                 break;
1057             }
1058             clause_walk = db_clause_next(clause_walk);
1059         }
1060         if (cmp) {
1061             if (!(clause = db_clause_new())
1062                 || db_clause_set_field(clause, "id")
1063                 || db_clause_set_type(clause, DB_CLAUSE_EQUAL)
1064                 || db_clause_set_operator(clause, DB_CLAUSE_OPERATOR_OR)
1065                 || db_value_copy(db_clause_get_value(clause), key_state_key_data_id(key_state))
1066                 || db_clause_list_add(clause_list, clause))
1067             {
1068                 db_clause_free(clause);
1069                 db_clause_list_free(clause_list);
1070                 return DB_ERROR_UNKNOWN;
1071             }
1072         }
1073 
1074         key_state = key_state_list_next(key_state_list);
1075     }
1076 
1077     if (!(key_state_list->key_data_id_list = key_data_list_new(db_object_connection(key_state_list->dbo)))
1078         || key_data_list_object_store(key_state_list->key_data_id_list)
1079         || key_data_list_get_by_clauses(key_state_list->key_data_id_list, clause_list))
1080     {
1081         if (key_state_list->key_data_id_list) {
1082             key_data_list_free(key_state_list->key_data_id_list);
1083             key_state_list->key_data_id_list = NULL;
1084         }
1085         db_clause_list_free(clause_list);
1086         return DB_ERROR_UNKNOWN;
1087     }
1088     db_clause_list_free(clause_list);
1089 
1090     for (i = 0; i < key_state_list->object_list_size; i++) {
1091         if (!(key_state_list->object_list[i])) {
1092             return DB_ERROR_UNKNOWN;
1093         }
1094 
1095         key_data_key_data_id = key_data_list_begin(key_state_list->key_data_id_list);
1096         while (key_data_key_data_id) {
1097             if (db_value_cmp(key_state_key_data_id(key_state_list->object_list[i]), key_data_id(key_data_key_data_id), &cmp)) {
1098                 return DB_ERROR_UNKNOWN;
1099             }
1100             if (!cmp) {
1101                 key_state_list->object_list[i]->associated_key_data_id = key_data_key_data_id;
1102             }
1103 
1104             key_data_key_data_id = key_data_list_next(key_state_list->key_data_id_list);
1105         }
1106     }
1107 
1108     key_state_list->object_list_first = 1;
1109     return DB_OK;
1110 }
1111 
key_state_list_get_by_clauses(key_state_list_t * key_state_list,const db_clause_list_t * clause_list)1112 int key_state_list_get_by_clauses(key_state_list_t* key_state_list, const db_clause_list_t* clause_list) {
1113     size_t i;
1114 
1115     if (!key_state_list) {
1116         return DB_ERROR_UNKNOWN;
1117     }
1118     if (!clause_list) {
1119         return DB_ERROR_UNKNOWN;
1120     }
1121     if (!key_state_list->dbo) {
1122         return DB_ERROR_UNKNOWN;
1123     }
1124 
1125     if (key_state_list->result_list) {
1126         db_result_list_free(key_state_list->result_list);
1127     }
1128     if (key_state_list->object_list_size) {
1129         for (i = 0; i < key_state_list->object_list_size; i++) {
1130             if (key_state_list->object_list[i]) {
1131                 key_state_free(key_state_list->object_list[i]);
1132             }
1133         }
1134         key_state_list->object_list_size = 0;
1135         key_state_list->object_list_first = 0;
1136     }
1137     if (key_state_list->object_list) {
1138         free(key_state_list->object_list);
1139         key_state_list->object_list = NULL;
1140     }
1141     if (!(key_state_list->result_list = db_object_read(key_state_list->dbo, NULL, clause_list))
1142         || db_result_list_fetch_all(key_state_list->result_list))
1143     {
1144         return DB_ERROR_UNKNOWN;
1145     }
1146     if (key_state_list->associated_fetch
1147         && key_state_list_get_associated(key_state_list))
1148     {
1149         return DB_ERROR_UNKNOWN;
1150     }
1151     return DB_OK;
1152 }
1153 
key_state_list_get_by_key_data_id(key_state_list_t * key_state_list,const db_value_t * key_data_id)1154 int key_state_list_get_by_key_data_id(key_state_list_t* key_state_list, const db_value_t* key_data_id) {
1155     db_clause_list_t* clause_list;
1156     db_clause_t* clause;
1157     size_t i;
1158 
1159     if (!key_state_list) {
1160         return DB_ERROR_UNKNOWN;
1161     }
1162     if (!key_state_list->dbo) {
1163         return DB_ERROR_UNKNOWN;
1164     }
1165     if (!key_data_id) {
1166         return DB_ERROR_UNKNOWN;
1167     }
1168     if (db_value_not_empty(key_data_id)) {
1169         return DB_ERROR_UNKNOWN;
1170     }
1171 
1172     if (!(clause_list = db_clause_list_new())) {
1173         return DB_ERROR_UNKNOWN;
1174     }
1175     if (!(clause = db_clause_new())
1176         || db_clause_set_field(clause, "keyDataId")
1177         || db_clause_set_type(clause, DB_CLAUSE_EQUAL)
1178         || db_value_copy(db_clause_get_value(clause), key_data_id)
1179         || db_clause_list_add(clause_list, clause))
1180     {
1181         db_clause_free(clause);
1182         db_clause_list_free(clause_list);
1183         return DB_ERROR_UNKNOWN;
1184     }
1185 
1186     if (key_state_list->result_list) {
1187         db_result_list_free(key_state_list->result_list);
1188     }
1189     if (key_state_list->object_list_size) {
1190         for (i = 0; i < key_state_list->object_list_size; i++) {
1191             if (key_state_list->object_list[i]) {
1192                 key_state_free(key_state_list->object_list[i]);
1193             }
1194         }
1195         key_state_list->object_list_size = 0;
1196         key_state_list->object_list_first = 0;
1197     }
1198     if (key_state_list->object_list) {
1199         free(key_state_list->object_list);
1200         key_state_list->object_list = NULL;
1201     }
1202     if (!(key_state_list->result_list = db_object_read(key_state_list->dbo, NULL, clause_list))
1203         || db_result_list_fetch_all(key_state_list->result_list))
1204     {
1205         db_clause_list_free(clause_list);
1206         return DB_ERROR_UNKNOWN;
1207     }
1208     db_clause_list_free(clause_list);
1209     if (key_state_list->associated_fetch
1210         && key_state_list_get_associated(key_state_list))
1211     {
1212         return DB_ERROR_UNKNOWN;
1213     }
1214     return DB_OK;
1215 }
1216 
key_state_list_new_get_by_key_data_id(const db_connection_t * connection,const db_value_t * key_data_id)1217 key_state_list_t* key_state_list_new_get_by_key_data_id(const db_connection_t* connection, const db_value_t* key_data_id) {
1218     key_state_list_t* key_state_list;
1219 
1220     if (!connection) {
1221         return NULL;
1222     }
1223     if (!key_data_id) {
1224         return NULL;
1225     }
1226     if (db_value_not_empty(key_data_id)) {
1227         return NULL;
1228     }
1229 
1230     if (!(key_state_list = key_state_list_new(connection))
1231         || key_state_list_get_by_key_data_id(key_state_list, key_data_id))
1232     {
1233         key_state_list_free(key_state_list);
1234         return NULL;
1235     }
1236 
1237     return key_state_list;
1238 }
1239 
key_state_list_begin(key_state_list_t * key_state_list)1240 const key_state_t* key_state_list_begin(key_state_list_t* key_state_list) {
1241     const db_result_t* result;
1242 
1243     if (!key_state_list) {
1244         return NULL;
1245     }
1246 
1247     if (key_state_list->object_store) {
1248         if (!key_state_list->object_list) {
1249             if (!key_state_list->result_list) {
1250                 return NULL;
1251             }
1252             if (!db_result_list_size(key_state_list->result_list)) {
1253                 return NULL;
1254             }
1255             if (!(key_state_list->object_list = (key_state_t**)calloc(db_result_list_size(key_state_list->result_list), sizeof(key_state_t*)))) {
1256                 return NULL;
1257             }
1258             key_state_list->object_list_size = db_result_list_size(key_state_list->result_list);
1259         }
1260         if (!(key_state_list->object_list[0])) {
1261             if (!key_state_list->result_list) {
1262                 return NULL;
1263             }
1264             if (!(result = db_result_list_begin(key_state_list->result_list))) {
1265                 return NULL;
1266             }
1267             if (!(key_state_list->object_list[0] = key_state_new(db_object_connection(key_state_list->dbo)))) {
1268                 return NULL;
1269             }
1270             if (key_state_from_result(key_state_list->object_list[0], result)) {
1271                 return NULL;
1272             }
1273         }
1274         key_state_list->object_list_position = 0;
1275         return key_state_list->object_list[0];
1276     }
1277 
1278     if (!key_state_list->result_list) {
1279         return NULL;
1280     }
1281 
1282     if (!(result = db_result_list_begin(key_state_list->result_list))) {
1283         return NULL;
1284     }
1285     if (!key_state_list->key_state) {
1286         if (!(key_state_list->key_state = key_state_new(db_object_connection(key_state_list->dbo)))) {
1287             return NULL;
1288         }
1289     }
1290     if (key_state_from_result(key_state_list->key_state, result)) {
1291         return NULL;
1292     }
1293     return key_state_list->key_state;
1294 }
1295 
key_state_list_get_begin(key_state_list_t * key_state_list)1296 key_state_t* key_state_list_get_begin(key_state_list_t* key_state_list) {
1297     const db_result_t* result;
1298     key_state_t* key_state;
1299 
1300     if (!key_state_list) {
1301         return NULL;
1302     }
1303 
1304     if (key_state_list->object_store) {
1305         if (!(key_state = key_state_new(db_object_connection(key_state_list->dbo)))) {
1306             return NULL;
1307         }
1308         if (key_state_copy(key_state, key_state_list_begin(key_state_list))) {
1309             key_state_free(key_state);
1310             return NULL;
1311         }
1312         return key_state;
1313     }
1314 
1315     if (!key_state_list->result_list) {
1316         return NULL;
1317     }
1318 
1319     if (!(result = db_result_list_begin(key_state_list->result_list))) {
1320         return NULL;
1321     }
1322     if (!(key_state = key_state_new(db_object_connection(key_state_list->dbo)))) {
1323         return NULL;
1324     }
1325     if (key_state_from_result(key_state, result)) {
1326         key_state_free(key_state);
1327         return NULL;
1328     }
1329     return key_state;
1330 }
1331 
key_state_list_next(key_state_list_t * key_state_list)1332 const key_state_t* key_state_list_next(key_state_list_t* key_state_list) {
1333     const db_result_t* result;
1334 
1335     if (!key_state_list) {
1336         return NULL;
1337     }
1338 
1339     if (key_state_list->object_store) {
1340         if (!key_state_list->object_list) {
1341             if (!key_state_list->result_list) {
1342                 return NULL;
1343             }
1344             if (!db_result_list_size(key_state_list->result_list)) {
1345                 return NULL;
1346             }
1347             if (!(key_state_list->object_list = (key_state_t**)calloc(db_result_list_size(key_state_list->result_list), sizeof(key_state_t*)))) {
1348                 return NULL;
1349             }
1350             key_state_list->object_list_size = db_result_list_size(key_state_list->result_list);
1351             key_state_list->object_list_position = 0;
1352         }
1353         else if (key_state_list->object_list_first) {
1354             key_state_list->object_list_first = 0;
1355             key_state_list->object_list_position = 0;
1356         }
1357         else {
1358             key_state_list->object_list_position++;
1359         }
1360         if (key_state_list->object_list_position >= key_state_list->object_list_size) {
1361             return NULL;
1362         }
1363         if (!(key_state_list->object_list[key_state_list->object_list_position])) {
1364             if (!key_state_list->result_list) {
1365                 return NULL;
1366             }
1367             if (!(result = db_result_list_next(key_state_list->result_list))) {
1368                 return NULL;
1369             }
1370             if (!(key_state_list->object_list[key_state_list->object_list_position] = key_state_new(db_object_connection(key_state_list->dbo)))) {
1371                 return NULL;
1372             }
1373             if (key_state_from_result(key_state_list->object_list[key_state_list->object_list_position], result)) {
1374                 return NULL;
1375             }
1376         }
1377         return key_state_list->object_list[key_state_list->object_list_position];
1378     }
1379 
1380     if (!key_state_list->result_list) {
1381         return NULL;
1382     }
1383 
1384     if (!(result = db_result_list_next(key_state_list->result_list))) {
1385         return NULL;
1386     }
1387     if (!key_state_list->key_state) {
1388         if (!(key_state_list->key_state = key_state_new(db_object_connection(key_state_list->dbo)))) {
1389             return NULL;
1390         }
1391     }
1392     if (key_state_from_result(key_state_list->key_state, result)) {
1393         return NULL;
1394     }
1395     return key_state_list->key_state;
1396 }
1397 
key_state_list_get_next(key_state_list_t * key_state_list)1398 key_state_t* key_state_list_get_next(key_state_list_t* key_state_list) {
1399     const db_result_t* result;
1400     key_state_t* key_state;
1401 
1402     if (!key_state_list) {
1403         return NULL;
1404     }
1405 
1406     if (key_state_list->object_store) {
1407         if (!(key_state = key_state_new(db_object_connection(key_state_list->dbo)))) {
1408             return NULL;
1409         }
1410         if (key_state_copy(key_state, key_state_list_next(key_state_list))) {
1411             key_state_free(key_state);
1412             return NULL;
1413         }
1414         return key_state;
1415     }
1416 
1417     if (!key_state_list->result_list) {
1418         return NULL;
1419     }
1420 
1421     if (!(result = db_result_list_next(key_state_list->result_list))) {
1422         return NULL;
1423     }
1424     if (!(key_state = key_state_new(db_object_connection(key_state_list->dbo)))) {
1425         return NULL;
1426     }
1427     if (key_state_from_result(key_state, result)) {
1428         key_state_free(key_state);
1429         return NULL;
1430     }
1431     return key_state;
1432 }
1433