2006-03-31 20:57:31 -04:00
/* statement.c - the statement type
*
2008-02-29 18:08:41 -04:00
* Copyright ( C ) 2005 - 2007 Gerhard H <EFBFBD> ring < gh @ ghaering . de >
2006-03-31 20:57:31 -04:00
*
* This file is part of pysqlite .
*
* This software is provided ' as - is ' , without any express or implied
* warranty . In no event will the authors be held liable for any damages
* arising from the use of this software .
*
* Permission is granted to anyone to use this software for any purpose ,
* including commercial applications , and to alter it and redistribute it
* freely , subject to the following restrictions :
*
* 1. The origin of this software must not be misrepresented ; you must not
* claim that you wrote the original software . If you use this software
* in a product , an acknowledgment in the product documentation would be
* appreciated but is not required .
* 2. Altered source versions must be plainly marked as such , and must not be
* misrepresented as being the original software .
* 3. This notice may not be removed or altered from any source distribution .
*/
# include "statement.h"
2006-04-01 04:36:27 -04:00
# include "cursor.h"
2006-03-31 20:57:31 -04:00
# include "connection.h"
2006-04-01 04:36:27 -04:00
# include "microprotocols.h"
# include "prepare_protocol.h"
2006-04-04 03:29:05 -03:00
# include "sqlitecompat.h"
2006-03-31 20:57:31 -04:00
/* prototypes */
2007-01-13 21:43:50 -04:00
static int pysqlite_check_remaining_sql ( const char * tail ) ;
2006-03-31 20:57:31 -04:00
typedef enum {
LINECOMMENT_1 ,
IN_LINECOMMENT ,
COMMENTSTART_1 ,
IN_COMMENT ,
COMMENTEND_1 ,
NORMAL
} parse_remaining_sql_state ;
2008-02-29 18:08:41 -04:00
typedef enum {
TYPE_INT ,
TYPE_LONG ,
TYPE_FLOAT ,
TYPE_STRING ,
TYPE_UNICODE ,
TYPE_BUFFER ,
TYPE_UNKNOWN
} parameter_type ;
2007-01-13 21:43:50 -04:00
int pysqlite_statement_create ( pysqlite_Statement * self , pysqlite_Connection * connection , PyObject * sql )
2006-03-31 20:57:31 -04:00
{
const char * tail ;
int rc ;
PyObject * sql_str ;
char * sql_cstr ;
self - > st = NULL ;
self - > in_use = 0 ;
if ( PyString_Check ( sql ) ) {
sql_str = sql ;
Py_INCREF ( sql_str ) ;
} else if ( PyUnicode_Check ( sql ) ) {
sql_str = PyUnicode_AsUTF8String ( sql ) ;
if ( ! sql_str ) {
rc = PYSQLITE_SQL_WRONG_TYPE ;
return rc ;
}
} else {
rc = PYSQLITE_SQL_WRONG_TYPE ;
return rc ;
}
2006-04-23 12:24:26 -03:00
self - > in_weakreflist = NULL ;
2006-03-31 20:57:31 -04:00
self - > sql = sql_str ;
sql_cstr = PyString_AsString ( sql_str ) ;
rc = sqlite3_prepare ( connection - > db ,
sql_cstr ,
- 1 ,
& self - > st ,
& tail ) ;
self - > db = connection - > db ;
2007-01-13 21:43:50 -04:00
if ( rc = = SQLITE_OK & & pysqlite_check_remaining_sql ( tail ) ) {
2006-03-31 20:57:31 -04:00
( void ) sqlite3_finalize ( self - > st ) ;
2006-04-16 00:37:19 -03:00
self - > st = NULL ;
2006-03-31 20:57:31 -04:00
rc = PYSQLITE_TOO_MUCH_SQL ;
}
return rc ;
}
2008-03-28 17:08:36 -03:00
int pysqlite_statement_bind_parameter ( pysqlite_Statement * self , int pos , PyObject * parameter , int allow_8bit_chars )
2006-04-01 04:36:27 -04:00
{
int rc = SQLITE_OK ;
long longval ;
PY_LONG_LONG longlongval ;
const char * buffer ;
char * string ;
2006-04-01 05:08:06 -04:00
Py_ssize_t buflen ;
2006-04-01 04:36:27 -04:00
PyObject * stringval ;
2008-02-29 18:08:41 -04:00
parameter_type paramtype ;
2008-03-28 17:08:36 -03:00
char * c ;
2006-04-01 04:36:27 -04:00
if ( parameter = = Py_None ) {
rc = sqlite3_bind_null ( self - > st , pos ) ;
2008-02-29 18:08:41 -04:00
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 ;
2006-04-01 04:36:27 -04:00
} else if ( PyInt_Check ( parameter ) ) {
2008-02-29 18:08:41 -04:00
paramtype = TYPE_INT ;
2006-04-01 04:36:27 -04:00
} else if ( PyLong_Check ( parameter ) ) {
2008-02-29 18:08:41 -04:00
paramtype = TYPE_LONG ;
2006-04-01 04:36:27 -04:00
} else if ( PyFloat_Check ( parameter ) ) {
2008-02-29 18:08:41 -04:00
paramtype = TYPE_FLOAT ;
} else if ( PyString_Check ( parameter ) ) {
paramtype = TYPE_STRING ;
} else if ( PyUnicode_Check ( parameter ) ) {
paramtype = TYPE_UNICODE ;
2006-04-01 04:36:27 -04:00
} else {
2008-02-29 18:08:41 -04:00
paramtype = TYPE_UNKNOWN ;
}
2008-03-28 17:08:36 -03:00
if ( paramtype = = TYPE_STRING & & ! allow_8bit_chars ) {
string = PyString_AS_STRING ( parameter ) ;
for ( c = string ; * c ! = 0 ; c + + ) {
if ( * c & 0x80 ) {
PyErr_SetString ( pysqlite_ProgrammingError , " You must not use 8-bit bytestrings unless you use a text_factory that can interpret 8-bit bytestrings (like text_factory = str). It is highly recommended that you instead just switch your application to Unicode strings. " ) ;
rc = - 1 ;
goto final ;
}
}
}
2008-02-29 18:08:41 -04:00
switch ( paramtype ) {
case TYPE_INT :
longval = PyInt_AsLong ( parameter ) ;
rc = sqlite3_bind_int64 ( self - > st , pos , ( sqlite_int64 ) longval ) ;
break ;
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 ;
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 ;
2006-04-01 04:36:27 -04:00
}
2008-02-29 18:08:41 -04:00
final :
2006-04-01 04:36:27 -04:00
return rc ;
}
2008-02-29 18:08:41 -04:00
/* 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 ;
}
}
2008-03-28 17:08:36 -03:00
void pysqlite_statement_bind_parameters ( pysqlite_Statement * self , PyObject * parameters , int allow_8bit_chars )
2006-04-01 04:36:27 -04:00
{
PyObject * current_param ;
PyObject * adapted ;
const char * binding_name ;
int i ;
int rc ;
int num_params_needed ;
int num_params ;
Py_BEGIN_ALLOW_THREADS
num_params_needed = sqlite3_bind_parameter_count ( self - > st ) ;
Py_END_ALLOW_THREADS
2008-02-29 18:08:41 -04:00
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 ;
}
}
2008-03-28 17:08:36 -03:00
rc = pysqlite_statement_bind_parameter ( self , i + 1 , adapted , allow_8bit_chars ) ;
2008-02-29 18:08:41 -04:00
Py_DECREF ( adapted ) ;
if ( rc ! = SQLITE_OK ) {
2008-03-28 17:08:36 -03:00
if ( ! PyErr_Occurred ( ) ) {
PyErr_Format ( pysqlite_InterfaceError , " Error binding parameter %d - probably unsupported type. " , i ) ;
}
2008-02-29 18:08:41 -04:00
return ;
}
}
} else if ( PyDict_Check ( parameters ) ) {
2006-04-01 04:36:27 -04:00
/* parameters passed as dictionary */
for ( i = 1 ; i < = num_params_needed ; i + + ) {
Py_BEGIN_ALLOW_THREADS
binding_name = sqlite3_bind_parameter_name ( self - > st , i ) ;
Py_END_ALLOW_THREADS
if ( ! binding_name ) {
2007-01-13 21:43:50 -04:00
PyErr_Format ( pysqlite_ProgrammingError , " Binding %d has no name, but you supplied a dictionary (which has only names). " , i ) ;
2006-04-01 04:36:27 -04:00
return ;
}
binding_name + + ; /* skip first char (the colon) */
2008-02-29 18:08:41 -04:00
if ( PyDict_CheckExact ( parameters ) ) {
current_param = PyDict_GetItemString ( parameters , binding_name ) ;
Py_XINCREF ( current_param ) ;
} else {
current_param = PyMapping_GetItemString ( parameters , ( char * ) binding_name ) ;
}
2006-04-01 04:36:27 -04:00
if ( ! current_param ) {
2007-01-13 21:43:50 -04:00
PyErr_Format ( pysqlite_ProgrammingError , " You did not supply a value for binding %d. " , i ) ;
2006-04-01 04:36:27 -04:00
return ;
}
2008-02-29 18:08:41 -04:00
if ( ! _need_adapt ( current_param ) ) {
2006-04-01 04:36:27 -04:00
adapted = current_param ;
2008-02-29 18:08:41 -04:00
} else {
adapted = microprotocols_adapt ( current_param , ( PyObject * ) & pysqlite_PrepareProtocolType , NULL ) ;
if ( adapted ) {
Py_DECREF ( current_param ) ;
} else {
PyErr_Clear ( ) ;
adapted = current_param ;
}
2006-04-01 04:36:27 -04:00
}
2008-03-28 17:08:36 -03:00
rc = pysqlite_statement_bind_parameter ( self , i , adapted , allow_8bit_chars ) ;
2006-04-01 04:36:27 -04:00
Py_DECREF ( adapted ) ;
if ( rc ! = SQLITE_OK ) {
2008-03-28 17:08:36 -03:00
if ( ! PyErr_Occurred ( ) ) {
PyErr_Format ( pysqlite_InterfaceError , " Error binding parameter :%s - probably unsupported type. " , binding_name ) ;
}
2006-04-01 04:36:27 -04:00
return ;
}
}
} else {
2008-02-29 18:08:41 -04:00
PyErr_SetString ( PyExc_ValueError , " parameters are of unsupported type " ) ;
2006-04-01 04:36:27 -04:00
}
}
2007-01-13 21:43:50 -04:00
int pysqlite_statement_recompile ( pysqlite_Statement * self , PyObject * params )
2006-03-31 20:57:31 -04:00
{
const char * tail ;
int rc ;
char * sql_cstr ;
sqlite3_stmt * new_st ;
sql_cstr = PyString_AsString ( self - > sql ) ;
rc = sqlite3_prepare ( self - > db ,
sql_cstr ,
- 1 ,
& new_st ,
& tail ) ;
if ( rc = = SQLITE_OK ) {
2006-04-01 04:36:27 -04:00
/* The efficient sqlite3_transfer_bindings is only available in SQLite
* version 3.2 .2 or later . For older SQLite releases , that might not
* even define SQLITE_VERSION_NUMBER , we do it the manual way .
*/
# ifdef SQLITE_VERSION_NUMBER
# if SQLITE_VERSION_NUMBER >= 3002002
2007-12-11 17:07:40 -04:00
/* The check for the number of parameters is necessary to not trigger a
* bug in certain SQLite versions ( experienced in 3.2 .8 and 3.3 .4 ) . */
if ( sqlite3_bind_parameter_count ( self - > st ) > 0 ) {
( void ) sqlite3_transfer_bindings ( self - > st , new_st ) ;
}
2006-04-01 04:36:27 -04:00
# endif
# else
statement_bind_parameters ( self , params ) ;
# endif
2006-03-31 20:57:31 -04:00
( void ) sqlite3_finalize ( self - > st ) ;
self - > st = new_st ;
}
return rc ;
}
2007-01-13 21:43:50 -04:00
int pysqlite_statement_finalize ( pysqlite_Statement * self )
2006-03-31 20:57:31 -04:00
{
int rc ;
rc = SQLITE_OK ;
if ( self - > st ) {
Py_BEGIN_ALLOW_THREADS
rc = sqlite3_finalize ( self - > st ) ;
Py_END_ALLOW_THREADS
self - > st = NULL ;
}
self - > in_use = 0 ;
return rc ;
}
2007-01-13 21:43:50 -04:00
int pysqlite_statement_reset ( pysqlite_Statement * self )
2006-03-31 20:57:31 -04:00
{
int rc ;
rc = SQLITE_OK ;
if ( self - > in_use & & self - > st ) {
Py_BEGIN_ALLOW_THREADS
rc = sqlite3_reset ( self - > st ) ;
Py_END_ALLOW_THREADS
if ( rc = = SQLITE_OK ) {
self - > in_use = 0 ;
}
}
return rc ;
}
2007-01-13 21:43:50 -04:00
void pysqlite_statement_mark_dirty ( pysqlite_Statement * self )
2006-03-31 20:57:31 -04:00
{
self - > in_use = 1 ;
}
2007-01-13 21:43:50 -04:00
void pysqlite_statement_dealloc ( pysqlite_Statement * self )
2006-03-31 20:57:31 -04:00
{
int rc ;
if ( self - > st ) {
Py_BEGIN_ALLOW_THREADS
rc = sqlite3_finalize ( self - > st ) ;
Py_END_ALLOW_THREADS
}
self - > st = NULL ;
Py_XDECREF ( self - > sql ) ;
2006-04-23 12:24:26 -03:00
if ( self - > in_weakreflist ! = NULL ) {
PyObject_ClearWeakRefs ( ( PyObject * ) self ) ;
}
2007-12-18 22:37:44 -04:00
Py_TYPE ( self ) - > tp_free ( ( PyObject * ) self ) ;
2006-03-31 20:57:31 -04:00
}
/*
* Checks if there is anything left in an SQL string after SQLite compiled it .
* This is used to check if somebody tried to execute more than one SQL command
* with one execute ( ) / executemany ( ) command , which the DB - API and we don ' t
* allow .
*
* Returns 1 if there is more left than should be . 0 if ok .
*/
2007-01-13 21:43:50 -04:00
static int pysqlite_check_remaining_sql ( const char * tail )
2006-03-31 20:57:31 -04:00
{
const char * pos = tail ;
parse_remaining_sql_state state = NORMAL ;
for ( ; ; ) {
switch ( * pos ) {
case 0 :
return 0 ;
case ' - ' :
if ( state = = NORMAL ) {
state = LINECOMMENT_1 ;
} else if ( state = = LINECOMMENT_1 ) {
state = IN_LINECOMMENT ;
}
break ;
case ' ' :
case ' \t ' :
break ;
case ' \n ' :
case 13 :
if ( state = = IN_LINECOMMENT ) {
state = NORMAL ;
}
break ;
case ' / ' :
if ( state = = NORMAL ) {
state = COMMENTSTART_1 ;
} else if ( state = = COMMENTEND_1 ) {
state = NORMAL ;
} else if ( state = = COMMENTSTART_1 ) {
return 1 ;
}
break ;
case ' * ' :
if ( state = = NORMAL ) {
return 1 ;
} else if ( state = = LINECOMMENT_1 ) {
return 1 ;
} else if ( state = = COMMENTSTART_1 ) {
state = IN_COMMENT ;
} else if ( state = = IN_COMMENT ) {
state = COMMENTEND_1 ;
}
break ;
default :
if ( state = = COMMENTEND_1 ) {
state = IN_COMMENT ;
} else if ( state = = IN_LINECOMMENT ) {
} else if ( state = = IN_COMMENT ) {
} else {
return 1 ;
}
}
pos + + ;
}
return 0 ;
}
2007-01-13 21:43:50 -04:00
PyTypeObject pysqlite_StatementType = {
2007-07-21 03:55:02 -03:00
PyVarObject_HEAD_INIT ( NULL , 0 )
2006-04-05 15:25:33 -03:00
MODULE_NAME " .Statement " , /* tp_name */
2007-01-13 21:43:50 -04:00
sizeof ( pysqlite_Statement ) , /* tp_basicsize */
2006-03-31 20:57:31 -04:00
0 , /* tp_itemsize */
2007-01-13 21:43:50 -04:00
( destructor ) pysqlite_statement_dealloc , /* tp_dealloc */
2006-03-31 20:57:31 -04:00
0 , /* tp_print */
0 , /* tp_getattr */
0 , /* tp_setattr */
0 , /* tp_compare */
0 , /* tp_repr */
0 , /* tp_as_number */
0 , /* tp_as_sequence */
0 , /* tp_as_mapping */
0 , /* tp_hash */
0 , /* tp_call */
0 , /* tp_str */
0 , /* tp_getattro */
0 , /* tp_setattro */
0 , /* tp_as_buffer */
2006-04-23 12:24:26 -03:00
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS , /* tp_flags */
2006-03-31 20:57:31 -04:00
0 , /* tp_doc */
0 , /* tp_traverse */
0 , /* tp_clear */
0 , /* tp_richcompare */
2007-01-13 21:43:50 -04:00
offsetof ( pysqlite_Statement , in_weakreflist ) , /* tp_weaklistoffset */
2006-03-31 20:57:31 -04:00
0 , /* tp_iter */
0 , /* tp_iternext */
0 , /* tp_methods */
0 , /* tp_members */
0 , /* tp_getset */
0 , /* tp_base */
0 , /* tp_dict */
0 , /* tp_descr_get */
0 , /* tp_descr_set */
0 , /* tp_dictoffset */
( initproc ) 0 , /* tp_init */
0 , /* tp_alloc */
0 , /* tp_new */
0 /* tp_free */
} ;
2007-01-13 21:43:50 -04:00
extern int pysqlite_statement_setup_types ( void )
2006-03-31 20:57:31 -04:00
{
2007-01-13 21:43:50 -04:00
pysqlite_StatementType . tp_new = PyType_GenericNew ;
return PyType_Ready ( & pysqlite_StatementType ) ;
2006-03-31 20:57:31 -04:00
}