]> jfr.im git - irc/rqf/shadowircd.git/blame - bandb/rsdb_sqlite3.c
Update FAQ.
[irc/rqf/shadowircd.git] / bandb / rsdb_sqlite3.c
CommitLineData
7641ecd8
WP
1/* src/rsdb_sqlite.h
2 * Contains the code for the sqlite database backend.
3 *
4 * Copyright (C) 2003-2006 Lee Hardy <leeh@leeh.co.uk>
5 * Copyright (C) 2003-2006 ircd-ratbox development team
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are
9 * met:
10 *
11 * 1.Redistributions of source code must retain the above copyright notice,
12 * this list of conditions and the following disclaimer.
13 * 2.Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3.The name of the author may not be used to endorse or promote products
17 * derived from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
23 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
27 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
28 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 *
31 * $Id: rsdb_sqlite3.c 26182 2008-11-11 02:52:41Z androsyn $
32 */
33#include "stdinc.h"
34#include "rsdb.h"
35
36#include <sqlite3.h>
37
38struct sqlite3 *rb_bandb;
39
40rsdb_error_cb *error_cb;
41
42static void
43mlog(const char *errstr, ...)
44{
45 if(error_cb != NULL)
46 {
47 char buf[256];
48 va_list ap;
49 va_start(ap, errstr);
50 rb_vsnprintf(buf, sizeof(buf), errstr, ap);
51 va_end(ap);
52 error_cb(buf);
53 }
54 else
55 exit(1);
56}
57
58int
59rsdb_init(rsdb_error_cb * ecb)
60{
61 const char *bandb_dpath;
62 char dbpath[PATH_MAX];
63 char errbuf[128];
64 error_cb = ecb;
65
66 /* try a path from the environment first, useful for basedir overrides */
67 bandb_dpath = getenv("BANDB_DPATH");
68
69 if(bandb_dpath != NULL)
70 rb_snprintf(dbpath, sizeof(dbpath), "%s/etc/ban.db", bandb_dpath);
71 else
72 rb_strlcpy(dbpath, DBPATH, sizeof(dbpath));
73
74 if(sqlite3_open(dbpath, &rb_bandb) != SQLITE_OK)
75 {
76 rb_snprintf(errbuf, sizeof(errbuf), "Unable to open sqlite database: %s",
77 sqlite3_errmsg(rb_bandb));
78 mlog(errbuf);
79 return -1;
80 }
81 if(access(dbpath, W_OK))
82 {
83 rb_snprintf(errbuf, sizeof(errbuf), "Unable to open sqlite database for write: %s", strerror(errno));
84 mlog(errbuf);
85 return -1;
86 }
87 return 0;
88}
89
90void
91rsdb_shutdown(void)
92{
93 if(rb_bandb)
94 sqlite3_close(rb_bandb);
95}
96
97const char *
98rsdb_quote(const char *src)
99{
100 static char buf[BUFSIZE * 4];
101 char *p = buf;
102
103 /* cheap and dirty length check.. */
104 if(strlen(src) >= (sizeof(buf) / 2))
105 return NULL;
106
107 while(*src)
108 {
109 if(*src == '\'')
110 *p++ = '\'';
111
112 *p++ = *src++;
113 }
114
115 *p = '\0';
116 return buf;
117}
118
119static int
120rsdb_callback_func(void *cbfunc, int argc, char **argv, char **colnames)
121{
122 rsdb_callback cb = (rsdb_callback)((uintptr_t)cbfunc);
123 (cb) (argc, (const char **)argv);
124 return 0;
125}
126
127void
128rsdb_exec(rsdb_callback cb, const char *format, ...)
129{
130 static char buf[BUFSIZE * 4];
131 va_list args;
132 char *errmsg;
133 unsigned int i;
134 int j;
135
136 va_start(args, format);
137 i = rs_vsnprintf(buf, sizeof(buf), format, args);
138 va_end(args);
139
140 if(i >= sizeof(buf))
141 {
142 mlog("fatal error: length problem with compiling sql");
143 }
144
145 if((i = sqlite3_exec(rb_bandb, buf, (cb ? rsdb_callback_func : NULL), (void *)((uintptr_t)cb), &errmsg)))
146 {
147 switch (i)
148 {
149 case SQLITE_BUSY:
150 for(j = 0; j < 5; j++)
151 {
152 rb_sleep(0, 500000);
153 if(!sqlite3_exec
154 (rb_bandb, buf, (cb ? rsdb_callback_func : NULL), (void *)((uintptr_t)cb), &errmsg))
155 return;
156 }
157
158 /* failed, fall through to default */
159 mlog("fatal error: problem with db file: %s", errmsg);
160 break;
161
162 default:
163 mlog("fatal error: problem with db file: %s", errmsg);
164 break;
165 }
166 }
167}
168
169void
170rsdb_exec_fetch(struct rsdb_table *table, const char *format, ...)
171{
172 static char buf[BUFSIZE * 4];
173 va_list args;
174 char *errmsg;
175 char **data;
176 int pos;
177 unsigned int retval;
178 int i, j;
179
180 va_start(args, format);
181 retval = rs_vsnprintf(buf, sizeof(buf), format, args);
182 va_end(args);
183
184 if(retval >= sizeof(buf))
185 {
186 mlog("fatal error: length problem with compiling sql");
187 }
188
189 if((retval =
190 sqlite3_get_table(rb_bandb, buf, &data, &table->row_count, &table->col_count, &errmsg)))
191 {
192 int success = 0;
193
194 switch (retval)
195 {
196 case SQLITE_BUSY:
197 for(i = 0; i < 5; i++)
198 {
199 rb_sleep(0, 500000);
200 if(!sqlite3_get_table
201 (rb_bandb, buf, &data, &table->row_count, &table->col_count,
202 &errmsg))
203 {
204 success++;
205 break;
206 }
207 }
208
209 if(success)
210 break;
211
212 mlog("fatal error: problem with db file: %s", errmsg);
213 break;
214
215 default:
216 mlog("fatal error: problem with db file: %s", errmsg);
217 break;
218 }
219 }
220
221 /* we need to be able to free data afterward */
222 table->arg = data;
223
224 if(table->row_count == 0)
225 {
226 table->row = NULL;
227 return;
228 }
229
230 /* sqlite puts the column names as the first row */
231 pos = table->col_count;
232 table->row = rb_malloc(sizeof(char **) * table->row_count);
233 for(i = 0; i < table->row_count; i++)
234 {
235 table->row[i] = rb_malloc(sizeof(char *) * table->col_count);
236
237 for(j = 0; j < table->col_count; j++)
238 {
239 table->row[i][j] = data[pos++];
240 }
241 }
242}
243
244void
245rsdb_exec_fetch_end(struct rsdb_table *table)
246{
247 int i;
248
249 for(i = 0; i < table->row_count; i++)
250 {
251 rb_free(table->row[i]);
252 }
253 rb_free(table->row);
254
255 sqlite3_free_table((char **)table->arg);
256}
257
258void
259rsdb_transaction(rsdb_transtype type)
260{
261 if(type == RSDB_TRANS_START)
262 rsdb_exec(NULL, "BEGIN TRANSACTION");
263 else if(type == RSDB_TRANS_END)
264 rsdb_exec(NULL, "COMMIT TRANSACTION");
265}