]>
Commit | Line | Data |
---|---|---|
ee8cd7d0 CP |
1 | /* |
2 | * SQLite module | |
3 | */ | |
4 | ||
5 | #include "../core/config.h" | |
6 | #include "../core/error.h" | |
7 | #include "../irc/irc_config.h" | |
8 | #include "../core/events.h" | |
9 | #include "../core/hooks.h" | |
10 | #include "../lib/irc_string.h" | |
11 | #include "../lib/version.h" | |
12 | #include "../lib/strlfunc.h" | |
76c8da69 | 13 | #include "../core/nsmalloc.h" |
ee8cd7d0 | 14 | #include "sqlite.h" |
827cbcd7 CP |
15 | |
16 | #define BUILDING_DBAPI | |
ee8cd7d0 CP |
17 | #include "../dbapi/dbapi.h" |
18 | ||
19 | #include <stdlib.h> | |
20 | #include <sys/poll.h> | |
21 | #include <stdarg.h> | |
22 | #include <string.h> | |
23 | ||
24 | MODULE_VERSION(""); | |
25 | ||
26 | static int dbconnected = 0; | |
27 | static struct sqlite3 *conn; | |
28 | ||
76c8da69 CP |
29 | #define SYNC_MODE "OFF" |
30 | ||
ee8cd7d0 CP |
31 | void _init(void) { |
32 | sstring *dbfile; | |
33 | int rc; | |
34 | ||
35 | dbfile = getcopyconfigitem("sqlite", "file", "newserv.db", 100); | |
36 | ||
37 | if(!dbfile) | |
38 | return; | |
39 | ||
40 | rc = sqlite3_open(dbfile->content, &conn); | |
41 | freesstring(dbfile); | |
42 | ||
43 | if(rc) { | |
44 | Error("sqlite", ERR_ERROR, "Unable to connect to database: %s", sqlite3_errmsg(conn)); | |
45 | return; | |
46 | } | |
47 | ||
48 | dbconnected = 1; | |
49 | ||
76c8da69 | 50 | sqliteasyncqueryf(0, NULL, NULL, 0, "PRAGMA synchronous=" SYNC_MODE ";"); |
ee8cd7d0 CP |
51 | } |
52 | ||
53 | void _fini(void) { | |
54 | if(!sqliteconnected()) | |
55 | return; | |
56 | ||
57 | sqlite3_close(conn); | |
58 | ||
59 | dbconnected = 0; | |
76c8da69 | 60 | nscheckfreeall(POOL_SQLITE); |
ee8cd7d0 CP |
61 | } |
62 | ||
63 | void sqliteasyncqueryf(int identifier, SQLiteQueryHandler handler, void *tag, int flags, char *format, ...) { | |
64 | char querybuf[8192]; | |
65 | va_list va; | |
66 | int len; | |
67 | int rc; | |
68 | sqlite3_stmt *s; | |
69 | ||
70 | if(!sqliteconnected()) | |
71 | return; | |
72 | ||
73 | va_start(va, format); | |
74 | len = vsnprintf(querybuf, sizeof(querybuf), format, va); | |
75 | va_end(va); | |
76 | ||
77 | rc = sqlite3_prepare(conn, querybuf, -1, &s, NULL); | |
78 | if(rc != SQLITE_OK) { | |
79 | if(flags != DB_CREATE) | |
80 | Error("sqlite", ERR_WARNING, "SQL error %d: %s (query: %s)", rc, sqlite3_errmsg(conn), querybuf); | |
81 | if(handler) | |
82 | handler(NULL, tag); | |
83 | return; | |
84 | } | |
85 | ||
86 | if(handler) { | |
87 | handler(s, tag); | |
88 | } else { | |
89 | rc = sqlite3_step(s); | |
90 | if(rc != SQLITE_DONE) | |
91 | Error("sqlite", ERR_WARNING, "SQL error %d: %s (query: %s)", rc, sqlite3_errmsg(conn), querybuf); | |
92 | } | |
93 | } | |
94 | ||
95 | int sqliteconnected(void) { | |
96 | return dbconnected; | |
97 | } | |
98 | ||
99 | void sqliteescapestring(char *buf, char *src, unsigned int len) { | |
100 | unsigned int i; | |
101 | char *p; | |
102 | ||
103 | for(p=src,i=0;i<len;i++,p++) { | |
104 | if(*p == '\'') | |
105 | *buf++ = *p; | |
106 | *buf++ = *p; | |
107 | } | |
108 | *buf = '\0'; | |
109 | } | |
110 | ||
111 | SQLiteResult *sqlitegetresult(SQLiteConn *r) { | |
112 | SQLiteResult *r2; | |
113 | if(!r) | |
114 | return NULL; | |
115 | ||
76c8da69 | 116 | r2 = (SQLiteResult *)nsmalloc(POOL_SQLITE, sizeof(SQLiteResult)); |
ee8cd7d0 CP |
117 | r2->r = r; |
118 | return r2; | |
119 | } | |
120 | ||
121 | int sqlitefetchrow(SQLiteResult *r) { | |
122 | int rc = sqlite3_step(r->r); | |
123 | if(rc != SQLITE_ROW) | |
124 | return 0; | |
125 | ||
126 | return 1; | |
127 | } | |
128 | ||
129 | void sqliteclear(SQLiteResult *r) { | |
130 | if(!r) | |
131 | return; | |
132 | ||
133 | if(r->r) | |
134 | sqlite3_finalize(r->r); | |
135 | ||
76c8da69 | 136 | nsfree(POOL_SQLITE, r); |
ee8cd7d0 CP |
137 | } |
138 | ||
139 | int sqlitequerysuccessful(SQLiteResult *r) { | |
140 | if(r && r->r) | |
141 | return 1; | |
142 | ||
143 | return 0; | |
144 | } | |
145 | ||
146 | void sqliteloadtable(char *tablename, SQLiteQueryHandler init, SQLiteQueryHandler data, SQLiteQueryHandler fini) { | |
147 | int rc; | |
148 | sqlite3_stmt *s; | |
149 | char buf[1024]; | |
150 | ||
151 | if(!sqliteconnected()) | |
152 | return; | |
153 | ||
154 | snprintf(buf, sizeof(buf), "SELECT COUNT(*) FROM %s", tablename); | |
155 | rc = sqlite3_prepare(conn, buf, -1, &s, NULL); | |
156 | if(rc != SQLITE_OK) { | |
157 | Error("sqlite", ERR_ERROR, "Error getting row count for %s.", tablename); | |
158 | return; | |
159 | } | |
160 | ||
161 | rc = sqlite3_step(s); | |
162 | if(rc != SQLITE_ROW) { | |
163 | Error("sqlite", ERR_ERROR, "Error getting row count for %s.", tablename); | |
164 | sqlite3_finalize(s); | |
165 | return; | |
166 | } | |
167 | ||
827cbcd7 | 168 | Error("sqlite", ERR_INFO, "Found %s entries in table %s, loading...", (char *)sqlite3_column_text(s, 0), tablename); |
ee8cd7d0 CP |
169 | sqlite3_finalize(s); |
170 | ||
171 | snprintf(buf, sizeof(buf), "SELECT * FROM %s", tablename); | |
172 | rc = sqlite3_prepare(conn, buf, -1, &s, NULL); | |
173 | ||
174 | if(rc != SQLITE_OK) { | |
175 | Error("sqlite", ERR_WARNING, "SQL error %d: %s", rc, sqlite3_errmsg(conn)); | |
176 | return; | |
177 | } | |
178 | ||
179 | if(init) | |
180 | init(s, NULL); | |
181 | data(s, NULL); | |
182 | if(fini) | |
183 | fini(s, NULL); | |
184 | } | |
76c8da69 CP |
185 | |
186 | void sqlitecreateschema(char *schema) { | |
187 | sqliteasyncqueryf(0, NULL, NULL, 0, "ATTACH DATABASE '%s.db' AS %s", schema, schema); | |
188 | sqliteasyncqueryf(0, NULL, NULL, 0, "PRAGMA %s.synchronous=" SYNC_MODE ";", schema); | |
189 | } |