Fri, 29 Jun 2012 17:45:37 +0100
MySQL: Avoid allocating the full column size to receive results, for variable-length types check result size before allocation (thanks Florob)
1 | 1 | #include "dbd_postgresql.h" |
2 | ||
33 | 3 | #define BOOLOID 16 |
4 | #define INT2OID 21 | |
5 | #define INT4OID 23 | |
6 | #define INT8OID 20 | |
7 | #define FLOAT4OID 700 | |
8 | #define FLOAT8OID 701 | |
9 | ||
1 | 10 | static lua_push_type_t postgresql_to_lua_push(unsigned int postgresql_type) { |
11 | lua_push_type_t lua_type; | |
12 | ||
13 | switch(postgresql_type) { | |
14 | case INT2OID: | |
15 | 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
|
16 | case INT8OID: |
1 | 17 | lua_type = LUA_PUSH_INTEGER; |
18 | break; | |
19 | ||
20 | case FLOAT4OID: | |
21 | case FLOAT8OID: | |
22 | lua_type = LUA_PUSH_NUMBER; | |
23 | break; | |
24 | ||
25 | case BOOLOID: | |
30
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
26 | lua_type = LUA_PUSH_BOOLEAN; |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
27 | break; |
1 | 28 | |
29 | default: | |
30 | lua_type = LUA_PUSH_STRING; | |
31 | } | |
32 | ||
33 | return lua_type; | |
34 | } | |
35 | ||
30
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
36 | static int deallocate(statement_t *statement) { |
38 | 37 | char command[IDLEN+13]; |
33 | 38 | PGresult *result; |
39 | ExecStatusType status; | |
30
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
40 | |
38 | 41 | snprintf(command, IDLEN+13, "DEALLOCATE \"%s\"", statement->name); |
33 | 42 | result = PQexec(statement->postgresql, command); |
30
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
43 | |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
44 | if (!result) |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
45 | return 1; |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
46 | |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
47 | status = PQresultStatus(result); |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
48 | PQclear(result); |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
49 | |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
50 | if (status != PGRES_COMMAND_OK && status != PGRES_TUPLES_OK) |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
51 | return 1; |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
52 | |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
53 | return 0; |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
54 | } |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
55 | |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
56 | |
21
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
20
diff
changeset
|
57 | /* |
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
20
diff
changeset
|
58 | * num_affected_rows = statement:affected() |
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
20
diff
changeset
|
59 | */ |
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
20
diff
changeset
|
60 | static int statement_affected(lua_State *L) { |
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
20
diff
changeset
|
61 | 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
|
62 | |
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
20
diff
changeset
|
63 | if (!statement->result) { |
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
20
diff
changeset
|
64 | luaL_error(L, DBI_ERR_INVALID_STATEMENT); |
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
20
diff
changeset
|
65 | } |
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
20
diff
changeset
|
66 | |
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
20
diff
changeset
|
67 | lua_pushinteger(L, atoi(PQcmdTuples(statement->result))); |
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
20
diff
changeset
|
68 | |
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
20
diff
changeset
|
69 | return 1; |
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
20
diff
changeset
|
70 | } |
1 | 71 | |
2 | 72 | /* |
73 | * success = statement:close() | |
74 | */ | |
1 | 75 | static int statement_close(lua_State *L) { |
76 | statement_t *statement = (statement_t *)luaL_checkudata(L, 1, DBD_POSTGRESQL_STATEMENT); | |
77 | ||
78 | if (statement->result) { | |
30
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
79 | /* |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
80 | * Deallocate prepared statement on the |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
81 | * server side |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
82 | */ |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
83 | deallocate(statement); |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
84 | |
1 | 85 | PQclear(statement->result); |
86 | statement->result = NULL; | |
87 | } | |
88 | ||
89 | return 0; | |
90 | } | |
91 | ||
2 | 92 | /* |
30
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
93 | * column_names = statement:columns() |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
94 | */ |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
95 | static int statement_columns(lua_State *L) { |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
96 | statement_t *statement = (statement_t *)luaL_checkudata(L, 1, DBD_POSTGRESQL_STATEMENT); |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
97 | |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
98 | int i; |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
99 | int num_columns; |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
100 | int d = 1; |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
101 | |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
102 | if (!statement->result) { |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
103 | luaL_error(L, DBI_ERR_INVALID_STATEMENT); |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
104 | return 0; |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
105 | } |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
106 | |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
107 | num_columns = PQnfields(statement->result); |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
108 | lua_newtable(L); |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
109 | for (i = 0; i < num_columns; i++) { |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
110 | const char *name = PQfname(statement->result, i); |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
111 | |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
112 | LUA_PUSH_ARRAY_STRING(d, name); |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
113 | } |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
114 | |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
115 | return 1; |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
116 | } |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
117 | |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
118 | /* |
2 | 119 | * success = statement:execute(...) |
120 | */ | |
1 | 121 | static int statement_execute(lua_State *L) { |
122 | int n = lua_gettop(L); | |
123 | statement_t *statement = (statement_t *)luaL_checkudata(L, 1, DBD_POSTGRESQL_STATEMENT); | |
124 | int num_bind_params = n - 1; | |
125 | ExecStatusType status; | |
126 | int p; | |
10 | 127 | const char *errstr = NULL; |
1 | 128 | |
9 | 129 | const char **params; |
1 | 130 | PGresult *result = NULL; |
131 | ||
132 | statement->tuple = 0; | |
133 | ||
134 | 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
|
135 | memset(params, 0, num_bind_params * sizeof(params)); |
1 | 136 | |
2 | 137 | /* |
138 | * convert and copy parameters into a string array | |
139 | */ | |
1 | 140 | for (p = 2; p <= n; p++) { |
30
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
141 | int i = p - 2; |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
142 | int type = lua_type(L, p); |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
143 | char err[64]; |
1 | 144 | |
30
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
145 | switch(type) { |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
146 | case LUA_TNIL: |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
147 | params[i] = NULL; |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
148 | break; |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
149 | case LUA_TBOOLEAN: |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
150 | /* |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
151 | * boolean values in postgresql can either be |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
152 | * t/f or 1/0. Pass integer values rather than |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
153 | * strings to maintain semantic compatibility |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
154 | * with other DBD drivers that pass booleans |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
155 | * as integers. |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
156 | */ |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
157 | params[i] = lua_toboolean(L, p) ? "1" : "0"; |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
158 | break; |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
159 | case LUA_TNUMBER: |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
160 | case LUA_TSTRING: |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
161 | params[i] = lua_tostring(L, p); |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
162 | break; |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
163 | default: |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
164 | snprintf(err, sizeof(err)-1, DBI_ERR_BINDING_TYPE_ERR, lua_typename(L, type)); |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
165 | errstr = err; |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
166 | goto cleanup; |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
167 | } |
1 | 168 | } |
169 | ||
170 | result = PQexecPrepared( | |
30
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
171 | statement->postgresql, |
1 | 172 | statement->name, |
173 | num_bind_params, | |
174 | (const char **)params, | |
30
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
175 | NULL, |
1 | 176 | NULL, |
177 | 0 | |
178 | ); | |
179 | ||
10 | 180 | cleanup: |
1 | 181 | free(params); |
182 | ||
10 | 183 | if (errstr) { |
30
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
184 | lua_pushboolean(L, 0); |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
185 | lua_pushfstring(L, DBI_ERR_BINDING_PARAMS, errstr); |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
186 | return 2; |
10 | 187 | } |
188 | ||
1 | 189 | if (!result) { |
30
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
190 | lua_pushboolean(L, 0); |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
191 | lua_pushfstring(L, DBI_ERR_ALLOC_RESULT, PQerrorMessage(statement->postgresql)); |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
192 | return 2; |
1 | 193 | } |
194 | ||
195 | status = PQresultStatus(result); | |
196 | if (status != PGRES_COMMAND_OK && status != PGRES_TUPLES_OK) { | |
30
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
197 | lua_pushboolean(L, 0); |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
198 | lua_pushfstring(L, DBI_ERR_BINDING_EXEC, PQresultErrorMessage(result)); |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
199 | return 2; |
1 | 200 | } |
201 | ||
202 | statement->result = result; | |
203 | ||
204 | lua_pushboolean(L, 1); | |
205 | return 1; | |
206 | } | |
207 | ||
2 | 208 | /* |
30
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
209 | * can only be called after an execute |
2 | 210 | */ |
11
b3e05e361f46
Bugfix: PSQL array returns were not being indexed properly.
nrich@ii.net
parents:
10
diff
changeset
|
211 | static int statement_fetch_impl(lua_State *L, statement_t *statement, int named_columns) { |
1 | 212 | int tuple = statement->tuple++; |
213 | int i; | |
214 | 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
|
215 | int d = 1; |
1 | 216 | |
3 | 217 | if (!statement->result) { |
30
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
218 | luaL_error(L, DBI_ERR_FETCH_INVALID); |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
219 | return 0; |
3 | 220 | } |
221 | ||
1 | 222 | if (PQresultStatus(statement->result) != PGRES_TUPLES_OK) { |
30
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
223 | lua_pushnil(L); |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
224 | return 1; |
1 | 225 | } |
226 | ||
227 | if (tuple >= PQntuples(statement->result)) { | |
30
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
228 | lua_pushnil(L); /* no more results */ |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
229 | return 1; |
1 | 230 | } |
231 | ||
232 | num_columns = PQnfields(statement->result); | |
233 | lua_newtable(L); | |
234 | for (i = 0; i < num_columns; i++) { | |
30
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
235 | const char *name = PQfname(statement->result, i); |
1 | 236 | |
30
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
237 | if (PQgetisnull(statement->result, tuple, i)) { |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
238 | if (named_columns) { |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
239 | LUA_PUSH_ATTRIB_NIL(name); |
1 | 240 | } else { |
241 | LUA_PUSH_ARRAY_NIL(d); | |
242 | } | |
30
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
243 | } else { |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
244 | const char *value = PQgetvalue(statement->result, tuple, i); |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
245 | lua_push_type_t lua_push = postgresql_to_lua_push(PQftype(statement->result, i)); |
1 | 246 | |
30
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
247 | /* |
2 | 248 | * data is returned as strings from PSQL |
9 | 249 | * convert them here into Lua types |
2 | 250 | */ |
251 | ||
1 | 252 | if (lua_push == LUA_PUSH_NIL) { |
253 | if (named_columns) { | |
254 | LUA_PUSH_ATTRIB_NIL(name); | |
255 | } else { | |
256 | LUA_PUSH_ARRAY_NIL(d); | |
257 | } | |
258 | } else if (lua_push == LUA_PUSH_INTEGER) { | |
259 | int val = atoi(value); | |
260 | ||
261 | if (named_columns) { | |
262 | LUA_PUSH_ATTRIB_INT(name, val); | |
263 | } else { | |
264 | LUA_PUSH_ARRAY_INT(d, val); | |
265 | } | |
266 | } else if (lua_push == LUA_PUSH_NUMBER) { | |
267 | double val = strtod(value, NULL); | |
268 | ||
269 | if (named_columns) { | |
270 | LUA_PUSH_ATTRIB_FLOAT(name, val); | |
271 | } else { | |
272 | LUA_PUSH_ARRAY_FLOAT(d, val); | |
273 | } | |
274 | } else if (lua_push == LUA_PUSH_STRING) { | |
275 | if (named_columns) { | |
276 | LUA_PUSH_ATTRIB_STRING(name, value); | |
277 | } else { | |
278 | LUA_PUSH_ARRAY_STRING(d, value); | |
279 | } | |
280 | } else if (lua_push == LUA_PUSH_BOOLEAN) { | |
30
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
281 | /* |
2 | 282 | * booleans are returned as a string |
283 | * either 't' or 'f' | |
284 | */ | |
1 | 285 | int val = value[0] == 't' ? 1 : 0; |
286 | ||
287 | if (named_columns) { | |
288 | LUA_PUSH_ATTRIB_BOOL(name, val); | |
289 | } else { | |
290 | LUA_PUSH_ARRAY_BOOL(d, val); | |
291 | } | |
292 | } else { | |
4 | 293 | luaL_error(L, DBI_ERR_UNKNOWN_PUSH); |
1 | 294 | } |
30
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
295 | } |
1 | 296 | } |
297 | ||
298 | return 1; | |
299 | } | |
300 | ||
11
b3e05e361f46
Bugfix: PSQL array returns were not being indexed properly.
nrich@ii.net
parents:
10
diff
changeset
|
301 | |
b3e05e361f46
Bugfix: PSQL array returns were not being indexed properly.
nrich@ii.net
parents:
10
diff
changeset
|
302 | static int next_iterator(lua_State *L) { |
b3e05e361f46
Bugfix: PSQL array returns were not being indexed properly.
nrich@ii.net
parents:
10
diff
changeset
|
303 | 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
|
304 | 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
|
305 | |
b3e05e361f46
Bugfix: PSQL array returns were not being indexed properly.
nrich@ii.net
parents:
10
diff
changeset
|
306 | return statement_fetch_impl(L, statement, named_columns); |
1 | 307 | } |
308 | ||
2 | 309 | /* |
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
|
310 | * table = statement:fetch(named_indexes) |
2 | 311 | */ |
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
|
312 | 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
|
313 | 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
|
314 | 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
|
315 | |
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
|
316 | 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
|
317 | } |
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
|
318 | |
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
|
319 | /* |
21
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
20
diff
changeset
|
320 | * num_rows = statement:rowcount() |
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
20
diff
changeset
|
321 | */ |
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
20
diff
changeset
|
322 | static int statement_rowcount(lua_State *L) { |
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
20
diff
changeset
|
323 | 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
|
324 | |
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
20
diff
changeset
|
325 | if (!statement->result) { |
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
20
diff
changeset
|
326 | luaL_error(L, DBI_ERR_INVALID_STATEMENT); |
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
20
diff
changeset
|
327 | } |
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
20
diff
changeset
|
328 | |
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
20
diff
changeset
|
329 | lua_pushinteger(L, PQntuples(statement->result)); |
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
20
diff
changeset
|
330 | |
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
20
diff
changeset
|
331 | return 1; |
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
20
diff
changeset
|
332 | } |
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
20
diff
changeset
|
333 | |
7956401a0c5e
Added the statement:affected() and statement:rowcount() methods.
nrich@ii.net
parents:
20
diff
changeset
|
334 | /* |
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
|
335 | * 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
|
336 | */ |
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
|
337 | 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
|
338 | if (lua_gettop(L) == 1) { |
b3e05e361f46
Bugfix: PSQL array returns were not being indexed properly.
nrich@ii.net
parents:
10
diff
changeset
|
339 | lua_pushvalue(L, 1); |
b3e05e361f46
Bugfix: PSQL array returns were not being indexed properly.
nrich@ii.net
parents:
10
diff
changeset
|
340 | lua_pushboolean(L, 0); |
b3e05e361f46
Bugfix: PSQL array returns were not being indexed properly.
nrich@ii.net
parents:
10
diff
changeset
|
341 | } else { |
b3e05e361f46
Bugfix: PSQL array returns were not being indexed properly.
nrich@ii.net
parents:
10
diff
changeset
|
342 | lua_pushvalue(L, 1); |
b3e05e361f46
Bugfix: PSQL array returns were not being indexed properly.
nrich@ii.net
parents:
10
diff
changeset
|
343 | lua_pushboolean(L, lua_toboolean(L, 2)); |
b3e05e361f46
Bugfix: PSQL array returns were not being indexed properly.
nrich@ii.net
parents:
10
diff
changeset
|
344 | } |
b3e05e361f46
Bugfix: PSQL array returns were not being indexed properly.
nrich@ii.net
parents:
10
diff
changeset
|
345 | |
b3e05e361f46
Bugfix: PSQL array returns were not being indexed properly.
nrich@ii.net
parents:
10
diff
changeset
|
346 | lua_pushcclosure(L, next_iterator, 2); |
b3e05e361f46
Bugfix: PSQL array returns were not being indexed properly.
nrich@ii.net
parents:
10
diff
changeset
|
347 | return 1; |
b3e05e361f46
Bugfix: PSQL array returns were not being indexed properly.
nrich@ii.net
parents:
10
diff
changeset
|
348 | } |
b3e05e361f46
Bugfix: PSQL array returns were not being indexed properly.
nrich@ii.net
parents:
10
diff
changeset
|
349 | |
b3e05e361f46
Bugfix: PSQL array returns were not being indexed properly.
nrich@ii.net
parents:
10
diff
changeset
|
350 | /* |
2 | 351 | * __gc |
352 | */ | |
1 | 353 | static int statement_gc(lua_State *L) { |
354 | /* always free the handle */ | |
355 | statement_close(L); | |
356 | ||
357 | return 0; | |
358 | } | |
359 | ||
32
03ed0ca09837
Add __tostring method to connection and statement objects.
nrich@ii.net
parents:
30
diff
changeset
|
360 | /* |
03ed0ca09837
Add __tostring method to connection and statement objects.
nrich@ii.net
parents:
30
diff
changeset
|
361 | * __tostring |
03ed0ca09837
Add __tostring method to connection and statement objects.
nrich@ii.net
parents:
30
diff
changeset
|
362 | */ |
03ed0ca09837
Add __tostring method to connection and statement objects.
nrich@ii.net
parents:
30
diff
changeset
|
363 | static int statement_tostring(lua_State *L) { |
03ed0ca09837
Add __tostring method to connection and statement objects.
nrich@ii.net
parents:
30
diff
changeset
|
364 | statement_t *statement = (statement_t *)luaL_checkudata(L, 1, DBD_POSTGRESQL_STATEMENT); |
03ed0ca09837
Add __tostring method to connection and statement objects.
nrich@ii.net
parents:
30
diff
changeset
|
365 | |
03ed0ca09837
Add __tostring method to connection and statement objects.
nrich@ii.net
parents:
30
diff
changeset
|
366 | lua_pushfstring(L, "%s: %p", DBD_POSTGRESQL_STATEMENT, statement); |
03ed0ca09837
Add __tostring method to connection and statement objects.
nrich@ii.net
parents:
30
diff
changeset
|
367 | |
03ed0ca09837
Add __tostring method to connection and statement objects.
nrich@ii.net
parents:
30
diff
changeset
|
368 | return 1; |
03ed0ca09837
Add __tostring method to connection and statement objects.
nrich@ii.net
parents:
30
diff
changeset
|
369 | } |
03ed0ca09837
Add __tostring method to connection and statement objects.
nrich@ii.net
parents:
30
diff
changeset
|
370 | |
1 | 371 | int dbd_postgresql_statement_create(lua_State *L, connection_t *conn, const char *sql_query) { |
372 | statement_t *statement = NULL; | |
373 | ExecStatusType status; | |
374 | PGresult *result = NULL; | |
375 | char *new_sql; | |
376 | char name[IDLEN]; | |
377 | ||
2 | 378 | /* |
379 | * convert SQL string into a PSQL API compatible SQL statement | |
380 | */ | |
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
|
381 | new_sql = replace_placeholders(L, '$', sql_query); |
1 | 382 | |
30
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
383 | snprintf(name, IDLEN, "dbd-postgresql-%017u", ++conn->statement_id); |
1 | 384 | |
385 | result = PQprepare(conn->postgresql, name, new_sql, 0, NULL); | |
2 | 386 | |
387 | /* | |
388 | * free converted statement after use | |
389 | */ | |
1 | 390 | free(new_sql); |
391 | ||
392 | if (!result) { | |
30
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
393 | lua_pushnil(L); |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
394 | lua_pushfstring(L, DBI_ERR_ALLOC_STATEMENT, PQerrorMessage(statement->postgresql)); |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
395 | return 2; |
1 | 396 | } |
397 | ||
398 | status = PQresultStatus(result); | |
399 | if (status != PGRES_COMMAND_OK && status != PGRES_TUPLES_OK) { | |
30
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
400 | const char *err_string = PQresultErrorMessage(result); |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
401 | PQclear(result); |
3 | 402 | |
30
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
403 | lua_pushnil(L); |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
404 | lua_pushfstring(L, DBI_ERR_PREP_STATEMENT, err_string); |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
405 | return 2; |
1 | 406 | } |
407 | ||
408 | PQclear(result); | |
409 | ||
410 | statement = (statement_t *)lua_newuserdata(L, sizeof(statement_t)); | |
411 | statement->postgresql = conn->postgresql; | |
412 | statement->result = NULL; | |
413 | statement->tuple = 0; | |
414 | strncpy(statement->name, name, IDLEN-1); | |
415 | statement->name[IDLEN-1] = '\0'; | |
416 | ||
417 | luaL_getmetatable(L, DBD_POSTGRESQL_STATEMENT); | |
418 | lua_setmetatable(L, -2); | |
419 | ||
420 | return 1; | |
421 | } | |
422 | ||
423 | int dbd_postgresql_statement(lua_State *L) { | |
2 | 424 | static const luaL_Reg statement_methods[] = { |
30
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
425 | {"affected", statement_affected}, |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
426 | {"close", statement_close}, |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
427 | {"columns", statement_columns}, |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
428 | {"execute", statement_execute}, |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
429 | {"fetch", statement_fetch}, |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
430 | {"rowcount", statement_rowcount}, |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
431 | {"rows", statement_rows}, |
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
432 | {NULL, NULL} |
2 | 433 | }; |
434 | ||
435 | static const luaL_Reg statement_class_methods[] = { | |
30
8599f34c139b
Add 'columns' method to statement handles to retrieve column names from a result set
nrich@ii.net
parents:
21
diff
changeset
|
436 | {NULL, NULL} |
2 | 437 | }; |
438 | ||
1 | 439 | luaL_newmetatable(L, DBD_POSTGRESQL_STATEMENT); |
440 | luaL_register(L, 0, statement_methods); | |
441 | lua_pushvalue(L,-1); | |
442 | lua_setfield(L, -2, "__index"); | |
443 | ||
444 | lua_pushcfunction(L, statement_gc); | |
445 | lua_setfield(L, -2, "__gc"); | |
446 | ||
32
03ed0ca09837
Add __tostring method to connection and statement objects.
nrich@ii.net
parents:
30
diff
changeset
|
447 | lua_pushcfunction(L, statement_tostring); |
03ed0ca09837
Add __tostring method to connection and statement objects.
nrich@ii.net
parents:
30
diff
changeset
|
448 | lua_setfield(L, -2, "__tostring"); |
03ed0ca09837
Add __tostring method to connection and statement objects.
nrich@ii.net
parents:
30
diff
changeset
|
449 | |
1 | 450 | luaL_register(L, DBD_POSTGRESQL_STATEMENT, statement_class_methods); |
451 | ||
452 | return 1; | |
453 | } |