]>
git.proxmox.com Git - mirror_frr.git/blob - lib/db.c
2 * Copyright (c) 2018 Rafael Zalamena <rzalamena@gmail.com>
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the Free
6 * Software Foundation; either version 2 of the License, or (at your option)
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * You should have received a copy of the GNU General Public License along
15 * with this program; see the file COPYING; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 * Copyright (c) 2016 Rafael Zalamena <rzalamena@gmail.com>
22 * Permission to use, copy, modify, and/or distribute this software for any
23 * purpose with or without fee is hereby granted, provided that the above
24 * copyright notice and this permission notice appear in all copies.
26 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
27 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
28 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
29 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
30 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
31 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
32 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
40 static struct sqlite3
*dbp
;
43 * Initialize the database in path.
45 * It's possible to use in memory database with ':memory:' path.
47 int db_init(const char *path_fmt
, ...)
55 va_start(ap
, path_fmt
);
56 vsnprintf(path
, sizeof(path
), path_fmt
, ap
);
59 if (sqlite3_open_v2(path
, &dbp
,
60 (SQLITE_OPEN_READWRITE
| SQLITE_OPEN_CREATE
), NULL
)
63 zlog_warn("%s: failed to open dabatase '%s'", __func__
,
68 zlog_warn("%s: failed to open database '%s': %s", __func__
,
69 path
, sqlite3_errmsg(dbp
));
70 if (sqlite3_close_v2(dbp
) != SQLITE_OK
)
71 zlog_warn("%s: failed to terminate database", __func__
);
79 /* Closes the database if open. */
85 if (sqlite3_close_v2(dbp
) != SQLITE_OK
) {
86 zlog_warn("%s: failed to terminate database", __func__
);
92 /* Helper function to handle formating. */
93 static int db_vbindf(struct sqlite3_stmt
*ss
, const char *fmt
, va_list vl
)
95 const char *sptr
= fmt
;
108 if (sptr
++ && *sptr
== 0)
113 uinteger
= va_arg(vl
, uint32_t);
114 if (sqlite3_bind_int(ss
, column
++, uinteger
)
119 uinteger64
= va_arg(vl
, uint64_t);
120 if (sqlite3_bind_int64(ss
, column
++, uinteger64
)
125 str
= va_arg(vl
, const char *);
126 vlen
= va_arg(vl
, int);
127 if (sqlite3_bind_text(ss
, column
++, str
, vlen
,
133 blob
= va_arg(vl
, void *);
134 vlen
= va_arg(vl
, int);
135 if (sqlite3_bind_blob(ss
, column
++, blob
, vlen
,
141 if (sqlite3_bind_null(ss
, column
++) != SQLITE_OK
)
145 zlog_warn("%s: invalid format '%c'", __func__
, *sptr
);
154 * Binds values using format to the database query.
156 * Might be used to bind variables to a query, insert or update.
158 int db_bindf(struct sqlite3_stmt
*ss
, const char *fmt
, ...)
164 result
= db_vbindf(ss
, fmt
, vl
);
170 /* Prepares an statement to the database with the statement length. */
171 struct sqlite3_stmt
*db_prepare_len(const char *stmt
, int stmtlen
)
173 struct sqlite3_stmt
*ss
;
179 c
= sqlite3_prepare_v2(dbp
, stmt
, stmtlen
, &ss
, NULL
);
181 zlog_warn("%s: failed to prepare (%d:%s)", __func__
, c
,
182 sqlite3_errmsg(dbp
));
189 /* Prepares an statement to the database. */
190 struct sqlite3_stmt
*db_prepare(const char *stmt
)
192 return db_prepare_len(stmt
, strlen(stmt
));
195 /* Run a prepared statement. */
196 int db_run(struct sqlite3_stmt
*ss
)
200 result
= sqlite3_step(ss
);
203 /* TODO handle busy database. */
208 * SQLITE_DONE just causes confusion since it means the query went OK,
209 * but it has a different value.
217 /* It is expected to receive SQLITE_ROW on search queries. */
221 zlog_warn("%s: step failed (%d:%s)", __func__
, result
,
222 sqlite3_errstr(result
));
228 /* Helper function to load format to variables. */
229 static int db_vloadf(struct sqlite3_stmt
*ss
, const char *fmt
, va_list vl
)
231 const char *sptr
= fmt
;
236 uint64_t *uinteger64
;
242 columncount
= sqlite3_column_count(ss
);
243 if (columncount
== 0)
251 if (sptr
++ && *sptr
== 0)
256 uinteger
= va_arg(vl
, uint32_t *);
257 *uinteger
= sqlite3_column_int(ss
, column
);
260 uinteger64
= va_arg(vl
, uint64_t *);
261 *uinteger64
= sqlite3_column_int64(ss
, column
);
264 str
= va_arg(vl
, const char **);
265 *str
= (const char *)sqlite3_column_text(ss
, column
);
268 blob
= va_arg(vl
, void *);
269 vlen
= va_arg(vl
, int);
270 dlen
= sqlite3_column_bytes(ss
, column
);
271 blobsrc
= sqlite3_column_blob(ss
, column
);
272 memcpy(blob
, blobsrc
, MIN(vlen
, dlen
));
275 zlog_warn("%s: invalid format '%c'", __func__
, *sptr
);
285 /* Function to load format from database row. */
286 int db_loadf(struct sqlite3_stmt
*ss
, const char *fmt
, ...)
292 result
= db_vloadf(ss
, fmt
, vl
);
298 /* Finalize query and return memory. */
299 void db_finalize(struct sqlite3_stmt
**ss
)
301 sqlite3_finalize(*ss
);
305 /* Execute one or more statements. */
306 int db_execute(const char *stmt_fmt
, ...)
314 va_start(ap
, stmt_fmt
);
315 vsnprintf(stmt
, sizeof(stmt
), stmt_fmt
, ap
);
318 if (sqlite3_exec(dbp
, stmt
, NULL
, 0, NULL
) != SQLITE_OK
) {
319 zlog_warn("%s: failed to execute statement(s): %s", __func__
,
320 sqlite3_errmsg(dbp
));