Fri, 19 Dec 2008 09:17:16 +0000
Added the statement:affected() and statement:rowcount() methods.
1 | 1 | #include "dbd_postgresql.h" |
2 | ||
3 | static lua_push_type_t postgresql_to_lua_push(unsigned int postgresql_type) { | |
4 | lua_push_type_t lua_type; | |
5 | ||
6 | switch(postgresql_type) { | |
7 | case INT2OID: | |
8 | case INT4OID: | |
20
5ab0b30f8fbd
Bugfix: the type return by 'select count(...)' was being pushed as a string because of missing psql => lua type mapping.
nrich@ii.net
parents:
17
diff
changeset
|
9 | case INT8OID: |
1 | 10 | lua_type = LUA_PUSH_INTEGER; |
11 | break; | |
12 | ||
13 | case FLOAT4OID: | |
14 | case FLOAT8OID: | |
15 | lua_type = LUA_PUSH_NUMBER; | |
16 | break; | |
17 | ||
18 | case BOOLOID: | |
19 | lua_type = LUA_PUSH_BOOLEAN; | |
20 | break; | |
21 | ||
22 | default: | |
23 | lua_type = LUA_PUSH_STRING; | |
24 | } | |
25 | ||
26 | return lua_type; | |
27 | } | |
28 | ||
21
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
20
diff
changeset
|
29 | /* |
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
20
diff
changeset
|
30 | * num_affected_rows = statement:affected() |
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
20
diff
changeset
|
31 | */ |
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
20
diff
changeset
|
32 | static int statement_affected(lua_State *L) { |
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
20
diff
changeset
|
33 | statement_t *statement = (statement_t *)luaL_checkudata(L, 1, DBD_POSTGRESQL_STATEMENT); |
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
20
diff
changeset
|
34 | |
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
20
diff
changeset
|
35 | if (!statement->result) { |
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
20
diff
changeset
|
36 | luaL_error(L, DBI_ERR_INVALID_STATEMENT); |
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
20
diff
changeset
|
37 | } |
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
20
diff
changeset
|
38 | |
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
20
diff
changeset
|
39 | lua_pushinteger(L, atoi(PQcmdTuples(statement->result))); |
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
20
diff
changeset
|
40 | |
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
20
diff
changeset
|
41 | return 1; |
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
20
diff
changeset
|
42 | } |
1 | 43 | |
2 | 44 | /* |
45 | * success = statement:close() | |
46 | */ | |
1 | 47 | static int statement_close(lua_State *L) { |
48 | statement_t *statement = (statement_t *)luaL_checkudata(L, 1, DBD_POSTGRESQL_STATEMENT); | |
49 | ||
50 | if (statement->result) { | |
51 | PQclear(statement->result); | |
52 | statement->result = NULL; | |
53 | } | |
54 | ||
55 | return 0; | |
56 | } | |
57 | ||
2 | 58 | /* |
59 | * success = statement:execute(...) | |
60 | */ | |
1 | 61 | static int statement_execute(lua_State *L) { |
62 | int n = lua_gettop(L); | |
63 | statement_t *statement = (statement_t *)luaL_checkudata(L, 1, DBD_POSTGRESQL_STATEMENT); | |
64 | int num_bind_params = n - 1; | |
65 | ExecStatusType status; | |
66 | int p; | |
10 | 67 | const char *errstr = NULL; |
1 | 68 | |
9 | 69 | const char **params; |
1 | 70 | PGresult *result = NULL; |
71 | ||
72 | statement->tuple = 0; | |
73 | ||
74 | params = malloc(num_bind_params * sizeof(params)); | |
11
b3e05e361f46
Bugfix: PSQL array returns were not being indexed properly.
nrich@ii.net
parents:
10
diff
changeset
|
75 | memset(params, 0, num_bind_params * sizeof(params)); |
1 | 76 | |
2 | 77 | /* |
78 | * convert and copy parameters into a string array | |
79 | */ | |
1 | 80 | for (p = 2; p <= n; p++) { |
81 | int i = p - 2; | |
10 | 82 | int type = lua_type(L, p); |
83 | char err[64]; | |
1 | 84 | |
10 | 85 | switch(type) { |
86 | case LUA_TNIL: | |
1 | 87 | params[i] = NULL; |
10 | 88 | break; |
89 | case LUA_TBOOLEAN: | |
90 | /* | |
91 | * boolean values in postgresql can either be | |
92 | * t/f or 1/0. Pass integer values rather than | |
93 | * strings to maintain semantic compatibility | |
94 | * with other DBD drivers that pass booleans | |
95 | * as integers. | |
96 | */ | |
97 | params[i] = lua_toboolean(L, p) ? "1" : "0"; | |
98 | break; | |
99 | case LUA_TNUMBER: | |
100 | case LUA_TSTRING: | |
101 | params[i] = lua_tostring(L, p); | |
102 | break; | |
103 | default: | |
104 | snprintf(err, sizeof(err)-1, DBI_ERR_BINDING_TYPE_ERR, lua_typename(L, type)); | |
105 | errstr = err; | |
106 | goto cleanup; | |
1 | 107 | } |
108 | } | |
109 | ||
110 | result = PQexecPrepared( | |
111 | statement->postgresql, | |
112 | statement->name, | |
113 | num_bind_params, | |
114 | (const char **)params, | |
115 | NULL, | |
116 | NULL, | |
117 | 0 | |
118 | ); | |
119 | ||
10 | 120 | cleanup: |
1 | 121 | free(params); |
122 | ||
10 | 123 | if (errstr) { |
124 | lua_pushboolean(L, 0); | |
125 | lua_pushfstring(L, DBI_ERR_BINDING_PARAMS, errstr); | |
126 | return 2; | |
127 | } | |
128 | ||
1 | 129 | if (!result) { |
130 | lua_pushboolean(L, 0); | |
4 | 131 | lua_pushfstring(L, DBI_ERR_ALLOC_RESULT, PQerrorMessage(statement->postgresql)); |
3 | 132 | return 2; |
1 | 133 | } |
134 | ||
135 | status = PQresultStatus(result); | |
136 | if (status != PGRES_COMMAND_OK && status != PGRES_TUPLES_OK) { | |
137 | lua_pushboolean(L, 0); | |
4 | 138 | lua_pushfstring(L, DBI_ERR_BINDING_EXEC, PQresultErrorMessage(result)); |
3 | 139 | return 2; |
1 | 140 | } |
141 | ||
142 | statement->result = result; | |
143 | ||
144 | lua_pushboolean(L, 1); | |
145 | return 1; | |
146 | } | |
147 | ||
2 | 148 | /* |
149 | * must be called after an execute | |
150 | */ | |
11
b3e05e361f46
Bugfix: PSQL array returns were not being indexed properly.
nrich@ii.net
parents:
10
diff
changeset
|
151 | static int statement_fetch_impl(lua_State *L, statement_t *statement, int named_columns) { |
1 | 152 | int tuple = statement->tuple++; |
153 | int i; | |
154 | int num_columns; | |
12
014ba3ab3903
Renamed statement:fetch() to statement:rows(), and statement:row() to statement:fetch(). The API reads better this way.
nrich@ii.net
parents:
11
diff
changeset
|
155 | int d = 1; |
1 | 156 | |
3 | 157 | if (!statement->result) { |
4 | 158 | luaL_error(L, DBI_ERR_FETCH_INVALID); |
3 | 159 | return 0; |
160 | } | |
161 | ||
1 | 162 | if (PQresultStatus(statement->result) != PGRES_TUPLES_OK) { |
163 | lua_pushnil(L); | |
164 | return 1; | |
165 | } | |
166 | ||
167 | if (tuple >= PQntuples(statement->result)) { | |
168 | lua_pushnil(L); /* no more results */ | |
169 | return 1; | |
170 | } | |
171 | ||
172 | num_columns = PQnfields(statement->result); | |
173 | lua_newtable(L); | |
174 | for (i = 0; i < num_columns; i++) { | |
175 | const char *name = PQfname(statement->result, i); | |
176 | ||
177 | if (PQgetisnull(statement->result, tuple, i)) { | |
178 | if (named_columns) { | |
179 | LUA_PUSH_ATTRIB_NIL(name); | |
180 | } else { | |
181 | LUA_PUSH_ARRAY_NIL(d); | |
182 | } | |
183 | } else { | |
184 | const char *value = PQgetvalue(statement->result, tuple, i); | |
185 | lua_push_type_t lua_push = postgresql_to_lua_push(PQftype(statement->result, i)); | |
186 | ||
2 | 187 | /* |
188 | * data is returned as strings from PSQL | |
9 | 189 | * convert them here into Lua types |
2 | 190 | */ |
191 | ||
1 | 192 | if (lua_push == LUA_PUSH_NIL) { |
193 | if (named_columns) { | |
194 | LUA_PUSH_ATTRIB_NIL(name); | |
195 | } else { | |
196 | LUA_PUSH_ARRAY_NIL(d); | |
197 | } | |
198 | } else if (lua_push == LUA_PUSH_INTEGER) { | |
199 | int val = atoi(value); | |
200 | ||
201 | if (named_columns) { | |
202 | LUA_PUSH_ATTRIB_INT(name, val); | |
203 | } else { | |
204 | LUA_PUSH_ARRAY_INT(d, val); | |
205 | } | |
206 | } else if (lua_push == LUA_PUSH_NUMBER) { | |
207 | double val = strtod(value, NULL); | |
208 | ||
209 | if (named_columns) { | |
210 | LUA_PUSH_ATTRIB_FLOAT(name, val); | |
211 | } else { | |
212 | LUA_PUSH_ARRAY_FLOAT(d, val); | |
213 | } | |
214 | } else if (lua_push == LUA_PUSH_STRING) { | |
215 | if (named_columns) { | |
216 | LUA_PUSH_ATTRIB_STRING(name, value); | |
217 | } else { | |
218 | LUA_PUSH_ARRAY_STRING(d, value); | |
219 | } | |
220 | } else if (lua_push == LUA_PUSH_BOOLEAN) { | |
2 | 221 | /* |
222 | * booleans are returned as a string | |
223 | * either 't' or 'f' | |
224 | */ | |
1 | 225 | int val = value[0] == 't' ? 1 : 0; |
226 | ||
227 | if (named_columns) { | |
228 | LUA_PUSH_ATTRIB_BOOL(name, val); | |
229 | } else { | |
230 | LUA_PUSH_ARRAY_BOOL(d, val); | |
231 | } | |
232 | } else { | |
4 | 233 | luaL_error(L, DBI_ERR_UNKNOWN_PUSH); |
1 | 234 | } |
235 | } | |
236 | } | |
237 | ||
238 | return 1; | |
239 | } | |
240 | ||
11
b3e05e361f46
Bugfix: PSQL array returns were not being indexed properly.
nrich@ii.net
parents:
10
diff
changeset
|
241 | |
b3e05e361f46
Bugfix: PSQL array returns were not being indexed properly.
nrich@ii.net
parents:
10
diff
changeset
|
242 | static int next_iterator(lua_State *L) { |
b3e05e361f46
Bugfix: PSQL array returns were not being indexed properly.
nrich@ii.net
parents:
10
diff
changeset
|
243 | statement_t *statement = (statement_t *)luaL_checkudata(L, lua_upvalueindex(1), DBD_POSTGRESQL_STATEMENT); |
b3e05e361f46
Bugfix: PSQL array returns were not being indexed properly.
nrich@ii.net
parents:
10
diff
changeset
|
244 | int named_columns = lua_toboolean(L, lua_upvalueindex(2)); |
b3e05e361f46
Bugfix: PSQL array returns were not being indexed properly.
nrich@ii.net
parents:
10
diff
changeset
|
245 | |
b3e05e361f46
Bugfix: PSQL array returns were not being indexed properly.
nrich@ii.net
parents:
10
diff
changeset
|
246 | return statement_fetch_impl(L, statement, named_columns); |
1 | 247 | } |
248 | ||
2 | 249 | /* |
12
014ba3ab3903
Renamed statement:fetch() to statement:rows(), and statement:row() to statement:fetch(). The API reads better this way.
nrich@ii.net
parents:
11
diff
changeset
|
250 | * table = statement:fetch(named_indexes) |
2 | 251 | */ |
12
014ba3ab3903
Renamed statement:fetch() to statement:rows(), and statement:row() to statement:fetch(). The API reads better this way.
nrich@ii.net
parents:
11
diff
changeset
|
252 | static int statement_fetch(lua_State *L) { |
014ba3ab3903
Renamed statement:fetch() to statement:rows(), and statement:row() to statement:fetch(). The API reads better this way.
nrich@ii.net
parents:
11
diff
changeset
|
253 | statement_t *statement = (statement_t *)luaL_checkudata(L, 1, DBD_POSTGRESQL_STATEMENT); |
014ba3ab3903
Renamed statement:fetch() to statement:rows(), and statement:row() to statement:fetch(). The API reads better this way.
nrich@ii.net
parents:
11
diff
changeset
|
254 | int named_columns = lua_toboolean(L, 2); |
11
b3e05e361f46
Bugfix: PSQL array returns were not being indexed properly.
nrich@ii.net
parents:
10
diff
changeset
|
255 | |
12
014ba3ab3903
Renamed statement:fetch() to statement:rows(), and statement:row() to statement:fetch(). The API reads better this way.
nrich@ii.net
parents:
11
diff
changeset
|
256 | return statement_fetch_impl(L, statement, named_columns); |
014ba3ab3903
Renamed statement:fetch() to statement:rows(), and statement:row() to statement:fetch(). The API reads better this way.
nrich@ii.net
parents:
11
diff
changeset
|
257 | } |
014ba3ab3903
Renamed statement:fetch() to statement:rows(), and statement:row() to statement:fetch(). The API reads better this way.
nrich@ii.net
parents:
11
diff
changeset
|
258 | |
014ba3ab3903
Renamed statement:fetch() to statement:rows(), and statement:row() to statement:fetch(). The API reads better this way.
nrich@ii.net
parents:
11
diff
changeset
|
259 | /* |
21
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
20
diff
changeset
|
260 | * num_rows = statement:rowcount() |
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
20
diff
changeset
|
261 | */ |
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
20
diff
changeset
|
262 | static int statement_rowcount(lua_State *L) { |
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
20
diff
changeset
|
263 | statement_t *statement = (statement_t *)luaL_checkudata(L, 1, DBD_POSTGRESQL_STATEMENT); |
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
20
diff
changeset
|
264 | |
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
20
diff
changeset
|
265 | if (!statement->result) { |
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
20
diff
changeset
|
266 | luaL_error(L, DBI_ERR_INVALID_STATEMENT); |
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
20
diff
changeset
|
267 | } |
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
20
diff
changeset
|
268 | |
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
20
diff
changeset
|
269 | lua_pushinteger(L, PQntuples(statement->result)); |
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
20
diff
changeset
|
270 | |
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
20
diff
changeset
|
271 | return 1; |
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
20
diff
changeset
|
272 | } |
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
20
diff
changeset
|
273 | |
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
20
diff
changeset
|
274 | /* |
12
014ba3ab3903
Renamed statement:fetch() to statement:rows(), and statement:row() to statement:fetch(). The API reads better this way.
nrich@ii.net
parents:
11
diff
changeset
|
275 | * iterfunc = statement:rows(named_indexes) |
014ba3ab3903
Renamed statement:fetch() to statement:rows(), and statement:row() to statement:fetch(). The API reads better this way.
nrich@ii.net
parents:
11
diff
changeset
|
276 | */ |
014ba3ab3903
Renamed statement:fetch() to statement:rows(), and statement:row() to statement:fetch(). The API reads better this way.
nrich@ii.net
parents:
11
diff
changeset
|
277 | static int statement_rows(lua_State *L) { |
11
b3e05e361f46
Bugfix: PSQL array returns were not being indexed properly.
nrich@ii.net
parents:
10
diff
changeset
|
278 | if (lua_gettop(L) == 1) { |
b3e05e361f46
Bugfix: PSQL array returns were not being indexed properly.
nrich@ii.net
parents:
10
diff
changeset
|
279 | lua_pushvalue(L, 1); |
b3e05e361f46
Bugfix: PSQL array returns were not being indexed properly.
nrich@ii.net
parents:
10
diff
changeset
|
280 | lua_pushboolean(L, 0); |
b3e05e361f46
Bugfix: PSQL array returns were not being indexed properly.
nrich@ii.net
parents:
10
diff
changeset
|
281 | } else { |
b3e05e361f46
Bugfix: PSQL array returns were not being indexed properly.
nrich@ii.net
parents:
10
diff
changeset
|
282 | lua_pushvalue(L, 1); |
b3e05e361f46
Bugfix: PSQL array returns were not being indexed properly.
nrich@ii.net
parents:
10
diff
changeset
|
283 | lua_pushboolean(L, lua_toboolean(L, 2)); |
b3e05e361f46
Bugfix: PSQL array returns were not being indexed properly.
nrich@ii.net
parents:
10
diff
changeset
|
284 | } |
b3e05e361f46
Bugfix: PSQL array returns were not being indexed properly.
nrich@ii.net
parents:
10
diff
changeset
|
285 | |
b3e05e361f46
Bugfix: PSQL array returns were not being indexed properly.
nrich@ii.net
parents:
10
diff
changeset
|
286 | lua_pushcclosure(L, next_iterator, 2); |
b3e05e361f46
Bugfix: PSQL array returns were not being indexed properly.
nrich@ii.net
parents:
10
diff
changeset
|
287 | return 1; |
b3e05e361f46
Bugfix: PSQL array returns were not being indexed properly.
nrich@ii.net
parents:
10
diff
changeset
|
288 | } |
b3e05e361f46
Bugfix: PSQL array returns were not being indexed properly.
nrich@ii.net
parents:
10
diff
changeset
|
289 | |
b3e05e361f46
Bugfix: PSQL array returns were not being indexed properly.
nrich@ii.net
parents:
10
diff
changeset
|
290 | /* |
2 | 291 | * __gc |
292 | */ | |
1 | 293 | static int statement_gc(lua_State *L) { |
294 | /* always free the handle */ | |
295 | statement_close(L); | |
296 | ||
297 | return 0; | |
298 | } | |
299 | ||
300 | int dbd_postgresql_statement_create(lua_State *L, connection_t *conn, const char *sql_query) { | |
301 | statement_t *statement = NULL; | |
302 | ExecStatusType status; | |
303 | PGresult *result = NULL; | |
304 | char *new_sql; | |
305 | char name[IDLEN]; | |
306 | ||
2 | 307 | /* |
308 | * convert SQL string into a PSQL API compatible SQL statement | |
309 | */ | |
17
21c4feaeafe7
Added initial Oracle driver support - functionality is complete, but may be too buggy in its current state for any serious use.
nrich@ii.net
parents:
12
diff
changeset
|
310 | new_sql = replace_placeholders(L, '$', sql_query); |
1 | 311 | |
312 | snprintf(name, IDLEN, "%017u", ++conn->statement_id); | |
313 | ||
314 | result = PQprepare(conn->postgresql, name, new_sql, 0, NULL); | |
2 | 315 | |
316 | /* | |
317 | * free converted statement after use | |
318 | */ | |
1 | 319 | free(new_sql); |
320 | ||
321 | if (!result) { | |
3 | 322 | lua_pushnil(L); |
4 | 323 | lua_pushfstring(L, DBI_ERR_ALLOC_STATEMENT, PQerrorMessage(statement->postgresql)); |
3 | 324 | return 2; |
1 | 325 | } |
326 | ||
327 | status = PQresultStatus(result); | |
328 | if (status != PGRES_COMMAND_OK && status != PGRES_TUPLES_OK) { | |
329 | const char *err_string = PQresultErrorMessage(result); | |
330 | PQclear(result); | |
3 | 331 | |
332 | lua_pushnil(L); | |
4 | 333 | lua_pushfstring(L, DBI_ERR_PREP_STATEMENT, err_string); |
3 | 334 | return 2; |
1 | 335 | } |
336 | ||
337 | PQclear(result); | |
338 | ||
339 | statement = (statement_t *)lua_newuserdata(L, sizeof(statement_t)); | |
340 | statement->postgresql = conn->postgresql; | |
341 | statement->result = NULL; | |
342 | statement->tuple = 0; | |
343 | strncpy(statement->name, name, IDLEN-1); | |
344 | statement->name[IDLEN-1] = '\0'; | |
345 | ||
346 | luaL_getmetatable(L, DBD_POSTGRESQL_STATEMENT); | |
347 | lua_setmetatable(L, -2); | |
348 | ||
349 | return 1; | |
350 | } | |
351 | ||
352 | int dbd_postgresql_statement(lua_State *L) { | |
2 | 353 | static const luaL_Reg statement_methods[] = { |
21
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
20
diff
changeset
|
354 | {"affected", statement_affected}, |
2 | 355 | {"close", statement_close}, |
356 | {"execute", statement_execute}, | |
357 | {"fetch", statement_fetch}, | |
21
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
20
diff
changeset
|
358 | {"rowcount", statement_rowcount}, |
12
014ba3ab3903
Renamed statement:fetch() to statement:rows(), and statement:row() to statement:fetch(). The API reads better this way.
nrich@ii.net
parents:
11
diff
changeset
|
359 | {"rows", statement_rows}, |
2 | 360 | {NULL, NULL} |
361 | }; | |
362 | ||
363 | static const luaL_Reg statement_class_methods[] = { | |
364 | {NULL, NULL} | |
365 | }; | |
366 | ||
1 | 367 | luaL_newmetatable(L, DBD_POSTGRESQL_STATEMENT); |
368 | luaL_register(L, 0, statement_methods); | |
369 | lua_pushvalue(L,-1); | |
370 | lua_setfield(L, -2, "__index"); | |
371 | ||
372 | lua_pushcfunction(L, statement_gc); | |
373 | lua_setfield(L, -2, "__gc"); | |
374 | ||
375 | luaL_register(L, DBD_POSTGRESQL_STATEMENT, statement_class_methods); | |
376 | ||
377 | return 1; | |
378 | } |