Added support for NULL in arrays (closes: #154)

This commit is contained in:
Federico Di Gregorio 2007-01-19 14:08:06 +00:00
parent 2883428791
commit 1c16009985
5 changed files with 37 additions and 14 deletions

View File

@ -1,6 +1,11 @@
2007-01-19 Federico Di Gregorio <fog@initd.org> 2007-01-19 Federico Di Gregorio <fog@initd.org>
* Release 2.0.6 beta 1. * psycopg/adapt_list.c: added support for None. And this closes
the other half.
* psycopg/typecast_array.c: added support for detecting the NULL
special string and converting it as a real NULL if not enclosed in
quotes. This closes half of #154.
2007-01-16 Federico Di Gregorio <fog@initd.org> 2007-01-16 Federico Di Gregorio <fog@initd.org>

View File

@ -51,9 +51,13 @@ list_quote(listObject *self)
tmp = PyTuple_New(len); tmp = PyTuple_New(len);
for (i=0; i<len; i++) { for (i=0; i<len; i++) {
PyObject *quoted = PyObject *quoted;
microprotocol_getquoted(PyList_GET_ITEM(self->wrapped, i), PyObject *wrapped = PyList_GET_ITEM(self->wrapped, i);
(connectionObject*)self->connection); if (wrapped == Py_None)
quoted = PyString_FromString("NULL");
else
quoted = microprotocol_getquoted(wrapped,
(connectionObject*)self->connection);
if (quoted == NULL) goto error; if (quoted == NULL) goto error;
/* here we don't loose a refcnt: SET_ITEM does not change the /* here we don't loose a refcnt: SET_ITEM does not change the

View File

@ -54,7 +54,7 @@ typecast_array_cleanup(char **str, int *len)
static int static int
typecast_array_tokenize(char *str, int strlength, typecast_array_tokenize(char *str, int strlength,
int *pos, char** token, int *length) int *pos, char** token, int *length, int *quotes)
{ {
/* FORTRAN glory */ /* FORTRAN glory */
int i, j, q, b, l, res; int i, j, q, b, l, res;
@ -117,10 +117,12 @@ typecast_array_tokenize(char *str, int strlength,
tokenize: tokenize:
/* remove initial quoting character and calculate raw length */ /* remove initial quoting character and calculate raw length */
*quotes = 0;
l = i - *pos; l = i - *pos;
if (str[*pos] == '"') { if (str[*pos] == '"') {
*pos += 1; *pos += 1;
l -= 2; l -= 2;
*quotes = 1;
} }
if (res == ASCAN_QUOTED) { if (res == ASCAN_QUOTED) {
@ -155,7 +157,7 @@ static int
typecast_array_scan(char *str, int strlength, typecast_array_scan(char *str, int strlength,
PyObject *curs, PyObject *base, PyObject *array) PyObject *curs, PyObject *base, PyObject *array)
{ {
int state, length = 0, pos = 0; int state, quotes, length = 0, pos = 0;
char *token; char *token;
PyObject *stack[MAX_DIMENSIONS]; PyObject *stack[MAX_DIMENSIONS];
@ -163,11 +165,20 @@ typecast_array_scan(char *str, int strlength,
while (1) { while (1) {
token = NULL; token = NULL;
state = typecast_array_tokenize(str, strlength, &pos, &token, &length); state = typecast_array_tokenize(str, strlength,
&pos, &token, &length, &quotes);
Dprintf("typecast_array_scan: state = %d, length = %d, token = '%s'", Dprintf("typecast_array_scan: state = %d, length = %d, token = '%s'",
state, length, token); state, length, token);
if (state == ASCAN_TOKEN || state == ASCAN_QUOTED) { if (state == ASCAN_TOKEN || state == ASCAN_QUOTED) {
PyObject *obj = typecast_cast(base, token, length, curs); PyObject *obj;
if (!quotes && length == 4
&& (token[0] == 'n' || token[0] == 'N')
&& (token[1] == 'u' || token[1] == 'U')
&& (token[2] == 'l' || token[2] == 'L')
&& (token[3] == 'l' || token[3] == 'L'))
obj = typecast_cast(base, NULL, 0, curs);
else
obj = typecast_cast(base, token, length, curs);
/* before anything else we free the memory */ /* before anything else we free the memory */
if (state == ASCAN_QUOTED) PyMem_Free(token); if (state == ASCAN_QUOTED) PyMem_Free(token);

View File

@ -1,6 +1,6 @@
import psycopg2 import psycopg2
conn = psycopg2.connect("dbname=test") conn = psycopg2.connect("port=5433 dbname=test")
curs = conn.cursor() curs = conn.cursor()
#curs.execute("SELECT ARRAY[1,2,3] AS foo") #curs.execute("SELECT ARRAY[1,2,3] AS foo")
@ -20,9 +20,12 @@ curs = conn.cursor()
#print curs.description #print curs.description
#print curs.fetchone()[0] #print curs.fetchone()[0]
curs.execute("SELECT 1 AS foo, ARRAY[1,2] AS bar") #curs.execute("SELECT 1 AS foo, ARRAY[1,2] AS bar")
print curs.fetchone() #print curs.fetchone()
curs.execute("SELECT * FROM test()") #curs.execute("SELECT * FROM test()")
#print curs.fetchone()
curs.execute("SELECT %s", ([1,2,None],))
print curs.fetchone() print curs.fetchone()

View File

@ -1,5 +1,5 @@
[build_ext] [build_ext]
define=PSYCOPG_EXTENSIONS,PSYCOPG_DISPLAY_SIZE,PSYCOPG_NEW_BOOLEAN,HAVE_PQFREEMEM,HAVE_PQPROTOCOL3 define=PSYCOPG_DEBUG,PSYCOPG_EXTENSIONS,PSYCOPG_DISPLAY_SIZE,PSYCOPG_NEW_BOOLEAN,HAVE_PQFREEMEM,HAVE_PQPROTOCOL3
# PSYCOPG_EXTENSIONS enables extensions to PEP-249 (you really want this) # PSYCOPG_EXTENSIONS enables extensions to PEP-249 (you really want this)
# PSYCOPG_DISPLAY_SIZE enable display size calculation (a little slower) # PSYCOPG_DISPLAY_SIZE enable display size calculation (a little slower)
# HAVE_PQFREEMEM should be defined on PostgreSQL >= 7.4 # HAVE_PQFREEMEM should be defined on PostgreSQL >= 7.4