dbd/postgresql/statement.c

changeset 30
8599f34c139b
parent 21
7956401a0c5e
child 32
03ed0ca09837
equal deleted inserted replaced
29:9b9d85320bc3 30:8599f34c139b
14 case FLOAT8OID: 14 case FLOAT8OID:
15 lua_type = LUA_PUSH_NUMBER; 15 lua_type = LUA_PUSH_NUMBER;
16 break; 16 break;
17 17
18 case BOOLOID: 18 case BOOLOID:
19 lua_type = LUA_PUSH_BOOLEAN; 19 lua_type = LUA_PUSH_BOOLEAN;
20 break; 20 break;
21 21
22 default: 22 default:
23 lua_type = LUA_PUSH_STRING; 23 lua_type = LUA_PUSH_STRING;
24 } 24 }
25 25
26 return lua_type; 26 return lua_type;
27 } 27 }
28 28
29 static int deallocate(statement_t *statement) {
30 char command[IDLEN+11];
31
32 snprintf(command, IDLEN+11, "DEALLOCATE %s", statement->name);
33
34 PGresult *result = PQexec(statement->postgresql, command);
35 ExecStatusType status;
36
37 if (!result)
38 return 1;
39
40 status = PQresultStatus(result);
41 PQclear(result);
42
43 if (status != PGRES_COMMAND_OK && status != PGRES_TUPLES_OK)
44 return 1;
45
46 return 0;
47 }
48
49
29 /* 50 /*
30 * num_affected_rows = statement:affected() 51 * num_affected_rows = statement:affected()
31 */ 52 */
32 static int statement_affected(lua_State *L) { 53 static int statement_affected(lua_State *L) {
33 statement_t *statement = (statement_t *)luaL_checkudata(L, 1, DBD_POSTGRESQL_STATEMENT); 54 statement_t *statement = (statement_t *)luaL_checkudata(L, 1, DBD_POSTGRESQL_STATEMENT);
46 */ 67 */
47 static int statement_close(lua_State *L) { 68 static int statement_close(lua_State *L) {
48 statement_t *statement = (statement_t *)luaL_checkudata(L, 1, DBD_POSTGRESQL_STATEMENT); 69 statement_t *statement = (statement_t *)luaL_checkudata(L, 1, DBD_POSTGRESQL_STATEMENT);
49 70
50 if (statement->result) { 71 if (statement->result) {
72 /*
73 * Deallocate prepared statement on the
74 * server side
75 */
76 deallocate(statement);
77
51 PQclear(statement->result); 78 PQclear(statement->result);
52 statement->result = NULL; 79 statement->result = NULL;
53 } 80 }
54 81
55 return 0; 82 return 0;
83 }
84
85 /*
86 * column_names = statement:columns()
87 */
88 static int statement_columns(lua_State *L) {
89 statement_t *statement = (statement_t *)luaL_checkudata(L, 1, DBD_POSTGRESQL_STATEMENT);
90
91 int i;
92 int num_columns;
93 int d = 1;
94
95 if (!statement->result) {
96 luaL_error(L, DBI_ERR_INVALID_STATEMENT);
97 return 0;
98 }
99
100 num_columns = PQnfields(statement->result);
101 lua_newtable(L);
102 for (i = 0; i < num_columns; i++) {
103 const char *name = PQfname(statement->result, i);
104
105 LUA_PUSH_ARRAY_STRING(d, name);
106 }
107
108 return 1;
56 } 109 }
57 110
58 /* 111 /*
59 * success = statement:execute(...) 112 * success = statement:execute(...)
60 */ 113 */
76 129
77 /* 130 /*
78 * convert and copy parameters into a string array 131 * convert and copy parameters into a string array
79 */ 132 */
80 for (p = 2; p <= n; p++) { 133 for (p = 2; p <= n; p++) {
81 int i = p - 2; 134 int i = p - 2;
82 int type = lua_type(L, p); 135 int type = lua_type(L, p);
83 char err[64]; 136 char err[64];
84 137
85 switch(type) { 138 switch(type) {
86 case LUA_TNIL: 139 case LUA_TNIL:
87 params[i] = NULL; 140 params[i] = NULL;
88 break; 141 break;
89 case LUA_TBOOLEAN: 142 case LUA_TBOOLEAN:
90 /* 143 /*
91 * boolean values in postgresql can either be 144 * boolean values in postgresql can either be
92 * t/f or 1/0. Pass integer values rather than 145 * t/f or 1/0. Pass integer values rather than
93 * strings to maintain semantic compatibility 146 * strings to maintain semantic compatibility
94 * with other DBD drivers that pass booleans 147 * with other DBD drivers that pass booleans
95 * as integers. 148 * as integers.
96 */ 149 */
97 params[i] = lua_toboolean(L, p) ? "1" : "0"; 150 params[i] = lua_toboolean(L, p) ? "1" : "0";
98 break; 151 break;
99 case LUA_TNUMBER: 152 case LUA_TNUMBER:
100 case LUA_TSTRING: 153 case LUA_TSTRING:
101 params[i] = lua_tostring(L, p); 154 params[i] = lua_tostring(L, p);
102 break; 155 break;
103 default: 156 default:
104 snprintf(err, sizeof(err)-1, DBI_ERR_BINDING_TYPE_ERR, lua_typename(L, type)); 157 snprintf(err, sizeof(err)-1, DBI_ERR_BINDING_TYPE_ERR, lua_typename(L, type));
105 errstr = err; 158 errstr = err;
106 goto cleanup; 159 goto cleanup;
107 } 160 }
108 } 161 }
109 162
110 result = PQexecPrepared( 163 result = PQexecPrepared(
111 statement->postgresql, 164 statement->postgresql,
112 statement->name, 165 statement->name,
113 num_bind_params, 166 num_bind_params,
114 (const char **)params, 167 (const char **)params,
115 NULL, 168 NULL,
116 NULL, 169 NULL,
117 0 170 0
118 ); 171 );
119 172
120 cleanup: 173 cleanup:
121 free(params); 174 free(params);
122 175
123 if (errstr) { 176 if (errstr) {
124 lua_pushboolean(L, 0); 177 lua_pushboolean(L, 0);
125 lua_pushfstring(L, DBI_ERR_BINDING_PARAMS, errstr); 178 lua_pushfstring(L, DBI_ERR_BINDING_PARAMS, errstr);
126 return 2; 179 return 2;
127 } 180 }
128 181
129 if (!result) { 182 if (!result) {
130 lua_pushboolean(L, 0); 183 lua_pushboolean(L, 0);
131 lua_pushfstring(L, DBI_ERR_ALLOC_RESULT, PQerrorMessage(statement->postgresql)); 184 lua_pushfstring(L, DBI_ERR_ALLOC_RESULT, PQerrorMessage(statement->postgresql));
132 return 2; 185 return 2;
133 } 186 }
134 187
135 status = PQresultStatus(result); 188 status = PQresultStatus(result);
136 if (status != PGRES_COMMAND_OK && status != PGRES_TUPLES_OK) { 189 if (status != PGRES_COMMAND_OK && status != PGRES_TUPLES_OK) {
137 lua_pushboolean(L, 0); 190 lua_pushboolean(L, 0);
138 lua_pushfstring(L, DBI_ERR_BINDING_EXEC, PQresultErrorMessage(result)); 191 lua_pushfstring(L, DBI_ERR_BINDING_EXEC, PQresultErrorMessage(result));
139 return 2; 192 return 2;
140 } 193 }
141 194
142 statement->result = result; 195 statement->result = result;
143 196
144 lua_pushboolean(L, 1); 197 lua_pushboolean(L, 1);
145 return 1; 198 return 1;
146 } 199 }
147 200
148 /* 201 /*
149 * must be called after an execute 202 * can only be called after an execute
150 */ 203 */
151 static int statement_fetch_impl(lua_State *L, statement_t *statement, int named_columns) { 204 static int statement_fetch_impl(lua_State *L, statement_t *statement, int named_columns) {
152 int tuple = statement->tuple++; 205 int tuple = statement->tuple++;
153 int i; 206 int i;
154 int num_columns; 207 int num_columns;
155 int d = 1; 208 int d = 1;
156 209
157 if (!statement->result) { 210 if (!statement->result) {
158 luaL_error(L, DBI_ERR_FETCH_INVALID); 211 luaL_error(L, DBI_ERR_FETCH_INVALID);
159 return 0; 212 return 0;
160 } 213 }
161 214
162 if (PQresultStatus(statement->result) != PGRES_TUPLES_OK) { 215 if (PQresultStatus(statement->result) != PGRES_TUPLES_OK) {
163 lua_pushnil(L); 216 lua_pushnil(L);
164 return 1; 217 return 1;
165 } 218 }
166 219
167 if (tuple >= PQntuples(statement->result)) { 220 if (tuple >= PQntuples(statement->result)) {
168 lua_pushnil(L); /* no more results */ 221 lua_pushnil(L); /* no more results */
169 return 1; 222 return 1;
170 } 223 }
171 224
172 num_columns = PQnfields(statement->result); 225 num_columns = PQnfields(statement->result);
173 lua_newtable(L); 226 lua_newtable(L);
174 for (i = 0; i < num_columns; i++) { 227 for (i = 0; i < num_columns; i++) {
175 const char *name = PQfname(statement->result, i); 228 const char *name = PQfname(statement->result, i);
176 229
177 if (PQgetisnull(statement->result, tuple, i)) { 230 if (PQgetisnull(statement->result, tuple, i)) {
178 if (named_columns) { 231 if (named_columns) {
179 LUA_PUSH_ATTRIB_NIL(name); 232 LUA_PUSH_ATTRIB_NIL(name);
180 } else { 233 } else {
181 LUA_PUSH_ARRAY_NIL(d); 234 LUA_PUSH_ARRAY_NIL(d);
182 } 235 }
183 } else { 236 } else {
184 const char *value = PQgetvalue(statement->result, tuple, i); 237 const char *value = PQgetvalue(statement->result, tuple, i);
185 lua_push_type_t lua_push = postgresql_to_lua_push(PQftype(statement->result, i)); 238 lua_push_type_t lua_push = postgresql_to_lua_push(PQftype(statement->result, i));
186 239
187 /* 240 /*
188 * data is returned as strings from PSQL 241 * data is returned as strings from PSQL
189 * convert them here into Lua types 242 * convert them here into Lua types
190 */ 243 */
191 244
192 if (lua_push == LUA_PUSH_NIL) { 245 if (lua_push == LUA_PUSH_NIL) {
216 LUA_PUSH_ATTRIB_STRING(name, value); 269 LUA_PUSH_ATTRIB_STRING(name, value);
217 } else { 270 } else {
218 LUA_PUSH_ARRAY_STRING(d, value); 271 LUA_PUSH_ARRAY_STRING(d, value);
219 } 272 }
220 } else if (lua_push == LUA_PUSH_BOOLEAN) { 273 } else if (lua_push == LUA_PUSH_BOOLEAN) {
221 /* 274 /*
222 * booleans are returned as a string 275 * booleans are returned as a string
223 * either 't' or 'f' 276 * either 't' or 'f'
224 */ 277 */
225 int val = value[0] == 't' ? 1 : 0; 278 int val = value[0] == 't' ? 1 : 0;
226 279
230 LUA_PUSH_ARRAY_BOOL(d, val); 283 LUA_PUSH_ARRAY_BOOL(d, val);
231 } 284 }
232 } else { 285 } else {
233 luaL_error(L, DBI_ERR_UNKNOWN_PUSH); 286 luaL_error(L, DBI_ERR_UNKNOWN_PUSH);
234 } 287 }
235 } 288 }
236 } 289 }
237 290
238 return 1; 291 return 1;
239 } 292 }
240 293
307 /* 360 /*
308 * convert SQL string into a PSQL API compatible SQL statement 361 * convert SQL string into a PSQL API compatible SQL statement
309 */ 362 */
310 new_sql = replace_placeholders(L, '$', sql_query); 363 new_sql = replace_placeholders(L, '$', sql_query);
311 364
312 snprintf(name, IDLEN, "%017u", ++conn->statement_id); 365 snprintf(name, IDLEN, "dbd-postgresql-%017u", ++conn->statement_id);
313 366
314 result = PQprepare(conn->postgresql, name, new_sql, 0, NULL); 367 result = PQprepare(conn->postgresql, name, new_sql, 0, NULL);
315 368
316 /* 369 /*
317 * free converted statement after use 370 * free converted statement after use
318 */ 371 */
319 free(new_sql); 372 free(new_sql);
320 373
321 if (!result) { 374 if (!result) {
322 lua_pushnil(L); 375 lua_pushnil(L);
323 lua_pushfstring(L, DBI_ERR_ALLOC_STATEMENT, PQerrorMessage(statement->postgresql)); 376 lua_pushfstring(L, DBI_ERR_ALLOC_STATEMENT, PQerrorMessage(statement->postgresql));
324 return 2; 377 return 2;
325 } 378 }
326 379
327 status = PQresultStatus(result); 380 status = PQresultStatus(result);
328 if (status != PGRES_COMMAND_OK && status != PGRES_TUPLES_OK) { 381 if (status != PGRES_COMMAND_OK && status != PGRES_TUPLES_OK) {
329 const char *err_string = PQresultErrorMessage(result); 382 const char *err_string = PQresultErrorMessage(result);
330 PQclear(result); 383 PQclear(result);
331 384
332 lua_pushnil(L); 385 lua_pushnil(L);
333 lua_pushfstring(L, DBI_ERR_PREP_STATEMENT, err_string); 386 lua_pushfstring(L, DBI_ERR_PREP_STATEMENT, err_string);
334 return 2; 387 return 2;
335 } 388 }
336 389
337 PQclear(result); 390 PQclear(result);
338 391
339 statement = (statement_t *)lua_newuserdata(L, sizeof(statement_t)); 392 statement = (statement_t *)lua_newuserdata(L, sizeof(statement_t));
349 return 1; 402 return 1;
350 } 403 }
351 404
352 int dbd_postgresql_statement(lua_State *L) { 405 int dbd_postgresql_statement(lua_State *L) {
353 static const luaL_Reg statement_methods[] = { 406 static const luaL_Reg statement_methods[] = {
354 {"affected", statement_affected}, 407 {"affected", statement_affected},
355 {"close", statement_close}, 408 {"close", statement_close},
356 {"execute", statement_execute}, 409 {"columns", statement_columns},
357 {"fetch", statement_fetch}, 410 {"execute", statement_execute},
358 {"rowcount", statement_rowcount}, 411 {"fetch", statement_fetch},
359 {"rows", statement_rows}, 412 {"rowcount", statement_rowcount},
360 {NULL, NULL} 413 {"rows", statement_rows},
414 {NULL, NULL}
361 }; 415 };
362 416
363 static const luaL_Reg statement_class_methods[] = { 417 static const luaL_Reg statement_class_methods[] = {
364 {NULL, NULL} 418 {NULL, NULL}
365 }; 419 };
366 420
367 luaL_newmetatable(L, DBD_POSTGRESQL_STATEMENT); 421 luaL_newmetatable(L, DBD_POSTGRESQL_STATEMENT);
368 luaL_register(L, 0, statement_methods); 422 luaL_register(L, 0, statement_methods);
369 lua_pushvalue(L,-1); 423 lua_pushvalue(L,-1);

mercurial