LCOV - code coverage report
Current view: top level - Modules/_sqlite - statement.c (source / functions) Hit Total Coverage
Test: CPython 3.12 LCOV report [commit acb105a7c1f] Lines: 85 87 97.7 %
Date: 2022-07-20 13:12:14 Functions: 5 5 100.0 %
Branches: 50 54 92.6 %

           Branch data     Line data    Source code
       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                 :       1581 : pysqlite_statement_create(pysqlite_Connection *connection, PyObject *sql)
      33                 :            : {
      34                 :       1581 :     pysqlite_state *state = connection->state;
      35                 :            :     assert(PyUnicode_Check(sql));
      36                 :            :     Py_ssize_t size;
      37                 :       1581 :     const char *sql_cstr = PyUnicode_AsUTF8AndSize(sql, &size);
      38         [ +  + ]:       1581 :     if (sql_cstr == NULL) {
      39                 :          4 :         return NULL;
      40                 :            :     }
      41                 :            : 
      42                 :       1577 :     sqlite3 *db = connection->db;
      43                 :       1577 :     int max_length = sqlite3_limit(db, SQLITE_LIMIT_SQL_LENGTH, -1);
      44         [ +  + ]:       1577 :     if (size > max_length) {
      45                 :          3 :         PyErr_SetString(connection->DataError,
      46                 :            :                         "query string is too large");
      47                 :          3 :         return NULL;
      48                 :            :     }
      49         [ +  + ]:       1574 :     if (strlen(sql_cstr) != (size_t)size) {
      50                 :          4 :         PyErr_SetString(connection->ProgrammingError,
      51                 :            :                         "the query contains a null character");
      52                 :          4 :         return NULL;
      53                 :            :     }
      54                 :            : 
      55                 :            :     sqlite3_stmt *stmt;
      56                 :            :     const char *tail;
      57                 :            :     int rc;
      58                 :       1570 :     Py_BEGIN_ALLOW_THREADS
      59                 :       1570 :     rc = sqlite3_prepare_v2(db, sql_cstr, (int)size + 1, &stmt, &tail);
      60                 :       1570 :     Py_END_ALLOW_THREADS
      61                 :            : 
      62         [ +  + ]:       1570 :     if (rc != SQLITE_OK) {
      63                 :         25 :         _pysqlite_seterror(state, db);
      64                 :         25 :         return NULL;
      65                 :            :     }
      66                 :            : 
      67         [ +  + ]:       1545 :     if (lstrip_sql(tail) != NULL) {
      68                 :         10 :         PyErr_SetString(connection->ProgrammingError,
      69                 :            :                         "You can only execute one statement at a time.");
      70                 :         10 :         goto error;
      71                 :            :     }
      72                 :            : 
      73                 :            :     /* Determine if the statement is a DML statement.
      74                 :            :        SELECT is the only exception. See #9924. */
      75                 :       1535 :     int is_dml = 0;
      76                 :       1535 :     const char *p = lstrip_sql(sql_cstr);
      77         [ +  + ]:       1535 :     if (p != NULL) {
      78                 :       3068 :         is_dml = (PyOS_strnicmp(p, "insert", 6) == 0)
      79         [ +  + ]:       1230 :                   || (PyOS_strnicmp(p, "update", 6) == 0)
      80         [ +  + ]:       1223 :                   || (PyOS_strnicmp(p, "delete", 6) == 0)
      81   [ +  +  +  + ]:       2764 :                   || (PyOS_strnicmp(p, "replace", 7) == 0);
      82                 :            :     }
      83                 :            : 
      84                 :       1535 :     pysqlite_Statement *self = PyObject_GC_New(pysqlite_Statement,
      85                 :            :                                                state->StatementType);
      86         [ -  + ]:       1535 :     if (self == NULL) {
      87                 :          0 :         goto error;
      88                 :            :     }
      89                 :            : 
      90                 :       1535 :     self->st = stmt;
      91                 :       1535 :     self->is_dml = is_dml;
      92                 :            : 
      93                 :       1535 :     PyObject_GC_Track(self);
      94                 :       1535 :     return self;
      95                 :            : 
      96                 :         10 : error:
      97                 :         10 :     (void)sqlite3_finalize(stmt);
      98                 :         10 :     return NULL;
      99                 :            : }
     100                 :            : 
     101                 :            : static void
     102                 :       1535 : stmt_dealloc(pysqlite_Statement *self)
     103                 :            : {
     104                 :       1535 :     PyTypeObject *tp = Py_TYPE(self);
     105                 :       1535 :     PyObject_GC_UnTrack(self);
     106         [ +  + ]:       1535 :     if (self->st) {
     107                 :       1534 :         Py_BEGIN_ALLOW_THREADS
     108                 :       1534 :         sqlite3_finalize(self->st);
     109                 :       1534 :         Py_END_ALLOW_THREADS
     110                 :       1534 :         self->st = 0;
     111                 :            :     }
     112                 :       1535 :     tp->tp_free(self);
     113                 :       1535 :     Py_DECREF(tp);
     114                 :       1535 : }
     115                 :            : 
     116                 :            : static int
     117                 :        334 : stmt_traverse(pysqlite_Statement *self, visitproc visit, void *arg)
     118                 :            : {
     119   [ +  -  -  + ]:        334 :     Py_VISIT(Py_TYPE(self));
     120                 :        334 :     return 0;
     121                 :            : }
     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                 :       3080 : lstrip_sql(const char *sql)
     135                 :            : {
     136                 :            :     // This loop is borrowed from the SQLite source code.
     137         [ +  + ]:       4096 :     for (const char *pos = sql; *pos; pos++) {
     138   [ +  +  +  + ]:       2563 :         switch (*pos) {
     139                 :       1008 :             case ' ':
     140                 :            :             case '\t':
     141                 :            :             case '\f':
     142                 :            :             case '\n':
     143                 :            :             case '\r':
     144                 :            :                 // Skip whitespace.
     145                 :       1008 :                 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                 :            :                     }
     153         [ +  + ]:          4 :                     if (pos[0] == '\0') {
     154                 :          2 :                         return NULL;
     155                 :            :                     }
     156                 :          2 :                     continue;
     157                 :            :                 }
     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                 :            :                     }
     166         [ +  + ]:          7 :                     if (pos[0] == '\0') {
     167                 :          1 :                         return NULL;
     168                 :            :                     }
     169                 :          6 :                     pos++;
     170                 :          6 :                     continue;
     171                 :            :                 }
     172                 :          2 :                 return pos;
     173                 :       1539 :             default:
     174                 :       1539 :                 return pos;
     175                 :            :         }
     176                 :            :     }
     177                 :            : 
     178                 :       1533 :     return NULL;
     179                 :            : }
     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                 :          5 : pysqlite_statement_setup_types(PyObject *module)
     197                 :            : {
     198                 :          5 :     PyObject *type = PyType_FromModuleAndSpec(module, &stmt_spec, NULL);
     199         [ -  + ]:          5 :     if (type == NULL) {
     200                 :          0 :         return -1;
     201                 :            :     }
     202                 :          5 :     pysqlite_state *state = pysqlite_get_state(module);
     203                 :          5 :     state->StatementType = (PyTypeObject *)type;
     204                 :          5 :     return 0;
     205                 :            : }

Generated by: LCOV version 1.14