diff options
| author | Gerhard Häring <gh@ghaering.de> | 2008-02-29 22:08:41 (GMT) | 
|---|---|---|
| committer | Gerhard Häring <gh@ghaering.de> | 2008-02-29 22:08:41 (GMT) | 
| commit | 1cc60ed214d83b1901a9e68782559c18f705ff07 (patch) | |
| tree | 31d9638597c104accd2d2149095b16b9e8c22325 /Modules/_sqlite/statement.c | |
| parent | 0e795e7d9225837bc6949a951ba514feab18f9ef (diff) | |
| download | cpython-1cc60ed214d83b1901a9e68782559c18f705ff07.zip cpython-1cc60ed214d83b1901a9e68782559c18f705ff07.tar.gz cpython-1cc60ed214d83b1901a9e68782559c18f705ff07.tar.bz2  | |
Updated to pysqlite 2.4.1. Documentation additions will come later.
Diffstat (limited to 'Modules/_sqlite/statement.c')
| -rw-r--r-- | Modules/_sqlite/statement.c | 216 | 
1 files changed, 154 insertions, 62 deletions
diff --git a/Modules/_sqlite/statement.c b/Modules/_sqlite/statement.c index 83c0790..556ea01 100644 --- a/Modules/_sqlite/statement.c +++ b/Modules/_sqlite/statement.c @@ -1,6 +1,6 @@  /* statement.c - the statement type   * - * Copyright (C) 2005-2006 Gerhard Häring <gh@ghaering.de> + * Copyright (C) 2005-2007 Gerhard Häring <gh@ghaering.de>   *   * This file is part of pysqlite.   * @@ -40,6 +40,16 @@ typedef enum {      NORMAL  } parse_remaining_sql_state; +typedef enum { +    TYPE_INT, +    TYPE_LONG, +    TYPE_FLOAT, +    TYPE_STRING, +    TYPE_UNICODE, +    TYPE_BUFFER, +    TYPE_UNKNOWN +} parameter_type; +  int pysqlite_statement_create(pysqlite_Statement* self, pysqlite_Connection* connection, PyObject* sql)  {      const char* tail; @@ -97,42 +107,96 @@ int pysqlite_statement_bind_parameter(pysqlite_Statement* self, int pos, PyObjec      char* string;      Py_ssize_t buflen;      PyObject* stringval; +    parameter_type paramtype;      if (parameter == Py_None) {          rc = sqlite3_bind_null(self->st, pos); +        goto final; +    } + +    if (PyInt_CheckExact(parameter)) { +        paramtype = TYPE_INT; +    } else if (PyLong_CheckExact(parameter)) { +        paramtype = TYPE_LONG; +    } else if (PyFloat_CheckExact(parameter)) { +        paramtype = TYPE_FLOAT; +    } else if (PyString_CheckExact(parameter)) { +        paramtype = TYPE_STRING; +    } else if (PyUnicode_CheckExact(parameter)) { +        paramtype = TYPE_UNICODE; +    } else if (PyBuffer_Check(parameter)) { +        paramtype = TYPE_BUFFER;      } else if (PyInt_Check(parameter)) { -        longval = PyInt_AsLong(parameter); -        rc = sqlite3_bind_int64(self->st, pos, (sqlite_int64)longval); -#ifdef HAVE_LONG_LONG +        paramtype = TYPE_INT;      } else if (PyLong_Check(parameter)) { -        longlongval = PyLong_AsLongLong(parameter); -        /* in the overflow error case, longlongval is -1, and an exception is set */ -        rc = sqlite3_bind_int64(self->st, pos, (sqlite_int64)longlongval); -#endif +        paramtype = TYPE_LONG;      } else if (PyFloat_Check(parameter)) { -        rc = sqlite3_bind_double(self->st, pos, PyFloat_AsDouble(parameter)); -    } else if (PyBuffer_Check(parameter)) { -        if (PyObject_AsCharBuffer(parameter, &buffer, &buflen) == 0) { -            rc = sqlite3_bind_blob(self->st, pos, buffer, buflen, SQLITE_TRANSIENT); -        } else { -            PyErr_SetString(PyExc_ValueError, "could not convert BLOB to buffer"); -            rc = -1; -        } -    } else if PyString_Check(parameter) { -        string = PyString_AsString(parameter); -        rc = sqlite3_bind_text(self->st, pos, string, -1, SQLITE_TRANSIENT); -    } else if PyUnicode_Check(parameter) { -        stringval = PyUnicode_AsUTF8String(parameter); -        string = PyString_AsString(stringval); -        rc = sqlite3_bind_text(self->st, pos, string, -1, SQLITE_TRANSIENT); -        Py_DECREF(stringval); +        paramtype = TYPE_FLOAT; +    } else if (PyString_Check(parameter)) { +        paramtype = TYPE_STRING; +    } else if (PyUnicode_Check(parameter)) { +        paramtype = TYPE_UNICODE;      } else { -        rc = -1; +        paramtype = TYPE_UNKNOWN;      } +    switch (paramtype) { +        case TYPE_INT: +            longval = PyInt_AsLong(parameter); +            rc = sqlite3_bind_int64(self->st, pos, (sqlite_int64)longval); +            break; +#ifdef HAVE_LONG_LONG +        case TYPE_LONG: +            longlongval = PyLong_AsLongLong(parameter); +            /* in the overflow error case, longlongval is -1, and an exception is set */ +            rc = sqlite3_bind_int64(self->st, pos, (sqlite_int64)longlongval); +            break; +#endif +        case TYPE_FLOAT: +            rc = sqlite3_bind_double(self->st, pos, PyFloat_AsDouble(parameter)); +            break; +        case TYPE_STRING: +            string = PyString_AS_STRING(parameter); +            rc = sqlite3_bind_text(self->st, pos, string, -1, SQLITE_TRANSIENT); +            break; +        case TYPE_UNICODE: +            stringval = PyUnicode_AsUTF8String(parameter); +            string = PyString_AsString(stringval); +            rc = sqlite3_bind_text(self->st, pos, string, -1, SQLITE_TRANSIENT); +            Py_DECREF(stringval); +            break; +        case TYPE_BUFFER: +            if (PyObject_AsCharBuffer(parameter, &buffer, &buflen) == 0) { +                rc = sqlite3_bind_blob(self->st, pos, buffer, buflen, SQLITE_TRANSIENT); +            } else { +                PyErr_SetString(PyExc_ValueError, "could not convert BLOB to buffer"); +                rc = -1; +            } +            break; +        case TYPE_UNKNOWN: +            rc = -1; +    } + +final:      return rc;  } +/* returns 0 if the object is one of Python's internal ones that don't need to be adapted */ +static int _need_adapt(PyObject* obj) +{ +    if (pysqlite_BaseTypeAdapted) { +        return 1; +    } + +    if (PyInt_CheckExact(obj) || PyLong_CheckExact(obj)  +            || PyFloat_CheckExact(obj) || PyString_CheckExact(obj) +            || PyUnicode_CheckExact(obj) || PyBuffer_Check(obj)) { +        return 0; +    } else { +        return 1; +    } +} +  void pysqlite_statement_bind_parameters(pysqlite_Statement* self, PyObject* parameters)  {      PyObject* current_param; @@ -147,7 +211,55 @@ void pysqlite_statement_bind_parameters(pysqlite_Statement* self, PyObject* para      num_params_needed = sqlite3_bind_parameter_count(self->st);      Py_END_ALLOW_THREADS -    if (PyDict_Check(parameters)) { +    if (PyTuple_CheckExact(parameters) || PyList_CheckExact(parameters) || (!PyDict_Check(parameters) && PySequence_Check(parameters))) { +        /* parameters passed as sequence */ +        if (PyTuple_CheckExact(parameters)) { +            num_params = PyTuple_GET_SIZE(parameters); +        } else if (PyList_CheckExact(parameters)) { +            num_params = PyList_GET_SIZE(parameters); +        } else { +            num_params = PySequence_Size(parameters); +        } +        if (num_params != num_params_needed) { +            PyErr_Format(pysqlite_ProgrammingError, "Incorrect number of bindings supplied. The current statement uses %d, and there are %d supplied.", +                         num_params_needed, num_params); +            return; +        } +        for (i = 0; i < num_params; i++) { +            if (PyTuple_CheckExact(parameters)) { +                current_param = PyTuple_GET_ITEM(parameters, i); +                Py_XINCREF(current_param); +            } else if (PyList_CheckExact(parameters)) { +                current_param = PyList_GET_ITEM(parameters, i); +                Py_XINCREF(current_param); +            } else { +                current_param = PySequence_GetItem(parameters, i); +            } +            if (!current_param) { +                return; +            } + +            if (!_need_adapt(current_param)) { +                adapted = current_param; +            } else { +                adapted = microprotocols_adapt(current_param, (PyObject*)&pysqlite_PrepareProtocolType, NULL); +                if (adapted) { +                    Py_DECREF(current_param); +                } else { +                    PyErr_Clear(); +                    adapted = current_param; +                } +            } + +            rc = pysqlite_statement_bind_parameter(self, i + 1, adapted); +            Py_DECREF(adapted); + +            if (rc != SQLITE_OK) { +                PyErr_Format(pysqlite_InterfaceError, "Error binding parameter %d - probably unsupported type.", i); +                return; +            } +        } +    } else if (PyDict_Check(parameters)) {          /* parameters passed as dictionary */          for (i = 1; i <= num_params_needed; i++) {              Py_BEGIN_ALLOW_THREADS @@ -159,19 +271,27 @@ void pysqlite_statement_bind_parameters(pysqlite_Statement* self, PyObject* para              }              binding_name++; /* skip first char (the colon) */ -            current_param = PyDict_GetItemString(parameters, binding_name); +            if (PyDict_CheckExact(parameters)) { +                current_param = PyDict_GetItemString(parameters, binding_name); +                Py_XINCREF(current_param); +            } else { +                current_param = PyMapping_GetItemString(parameters, (char*)binding_name); +            }              if (!current_param) {                  PyErr_Format(pysqlite_ProgrammingError, "You did not supply a value for binding %d.", i);                  return;              } -            Py_INCREF(current_param); -            adapted = microprotocols_adapt(current_param, (PyObject*)&pysqlite_PrepareProtocolType, NULL); -            if (adapted) { -                Py_DECREF(current_param); -            } else { -                PyErr_Clear(); +            if (!_need_adapt(current_param)) {                  adapted = current_param; +            } else { +                adapted = microprotocols_adapt(current_param, (PyObject*)&pysqlite_PrepareProtocolType, NULL); +                if (adapted) { +                    Py_DECREF(current_param); +                } else { +                    PyErr_Clear(); +                    adapted = current_param; +                }              }              rc = pysqlite_statement_bind_parameter(self, i, adapted); @@ -183,35 +303,7 @@ void pysqlite_statement_bind_parameters(pysqlite_Statement* self, PyObject* para             }          }      } else { -        /* parameters passed as sequence */ -        num_params = PySequence_Length(parameters); -        if (num_params != num_params_needed) { -            PyErr_Format(pysqlite_ProgrammingError, "Incorrect number of bindings supplied. The current statement uses %d, and there are %d supplied.", -                         num_params_needed, num_params); -            return; -        } -        for (i = 0; i < num_params; i++) { -            current_param = PySequence_GetItem(parameters, i); -            if (!current_param) { -                return; -            } -            adapted = microprotocols_adapt(current_param, (PyObject*)&pysqlite_PrepareProtocolType, NULL); - -            if (adapted) { -                Py_DECREF(current_param); -            } else { -                PyErr_Clear(); -                adapted = current_param; -            } - -            rc = pysqlite_statement_bind_parameter(self, i + 1, adapted); -            Py_DECREF(adapted); - -            if (rc != SQLITE_OK) { -                PyErr_Format(pysqlite_InterfaceError, "Error binding parameter %d - probably unsupported type.", i); -                return; -            } -        } +        PyErr_SetString(PyExc_ValueError, "parameters are of unsupported type");      }  }  | 
