Kannel: Open Source WAP and SMS gateway  svn-r5335
sqlbox_sqlite.c
Go to the documentation of this file.
1 #include "gwlib/gwlib.h"
2 #ifdef HAVE_SQLITE
3 #include "gwlib/dbpool.h"
4 #include <sqlite.h>
5 #include "sqlbox_sqlite.h"
6 
7 #define sql_update sqlite_update
8 #define sql_select sqlite_select
9 
10 static Octstr *sqlbox_logtable;
11 static Octstr *sqlbox_insert_table;
12 
13 /*
14  * Our connection pool to sqlite.
15  */
16 
17 static DBPool *pool = NULL;
18 
19 /*
20  *-------------------------------------------------
21  * sqlite thingies
22  *-------------------------------------------------
23 */
24 
25 #define octstr_null_create(x) ((x != NULL) ? octstr_create(x) : octstr_create(""))
26 #define atol_null(x) ((x != NULL) ? atol(x) : -1)
27 
28 static int sqlite_update(DBPoolConn *conn, const Octstr *sql)
29 {
30  int state;
31  char *errmsg = 0;
32  //struct DBPoolConn *conn = (struct DBPoolConn*) theconn;
33 
34 #if defined(SQLBOX_TRACE)
35  debug("SQLBOX", 0, "sql: %s", octstr_get_cstr(sql));
36 #endif
37 
38  state = sqlite_exec(conn->conn, octstr_get_cstr(sql), NULL, 0, &errmsg);
39  if (state != SQLITE_OK) {
40  error(0, "SQLITE: %s", errmsg);
41  return -1;
42  }
43  return sqlite_changes(conn->conn);
44 }
45 
46 sqlite_vm* sqlite_select(DBPoolConn *conn, const Octstr *sql)
47 {
48  int res;
49  char *errmsg = 0;
50  const char *query_tail = NULL;
51  sqlite_vm *vm = NULL;
52  //struct DBPoolConn *conn = (struct DBPoolConn*) theconn;
53 
54 #if defined(SQLBOX_TRACE)
55  debug("SQLBOX", 0, "sql: %s", octstr_get_cstr(sql));
56 #endif
57 
58  res = sqlite_compile(conn->conn, octstr_get_cstr(sql), &query_tail, &vm, &errmsg);
59  if (res != SQLITE_OK) {
60  error(0, "SQLITE: Could not compile query: %s", errmsg);
61  return NULL;
62  }
63  return vm;
64 }
65 
66 void sqlbox_configure_sqlite(Cfg* cfg)
67 {
68  CfgGroup *grp;
69  Octstr *sql;
70  DBPoolConn *pc;
71 
72  if (!(grp = cfg_get_single_group(cfg, octstr_imm("sqlbox"))))
73  panic(0, "SQLBOX: Sqlite: group 'sqlbox' is not specified!");
74 
75  sqlbox_logtable = cfg_get(grp, octstr_imm("sql-log-table"));
76  if (sqlbox_logtable == NULL) {
77  panic(0, "Parameter 'sql-log-table' not configured.");
78  }
79  sqlbox_insert_table = cfg_get(grp, octstr_imm("sql-insert-table"));
80  if (sqlbox_insert_table == NULL) {
81  panic(0, "Parameter 'sql-insert-table' not configured.");
82  }
83 
84  pc = dbpool_conn_consume(pool);
85  if (pc == NULL) {
86  error(0, "SQLITE: Database pool got no connection! DB update failed!");
87  return;
88  }
89 
90  /* create send_sms && sent_sms tables if they do not exist */
91  sql = octstr_format(SQLBOX_SQLITE_CREATE_LOG_TABLE, sqlbox_logtable);
92  sql_update(pc, sql);
93  octstr_destroy(sql);
94  sql = octstr_format(SQLBOX_SQLITE_CREATE_INSERT_TABLE, sqlbox_insert_table);
95  sql_update(pc, sql);
96  octstr_destroy(sql);
97  /* end table creation */
99 }
100 
101 Msg *sqlite_fetch_msg()
102 {
103  int state;
104  DBPoolConn *pc;
105  char *errmsg = 0;
106  const char *query_tail = NULL;
107  sqlite_vm *res = NULL;
108  int i, cols = 0, rows = 0;
109  const char **row = NULL;
110  const char **col_name = NULL;
111 
112  Msg *msg = NULL;
113  Octstr *sql, *delet, *id;
114 
115  pc = dbpool_conn_consume(pool);
116  if (pc == NULL) {
117  error(0, "SQLITE: Database pool got no connection! DB update failed!");
118  return NULL;
119  }
120 
121  sql = octstr_format(SQLBOX_SQLITE_SELECT_QUERY, sqlbox_insert_table);
122 #if defined(SQLBOX_TRACE)
123  debug("SQLBOX", 0, "sql: %s", octstr_get_cstr(sql));
124 #endif
125  res = sql_select(pc, sql);
126  do {
127  state=sqlite_step(res, &cols, &row, &col_name);
128  if (state==SQLITE_ROW){
129  rows++;
130  id = octstr_null_create(row[0]);
131  /* save fields in this row as msg struct */
132  msg = msg_create(sms);
133  /* we abuse the foreign_id field in the message struct for our sql_id value */
134  msg->sms.foreign_id = octstr_null_create(row[0]);
135  msg->sms.sender = octstr_null_create(row[2]);
136  msg->sms.receiver = octstr_null_create(row[3]);
137  msg->sms.udhdata = octstr_null_create(row[4]);
138  msg->sms.msgdata = octstr_null_create(row[5]);
139  msg->sms.time = atol_null(row[6]);
140  msg->sms.smsc_id = octstr_null_create(row[7]);
141  msg->sms.service = octstr_null_create(row[8]);
142  msg->sms.account = octstr_null_create(row[9]);
143  /* msg->sms.id = atol_null(row[10]); */
144  msg->sms.sms_type = atol_null(row[11]);
145  msg->sms.mclass = atol_null(row[12]);
146  msg->sms.mwi = atol_null(row[13]);
147  msg->sms.coding = atol_null(row[14]);
148  msg->sms.compress = atol_null(row[15]);
149  msg->sms.validity = atol_null(row[16]);
150  msg->sms.deferred = atol_null(row[17]);
151  msg->sms.dlr_mask = atol_null(row[18]);
152  msg->sms.dlr_url = octstr_null_create(row[19]);
153  msg->sms.pid = atol_null(row[20]);
154  msg->sms.alt_dcs = atol_null(row[21]);
155  msg->sms.rpi = atol_null(row[22]);
156  msg->sms.charset = octstr_null_create(row[23]);
157  msg->sms.binfo = octstr_null_create(row[25]);
158  msg->sms.meta_data = octstr_null_create(row[26]);
159  if (row[24] == NULL) {
160  msg->sms.boxc_id= octstr_duplicate(sqlbox_id);
161  } else {
162  msg->sms.boxc_id= octstr_null_create(row[24]);
163  }
164  }
165  } while (state==SQLITE_ROW);
166  sqlite_finalize(res, NULL);
167 
168  if ( rows > 0) {
169  /* delete current row */
170  delet = octstr_format(SQLBOX_SQLITE_DELETE_QUERY, sqlbox_insert_table, id);
171 #if defined(SQLBOX_TRACE)
172  debug("SQLBOX", 0, "sql: %s", octstr_get_cstr(delet));
173 #endif
174  sql_update(pc, delet);
175  octstr_destroy(id);
176  octstr_destroy(delet);
177  }
178  octstr_destroy(sql);
180  return msg;
181 }
182 
183 static Octstr *get_numeric_value_or_return_null(long int num)
184 {
185  if (num == -1) {
186  return octstr_create("NULL");
187  }
188  return octstr_format("%ld", num);
189 }
190 
191 static Octstr *get_string_value_or_return_null(Octstr *str)
192 {
193  if (str == NULL) {
194  return octstr_create("NULL");
195  }
196  if (octstr_compare(str, octstr_imm("")) == 0) {
197  return octstr_create("NULL");
198  }
199  octstr_replace(str, octstr_imm("\\"), octstr_imm("\\\\"));
200  octstr_replace(str, octstr_imm("\'"), octstr_imm("\\\'"));
201  return octstr_format("\'%S\'", str);
202 }
203 
204 #define st_num(x) (stuffer[stuffcount++] = get_numeric_value_or_return_null(x))
205 #define st_str(x) (stuffer[stuffcount++] = get_string_value_or_return_null(x))
206 
207 void sqlite_save_msg(Msg *msg, Octstr *momt /*, Octstr smsbox_id */)
208 {
209  Octstr *sql;
210  Octstr *stuffer[30];
211  int stuffcount = 0;
212  DBPoolConn *pc;
213 
214  pc = dbpool_conn_consume(pool);
215  if (pc == NULL) {
216  error(0, "SQLITE: Database pool got no connection! DB update failed!");
217  return;
218  }
219 
220  sql = octstr_format(SQLBOX_SQLITE_INSERT_QUERY, sqlbox_logtable, st_str(momt), st_str(msg->sms.sender),
221  st_str(msg->sms.receiver), st_str(msg->sms.udhdata), st_str(msg->sms.msgdata), st_num(msg->sms.time),
222  st_str(msg->sms.smsc_id), st_str(msg->sms.service), st_str(msg->sms.account), st_num(msg->sms.sms_type),
223  st_num(msg->sms.mclass), st_num(msg->sms.mwi), st_num(msg->sms.coding), st_num(msg->sms.compress),
224  st_num(msg->sms.validity), st_num(msg->sms.deferred), st_num(msg->sms.dlr_mask), st_str(msg->sms.dlr_url),
225  st_num(msg->sms.pid), st_num(msg->sms.alt_dcs), st_num(msg->sms.rpi), st_str(msg->sms.charset),
226  st_str(msg->sms.boxc_id), st_str(msg->sms.binfo), st_str(msg->sms.meta_data), st_str(msg->sms.foreign_id));
227  sql_update(pc, sql);
228  while (stuffcount > 0) {
229  octstr_destroy(stuffer[--stuffcount]);
230  }
231  octstr_destroy(sql);
233 }
234 
235 void sqlite_leave()
236 {
237  dbpool_destroy(pool);
238 }
239 
240 struct server_type *sqlbox_init_sqlite(Cfg* cfg)
241 {
242  CfgGroup *grp;
243  List *grplist;
244  Octstr *sqlite_db, *sqlite_id;
245  Octstr *p = NULL;
246  long pool_size;
247  int lock_timeout;
248  DBConf *db_conf = NULL;
249  struct server_type *res = NULL;
250 
251  /*
252  * check for all mandatory directives that specify the field names
253  * of the used Sqlite table
254  */
255  if (!(grp = cfg_get_single_group(cfg, octstr_imm("sqlbox"))))
256  panic(0, "SQLBOX: Sqlite: group 'sqlbox' is not specified!");
257 
258  if (!(sqlite_id = cfg_get(grp, octstr_imm("id"))))
259  panic(0, "SQLBOX: Sqlite: directive 'id' is not specified!");
260 
261  /*
262  * now grap the required information from the 'sqlite-connection' group
263  * with the sqlite-id we just obtained
264  *
265  * we have to loop through all available Sqlite connection definitions
266  * and search for the one we are looking for
267  */
268 
269  grplist = cfg_get_multi_group(cfg, octstr_imm("sqlite-connection"));
270  while (grplist && (grp = (CfgGroup *)gwlist_extract_first(grplist)) != NULL) {
271  p = cfg_get(grp, octstr_imm("id"));
272  if (p != NULL && octstr_compare(p, sqlite_id) == 0) {
273  goto found;
274  }
275  if (p != NULL) octstr_destroy(p);
276  }
277  panic(0, "SQLBOX: Sqlite: connection settings for id '%s' are not specified!",
278  octstr_get_cstr(sqlite_id));
279 
280 found:
281  octstr_destroy(p);
282  gwlist_destroy(grplist, NULL);
283 
284  if (cfg_get_integer(&pool_size, grp, octstr_imm("max-connections")) == -1 || pool_size == 0)
285  pool_size = 1;
286 
287  if (!(sqlite_db = cfg_get(grp, octstr_imm("database"))))
288  panic(0, "SQLBOX: Sqlite: directive 'database' is not specified!");
289 
290  if (cfg_get_integer(&lock_timeout, grp, octstr_imm("lock-timeout")) == -1 || lock_timeout == 0 )
291  lock_timeout = 0;
292  /*
293  * ok, ready to connect to Sqlite
294  */
295  db_conf = gw_malloc(sizeof(DBConf));
296  gw_assert(db_conf != NULL);
297 
298  db_conf->sqlite = gw_malloc(sizeof(SQLiteConf));
299  gw_assert(db_conf->sqlite != NULL);
300 
301  db_conf->sqlite->file = sqlite_db;
302  db_conf->sqlite->lock_timeout = lock_timeout;
303 
304  pool = dbpool_create(DBPOOL_SQLITE, db_conf, pool_size);
305  gw_assert(pool != NULL);
306 
307  /*
308  * XXX should a failing connect throw panic?!
309  */
310  if (dbpool_conn_count(pool) == 0)
311  panic(0,"SQLBOX: Sqlite: database pool has no connections!");
312 
313  octstr_destroy(sqlite_id);
314 
315  res = gw_malloc(sizeof(struct server_type));
316  gw_assert(res != NULL);
317 
318  res->type = octstr_create("Sqlite");
319  res->sql_enter = sqlbox_configure_sqlite;
320  res->sql_leave = sqlite_leave;
321  res->sql_fetch_msg = sqlite_fetch_msg;
322  res->sql_save_msg = sqlite_save_msg;
323  res->sql_fetch_msg_list = NULL;
324  res->sql_save_list = NULL;
325  return res;
326 }
327 #endif
void error(int err, const char *fmt,...)
Definition: log.c:648
int(* sql_fetch_msg_list)(List *, long)
Definition: sqlbox_sql.h:19
void octstr_replace(Octstr *haystack, Octstr *needle, Octstr *repl)
Definition: octstr.c:2649
long dbpool_conn_count(DBPool *p)
DBPool * dbpool_create(enum db_type db_type, DBConf *conf, unsigned int connections)
gw_assert(wtls_machine->packet_to_send !=NULL)
#define cfg_get(grp, varname)
Definition: cfg.h:86
#define msg_create(type)
Definition: msg.h:136
void(* sql_save_list)(List *, Octstr *, int)
Definition: sqlbox_sql.h:20
static Cfg * cfg
Definition: opensmppbox.c:95
void(* sql_leave)()
Definition: sqlbox_sql.h:16
#define octstr_get_cstr(ostr)
Definition: octstr.h:233
static struct pid_list * found
void(* sql_enter)(Cfg *)
Definition: sqlbox_sql.h:15
void dbpool_conn_produce(DBPoolConn *conn)
Octstr * octstr_imm(const char *cstr)
Definition: octstr.c:283
Definition: msg.h:79
Definition: cfg.c:164
void * gwlist_extract_first(List *list)
Definition: list.c:305
Msg *(* sql_fetch_msg)()
Definition: sqlbox_sql.h:17
#define octstr_duplicate(ostr)
Definition: octstr.h:187
List * cfg_get_multi_group(Cfg *cfg, Octstr *name)
Definition: cfg.c:645
Octstr * octstr_format(const char *fmt,...)
Definition: octstr.c:2464
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:324
#define octstr_create(cstr)
Definition: octstr.h:125
Definition: dbpool.h:164
void dbpool_destroy(DBPool *p)
Definition: octstr.c:118
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:726
int cfg_get_integer(long *n, CfgGroup *grp, Octstr *varname)
Definition: cfg.c:742
#define panic
Definition: log.h:87
Definition: cfg.c:73
DBPoolConn * dbpool_conn_consume(DBPool *p)
Octstr * type
Definition: sqlbox_sql.h:14
void * conn
Definition: dbpool.h:95
Octstr * file
Definition: dbpool.h:128
int lock_timeout
Definition: dbpool.h:129
CfgGroup * cfg_get_single_group(Cfg *cfg, Octstr *name)
Definition: cfg.c:639
Octstr * sqlbox_id
Definition: sqlbox.c:95
Definition: list.c:102
static XMLRPCDocument * msg
Definition: test_xmlrpc.c:86
SQLiteConf * sqlite
Definition: dbpool.h:169
void(* sql_save_msg)(Msg *, Octstr *)
Definition: sqlbox_sql.h:18
int octstr_compare(const Octstr *ostr1, const Octstr *ostr2)
Definition: octstr.c:871
void gwlist_destroy(List *list, gwlist_item_destructor_t *destructor)
Definition: list.c:145
See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.