blob: a2c0f13c293f161b0e1d3b354db6141b48c7cef0 [file] [log] [blame]
Anthony Baxterc51ee692006-04-01 00:57:31 +00001/* statement.c - the statement type
2 *
3 * Copyright (C) 2005-2006 Gerhard Häring <gh@ghaering.de>
4 *
5 * This file is part of pysqlite.
6 *
7 * This software is provided 'as-is', without any express or implied
8 * warranty. In no event will the authors be held liable for any damages
9 * arising from the use of this software.
10 *
11 * Permission is granted to anyone to use this software for any purpose,
12 * including commercial applications, and to alter it and redistribute it
13 * freely, subject to the following restrictions:
14 *
15 * 1. The origin of this software must not be misrepresented; you must not
16 * claim that you wrote the original software. If you use this software
17 * in a product, an acknowledgment in the product documentation would be
18 * appreciated but is not required.
19 * 2. Altered source versions must be plainly marked as such, and must not be
20 * misrepresented as being the original software.
21 * 3. This notice may not be removed or altered from any source distribution.
22 */
23
24#include "statement.h"
25#include "connection.h"
26
27/* prototypes */
28int check_remaining_sql(const char* tail);
29
30typedef enum {
31 LINECOMMENT_1,
32 IN_LINECOMMENT,
33 COMMENTSTART_1,
34 IN_COMMENT,
35 COMMENTEND_1,
36 NORMAL
37} parse_remaining_sql_state;
38
39int statement_create(Statement* self, Connection* connection, PyObject* sql)
40{
41 const char* tail;
42 int rc;
43 PyObject* sql_str;
44 char* sql_cstr;
45
46 self->st = NULL;
47
48 self->st = NULL;
49 self->in_use = 0;
50
51 if (PyString_Check(sql)) {
52 sql_str = sql;
53 Py_INCREF(sql_str);
54 } else if (PyUnicode_Check(sql)) {
55 sql_str = PyUnicode_AsUTF8String(sql);
56 if (!sql_str) {
57 rc = PYSQLITE_SQL_WRONG_TYPE;
58 return rc;
59 }
60 } else {
61 rc = PYSQLITE_SQL_WRONG_TYPE;
62 return rc;
63 }
64
65 self->sql = sql_str;
66
67 sql_cstr = PyString_AsString(sql_str);
68
69 rc = sqlite3_prepare(connection->db,
70 sql_cstr,
71 -1,
72 &self->st,
73 &tail);
74
75 self->db = connection->db;
76
77 if (rc == SQLITE_OK && check_remaining_sql(tail)) {
78 (void)sqlite3_finalize(self->st);
79 rc = PYSQLITE_TOO_MUCH_SQL;
80 }
81
82 return rc;
83}
84
85int statement_recompile(Statement* self)
86{
87 const char* tail;
88 int rc;
89 char* sql_cstr;
90 sqlite3_stmt* new_st;
91
92 sql_cstr = PyString_AsString(self->sql);
93
94 rc = sqlite3_prepare(self->db,
95 sql_cstr,
96 -1,
97 &new_st,
98 &tail);
99
100 if (rc == SQLITE_OK) {
101 (void)sqlite3_transfer_bindings(self->st, new_st);
102
103 (void)sqlite3_finalize(self->st);
104 self->st = new_st;
105 }
106
107 return rc;
108}
109
110int statement_finalize(Statement* self)
111{
112 int rc;
113
114 rc = SQLITE_OK;
115 if (self->st) {
116 Py_BEGIN_ALLOW_THREADS
117 rc = sqlite3_finalize(self->st);
118 Py_END_ALLOW_THREADS
119 self->st = NULL;
120 }
121
122 self->in_use = 0;
123
124 return rc;
125}
126
127int statement_reset(Statement* self)
128{
129 int rc;
130
131 rc = SQLITE_OK;
132
133 if (self->in_use && self->st) {
134 Py_BEGIN_ALLOW_THREADS
135 rc = sqlite3_reset(self->st);
136 Py_END_ALLOW_THREADS
137
138 if (rc == SQLITE_OK) {
139 self->in_use = 0;
140 }
141 }
142
143 return rc;
144}
145
146void statement_mark_dirty(Statement* self)
147{
148 self->in_use = 1;
149}
150
151void statement_dealloc(Statement* self)
152{
153 int rc;
154
155 if (self->st) {
156 Py_BEGIN_ALLOW_THREADS
157 rc = sqlite3_finalize(self->st);
158 Py_END_ALLOW_THREADS
159 }
160
161 self->st = NULL;
162
163 Py_XDECREF(self->sql);
164
165 self->ob_type->tp_free((PyObject*)self);
166}
167
168/*
169 * Checks if there is anything left in an SQL string after SQLite compiled it.
170 * This is used to check if somebody tried to execute more than one SQL command
171 * with one execute()/executemany() command, which the DB-API and we don't
172 * allow.
173 *
174 * Returns 1 if there is more left than should be. 0 if ok.
175 */
176int check_remaining_sql(const char* tail)
177{
178 const char* pos = tail;
179
180 parse_remaining_sql_state state = NORMAL;
181
182 for (;;) {
183 switch (*pos) {
184 case 0:
185 return 0;
186 case '-':
187 if (state == NORMAL) {
188 state = LINECOMMENT_1;
189 } else if (state == LINECOMMENT_1) {
190 state = IN_LINECOMMENT;
191 }
192 break;
193 case ' ':
194 case '\t':
195 break;
196 case '\n':
197 case 13:
198 if (state == IN_LINECOMMENT) {
199 state = NORMAL;
200 }
201 break;
202 case '/':
203 if (state == NORMAL) {
204 state = COMMENTSTART_1;
205 } else if (state == COMMENTEND_1) {
206 state = NORMAL;
207 } else if (state == COMMENTSTART_1) {
208 return 1;
209 }
210 break;
211 case '*':
212 if (state == NORMAL) {
213 return 1;
214 } else if (state == LINECOMMENT_1) {
215 return 1;
216 } else if (state == COMMENTSTART_1) {
217 state = IN_COMMENT;
218 } else if (state == IN_COMMENT) {
219 state = COMMENTEND_1;
220 }
221 break;
222 default:
223 if (state == COMMENTEND_1) {
224 state = IN_COMMENT;
225 } else if (state == IN_LINECOMMENT) {
226 } else if (state == IN_COMMENT) {
227 } else {
228 return 1;
229 }
230 }
231
232 pos++;
233 }
234
235 return 0;
236}
237
238PyTypeObject StatementType = {
239 PyObject_HEAD_INIT(NULL)
240 0, /* ob_size */
241 "pysqlite2.dbapi2.Statement", /* tp_name */
242 sizeof(Statement), /* tp_basicsize */
243 0, /* tp_itemsize */
244 (destructor)statement_dealloc, /* tp_dealloc */
245 0, /* tp_print */
246 0, /* tp_getattr */
247 0, /* tp_setattr */
248 0, /* tp_compare */
249 0, /* tp_repr */
250 0, /* tp_as_number */
251 0, /* tp_as_sequence */
252 0, /* tp_as_mapping */
253 0, /* tp_hash */
254 0, /* tp_call */
255 0, /* tp_str */
256 0, /* tp_getattro */
257 0, /* tp_setattro */
258 0, /* tp_as_buffer */
259 Py_TPFLAGS_DEFAULT, /* tp_flags */
260 0, /* tp_doc */
261 0, /* tp_traverse */
262 0, /* tp_clear */
263 0, /* tp_richcompare */
264 0, /* tp_weaklistoffset */
265 0, /* tp_iter */
266 0, /* tp_iternext */
267 0, /* tp_methods */
268 0, /* tp_members */
269 0, /* tp_getset */
270 0, /* tp_base */
271 0, /* tp_dict */
272 0, /* tp_descr_get */
273 0, /* tp_descr_set */
274 0, /* tp_dictoffset */
275 (initproc)0, /* tp_init */
276 0, /* tp_alloc */
277 0, /* tp_new */
278 0 /* tp_free */
279};
280
281extern int statement_setup_types(void)
282{
283 StatementType.tp_new = PyType_GenericNew;
284 return PyType_Ready(&StatementType);
285}