Array quoting (not completely working.)

This commit is contained in:
Federico Di Gregorio 2005-03-23 00:43:36 +00:00
parent def14d5925
commit cddb1a15d4
3 changed files with 71 additions and 30 deletions

View File

@ -26,16 +26,23 @@
#define ASCAN_BEGIN 1 #define ASCAN_BEGIN 1
#define ASCAN_END 2 #define ASCAN_END 2
#define ASCAN_TOKEN 3 #define ASCAN_TOKEN 3
#define ASCAN_QUOTED 4
static int static int
typecast_array_tokenize(unsigned char *str, int strlength, typecast_array_tokenize(unsigned char *str, int strlength,
int *pos, unsigned char** token, int *length) int *pos, unsigned char** token, int *length)
{ {
int i = *pos; int i;
int quoted = 0;
Dprintf("TOKENIZE for %d, pos = %d", strlength, *pos); /* first we check for quotes, used when the content of the item contains
special or quoted characters */
if (str[*pos] == '"') {
quoted = 1;
*pos += 1;
}
while (i < strlength) { for (i = *pos ; i < strlength ; i++) {
switch (str[i]) { switch (str[i]) {
case '{': case '{':
*pos = i+1; *pos = i+1;
@ -48,17 +55,21 @@ typecast_array_tokenize(unsigned char *str, int strlength,
case ',': case ',':
*token = &str[*pos]; *token = &str[*pos];
*length = i - *pos; *length = i - *pos;
if (quoted == 1)
*length -= 1;
*pos = i+1; *pos = i+1;
Dprintf("TOKENIZE pos = %d, length = %d", *pos, *length);
return ASCAN_TOKEN; return ASCAN_TOKEN;
default: default:
i++; /* nothing to do right now */
break;
} }
} }
*token = &str[*pos]; *token = &str[*pos];
*length = i - *pos; *length = i - *pos;
if (quoted == 1)
*length -= 1;
return ASCAN_EOF; return ASCAN_EOF;
} }
@ -89,10 +100,12 @@ typecast_array_scan(unsigned char *str, int strlength,
return 1; return 1;
} }
/** LONGINTEGERARRAY and INTEGERARRAY - cast integers arrays **/
/** GENERIC - a generic typecaster that can be used when no special actions
have to be taken on the single items **/
static PyObject * static PyObject *
typecast_INTEGERARRAY_cast(unsigned char *str, int len, PyObject *curs) typecast_GENERIC_ARRAY_cast(unsigned char *str, int len, PyObject *curs)
{ {
PyObject *obj = NULL; PyObject *obj = NULL;
PyObject *base = ((typecastObject*)((cursorObject*)curs)->caster)->bcast; PyObject *base = ((typecastObject*)((cursorObject*)curs)->caster)->bcast;
@ -114,16 +127,12 @@ typecast_INTEGERARRAY_cast(unsigned char *str, int len, PyObject *curs)
return obj; return obj;
} }
#define typecast_LONGINTEGERARRAY_cast typecast_INTEGERARRAY_cast /** LONGINTEGERARRAY and INTEGERARRAY - cast integers arrays **/
#define typecast_LONGINTEGERARRAY_cast typecast_GENERIC_ARRAY_cast
#define typecast_INTEGERARRAY_cast typecast_GENERIC_ARRAY_cast
/** STRINGARRAY - cast integers arrays **/ /** STRINGARRAY - cast integers arrays **/
static PyObject * #define typecast_STRINGARRAY_cast typecast_GENERIC_ARRAY_cast
typecast_STRINGARRAY_cast(unsigned char *str, int len, PyObject *curs)
{
PyObject* obj = NULL;
if (str == NULL) {Py_INCREF(Py_None); return Py_None;}
return obj;
}

View File

@ -30,8 +30,11 @@ typecast_INTEGER_cast(unsigned char *s, int len, PyObject *curs)
unsigned char buffer[12]; unsigned char buffer[12];
if (s == NULL) {Py_INCREF(Py_None); return Py_None;} if (s == NULL) {Py_INCREF(Py_None); return Py_None;}
if (s[len] != '\0') {
strncpy(buffer, s, len); buffer[len] = '\0'; strncpy(buffer, s, len); buffer[len] = '\0';
return PyInt_FromString(buffer, NULL, 0); s = buffer;
}
return PyInt_FromString(s, NULL, 0);
} }
/** LONGINTEGER - cast long integers (8 bytes) to python long **/ /** LONGINTEGER - cast long integers (8 bytes) to python long **/
@ -42,7 +45,10 @@ typecast_LONGINTEGER_cast(unsigned char *s, int len, PyObject *curs)
unsigned char buffer[24]; unsigned char buffer[24];
if (s == NULL) {Py_INCREF(Py_None); return Py_None;} if (s == NULL) {Py_INCREF(Py_None); return Py_None;}
if (s[len] != '\0') {
strncpy(buffer, s, len); buffer[len] = '\0'; strncpy(buffer, s, len); buffer[len] = '\0';
s = buffer;
}
return PyLong_FromString(s, NULL, 0); return PyLong_FromString(s, NULL, 0);
} }
@ -51,10 +57,14 @@ typecast_LONGINTEGER_cast(unsigned char *s, int len, PyObject *curs)
static PyObject * static PyObject *
typecast_FLOAT_cast(unsigned char *s, int len, PyObject *curs) typecast_FLOAT_cast(unsigned char *s, int len, PyObject *curs)
{ {
/* FIXME: is 64 large enough for any float? */
unsigned char buffer[64]; unsigned char buffer[64];
if (s == NULL) {Py_INCREF(Py_None); return Py_None;} if (s == NULL) {Py_INCREF(Py_None); return Py_None;}
if (s[len] != '\0') {
strncpy(buffer, s, len); buffer[len] = '\0'; strncpy(buffer, s, len); buffer[len] = '\0';
s = buffer;
}
return PyFloat_FromDouble(atof(s)); return PyFloat_FromDouble(atof(s));
} }
@ -144,17 +154,23 @@ static PyObject *
typecast_BINARY_cast(unsigned char *s, int l, PyObject *curs) typecast_BINARY_cast(unsigned char *s, int l, PyObject *curs)
{ {
PyObject *res; PyObject *res;
unsigned char *str, saved; unsigned char *str, *buffer = NULL;
size_t len; size_t len;
if (s == NULL) {Py_INCREF(Py_None); return Py_None;} if (s == NULL) {Py_INCREF(Py_None); return Py_None;}
/* PQunescapeBytea absolutely wants a 0-terminated string and we don't /* PQunescapeBytea absolutely wants a 0-terminated string and we don't
want to copy the whole buffer, right? Wrong... :/ */ want to copy the whole buffer, right? Wrong, but there isn't any other
saved = s[l]; s[l] = '\0'; way :/ */
if (s[l] != '\0') {
if ((buffer = PyMem_Malloc(l+1)) == NULL)
PyErr_NoMemory();
strncpy(buffer, s, l); buffer[l] = '\0';
s = buffer;
}
str = PQunescapeBytea(s, &len); str = PQunescapeBytea(s, &len);
Dprintf("typecast_BINARY_cast: unescaped %d bytes", len); Dprintf("typecast_BINARY_cast: unescaped %d bytes", len);
s[l] = saved; if (buffer) PyMem_Free(buffer);
/* TODO: using a PyBuffer would make this a zero-copy operation but we'll /* TODO: using a PyBuffer would make this a zero-copy operation but we'll
need to define our own buffer-derived object to keep a reference to the need to define our own buffer-derived object to keep a reference to the
@ -196,7 +212,8 @@ typecast_DECIMAL_cast(unsigned char *s, int len, PyObject *curs)
if (s == NULL) {Py_INCREF(Py_None); return Py_None;} if (s == NULL) {Py_INCREF(Py_None); return Py_None;}
buffer = PyMem_Malloc(len+1); if ((buffer = PyMem_Malloc(len+1)) == NULL)
PyErr_NoMemory();
strncpy(buffer, s, len); buffer[len] = '\0'; strncpy(buffer, s, len); buffer[len] = '\0';
res = PyObject_CallFunction(decimalType, "s", buffer); res = PyObject_CallFunction(decimalType, "s", buffer);
PyMem_Free(buffer); PyMem_Free(buffer);

15
sandbox/array.py Normal file
View File

@ -0,0 +1,15 @@
import psycopg
conn = psycopg.connect("dbname=test")
curs = conn.cursor()
curs.execute("SELECT ARRAY[1,2,3] AS foo")
print curs.fetchone()
curs.execute("SELECT ARRAY['1','2','3'] AS foo")
print curs.fetchone()
curs.execute("""SELECT ARRAY['','"',''] AS foo""")
d = curs.fetchone()
print d, '->', d[0][0], d[0][1], d[0][2]