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