dbd/postgresql/statement.c

Sun, 23 Nov 2008 01:29:09 +0000

author
nrich@ii.net
date
Sun, 23 Nov 2008 01:29:09 +0000
changeset 1
408291a6eb3e
child 2
c4f02fc67e5a
permissions
-rw-r--r--

Initial import.

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
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
3 #define MAX_PLACEHOLDERS 9999
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
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
31 static char *replace_placeholders(lua_State *L, const char *sql) {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
32 size_t len = strlen(sql);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
33 int num_placeholders = 0;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
34 int extra_space = 0;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
35 int i;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
36 char *newsql;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
37 int newpos = 1;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
38 int ph_num = 1;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
39 int in_quote = 0;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
40
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
41 for (i = 1; i < len; i++) {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
42 if (sql[i] == '?') {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
43 num_placeholders++;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
44 }
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
45 }
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
46
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
47 extra_space = num_placeholders * (MAX_PLACEHOLDER_SIZE-1);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
48
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
49 newsql = malloc(sizeof(char) * (len+extra_space+1));
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
50 memset(newsql, 0, sizeof(char) * (len+extra_space+1));
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
51
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
52 /* copy first char */
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
53 newsql[0] = sql[0];
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
54 for (i = 1; i < len; i++) {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
55 if (sql[i] == '\'' && sql[i-1] != '\\') {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
56 in_quote = !in_quote;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
57 }
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
58
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
59 if (sql[i] == '?' && !in_quote) {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
60 size_t n;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
61
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
62 if (ph_num > MAX_PLACEHOLDERS) {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
63 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
64 }
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
65
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
66 n = snprintf(&newsql[newpos], MAX_PLACEHOLDER_SIZE, "$%u", ph_num++);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
67
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
68 newpos += n;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
69 } else {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
70 newsql[newpos] = sql[i];
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
71 newpos++;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
72 }
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
73 }
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
74
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
75 /* terminate string on the last position */
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
76 newsql[newpos] = '\0';
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
77
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
78 /* fprintf(stderr, "[%s]\n", newsql); */
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
79 return newsql;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
80 }
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
81
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
82 static int statement_close(lua_State *L) {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
83 statement_t *statement = (statement_t *)luaL_checkudata(L, 1, DBD_POSTGRESQL_STATEMENT);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
84
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
85 if (statement->result) {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
86 PQclear(statement->result);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
87 statement->result = NULL;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
88 }
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
89
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
90 return 0;
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 static int statement_execute(lua_State *L) {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
94 int n = lua_gettop(L);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
95 statement_t *statement = (statement_t *)luaL_checkudata(L, 1, DBD_POSTGRESQL_STATEMENT);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
96 int num_bind_params = n - 1;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
97 ExecStatusType status;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
98 int p;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
99
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
100 char **params;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
101 PGresult *result = NULL;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
102
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
103 statement->tuple = 0;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
104
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
105 params = malloc(num_bind_params * sizeof(params));
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
106
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
107 for (p = 2; p <= n; p++) {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
108 int i = p - 2;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
109
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
110 if (lua_isnil(L, p)) {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
111 params[i] = NULL;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
112 } else {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
113 const char *param = lua_tostring(L, p);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
114 size_t len = strlen(param) + 1;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
115
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
116 params[i] = malloc(len * sizeof(char));
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
117 memset(params[i], 0, len);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
118
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
119 strncpy(params[i], param, len);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
120 params[i][len] = '\0';
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
121 }
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
122 }
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
123
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
124 result = PQexecPrepared(
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
125 statement->postgresql,
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
126 statement->name,
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
127 num_bind_params,
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
128 (const char **)params,
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
129 NULL,
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
130 NULL,
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
131 0
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
132 );
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
133
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
134 for (p = 0; p < num_bind_params; p++) {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
135 if (params[p]) {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
136 free(params[p]);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
137 }
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
138 }
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
139 free(params);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
140
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
141 if (!result) {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
142 luaL_error(L, "Unable to allocate result handle");
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
143 lua_pushboolean(L, 0);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
144 return 1;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
145 }
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
146
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
147 status = PQresultStatus(result);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
148 if (status != PGRES_COMMAND_OK && status != PGRES_TUPLES_OK) {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
149 luaL_error(L, "Unable to execute statment: %s", PQresultErrorMessage(result));
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
150 lua_pushboolean(L, 0);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
151 return 1;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
152 }
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
153
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
154 statement->result = result;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
155
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
156 lua_pushboolean(L, 1);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
157 return 1;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
158 }
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
159
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
160 static int statement_fetch_impl(lua_State *L, int named_columns) {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
161 statement_t *statement = (statement_t *)luaL_checkudata(L, 1, DBD_POSTGRESQL_STATEMENT);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
162 int tuple = statement->tuple++;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
163 int i;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
164 int num_columns;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
165
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
166 if (PQresultStatus(statement->result) != PGRES_TUPLES_OK) {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
167 lua_pushnil(L);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
168 return 1;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
169 }
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
170
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
171 if (tuple >= PQntuples(statement->result)) {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
172 lua_pushnil(L); /* no more results */
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
173 return 1;
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 num_columns = PQnfields(statement->result);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
177 lua_newtable(L);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
178 for (i = 0; i < num_columns; i++) {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
179 int d = 1;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
180 const char *name = PQfname(statement->result, i);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
181
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
182 if (PQgetisnull(statement->result, tuple, i)) {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
183 if (named_columns) {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
184 LUA_PUSH_ATTRIB_NIL(name);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
185 } else {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
186 LUA_PUSH_ARRAY_NIL(d);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
187 }
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
188 } else {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
189 const char *value = PQgetvalue(statement->result, tuple, i);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
190 lua_push_type_t lua_push = postgresql_to_lua_push(PQftype(statement->result, i));
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
191
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
192 if (lua_push == LUA_PUSH_NIL) {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
193 if (named_columns) {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
194 LUA_PUSH_ATTRIB_NIL(name);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
195 } else {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
196 LUA_PUSH_ARRAY_NIL(d);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
197 }
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
198 } else if (lua_push == LUA_PUSH_INTEGER) {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
199 int val = atoi(value);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
200
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
201 if (named_columns) {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
202 LUA_PUSH_ATTRIB_INT(name, val);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
203 } else {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
204 LUA_PUSH_ARRAY_INT(d, val);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
205 }
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
206 } else if (lua_push == LUA_PUSH_NUMBER) {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
207 double val = strtod(value, NULL);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
208
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
209 if (named_columns) {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
210 LUA_PUSH_ATTRIB_FLOAT(name, val);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
211 } else {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
212 LUA_PUSH_ARRAY_FLOAT(d, val);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
213 }
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
214 } else if (lua_push == LUA_PUSH_STRING) {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
215 if (named_columns) {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
216 LUA_PUSH_ATTRIB_STRING(name, value);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
217 } else {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
218 LUA_PUSH_ARRAY_STRING(d, value);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
219 }
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
220 } else if (lua_push == LUA_PUSH_BOOLEAN) {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
221 int val = value[0] == 't' ? 1 : 0;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
222
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
223 if (named_columns) {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
224 LUA_PUSH_ATTRIB_BOOL(name, val);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
225 } else {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
226 LUA_PUSH_ARRAY_BOOL(d, val);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
227 }
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
228 } else {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
229 luaL_error(L, "Unknown push type in result set");
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
230 }
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
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
234 return 1;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
235 }
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 static int statement_fetch(lua_State *L) {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
239 return statement_fetch_impl(L, 0);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
240 }
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
241
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
242 static int statement_fetchtable(lua_State *L) {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
243 return statement_fetch_impl(L, 1);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
244 }
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
245
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
246 static int statement_gc(lua_State *L) {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
247 /* always free the handle */
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
248 statement_close(L);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
249
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
250 return 0;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
251 }
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
252
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
253
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
254 static const luaL_Reg statement_methods[] = {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
255 {"close", statement_close},
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
256 {"execute", statement_execute},
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
257 {"fetch", statement_fetch},
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
258 {"fetchtable", statement_fetchtable},
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
259 {NULL, NULL}
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
260 };
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
261
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
262 static const luaL_Reg statement_class_methods[] = {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
263 {NULL, NULL}
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
264 };
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
265
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
266 int dbd_postgresql_statement_create(lua_State *L, connection_t *conn, const char *sql_query) {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
267 statement_t *statement = NULL;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
268 ExecStatusType status;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
269 PGresult *result = NULL;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
270 char *new_sql;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
271 char name[IDLEN];
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
272
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
273 new_sql = replace_placeholders(L, sql_query);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
274
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
275 snprintf(name, IDLEN, "%017u", ++conn->statement_id);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
276
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
277 result = PQprepare(conn->postgresql, name, new_sql, 0, NULL);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
278 free(new_sql);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
279
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
280 if (!result) {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
281 luaL_error(L, "Unable to allocate prepare result handle");
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
282 }
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
283
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
284 status = PQresultStatus(result);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
285 if (status != PGRES_COMMAND_OK && status != PGRES_TUPLES_OK) {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
286 const char *err_string = PQresultErrorMessage(result);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
287 PQclear(result);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
288 luaL_error(L, "Unable to prepare statment: %s", err_string);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
289 return 0;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
290 }
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
291
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
292 PQclear(result);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
293
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
294 statement = (statement_t *)lua_newuserdata(L, sizeof(statement_t));
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
295 statement->postgresql = conn->postgresql;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
296 statement->result = NULL;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
297 statement->tuple = 0;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
298 strncpy(statement->name, name, IDLEN-1);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
299 statement->name[IDLEN-1] = '\0';
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
300
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
301 luaL_getmetatable(L, DBD_POSTGRESQL_STATEMENT);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
302 lua_setmetatable(L, -2);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
303
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
304 return 1;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
305 }
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
306
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
307 int dbd_postgresql_statement(lua_State *L) {
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
308 luaL_newmetatable(L, DBD_POSTGRESQL_STATEMENT);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
309 luaL_register(L, 0, statement_methods);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
310 lua_pushvalue(L,-1);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
311 lua_setfield(L, -2, "__index");
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
312
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
313 lua_pushcfunction(L, statement_gc);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
314 lua_setfield(L, -2, "__gc");
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
315
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
316 luaL_register(L, DBD_POSTGRESQL_STATEMENT, statement_class_methods);
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
317
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
318 return 1;
408291a6eb3e Initial import.
nrich@ii.net
parents:
diff changeset
319 }

mercurial