dbd/postgresql/statement.c

Mon, 01 Dec 2008 07:22:44 +0000

author
nrich@ii.net
date
Mon, 01 Dec 2008 07:22:44 +0000
changeset 10
3aa8a37a3dd8
parent 9
06eb2850703f
child 11
b3e05e361f46
permissions
-rw-r--r--

Added new typechecks and errors

1
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
1 #include "dbd_postgresql.h"
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
2
2
c4f02fc67e5a Cleanup and commenting
nrich@ii.net
parents: 1
diff changeset
3 #define MAX_PLACEHOLDERS 9999
1
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
4 #define MAX_PLACEHOLDER_SIZE (1+4) /* $\d{4} */
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
5
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
6 static lua_push_type_t postgresql_to_lua_push(unsigned int postgresql_type) {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
7 lua_push_type_t lua_type;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
8
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
9 switch(postgresql_type) {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
10 case INT2OID:
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
11 case INT4OID:
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
12 lua_type = LUA_PUSH_INTEGER;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
13 break;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
14
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
15 case FLOAT4OID:
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
16 case FLOAT8OID:
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
17 lua_type = LUA_PUSH_NUMBER;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
18 break;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
19
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
20 case BOOLOID:
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
21 lua_type = LUA_PUSH_BOOLEAN;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
22 break;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
23
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
24 default:
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
25 lua_type = LUA_PUSH_STRING;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
26 }
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
27
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
28 return lua_type;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
29 }
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
30
2
c4f02fc67e5a Cleanup and commenting
nrich@ii.net
parents: 1
diff changeset
31 /*
c4f02fc67e5a Cleanup and commenting
nrich@ii.net
parents: 1
diff changeset
32 * replace '?' placeholders with $\d+ placeholders
c4f02fc67e5a Cleanup and commenting
nrich@ii.net
parents: 1
diff changeset
33 * to be compatible with PSQL API
c4f02fc67e5a Cleanup and commenting
nrich@ii.net
parents: 1
diff changeset
34 */
1
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
35 static char *replace_placeholders(lua_State *L, const char *sql) {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
36 size_t len = strlen(sql);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
37 int num_placeholders = 0;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
38 int extra_space = 0;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
39 int i;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
40 char *newsql;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
41 int newpos = 1;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
42 int ph_num = 1;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
43 int in_quote = 0;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
44
2
c4f02fc67e5a Cleanup and commenting
nrich@ii.net
parents: 1
diff changeset
45 /*
c4f02fc67e5a Cleanup and commenting
nrich@ii.net
parents: 1
diff changeset
46 * dumb count of all '?'
c4f02fc67e5a Cleanup and commenting
nrich@ii.net
parents: 1
diff changeset
47 * this will match more placeholders than necessesary
c4f02fc67e5a Cleanup and commenting
nrich@ii.net
parents: 1
diff changeset
48 * but it's safer to allocate more placeholders at the
c4f02fc67e5a Cleanup and commenting
nrich@ii.net
parents: 1
diff changeset
49 * cost of a few bytes than risk a buffer overflow
c4f02fc67e5a Cleanup and commenting
nrich@ii.net
parents: 1
diff changeset
50 */
1
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
51 for (i = 1; i < len; i++) {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
52 if (sql[i] == '?') {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
53 num_placeholders++;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
54 }
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
55 }
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
56
2
c4f02fc67e5a Cleanup and commenting
nrich@ii.net
parents: 1
diff changeset
57 /*
c4f02fc67e5a Cleanup and commenting
nrich@ii.net
parents: 1
diff changeset
58 * this is MAX_PLACEHOLDER_SIZE-1 because the '?' is
c4f02fc67e5a Cleanup and commenting
nrich@ii.net
parents: 1
diff changeset
59 * replaced with '$'
c4f02fc67e5a Cleanup and commenting
nrich@ii.net
parents: 1
diff changeset
60 */
1
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
61 extra_space = num_placeholders * (MAX_PLACEHOLDER_SIZE-1);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
62
2
c4f02fc67e5a Cleanup and commenting
nrich@ii.net
parents: 1
diff changeset
63 /*
c4f02fc67e5a Cleanup and commenting
nrich@ii.net
parents: 1
diff changeset
64 * allocate a new string for the converted SQL statement
c4f02fc67e5a Cleanup and commenting
nrich@ii.net
parents: 1
diff changeset
65 */
1
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
66 newsql = malloc(sizeof(char) * (len+extra_space+1));
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
67 memset(newsql, 0, sizeof(char) * (len+extra_space+1));
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
68
2
c4f02fc67e5a Cleanup and commenting
nrich@ii.net
parents: 1
diff changeset
69 /*
c4f02fc67e5a Cleanup and commenting
nrich@ii.net
parents: 1
diff changeset
70 * copy first char. In valid SQL this cannot be a placeholder
c4f02fc67e5a Cleanup and commenting
nrich@ii.net
parents: 1
diff changeset
71 */
1
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
72 newsql[0] = sql[0];
2
c4f02fc67e5a Cleanup and commenting
nrich@ii.net
parents: 1
diff changeset
73
c4f02fc67e5a Cleanup and commenting
nrich@ii.net
parents: 1
diff changeset
74 /*
c4f02fc67e5a Cleanup and commenting
nrich@ii.net
parents: 1
diff changeset
75 * only replace '?' not in a single quoted string
c4f02fc67e5a Cleanup and commenting
nrich@ii.net
parents: 1
diff changeset
76 */
1
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
77 for (i = 1; i < len; i++) {
2
c4f02fc67e5a Cleanup and commenting
nrich@ii.net
parents: 1
diff changeset
78 /*
c4f02fc67e5a Cleanup and commenting
nrich@ii.net
parents: 1
diff changeset
79 * don't change the quote flag if the ''' is preceded
c4f02fc67e5a Cleanup and commenting
nrich@ii.net
parents: 1
diff changeset
80 * bt a '\' to account for escaping
c4f02fc67e5a Cleanup and commenting
nrich@ii.net
parents: 1
diff changeset
81 */
1
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
82 if (sql[i] == '\'' && sql[i-1] != '\\') {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
83 in_quote = !in_quote;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
84 }
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
85
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
86 if (sql[i] == '?' && !in_quote) {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
87 size_t n;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
88
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
89 if (ph_num > MAX_PLACEHOLDERS) {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
90 luaL_error(L, "Sorry, you are using more than %d placeholders. Use ${num} format instead", MAX_PLACEHOLDERS);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
91 }
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
92
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
93 n = snprintf(&newsql[newpos], MAX_PLACEHOLDER_SIZE, "$%u", ph_num++);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
94
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
95 newpos += n;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
96 } else {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
97 newsql[newpos] = sql[i];
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
98 newpos++;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
99 }
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
100 }
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
101
2
c4f02fc67e5a Cleanup and commenting
nrich@ii.net
parents: 1
diff changeset
102 /*
c4f02fc67e5a Cleanup and commenting
nrich@ii.net
parents: 1
diff changeset
103 * terminate string on the last position
c4f02fc67e5a Cleanup and commenting
nrich@ii.net
parents: 1
diff changeset
104 */
1
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
105 newsql[newpos] = '\0';
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
106
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
107 /* fprintf(stderr, "[%s]\n", newsql); */
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
108 return newsql;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
109 }
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
110
2
c4f02fc67e5a Cleanup and commenting
nrich@ii.net
parents: 1
diff changeset
111 /*
c4f02fc67e5a Cleanup and commenting
nrich@ii.net
parents: 1
diff changeset
112 * success = statement:close()
c4f02fc67e5a Cleanup and commenting
nrich@ii.net
parents: 1
diff changeset
113 */
1
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
114 static int statement_close(lua_State *L) {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
115 statement_t *statement = (statement_t *)luaL_checkudata(L, 1, DBD_POSTGRESQL_STATEMENT);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
116
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
117 if (statement->result) {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
118 PQclear(statement->result);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
119 statement->result = NULL;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
120 }
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
121
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
122 return 0;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
123 }
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
124
2
c4f02fc67e5a Cleanup and commenting
nrich@ii.net
parents: 1
diff changeset
125 /*
c4f02fc67e5a Cleanup and commenting
nrich@ii.net
parents: 1
diff changeset
126 * success = statement:execute(...)
c4f02fc67e5a Cleanup and commenting
nrich@ii.net
parents: 1
diff changeset
127 */
1
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
128 static int statement_execute(lua_State *L) {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
129 int n = lua_gettop(L);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
130 statement_t *statement = (statement_t *)luaL_checkudata(L, 1, DBD_POSTGRESQL_STATEMENT);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
131 int num_bind_params = n - 1;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
132 ExecStatusType status;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
133 int p;
10
3aa8a37a3dd8 Added new typechecks and errors
nrich@ii.net
parents: 9
diff changeset
134 const char *errstr = NULL;
1
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
135
9
06eb2850703f Bugfix: fix connection in DBD.SQLite3.New
nrich@ii.net
parents: 8
diff changeset
136 const char **params;
1
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
137 PGresult *result = NULL;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
138
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
139 statement->tuple = 0;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
140
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
141 params = malloc(num_bind_params * sizeof(params));
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
142
2
c4f02fc67e5a Cleanup and commenting
nrich@ii.net
parents: 1
diff changeset
143 /*
c4f02fc67e5a Cleanup and commenting
nrich@ii.net
parents: 1
diff changeset
144 * convert and copy parameters into a string array
c4f02fc67e5a Cleanup and commenting
nrich@ii.net
parents: 1
diff changeset
145 */
1
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
146 for (p = 2; p <= n; p++) {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
147 int i = p - 2;
10
3aa8a37a3dd8 Added new typechecks and errors
nrich@ii.net
parents: 9
diff changeset
148 int type = lua_type(L, p);
3aa8a37a3dd8 Added new typechecks and errors
nrich@ii.net
parents: 9
diff changeset
149 char err[64];
1
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
150
10
3aa8a37a3dd8 Added new typechecks and errors
nrich@ii.net
parents: 9
diff changeset
151 switch(type) {
3aa8a37a3dd8 Added new typechecks and errors
nrich@ii.net
parents: 9
diff changeset
152 case LUA_TNIL:
1
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
153 params[i] = NULL;
10
3aa8a37a3dd8 Added new typechecks and errors
nrich@ii.net
parents: 9
diff changeset
154 break;
3aa8a37a3dd8 Added new typechecks and errors
nrich@ii.net
parents: 9
diff changeset
155 case LUA_TBOOLEAN:
3aa8a37a3dd8 Added new typechecks and errors
nrich@ii.net
parents: 9
diff changeset
156 /*
3aa8a37a3dd8 Added new typechecks and errors
nrich@ii.net
parents: 9
diff changeset
157 * boolean values in postgresql can either be
3aa8a37a3dd8 Added new typechecks and errors
nrich@ii.net
parents: 9
diff changeset
158 * t/f or 1/0. Pass integer values rather than
3aa8a37a3dd8 Added new typechecks and errors
nrich@ii.net
parents: 9
diff changeset
159 * strings to maintain semantic compatibility
3aa8a37a3dd8 Added new typechecks and errors
nrich@ii.net
parents: 9
diff changeset
160 * with other DBD drivers that pass booleans
3aa8a37a3dd8 Added new typechecks and errors
nrich@ii.net
parents: 9
diff changeset
161 * as integers.
3aa8a37a3dd8 Added new typechecks and errors
nrich@ii.net
parents: 9
diff changeset
162 */
3aa8a37a3dd8 Added new typechecks and errors
nrich@ii.net
parents: 9
diff changeset
163 params[i] = lua_toboolean(L, p) ? "1" : "0";
3aa8a37a3dd8 Added new typechecks and errors
nrich@ii.net
parents: 9
diff changeset
164 break;
3aa8a37a3dd8 Added new typechecks and errors
nrich@ii.net
parents: 9
diff changeset
165 case LUA_TNUMBER:
3aa8a37a3dd8 Added new typechecks and errors
nrich@ii.net
parents: 9
diff changeset
166 case LUA_TSTRING:
3aa8a37a3dd8 Added new typechecks and errors
nrich@ii.net
parents: 9
diff changeset
167 params[i] = lua_tostring(L, p);
3aa8a37a3dd8 Added new typechecks and errors
nrich@ii.net
parents: 9
diff changeset
168 break;
3aa8a37a3dd8 Added new typechecks and errors
nrich@ii.net
parents: 9
diff changeset
169 default:
3aa8a37a3dd8 Added new typechecks and errors
nrich@ii.net
parents: 9
diff changeset
170 snprintf(err, sizeof(err)-1, DBI_ERR_BINDING_TYPE_ERR, lua_typename(L, type));
3aa8a37a3dd8 Added new typechecks and errors
nrich@ii.net
parents: 9
diff changeset
171 errstr = err;
3aa8a37a3dd8 Added new typechecks and errors
nrich@ii.net
parents: 9
diff changeset
172 goto cleanup;
1
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
173 }
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
174 }
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
175
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
176 result = PQexecPrepared(
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
177 statement->postgresql,
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
178 statement->name,
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
179 num_bind_params,
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
180 (const char **)params,
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
181 NULL,
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
182 NULL,
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
183 0
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
184 );
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
185
10
3aa8a37a3dd8 Added new typechecks and errors
nrich@ii.net
parents: 9
diff changeset
186 cleanup:
1
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
187 free(params);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
188
10
3aa8a37a3dd8 Added new typechecks and errors
nrich@ii.net
parents: 9
diff changeset
189 if (errstr) {
3aa8a37a3dd8 Added new typechecks and errors
nrich@ii.net
parents: 9
diff changeset
190 lua_pushboolean(L, 0);
3aa8a37a3dd8 Added new typechecks and errors
nrich@ii.net
parents: 9
diff changeset
191 lua_pushfstring(L, DBI_ERR_BINDING_PARAMS, errstr);
3aa8a37a3dd8 Added new typechecks and errors
nrich@ii.net
parents: 9
diff changeset
192 return 2;
3aa8a37a3dd8 Added new typechecks and errors
nrich@ii.net
parents: 9
diff changeset
193 }
3aa8a37a3dd8 Added new typechecks and errors
nrich@ii.net
parents: 9
diff changeset
194
1
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
195 if (!result) {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
196 lua_pushboolean(L, 0);
4
c50b0e6f25d6 Clean up error messages for consistency.
nrich@ii.net
parents: 3
diff changeset
197 lua_pushfstring(L, DBI_ERR_ALLOC_RESULT, PQerrorMessage(statement->postgresql));
3
b61020ca4753 Cleanup and 'assert' error handling.
nrich@ii.net
parents: 2
diff changeset
198 return 2;
1
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
199 }
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
200
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
201 status = PQresultStatus(result);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
202 if (status != PGRES_COMMAND_OK && status != PGRES_TUPLES_OK) {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
203 lua_pushboolean(L, 0);
4
c50b0e6f25d6 Clean up error messages for consistency.
nrich@ii.net
parents: 3
diff changeset
204 lua_pushfstring(L, DBI_ERR_BINDING_EXEC, PQresultErrorMessage(result));
3
b61020ca4753 Cleanup and 'assert' error handling.
nrich@ii.net
parents: 2
diff changeset
205 return 2;
1
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
206 }
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
207
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
208 statement->result = result;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
209
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
210 lua_pushboolean(L, 1);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
211 return 1;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
212 }
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
213
2
c4f02fc67e5a Cleanup and commenting
nrich@ii.net
parents: 1
diff changeset
214 /*
c4f02fc67e5a Cleanup and commenting
nrich@ii.net
parents: 1
diff changeset
215 * must be called after an execute
c4f02fc67e5a Cleanup and commenting
nrich@ii.net
parents: 1
diff changeset
216 */
1
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
217 static int statement_fetch_impl(lua_State *L, int named_columns) {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
218 statement_t *statement = (statement_t *)luaL_checkudata(L, 1, DBD_POSTGRESQL_STATEMENT);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
219 int tuple = statement->tuple++;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
220 int i;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
221 int num_columns;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
222
3
b61020ca4753 Cleanup and 'assert' error handling.
nrich@ii.net
parents: 2
diff changeset
223 if (!statement->result) {
4
c50b0e6f25d6 Clean up error messages for consistency.
nrich@ii.net
parents: 3
diff changeset
224 luaL_error(L, DBI_ERR_FETCH_INVALID);
3
b61020ca4753 Cleanup and 'assert' error handling.
nrich@ii.net
parents: 2
diff changeset
225 return 0;
b61020ca4753 Cleanup and 'assert' error handling.
nrich@ii.net
parents: 2
diff changeset
226 }
b61020ca4753 Cleanup and 'assert' error handling.
nrich@ii.net
parents: 2
diff changeset
227
1
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
228 if (PQresultStatus(statement->result) != PGRES_TUPLES_OK) {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
229 lua_pushnil(L);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
230 return 1;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
231 }
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
232
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
233 if (tuple >= PQntuples(statement->result)) {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
234 lua_pushnil(L); /* no more results */
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
235 return 1;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
236 }
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
237
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
238 num_columns = PQnfields(statement->result);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
239 lua_newtable(L);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
240 for (i = 0; i < num_columns; i++) {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
241 int d = 1;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
242 const char *name = PQfname(statement->result, i);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
243
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
244 if (PQgetisnull(statement->result, tuple, i)) {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
245 if (named_columns) {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
246 LUA_PUSH_ATTRIB_NIL(name);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
247 } else {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
248 LUA_PUSH_ARRAY_NIL(d);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
249 }
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
250 } else {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
251 const char *value = PQgetvalue(statement->result, tuple, i);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
252 lua_push_type_t lua_push = postgresql_to_lua_push(PQftype(statement->result, i));
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
253
2
c4f02fc67e5a Cleanup and commenting
nrich@ii.net
parents: 1
diff changeset
254 /*
c4f02fc67e5a Cleanup and commenting
nrich@ii.net
parents: 1
diff changeset
255 * data is returned as strings from PSQL
9
06eb2850703f Bugfix: fix connection in DBD.SQLite3.New
nrich@ii.net
parents: 8
diff changeset
256 * convert them here into Lua types
2
c4f02fc67e5a Cleanup and commenting
nrich@ii.net
parents: 1
diff changeset
257 */
c4f02fc67e5a Cleanup and commenting
nrich@ii.net
parents: 1
diff changeset
258
1
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
259 if (lua_push == LUA_PUSH_NIL) {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
260 if (named_columns) {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
261 LUA_PUSH_ATTRIB_NIL(name);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
262 } else {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
263 LUA_PUSH_ARRAY_NIL(d);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
264 }
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
265 } else if (lua_push == LUA_PUSH_INTEGER) {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
266 int val = atoi(value);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
267
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
268 if (named_columns) {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
269 LUA_PUSH_ATTRIB_INT(name, val);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
270 } else {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
271 LUA_PUSH_ARRAY_INT(d, val);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
272 }
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
273 } else if (lua_push == LUA_PUSH_NUMBER) {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
274 double val = strtod(value, NULL);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
275
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
276 if (named_columns) {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
277 LUA_PUSH_ATTRIB_FLOAT(name, val);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
278 } else {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
279 LUA_PUSH_ARRAY_FLOAT(d, val);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
280 }
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
281 } else if (lua_push == LUA_PUSH_STRING) {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
282 if (named_columns) {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
283 LUA_PUSH_ATTRIB_STRING(name, value);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
284 } else {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
285 LUA_PUSH_ARRAY_STRING(d, value);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
286 }
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
287 } else if (lua_push == LUA_PUSH_BOOLEAN) {
2
c4f02fc67e5a Cleanup and commenting
nrich@ii.net
parents: 1
diff changeset
288 /*
c4f02fc67e5a Cleanup and commenting
nrich@ii.net
parents: 1
diff changeset
289 * booleans are returned as a string
c4f02fc67e5a Cleanup and commenting
nrich@ii.net
parents: 1
diff changeset
290 * either 't' or 'f'
c4f02fc67e5a Cleanup and commenting
nrich@ii.net
parents: 1
diff changeset
291 */
1
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
292 int val = value[0] == 't' ? 1 : 0;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
293
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
294 if (named_columns) {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
295 LUA_PUSH_ATTRIB_BOOL(name, val);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
296 } else {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
297 LUA_PUSH_ARRAY_BOOL(d, val);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
298 }
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
299 } else {
4
c50b0e6f25d6 Clean up error messages for consistency.
nrich@ii.net
parents: 3
diff changeset
300 luaL_error(L, DBI_ERR_UNKNOWN_PUSH);
1
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
301 }
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
302 }
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
303 }
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
304
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
305 return 1;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
306 }
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
307
2
c4f02fc67e5a Cleanup and commenting
nrich@ii.net
parents: 1
diff changeset
308 /*
c4f02fc67e5a Cleanup and commenting
nrich@ii.net
parents: 1
diff changeset
309 * array = statement:fetch()
c4f02fc67e5a Cleanup and commenting
nrich@ii.net
parents: 1
diff changeset
310 */
1
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
311 static int statement_fetch(lua_State *L) {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
312 return statement_fetch_impl(L, 0);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
313 }
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
314
2
c4f02fc67e5a Cleanup and commenting
nrich@ii.net
parents: 1
diff changeset
315 /*
c4f02fc67e5a Cleanup and commenting
nrich@ii.net
parents: 1
diff changeset
316 * hashmap = statement:fetchtable()
c4f02fc67e5a Cleanup and commenting
nrich@ii.net
parents: 1
diff changeset
317 */
1
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
318 static int statement_fetchtable(lua_State *L) {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
319 return statement_fetch_impl(L, 1);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
320 }
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
321
2
c4f02fc67e5a Cleanup and commenting
nrich@ii.net
parents: 1
diff changeset
322 /*
c4f02fc67e5a Cleanup and commenting
nrich@ii.net
parents: 1
diff changeset
323 * __gc
c4f02fc67e5a Cleanup and commenting
nrich@ii.net
parents: 1
diff changeset
324 */
1
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
325 static int statement_gc(lua_State *L) {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
326 /* always free the handle */
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
327 statement_close(L);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
328
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
329 return 0;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
330 }
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
331
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
332 int dbd_postgresql_statement_create(lua_State *L, connection_t *conn, const char *sql_query) {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
333 statement_t *statement = NULL;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
334 ExecStatusType status;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
335 PGresult *result = NULL;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
336 char *new_sql;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
337 char name[IDLEN];
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
338
2
c4f02fc67e5a Cleanup and commenting
nrich@ii.net
parents: 1
diff changeset
339 /*
c4f02fc67e5a Cleanup and commenting
nrich@ii.net
parents: 1
diff changeset
340 * convert SQL string into a PSQL API compatible SQL statement
c4f02fc67e5a Cleanup and commenting
nrich@ii.net
parents: 1
diff changeset
341 */
1
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
342 new_sql = replace_placeholders(L, sql_query);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
343
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
344 snprintf(name, IDLEN, "%017u", ++conn->statement_id);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
345
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
346 result = PQprepare(conn->postgresql, name, new_sql, 0, NULL);
2
c4f02fc67e5a Cleanup and commenting
nrich@ii.net
parents: 1
diff changeset
347
c4f02fc67e5a Cleanup and commenting
nrich@ii.net
parents: 1
diff changeset
348 /*
c4f02fc67e5a Cleanup and commenting
nrich@ii.net
parents: 1
diff changeset
349 * free converted statement after use
c4f02fc67e5a Cleanup and commenting
nrich@ii.net
parents: 1
diff changeset
350 */
1
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
351 free(new_sql);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
352
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
353 if (!result) {
3
b61020ca4753 Cleanup and 'assert' error handling.
nrich@ii.net
parents: 2
diff changeset
354 lua_pushnil(L);
4
c50b0e6f25d6 Clean up error messages for consistency.
nrich@ii.net
parents: 3
diff changeset
355 lua_pushfstring(L, DBI_ERR_ALLOC_STATEMENT, PQerrorMessage(statement->postgresql));
3
b61020ca4753 Cleanup and 'assert' error handling.
nrich@ii.net
parents: 2
diff changeset
356 return 2;
1
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
357 }
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
358
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
359 status = PQresultStatus(result);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
360 if (status != PGRES_COMMAND_OK && status != PGRES_TUPLES_OK) {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
361 const char *err_string = PQresultErrorMessage(result);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
362 PQclear(result);
3
b61020ca4753 Cleanup and 'assert' error handling.
nrich@ii.net
parents: 2
diff changeset
363
b61020ca4753 Cleanup and 'assert' error handling.
nrich@ii.net
parents: 2
diff changeset
364 lua_pushnil(L);
4
c50b0e6f25d6 Clean up error messages for consistency.
nrich@ii.net
parents: 3
diff changeset
365 lua_pushfstring(L, DBI_ERR_PREP_STATEMENT, err_string);
3
b61020ca4753 Cleanup and 'assert' error handling.
nrich@ii.net
parents: 2
diff changeset
366 return 2;
1
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
367 }
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
368
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
369 PQclear(result);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
370
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
371 statement = (statement_t *)lua_newuserdata(L, sizeof(statement_t));
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
372 statement->postgresql = conn->postgresql;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
373 statement->result = NULL;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
374 statement->tuple = 0;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
375 strncpy(statement->name, name, IDLEN-1);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
376 statement->name[IDLEN-1] = '\0';
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
377
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
378 luaL_getmetatable(L, DBD_POSTGRESQL_STATEMENT);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
379 lua_setmetatable(L, -2);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
380
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
381 return 1;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
382 }
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
383
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
384 int dbd_postgresql_statement(lua_State *L) {
2
c4f02fc67e5a Cleanup and commenting
nrich@ii.net
parents: 1
diff changeset
385 static const luaL_Reg statement_methods[] = {
c4f02fc67e5a Cleanup and commenting
nrich@ii.net
parents: 1
diff changeset
386 {"close", statement_close},
c4f02fc67e5a Cleanup and commenting
nrich@ii.net
parents: 1
diff changeset
387 {"execute", statement_execute},
c4f02fc67e5a Cleanup and commenting
nrich@ii.net
parents: 1
diff changeset
388 {"fetch", statement_fetch},
c4f02fc67e5a Cleanup and commenting
nrich@ii.net
parents: 1
diff changeset
389 {"fetchtable", statement_fetchtable},
c4f02fc67e5a Cleanup and commenting
nrich@ii.net
parents: 1
diff changeset
390 {NULL, NULL}
c4f02fc67e5a Cleanup and commenting
nrich@ii.net
parents: 1
diff changeset
391 };
c4f02fc67e5a Cleanup and commenting
nrich@ii.net
parents: 1
diff changeset
392
c4f02fc67e5a Cleanup and commenting
nrich@ii.net
parents: 1
diff changeset
393 static const luaL_Reg statement_class_methods[] = {
c4f02fc67e5a Cleanup and commenting
nrich@ii.net
parents: 1
diff changeset
394 {NULL, NULL}
c4f02fc67e5a Cleanup and commenting
nrich@ii.net
parents: 1
diff changeset
395 };
c4f02fc67e5a Cleanup and commenting
nrich@ii.net
parents: 1
diff changeset
396
1
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
397 luaL_newmetatable(L, DBD_POSTGRESQL_STATEMENT);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
398 luaL_register(L, 0, statement_methods);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
399 lua_pushvalue(L,-1);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
400 lua_setfield(L, -2, "__index");
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
401
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
402 lua_pushcfunction(L, statement_gc);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
403 lua_setfield(L, -2, "__gc");
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
404
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
405 luaL_register(L, DBD_POSTGRESQL_STATEMENT, statement_class_methods);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
406
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
407 return 1;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
408 }

mercurial