Browse code

database module interface moved.

Jan Janak authored on 09/07/2002 09:08:25
Showing 9 changed files
... ...
@@ -11,7 +11,7 @@
11 11
 # defines: sources, objs, depends
12 12
 #
13 13
 
14
-sources=$(filter-out $(auto_gen), $(wildcard *.c) $(wildcard mem/*.c) $(wildcard parser/*.c) ) $(auto_gen)
14
+sources=$(filter-out $(auto_gen), $(wildcard *.c) $(wildcard mem/*.c) $(wildcard parser/*.c) $(wildcard db/*.c) ) $(auto_gen)
15 15
 objs=$(sources:.c=.o)
16 16
 extra_objs=
17 17
 depends=$(sources:.c=.d)
18 18
new file mode 100644
... ...
@@ -0,0 +1,33 @@
0
+#include "db.h"
1
+#include "../sr_module.h"
2
+
3
+db_func_t dbf;
4
+
5
+
6
+int bind_dbmod(void)
7
+{
8
+	dbf.use_table = (db_use_table_f)find_export("db_use_table", 2);
9
+
10
+	dbf.init = (db_init_f)find_export("db_init", 1);
11
+	if (!dbf.init) return 1;
12
+
13
+	dbf.close = (db_close_f)find_export("db_close", 2);
14
+	if (!dbf.close) return 1;
15
+
16
+	dbf.query = (db_query_f)find_export("db_query", 2);
17
+	if (!dbf.query) return 1;
18
+
19
+	dbf.free_query = (db_free_query_f)find_export("db_free_query", 2);
20
+	if (!dbf.free_query) return 1;
21
+
22
+	dbf.insert = (db_insert_f)find_export("db_insert", 2);
23
+	if (!dbf.insert) return 1;
24
+
25
+	dbf.delete = (db_delete_f)find_export("db_delete", 2);
26
+	if (!dbf.delete) return 1;
27
+
28
+	dbf.update = (db_update_f)find_export("db_update", 2);
29
+	if (!dbf.update) return 1;
30
+
31
+	return 0;
32
+}
0 33
new file mode 100644
... ...
@@ -0,0 +1,251 @@
0
+#ifndef __DB_H__
1
+#define __DB_H__
2
+
3
+#include <time.h>
4
+
5
+/*
6
+ * Generic database interface
7
+ *
8
+ * $id$
9
+ */
10
+
11
+
12
+/* =================== db_key =============== */
13
+
14
+/*
15
+ * Type of a database key (column)
16
+ */
17
+typedef const char* db_key_t;
18
+
19
+
20
+/* =================== db_val =============== */
21
+
22
+/*
23
+ * Accepted column types
24
+ */
25
+typedef enum {
26
+	DB_INT,
27
+        DB_DOUBLE,
28
+	DB_STRING,
29
+	DB_DATETIME
30
+} db_type_t;
31
+
32
+
33
+/*
34
+ * Column value structure
35
+ */
36
+typedef struct {
37
+	db_type_t type;                  /* Type of the value */
38
+	int nul;                         /* Means that the column in database has no value */
39
+	union {
40
+		int          int_val;    /* integer value */
41
+		double       double_val; /* double value */
42
+		time_t       time_val;   /* unix time value */
43
+		const char*  string_val; /* NULL terminated string */
44
+	} val;                           /* union of all possible types */
45
+} db_val_t;
46
+
47
+
48
+/*
49
+ * Useful macros for accessing attributes of db_val structure
50
+ */
51
+
52
+/* Get value type */
53
+#define VAL_TYPE(dv)   ((dv)->type)
54
+
55
+/* Get null flag (means that value in dabase is null) */
56
+#define VAL_NULL(dv)   ((dv)->nul)
57
+
58
+/* Get integer value */
59
+#define VAL_INT(dv)    ((dv)->val.int_val)
60
+
61
+/* Get double value */
62
+#define VAL_DOUBLE(dv) ((dv)->val.double_val)
63
+
64
+/* Get time_t value */
65
+#define VAL_TIME(dv)   ((dv)->val.time_val)
66
+
67
+/* Get char* value */
68
+#define VAL_STRING(dv) ((dv)->val.string_val)
69
+
70
+
71
+/* ==================== db_con ======================= */
72
+
73
+/*
74
+ * This structure represents a database connection
75
+ * and pointer to this structure is used as a connection
76
+ * handle
77
+ */
78
+typedef struct {
79
+	char* table;     /* Default table to use */
80
+	void* con;       /* Mysql Connection */
81
+	void* res;       /* Result of previous operation */
82
+	void* row;       /* Actual row in the result */
83
+	int   connected; /* TRUE if connection is established */
84
+} db_con_t;
85
+
86
+
87
+/* ===================== db_row ====================== */
88
+
89
+/*
90
+ * Structure holding result of query_table function (ie. table row)
91
+ */
92
+typedef struct db_row {
93
+	db_val_t* values;  /* Columns in the row */
94
+	int n;             /* Number of columns in the row */
95
+} db_row_t;
96
+
97
+/* Useful macros for manipulating db_row structure attributes */
98
+
99
+/* Get row members */
100
+#define ROW_VALUES(rw) ((rw)->values)
101
+
102
+/* Get number of member in the row */
103
+#define ROW_N(rw)      ((rw)->n)
104
+
105
+
106
+/* ===================== db_res ====================== */
107
+
108
+typedef struct db_res {
109
+	struct {
110
+		db_key_t* names;   /* Column names */
111
+		db_type_t* types;  /* Column types */
112
+		int n;             /* Number of columns */
113
+	} col;
114
+	struct db_row* rows;       /* Rows */
115
+	int n;                     /* Number of rows */
116
+} db_res_t;
117
+
118
+/* Useful macros for manipulating db_res attributes */
119
+
120
+/* Column names */
121
+#define RES_NAMES(re) ((re)->col.names)
122
+
123
+/* Column types */
124
+#define RES_TYPES(re) ((re)->col.types)
125
+
126
+/* Number of columns */
127
+#define RES_COL_N(re) ((re)->col.n)
128
+
129
+/* Rows */
130
+#define RES_ROWS(re)  ((re)->rows)
131
+
132
+/* Number of rows */
133
+#define RES_ROW_N(re) ((re)->n)
134
+
135
+
136
+/*
137
+ * Specify table name that will be used for
138
+ * subsequent operations
139
+ */
140
+typedef int (*db_use_table_f)(db_con_t* _h, const char* _t);
141
+
142
+
143
+/*
144
+ * Initialize database connection and
145
+ * obtain the connection handle
146
+ */
147
+typedef db_con_t* (*db_init_f) (const char* _sqlurl);
148
+
149
+
150
+/*
151
+ * Close a database connection and free
152
+ * all memory used
153
+ */
154
+typedef void (*db_close_f) (db_con_t* _h); 
155
+
156
+
157
+/*
158
+ * Query table for specified rows
159
+ * _h: structure representing database connection
160
+ * _k: key names
161
+ * _v: values of the keys that must match
162
+ * _c: column names to return
163
+ * _n: nmber of key=values pairs to compare
164
+ * _nc: number of columns to return
165
+ * _o: order by the specified column
166
+ * _r: Result will be stored in this variable
167
+ *     NULL if there is no result
168
+ */
169
+typedef int (*db_query_f) (db_con_t* _h, db_key_t* _k, 
170
+			   db_val_t* _v, db_key_t* _c, 
171
+			   int _n, int _nc,
172
+			   db_key_t _o, db_res_t** _r);
173
+
174
+
175
+/*
176
+ * Free a result allocated by db_query
177
+ * _h: structure representing database connection
178
+ * _r: db_res structure
179
+ */
180
+typedef int (*db_free_query_f) (db_con_t* _h, db_res_t* _r);
181
+
182
+
183
+/*
184
+ * Insert a row into specified table
185
+ * _h: structure representing database connection
186
+ * _k: key names
187
+ * _v: values of the keys
188
+ * _n: number of key=value pairs
189
+ */
190
+typedef int (*db_insert_f) (db_con_t* _h, db_key_t* _k, db_val_t* _v, int _n);
191
+
192
+
193
+/*
194
+ * Delete a row from the specified table
195
+ * _h: structure representing database connection
196
+ * _k: key names
197
+ * _v: values of the keys that must match
198
+ * _n: number of key=value pairs
199
+ */
200
+typedef int (*db_delete_f) (db_con_t* _h, db_key_t* _k, db_val_t* _v, int _n);
201
+
202
+
203
+/*
204
+ * Update some rows in the specified table
205
+ * _h: structure representing database connection
206
+ * _k: key names
207
+ * _v: values of the keys that must match
208
+ * _uk: updated columns
209
+ * _uv: updated values of the columns
210
+ * _n: number of key=value pairs
211
+ * _un: number of columns to update
212
+ */
213
+typedef int (*db_update_f) (db_con_t* _h, db_key_t* _k, db_val_t* _v,
214
+			    db_key_t* _uk, db_val_t* _uv, int _n, int _un);
215
+
216
+
217
+
218
+typedef struct db_func{
219
+	db_use_table_f  use_table;   /* Specify table name */
220
+	db_init_f       init;        /* Initialize dabase connection */
221
+	db_close_f      close;       /* Close database connection */
222
+	db_query_f      query;       /* query a table */
223
+	db_free_query_f free_query;  /* Free a query result */
224
+	db_insert_f     insert;      /* Insert into table */
225
+	db_delete_f     delete;      /* Delete from table */ 
226
+	db_update_f     update;      /* Update table */
227
+} db_func_t;
228
+
229
+
230
+/*
231
+ * Bind database module functions
232
+ * returns TRUE if everything went OK
233
+ * FALSE otherwise
234
+ */
235
+int bind_dbmod(void);
236
+
237
+
238
+extern db_func_t dbf;
239
+
240
+
241
+#define db_use_table  (dbf.use_table)
242
+#define db_init       (dbf.init)
243
+#define db_close      (dbf.close)
244
+#define db_query      (dbf.query)
245
+#define db_free_query (dbf.free_query)
246
+#define db_insert     (dbf.insert)
247
+#define db_delete     (dbf.delete)
248
+#define db_update     (dbf.update)
249
+ 
250
+#endif
0 251
new file mode 100644
... ...
@@ -0,0 +1,4 @@
0
+How to write a support for a new database
1
+
2
+TBD
3
+
0 4
new file mode 100644
... ...
@@ -0,0 +1,525 @@
0
+$Id$
1
+
2
+Generic Database Interface
3
+--------------------------
4
+
5
+This is a generic database interface for modules that need to utilize a 
6
+database. The interface should be used by all modules that access database.
7
+The interface will be independent of the underlying database server.
8
+
9
+Notes:
10
+
11
+If possible, use predefined macros if you need to access any structure 
12
+attributes.  
13
+
14
+For additional description, see comments in sources of mysql module.
15
+
16
+If you want to see more complicated examples of how the API could be used, 
17
+see sources of dbexample, usrloc or auth modules.
18
+
19
+
20
+1 Data types
21
+
22
+There are several new data types. All of them are defined in header file db.h,
23
+a client must include the header file to be able to use them.
24
+
25
+1.1 Type db_con_t
26
+
27
+1.1.1 Description
28
+
29
+This type represents a database connection, all database functions (described 
30
+below) use a variable of this type as one argument. In other words, variable 
31
+of db_con_t type serves as a handle for a particular database connection.
32
+
33
+1.1.2 Definition
34
+
35
+   typedef struct db_con {
36
+        char* table;     /* Default table to use */
37
+        void* con;       /* Database connection */
38
+        void* res;       /* Result of previous operation */
39
+        void* row;       /* Internal, not for public use */
40
+        int connected;   /* TRUE if connection is established */
41
+   } db_con_t;
42
+
43
+1.1.3 Macros
44
+
45
+There are no macros for db_con_t type.
46
+
47
+
48
+1.2 Type db_key_t
49
+
50
+1.2.1 Description
51
+
52
+This type represents a database key. Every time you need to specify a key 
53
+value, this type should be used. In fact, this type is identical to const 
54
+char*.
55
+
56
+1.2.2 Definion
57
+   
58
+   typedef const char* db_key_t;
59
+
60
+1.2.3 Macros
61
+
62
+There are no macros (It is not needed).
63
+
64
+
65
+1.3 Type db_type_t
66
+
67
+1.3.1 Description
68
+
69
+Each cell in a database table can be of a different type. To distinguish
70
+among these types, the db_type_t enumeration is used. Every value of the
71
+enumeration represents one datatype that is recognized by the database
72
+API. This enumeration is used in conjunction with db_type_t. For more
73
+information, see the next section.
74
+
75
+1.3.2 Definition
76
+
77
+   typedef enum {
78
+       DB_INT,       /* Integer number */
79
+       DB_DOUBLE,    /* Decimal number */
80
+       DB_STRING,    /* String */
81
+       DB_DATETIME   /* Date and time */
82
+   } db_type_t;
83
+
84
+1.3.3 Macros
85
+
86
+There are no macros.
87
+
88
+
89
+1.4 Type db_val_t
90
+
91
+1.4.1 Description
92
+
93
+This structure represents a value in the database. Several datatypes are
94
+recognized and converted by the database API:
95
+
96
+DB_INT      - Value in the database represents an integer number
97
+DB_DOUBLE   - Value in the database represents a decimal number
98
+DB_STRING   - Value in the database represents a string
99
+DB_DATETIME - Value in the database represents date and time
100
+
101
+These datatypes are automaticaly recognized, converted from internal database
102
+representation and stored in the variable of corresponding type.
103
+
104
+1.4.2 Definition
105
+
106
+    typedef struct db_val {
107
+         db_type_t type;              /* Type of the value */
108
+         int nul;                     /* NULL flag */
109
+         union {                      
110
+             int int_val;             /* Integer value */
111
+             double double_val;       /* Double value */
112
+             time_t time_val;         /* Unix time_t value */
113
+             const char* string_val;  /* Zero terminated string */
114
+         } val;
115
+    } db_val_t;
116
+
117
+1.4.3 Macros
118
+
119
+Note: All macros expect reference to db_val_t variable as the parameter.
120
+
121
+1.4.3.1 VAL_TYPE(value) Macro
122
+
123
+Use this macro if you need to set/get the type of the value
124
+
125
+Example: VAL_TYPE(val) = DB_INT;
126
+         if (VAL_TYPE(val) == DB_FLOAT) ...
127
+
128
+1.4.3.2 VAL_NULL(value) Macro
129
+
130
+Use this macro if you need to set/get the null flag. Non-zero flag means that 
131
+the corresponding cell in the database contained no data (NULL value in MySQL
132
+terminology).
133
+
134
+Example: if (VAL_NULL(val) == 1) {
135
+             printf("The cell is NULL");
136
+         }
137
+
138
+1.4.3.3 VAL_INT(value) Macro
139
+
140
+Use this macro if you need to access integer value in the db_val_t structure.
141
+
142
+Example: if (VAL_TYPE(val) == DB_INT) {
143
+             printf("%d", VAL_INT(val));
144
+         }
145
+
146
+1.4.3.4 VAL_DOUBLE(value) Macro 
147
+
148
+Use this macro if you need to access double value in the db_val_t structure.
149
+
150
+Example: if (VAL_TYPE(val) == DB_DOUBLE) {
151
+             printf("%f", VAL_DOUBLE(val));
152
+         }
153
+
154
+1.4.3.5 VAL_TIME(value) Macro 
155
+
156
+Use this macro if you need to access time_t value in the db_val_t structure.
157
+
158
+Example: time_t tim;
159
+         if (VAL_TYPE(val) == DB_DATETIME) {
160
+             tim = VAL_TIME(val);
161
+         }
162
+
163
+1.4.3.6 VAL_STRING(value) Macro 
164
+
165
+Use this macro if you need to access string value in the db_val_t structure.
166
+
167
+Example: if (VAL_TYPE(val) == DB_STRING) {
168
+             printf("%s", VAL_STRING(val));
169
+         }
170
+
171
+
172
+1.5 Type db_row_t
173
+
174
+1.5.1 Description
175
+
176
+This type represents one row in a database table. In other words, the row is an
177
+array of db_val_t variables, where each db_val_t variable represents exactly 
178
+one cell in the table.
179
+
180
+1.5.2 Definition
181
+
182
+   typedef struct db_row {
183
+       db_val_t* values;    /* Array of values in the row */
184
+       int n;               /* Number of values in the row */
185
+   } db_val_t;
186
+
187
+1.5.3 Macros
188
+
189
+1.5.3.1 ROW_VALUES(row) Macro 
190
+
191
+Use this macro to get pointer to the array of db_val_t structures.
192
+
193
+Example: db_val_t* v = ROW_VALUES(row);
194
+         if (VAL_TYPE(v) == DB_INT) ....
195
+
196
+1.5.3.2 ROW_N(row) Macro 
197
+
198
+Use this macro to get number of cells in the row.
199
+
200
+Example: db_val_t* val = ROW_VALUES(row);
201
+         for(i = 0; i < ROW_N(row); i++) {
202
+             switch(VAL_TYPE(val + i)) {
203
+             case DB_INT: ...; break;
204
+             case DB_DOUBLE: ...; break;
205
+             ...
206
+             }
207
+         }
208
+
209
+
210
+1.6 Type db_res_t
211
+
212
+1.6.1 Description
213
+
214
+This type represents a result returned by db_query function (see below). The 
215
+result can consist of zero or more rows (see db_row_t description).
216
+
217
+Note: A variable of type db_res_t returned by db_query function uses dynamicaly
218
+      allocated memory, don't forget to call db_free_query if you don't need 
219
+      the variable anymore. You will encounter memory leaks if you fail to do 
220
+      this !
221
+
222
+In addition to zero or more rows, each db_res_t object contains also an array 
223
+of db_key_t objects. The objects represent keys (names of columns).
224
+
225
+1.6.2 Definition
226
+
227
+   typedef struct db_res {
228
+       struct {
229
+           db_key_t* keys;    /* Array of column names */
230
+           db_type_t* types;  /* Array of column types */
231
+           int n;             /* Number of columns */
232
+       } col;
233
+       struct db_row* rows;   /* Array of rows */
234
+       int n;                 /* Number of rows */
235
+   } db_res_t;
236
+
237
+1.6.3 Macros
238
+
239
+1.6.3.1 RES_NAMES(res) Macro 
240
+
241
+Use this macro if you want to obtain pointer to the array of cell names.
242
+
243
+Example: db_key_t* column_names = ROW_NAMES(row);
244
+
245
+1.6.3.2 RES_COL_N(res) Macro 
246
+
247
+Use this macro if you want to get the number of columns in the result.
248
+
249
+Example: int ncol = RES_COL_N(res)
250
+         for(i = 0; i < ncol; i++) {
251
+             /* do something with the column */
252
+         }
253
+
254
+1.6.3.3 RES_ROWS(res) Macro 
255
+
256
+Use this macro if you need to obtain pointer to array of rows.
257
+
258
+Example: db_row_t* rows = RES_ROWS(res);
259
+ 
260
+1.6.3.4 RES_ROW_N(res) Macro 
261
+
262
+Use this macro if you need to obtain the number of rows in the result
263
+
264
+Example: int n = RES_ROW_N(res);
265
+
266
+
267
+
268
+2 Functions
269
+
270
+There are several functions that implement the database API logic. All function
271
+names start with db_ prefix, except bind_dbmod. bind_dbmod function is 
272
+implemented in db.c file, all other functions are implemented in a standalone 
273
+database module. You will need to compile and link db.c in your module to be 
274
+able to use the bind_dbmod function. Detailed function description follows.
275
+
276
+
277
+2.1 Function bind_dbmod
278
+
279
+2.1.1 Description
280
+
281
+This function is special, it's only purpose is to call find_export function in
282
+the ser core and find addresses of all other functions (starting with db_
283
+prefix). This function MUST be called __FIRST__ !
284
+
285
+2.1.2 Prototype
286
+
287
+   int bind_dbmod(void);
288
+
289
+2.1.3 Parameters
290
+
291
+The function takes no parameters.
292
+
293
+2.1.4 Return Value
294
+
295
+The function returns TRUE if it was able to find addresses of all other 
296
+functions, otherwise FALSE is returned.
297
+
298
+
299
+2.2 Function db_init
300
+
301
+2.2.1 Description
302
+
303
+Use this function to initialize the database API and open a new database 
304
+connection. This function must be called after bind_dbmod but before any other 
305
+function is called.
306
+
307
+2.2.2 Prototype
308
+
309
+   db_con_t* db_init(const char* _sql_url);
310
+
311
+2.2.3 Parameters
312
+
313
+The function takes one parameter, the parameter must contain database 
314
+connection URL. The URL is of the form 
315
+sql://username:password@host:port/database where:
316
+
317
+username: Username to use when logging into database (optional).
318
+password: password if it was set (optional)
319
+host:     Hosname or IP address of the host where database server lives 
320
+          (mandatory)
321
+port:     Port number of the server if the port differs from default value 
322
+          (optional)
323
+database: If the database server supports multiple databases, you must specify 
324
+          name of the database (optional).
325
+
326
+
327
+2.2.4 Return Value
328
+
329
+The function returns pointer to db_con_t* representing the connection if it was
330
+successful, otherwise NULL is returned.
331
+
332
+
333
+2.3 Function db_close
334
+
335
+2.3.1 Description
336
+
337
+The function closes previously open connection and frees all previously 
338
+allocated memory. The function db_close must be the very last function called.
339
+
340
+
341
+2.3.2 Prototype
342
+
343
+   void db_close(db_con_t* _h);
344
+
345
+2.3.3 Parameters
346
+
347
+The function takes one parameter, this parameter is a pointer to db_con_t
348
+structure representing database connection that should be closed.
349
+
350
+2.3.4 Return Value
351
+
352
+Function doesn't return anything.
353
+
354
+
355
+2.4 Function db_query
356
+
357
+2.4.1 Description
358
+
359
+This function implements SELECT SQL directive.
360
+
361
+2.4.2 Prototype
362
+
363
+   int db_query(db_con_t* _h, db_key_t* _k,
364
+                db_val_t* _v, db_key_t* _c, 
365
+	        int _n, int _nc, db_key_t _o, db_res_t** _r);
366
+
367
+2.4.3 Parameters
368
+
369
+The function takes 7 parameters:
370
+_h: Database connection handle
371
+_k: Array of column names that will be compared and their values must match
372
+_v: Array of values, columns specified in _k parameter must match these values
373
+_c: Array of column names that you are interested in
374
+_n: Number of key-value pairs to match in _k and _v parameters
375
+_nc: Number of columns in _c parameter
376
+_o: Order by
377
+_r: Address of variable where pointer to the result will be stored
378
+
379
+If _k and _v parameters are NULL and _n is zero, you will get the whole table.
380
+if _c is NULL and _nc is zero, you will get all table columns in the result
381
+
382
+_r will point to a dynamically allocated structure, it is neccessary to call
383
+db_free_query function once you are finished with the result.
384
+
385
+Strings in the result are not duplicated, they will be discarded if you call
386
+db_free_query, make a copy yourself if you need to keep it after db_free_query.
387
+
388
+You must call db_free_query _BEFORE_ you can call db_query again !
389
+
390
+2.4.4 Return Value
391
+
392
+The function returns TRUE if everything is OK, otherwise FALSE is returned.
393
+
394
+
395
+2.5 Function db_free_query
396
+
397
+2.5.1 Description
398
+
399
+This function frees all memory allocated previously in db_query, it is
400
+neccessary to call this function on a db_res_t structure if you don't need the
401
+structure anymore. You must call this function _BEFORE_ you call db_query
402
+again !
403
+
404
+2.5.2 Prototype
405
+
406
+   int db_free_query(db_con_t* _h, db_res_t* _r);
407
+
408
+2.5.3 Parameters
409
+
410
+The function takes 2 parameters:
411
+_h: Database connection handle
412
+_r: Pointer to db_res_t structure to destroy
413
+
414
+2.5.4 Return Value
415
+
416
+The function returns TRUE if everything is OK, otherwise the function returns
417
+FALSE.
418
+
419
+
420
+2.6 Function db_insert
421
+
422
+2.6.1 Description
423
+
424
+This function implements INSERT SQL directive, you can insert one or more
425
+rows in a table using this function.
426
+
427
+2.6.2 Prototype
428
+
429
+   int db_insert(db_con_t* _h, db_key_t* _k, db_val_t* _v, int _n);
430
+
431
+2.6.3 Parameters
432
+
433
+The function takes 4 parameters:
434
+_h: Database connection handle
435
+_k: Array of keys (column names) 
436
+_v: Array of values for keys specified in _k parameter
437
+_n: Number of keys-value pairs int _k and _v parameters
438
+
439
+2.6.4 Return Value
440
+
441
+The function returns TRUE if everything is OK, otherwise the function returns
442
+FALSE.
443
+
444
+
445
+2.7 Function db_delete
446
+
447
+2.7.1 Description
448
+
449
+This function implements DELETE SQL directive, it is possible to delete one or
450
+more rows from a table.
451
+
452
+2.7.2 Prototype
453
+
454
+   int db_delete(db_con_t* _h, db_key_t* _k, db_val_t* _v, int _n);
455
+
456
+2.7.3 Parameters
457
+
458
+The function takes 4 parameters:
459
+_h: Database connection handle
460
+_k: Array of keys (column names) that will be matched
461
+_v: Array of values that the row must match to be deleted
462
+_n: Number of keys-value parameters in _k and _v parameters
463
+
464
+If _k is NULL and _v is NULL and _n is zero, all rows are deleted (table will
465
+be empty).
466
+
467
+2.7.4 Return Value
468
+
469
+The function returns TRUE fi everything is OK, otherwise the function returns
470
+FALSE.
471
+
472
+
473
+2.8 Function db_update
474
+
475
+2.8.1 Description
476
+
477
+The function implements UPDATE SQL directive. It is possible to modify one
478
+or more rows in a table using this function.
479
+
480
+2.8.2 Prototype
481
+
482
+   int db_update(db_con_t* _h, db_key_t* _k, db_val_t* _v,
483
+	         db_key_t* _uk, db_val_t* _uv, int _n, int _un);
484
+
485
+2.8.3 Parameters
486
+
487
+The function takes 7 parameters:
488
+_h: Database connection handle
489
+_k: Array of keys (column names) that will be matched
490
+_v: Array of values that the row must match to be modified
491
+_uk: Array of keys (column names) that will be modified
492
+_uv: New values for keys specified in _k parameter
493
+_n: Number of key-value pairs in _k and _v parameters
494
+_un: Number of key-value pairs in _uk and _uv parameters 
495
+
496
+2.8.4 Return Value
497
+
498
+The function returns TRUE if everything is OK, otherwise the function returns
499
+FALSE.
500
+
501
+
502
+2.9 Function db_use_table
503
+
504
+2.9.1 Description
505
+
506
+The function db_use_table takes a table name and stores it db_con_t structure.
507
+All subsequent operations (insert, delete, update, query) are performed on
508
+that table.
509
+
510
+2.9.2 Prototype
511
+
512
+   int db_use_table_f(db_con_t* _h, const char* _t);
513
+
514
+2.9.3 Parameters
515
+
516
+The function takes 2 parameters:
517
+_h: Database connection handle
518
+_t: Table name
519
+
520
+2.9.4 Return Value
521
+
522
+The function returns TRUE if everything is OK, otherwise the function returns
523
+FALSE.
524
+
0 525
new file mode 100644
... ...
@@ -0,0 +1,12 @@
0
+# $Id$
1
+#
2
+# database example module makefile
3
+#
4
+# 
5
+# WARNING: do not run this directly, it should be run by the master Makefile
6
+
7
+auto_gen=
8
+NAME=dbexample.so
9
+LIBS=
10
+
11
+include ../../Makefile.modules
0 12
new file mode 100644
... ...
@@ -0,0 +1,5 @@
0
+This is very simple example module that shows, how to
1
+use database interface.
2
+
3
+If you want to compile this module, move it to modules
4
+directory.
0 5
\ No newline at end of file
1 6
new file mode 100644
... ...
@@ -0,0 +1,228 @@
0
+#include "../../sr_module.h"
1
+#include <stdio.h>
2
+#include "../../db/db.h"
3
+
4
+
5
+#define DB_URL   "sql://root@localhost/ser"
6
+#define DB_TABLE "location"
7
+
8
+#define TRUE 1
9
+#define FALSE 0
10
+
11
+
12
+/*
13
+ * Dabase module client example
14
+ */
15
+
16
+
17
+static struct module_exports dbex_exports= {	
18
+	"DBExample", 
19
+	(char*[]) {
20
+	},
21
+	(cmd_function[]) {
22
+	},
23
+	(int[]) {
24
+	},
25
+	(fixup_function[]) {
26
+	},
27
+	0,       /* number of functions*/
28
+	NULL,    /* Module parameter names */
29
+	NULL,    /* Module parameter types */
30
+	NULL,    /* Module parameter variable pointers */
31
+	0,       /* Number of module parameters */
32
+	0,       /* response function*/
33
+	0        /* destroy function */
34
+};
35
+
36
+
37
+static int print_res(db_res_t* _r)
38
+{
39
+	int i, j;
40
+
41
+	for(i = 0; i < RES_COL_N(_r); i++) {
42
+		printf("%s ", RES_NAMES(_r)[i]);
43
+	}
44
+	printf("\n");
45
+
46
+	for(i = 0; i < RES_ROW_N(_r); i++) {
47
+		for(j = 0; j < RES_COL_N(_r); j++) {
48
+			if (RES_ROWS(_r)[i].values[j].nul == TRUE) {
49
+				printf("NULL ");
50
+				continue;
51
+			}
52
+			switch(RES_ROWS(_r)[i].values[j].type) {
53
+			case DB_INT:
54
+				printf("%d ", RES_ROWS(_r)[i].values[j].val.int_val);
55
+				break;
56
+			case DB_DOUBLE:
57
+				printf("%f ", RES_ROWS(_r)[i].values[j].val.double_val);
58
+				break;
59
+			case DB_DATETIME:
60
+				printf("%s ", ctime(&(RES_ROWS(_r)[i].values[j].val.time_val)));
61
+				break;
62
+			case DB_STRING:
63
+				printf("%s ", RES_ROWS(_r)[i].values[j].val.string_val);
64
+			}
65
+			
66
+		}
67
+		printf("\n");
68
+	}
69
+			
70
+	return TRUE;
71
+}
72
+
73
+
74
+
75
+
76
+
77
+struct module_exports* mod_register()
78
+{
79
+	     /*
80
+	      * Column names of table location
81
+	      */
82
+	db_key_t keys1[] = {"user", "contact", "q", "expire" };
83
+	db_key_t keys2[] = {"user", "q"};
84
+	db_key_t keys3[] = {"user", "contact"};
85
+	db_key_t keys4[] = {"contact", "q"};
86
+
87
+	db_val_t vals1[] = { 
88
+		{ DB_STRING  , 0, { .string_val = "foo@bar.com" }      },
89
+		{ DB_STRING  , 0, { .string_val = "real@foo.bar.com" } },
90
+		{ DB_DOUBLE  , 0, { .double_val = 1.2 }                 },
91
+		{ DB_DATETIME, 0, { .time_val = 439826493 }            }
92
+	};
93
+
94
+	db_val_t vals2[] = { 
95
+		{ DB_STRING  , 0, { .string_val = "foo2@bar2.com" }      },
96
+		{ DB_STRING  , 0, { .string_val = "real2@foo.bar2.com" } },
97
+		{ DB_DOUBLE  , 0, { .double_val = 1.3 }                   },
98
+		{ DB_DATETIME, 0, { .time_val = 12345 }                  }
99
+	};
100
+
101
+	db_val_t vals3[] = { 
102
+		{ DB_STRING  , 0, { .string_val = "foo3@bar3.com" }      },
103
+		{ DB_STRING  , 0, { .string_val = "real3@foo.bar3.com" } },
104
+		{ DB_DOUBLE  , 0, { .double_val = 1.5 }                  },
105
+		{ DB_DATETIME, 0, { .time_val = 123456 }                 }
106
+	};
107
+
108
+	db_val_t vals4[] = {
109
+		{ DB_STRING, 0, { .string_val = "foo2@bar2.com" } },
110
+		{ DB_DOUBLE, 0, { .double_val = 1.30 }            }
111
+	};
112
+		  
113
+	db_val_t vals5[] = {
114
+		{ DB_STRING, 0, { .string_val = "foo3@bar3.com" }      },
115
+		{ DB_STRING, 0, { .string_val = "real3@foo.bar3.com" } }
116
+	};
117
+
118
+	db_val_t vals6[] = {
119
+		{ DB_STRING, 0, { .string_val = "different@address.com" } },
120
+		{ DB_DOUBLE, 0, { .double_val = 2.5 }                     }
121
+	};
122
+
123
+	db_con_t* h;
124
+	db_res_t* res;
125
+
126
+	fprintf(stderr, "DBExample - registering...\n");
127
+
128
+	     /* The first call must be bind_dbmod
129
+	      * This call will search for functions
130
+	      * exported by a database module
131
+	      */
132
+	if (bind_dbmod()) {
133
+		fprintf(stderr, "Error while binding database module, did you forget to load a database module ?\n");
134
+		return &dbex_exports;
135
+	}
136
+
137
+	     /*
138
+	      * Create a database connection
139
+	      * DB_URL is database URL of form
140
+	      * sql://user:password@host:port/database
141
+	      * The function returns handle, that
142
+	      * represents a database connection
143
+	      */
144
+	h = db_init(DB_URL);
145
+	if (!h) {
146
+		fprintf(stderr, "Error while initializing database connection\n");
147
+		return &dbex_exports;
148
+	}
149
+
150
+	     /* 
151
+	      * Specify a table name, that will
152
+	      * be used for manipulations
153
+	      */
154
+	if (db_use_table(h, DB_TABLE) == FALSE) {
155
+		fprintf(stderr, "Error while calling db_use_table\n");
156
+		return &dbex_exports;
157
+	}
158
+
159
+	     /* If you do not specify any keys and values to be
160
+	      * matched, all rows will be deleted
161
+	      */
162
+	if (db_delete(h, NULL, NULL, 0) == FALSE) {
163
+		fprintf(stderr, "Error while flushing table\n");
164
+		return &dbex_exports;
165
+	}
166
+
167
+	if (db_insert(h, keys1, vals1, 4) == FALSE) {
168
+		fprintf(stderr, "Error while inserting line 1\n");
169
+		return &dbex_exports;
170
+	}
171
+
172
+	if (db_insert(h, keys1, vals2, 4) == FALSE) {
173
+		fprintf(stderr, "Error while inserting line 2\n");
174
+		return &dbex_exports;
175
+	}
176
+
177
+	if (db_insert(h, keys1, vals3, 4) == FALSE) {
178
+		fprintf(stderr, "Error while inserting line 3\n");
179
+		return &dbex_exports;
180
+	}
181
+
182
+	     /*
183
+	      * Let's delete middle line with
184
+	      * user = foo2@bar2.com and q = 1.3
185
+	      */
186
+	if (db_delete(h, keys2, vals4, 2) == FALSE) {
187
+		fprintf(stderr, "Error while deleting line\n");
188
+		return &dbex_exports;
189
+	}
190
+
191
+	     /*
192
+	      * Modify last line
193
+	      */
194
+	if (db_update(h, keys3, vals5, keys4, vals6, 2, 2) == FALSE) {
195
+		fprintf(stderr, "Error while modifying table\n");
196
+		return &dbex_exports;
197
+	}
198
+
199
+	     /*
200
+	      * Last but not least, dump the result of db_query
201
+	      */
202
+
203
+	if (db_query(h, NULL, NULL, NULL, 0, 0, NULL, &res) == FALSE) {
204
+		fprintf(stderr, "Error while querying table\n");
205
+		return &dbex_exports;
206
+	}
207
+
208
+
209
+	print_res(res);
210
+
211
+	     /*
212
+	      * Free the result because we don't need it
213
+	      * anymore
214
+	      */
215
+	if (db_free_query(h, res) == FALSE) {
216
+		fprintf(stderr, "Error while freeing result of query\n");
217
+		return &dbex_exports;
218
+	}
219
+
220
+	     /*
221
+	      * Close existing database connection
222
+	      * and free previously allocated 
223
+	      * memory
224
+	      */
225
+	db_close(h);
226
+	return &dbex_exports;
227
+}
... ...
@@ -6,6 +6,7 @@ fork=no          # (cmd. line: -D)
6 6
 log_stderror=yes # (cmd line: -E)
7 7
 # for more info: sip_router -h
8 8
 
9
+
9 10
 route{
10 11
 
11 12
 	if false and forward("mobile69") { log("forwarded ok\n"); break; }