]> jfr.im git - solanum.git/blob - bandb/rsdb_sqlite3.c
Terminate last line in setfilter help
[solanum.git] / bandb / rsdb_sqlite3.c
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 #include "stdinc.h"
32 #include "rsdb.h"
33
34 #include <sqlite3.h>
35
36 struct sqlite3 *rb_bandb;
37
38 rsdb_error_cb *error_cb;
39
40 static void
41 mlog(const char *errstr, ...)
42 {
43 if(error_cb != NULL)
44 {
45 char buf[256];
46 va_list ap;
47 va_start(ap, errstr);
48 vsnprintf(buf, sizeof(buf), errstr, ap);
49 va_end(ap);
50 error_cb(buf);
51 }
52 else
53 exit(1);
54 }
55
56 int
57 rsdb_init(rsdb_error_cb * ecb)
58 {
59 const char *bandb_dbpath_env;
60 char dbpath[PATH_MAX];
61 char errbuf[128];
62 error_cb = ecb;
63
64 /* try a path from the environment first, useful for basedir overrides */
65 bandb_dbpath_env = getenv("BANDB_DBPATH");
66
67 if(bandb_dbpath_env != NULL)
68 rb_strlcpy(dbpath, bandb_dbpath_env, sizeof(dbpath));
69 else
70 rb_strlcpy(dbpath, DBPATH, sizeof(dbpath));
71
72 if(sqlite3_open(dbpath, &rb_bandb) != SQLITE_OK)
73 {
74 snprintf(errbuf, sizeof(errbuf), "Unable to open sqlite database: %s",
75 sqlite3_errmsg(rb_bandb));
76 mlog(errbuf);
77 return -1;
78 }
79 if(access(dbpath, W_OK))
80 {
81 snprintf(errbuf, sizeof(errbuf), "Unable to open sqlite database for write: %s", strerror(errno));
82 mlog(errbuf);
83 return -1;
84 }
85 return 0;
86 }
87
88 void
89 rsdb_shutdown(void)
90 {
91 if(rb_bandb)
92 sqlite3_close(rb_bandb);
93 }
94
95 const char *
96 rsdb_quote(const char *src)
97 {
98 static char buf[BUFSIZE * 4];
99 char *p = buf;
100
101 /* cheap and dirty length check.. */
102 if(strlen(src) >= (sizeof(buf) / 2))
103 return NULL;
104
105 while(*src)
106 {
107 if(*src == '\'')
108 *p++ = '\'';
109
110 *p++ = *src++;
111 }
112
113 *p = '\0';
114 return buf;
115 }
116
117 static int
118 rsdb_callback_func(void *cbfunc, int argc, char **argv, char **colnames)
119 {
120 rsdb_callback cb = (rsdb_callback)((uintptr_t)cbfunc);
121 (cb) (argc, (const char **)(void *)argv);
122 return 0;
123 }
124
125 void
126 rsdb_exec(rsdb_callback cb, const char *format, ...)
127 {
128 static char buf[BUFSIZE * 4];
129 va_list args;
130 char *errmsg;
131 unsigned int i;
132 int j;
133
134 va_start(args, format);
135 i = rs_vsnprintf(buf, sizeof(buf), format, args);
136 va_end(args);
137
138 if(i >= sizeof(buf))
139 {
140 mlog("fatal error: length problem with compiling sql");
141 }
142
143 if((i = sqlite3_exec(rb_bandb, buf, (cb ? rsdb_callback_func : NULL), (void *)((uintptr_t)cb), &errmsg)))
144 {
145 switch (i)
146 {
147 case SQLITE_BUSY:
148 for(j = 0; j < 5; j++)
149 {
150 rb_sleep(0, 500000);
151 if(!sqlite3_exec
152 (rb_bandb, buf, (cb ? rsdb_callback_func : NULL), (void *)((uintptr_t)cb), &errmsg))
153 return;
154 }
155
156 /* failed, fall through to default */
157 mlog("fatal error: problem with db file: %s", errmsg);
158 break;
159
160 default:
161 mlog("fatal error: problem with db file: %s", errmsg);
162 break;
163 }
164 }
165 }
166
167 void
168 rsdb_exec_fetch(struct rsdb_table *table, const char *format, ...)
169 {
170 static char buf[BUFSIZE * 4];
171 va_list args;
172 char *errmsg;
173 char **data;
174 int pos;
175 unsigned int retval;
176 int i, j;
177
178 va_start(args, format);
179 retval = rs_vsnprintf(buf, sizeof(buf), format, args);
180 va_end(args);
181
182 if(retval >= sizeof(buf))
183 {
184 mlog("fatal error: length problem with compiling sql");
185 }
186
187 if((retval =
188 sqlite3_get_table(rb_bandb, buf, &data, &table->row_count, &table->col_count, &errmsg)))
189 {
190 int success = 0;
191
192 switch (retval)
193 {
194 case SQLITE_BUSY:
195 for(i = 0; i < 5; i++)
196 {
197 rb_sleep(0, 500000);
198 if(!sqlite3_get_table
199 (rb_bandb, buf, &data, &table->row_count, &table->col_count,
200 &errmsg))
201 {
202 success++;
203 break;
204 }
205 }
206
207 if(success)
208 break;
209
210 mlog("fatal error: problem with db file: %s", errmsg);
211 break;
212
213 default:
214 mlog("fatal error: problem with db file: %s", errmsg);
215 break;
216 }
217 }
218
219 /* we need to be able to free data afterward */
220 table->arg = data;
221
222 if(table->row_count == 0)
223 {
224 table->row = NULL;
225 return;
226 }
227
228 /* sqlite puts the column names as the first row */
229 pos = table->col_count;
230 table->row = rb_malloc(sizeof(char **) * table->row_count);
231 for(i = 0; i < table->row_count; i++)
232 {
233 table->row[i] = rb_malloc(sizeof(char *) * table->col_count);
234
235 for(j = 0; j < table->col_count; j++)
236 {
237 table->row[i][j] = data[pos++];
238 }
239 }
240 }
241
242 void
243 rsdb_exec_fetch_end(struct rsdb_table *table)
244 {
245 int i;
246
247 for(i = 0; i < table->row_count; i++)
248 {
249 rb_free(table->row[i]);
250 }
251 rb_free(table->row);
252
253 sqlite3_free_table((char **)table->arg);
254 }
255
256 void
257 rsdb_transaction(rsdb_transtype type)
258 {
259 if(type == RSDB_TRANS_START)
260 rsdb_exec(NULL, "BEGIN TRANSACTION");
261 else if(type == RSDB_TRANS_END)
262 rsdb_exec(NULL, "COMMIT TRANSACTION");
263 }