/Users/erlendaasland/src/cpython.git/Modules/_sqlite/statement.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* statement.c - the statement type |
2 | | * |
3 | | * Copyright (C) 2005-2010 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 "connection.h" |
25 | | #include "statement.h" |
26 | | #include "util.h" |
27 | | |
28 | | /* prototypes */ |
29 | | static const char *lstrip_sql(const char *sql); |
30 | | |
31 | | pysqlite_Statement * |
32 | | pysqlite_statement_create(pysqlite_Connection *connection, PyObject *sql) |
33 | 1.57k | { |
34 | 1.57k | pysqlite_state *state = connection->state; |
35 | 1.57k | assert(PyUnicode_Check(sql)); |
36 | 0 | Py_ssize_t size; |
37 | 1.57k | const char *sql_cstr = PyUnicode_AsUTF8AndSize(sql, &size); |
38 | 1.57k | if (sql_cstr == NULL) { |
39 | 4 | return NULL; |
40 | 4 | } |
41 | | |
42 | 1.57k | sqlite3 *db = connection->db; |
43 | 1.57k | int max_length = sqlite3_limit(db, SQLITE_LIMIT_SQL_LENGTH, -1); |
44 | 1.57k | if (size > max_length) { |
45 | 3 | PyErr_SetString(connection->DataError, |
46 | 3 | "query string is too large"); |
47 | 3 | return NULL; |
48 | 3 | } |
49 | 1.57k | if (strlen(sql_cstr) != (size_t)size) { |
50 | 4 | PyErr_SetString(connection->ProgrammingError, |
51 | 4 | "the query contains a null character"); |
52 | 4 | return NULL; |
53 | 4 | } |
54 | | |
55 | 1.56k | sqlite3_stmt *stmt; |
56 | 1.56k | const char *tail; |
57 | 1.56k | int rc; |
58 | 1.56k | Py_BEGIN_ALLOW_THREADS |
59 | 1.56k | rc = sqlite3_prepare_v2(db, sql_cstr, (int)size + 1, &stmt, &tail); |
60 | 1.56k | Py_END_ALLOW_THREADS |
61 | | |
62 | 1.56k | if (rc != SQLITE_OK) { |
63 | 25 | _pysqlite_seterror(state, db); |
64 | 25 | return NULL; |
65 | 25 | } |
66 | | |
67 | 1.54k | if (lstrip_sql(tail) != NULL) { |
68 | 10 | PyErr_SetString(connection->ProgrammingError, |
69 | 10 | "You can only execute one statement at a time."); |
70 | 10 | goto error; |
71 | 10 | } |
72 | | |
73 | | /* Determine if the statement is a DML statement. |
74 | | SELECT is the only exception. See #9924. */ |
75 | 1.53k | int is_dml = 0; |
76 | 1.53k | const char *p = lstrip_sql(sql_cstr); |
77 | 1.53k | if (p != NULL) { |
78 | 1.53k | is_dml = (PyOS_strnicmp(p, "insert", 6) == 0) |
79 | 1.53k | || (PyOS_strnicmp(p, "update", 6) == 0) |
80 | 1.53k | || (PyOS_strnicmp(p, "delete", 6) == 0) |
81 | 1.53k | || (PyOS_strnicmp(p, "replace", 7) == 0); |
82 | 1.53k | } |
83 | | |
84 | 1.53k | pysqlite_Statement *self = PyObject_GC_New(pysqlite_Statement, |
85 | 1.53k | state->StatementType); |
86 | 1.53k | if (self == NULL) { |
87 | 0 | goto error; |
88 | 0 | } |
89 | | |
90 | 1.53k | self->st = stmt; |
91 | 1.53k | self->is_dml = is_dml; |
92 | | |
93 | 1.53k | PyObject_GC_Track(self); |
94 | 1.53k | return self; |
95 | | |
96 | 10 | error: |
97 | 10 | (void)sqlite3_finalize(stmt); |
98 | 10 | return NULL; |
99 | 1.53k | } |
100 | | |
101 | | static void |
102 | | stmt_dealloc(pysqlite_Statement *self) |
103 | 1.53k | { |
104 | 1.53k | PyTypeObject *tp = Py_TYPE(self); |
105 | 1.53k | PyObject_GC_UnTrack(self); |
106 | 1.53k | if (self->st) { |
107 | 1.53k | Py_BEGIN_ALLOW_THREADS |
108 | 1.53k | sqlite3_finalize(self->st); |
109 | 1.53k | Py_END_ALLOW_THREADS |
110 | 1.53k | self->st = 0; |
111 | 1.53k | } |
112 | 1.53k | tp->tp_free(self); |
113 | 1.53k | Py_DECREF(tp); |
114 | 1.53k | } |
115 | | |
116 | | static int |
117 | | stmt_traverse(pysqlite_Statement *self, visitproc visit, void *arg) |
118 | 1.87k | { |
119 | 1.87k | Py_VISIT(Py_TYPE(self)); |
120 | 1.87k | return 0; |
121 | 1.87k | } |
122 | | |
123 | | /* |
124 | | * Strip leading whitespace and comments from incoming SQL (null terminated C |
125 | | * string) and return a pointer to the first non-whitespace, non-comment |
126 | | * character. |
127 | | * |
128 | | * This is used to check if somebody tries to execute more than one SQL query |
129 | | * with one execute()/executemany() command, which the DB-API don't allow. |
130 | | * |
131 | | * It is also used to harden DML query detection. |
132 | | */ |
133 | | static inline const char * |
134 | | lstrip_sql(const char *sql) |
135 | 3.07k | { |
136 | | // This loop is borrowed from the SQLite source code. |
137 | 4.09k | for (const char *pos = sql; *pos; pos++) { |
138 | 2.56k | switch (*pos) { |
139 | 929 | case ' ': |
140 | 929 | case '\t': |
141 | 929 | case '\f': |
142 | 1.00k | case '\n': |
143 | 1.00k | case '\r': |
144 | | // Skip whitespace. |
145 | 1.00k | break; |
146 | 7 | case '-': |
147 | | // Skip line comments. |
148 | 7 | if (pos[1] == '-') { |
149 | 4 | pos += 2; |
150 | 24 | while (pos[0] && pos[0] != '\n') { |
151 | 20 | pos++; |
152 | 20 | } |
153 | 4 | if (pos[0] == '\0') { |
154 | 2 | return NULL; |
155 | 2 | } |
156 | 2 | continue; |
157 | 4 | } |
158 | 3 | return pos; |
159 | 9 | case '/': |
160 | | // Skip C style comments. |
161 | 9 | if (pos[1] == '*') { |
162 | 7 | pos += 2; |
163 | 93 | while (pos[0] && (pos[0] != '*' || pos[1] != '/')) { |
164 | 86 | pos++; |
165 | 86 | } |
166 | 7 | if (pos[0] == '\0') { |
167 | 1 | return NULL; |
168 | 1 | } |
169 | 6 | pos++; |
170 | 6 | continue; |
171 | 7 | } |
172 | 2 | return pos; |
173 | 1.53k | default: |
174 | 1.53k | return pos; |
175 | 2.56k | } |
176 | 2.56k | } |
177 | | |
178 | 1.53k | return NULL; |
179 | 3.07k | } |
180 | | |
181 | | static PyType_Slot stmt_slots[] = { |
182 | | {Py_tp_dealloc, stmt_dealloc}, |
183 | | {Py_tp_traverse, stmt_traverse}, |
184 | | {0, NULL}, |
185 | | }; |
186 | | |
187 | | static PyType_Spec stmt_spec = { |
188 | | .name = MODULE_NAME ".Statement", |
189 | | .basicsize = sizeof(pysqlite_Statement), |
190 | | .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | |
191 | | Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_DISALLOW_INSTANTIATION), |
192 | | .slots = stmt_slots, |
193 | | }; |
194 | | |
195 | | int |
196 | | pysqlite_statement_setup_types(PyObject *module) |
197 | 1 | { |
198 | 1 | PyObject *type = PyType_FromModuleAndSpec(module, &stmt_spec, NULL); |
199 | 1 | if (type == NULL) { |
200 | 0 | return -1; |
201 | 0 | } |
202 | 1 | pysqlite_state *state = pysqlite_get_state(module); |
203 | 1 | state->StatementType = (PyTypeObject *)type; |
204 | 1 | return 0; |
205 | 1 | } |