Skip to content

Commit cb9cec5

Browse files
committed
Array support for all basic types.
1 parent 19cb161 commit cb9cec5

File tree

6 files changed

+59
-38
lines changed

6 files changed

+59
-38
lines changed

psycopg/typecast.c

Lines changed: 7 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ typecast_init(PyObject *dict)
116116

117117
Dprintf("typecast_init: initializing %s", typecast_builtins[i].name);
118118

119-
t = (typecastObject *)typecast_from_c(&(typecast_builtins[i]));
119+
t = (typecastObject *)typecast_from_c(&(typecast_builtins[i]), dict);
120120
if (t == NULL) return -1;
121121
if (typecast_add((PyObject *)t, 0) != 0) return -1;
122122

@@ -129,14 +129,14 @@ typecast_init(PyObject *dict)
129129
}
130130

131131
/* create and save a default cast object (but does not register it) */
132-
psyco_default_cast = typecast_from_c(&typecast_default);
132+
psyco_default_cast = typecast_from_c(&typecast_default, dict);
133133

134134
/* register the date/time typecasters with their original names */
135135
#ifdef HAVE_MXDATETIME
136136
for (i = 0; typecast_mxdatetime[i].name != NULL; i++) {
137137
typecastObject *t;
138138
Dprintf("typecast_init: initializing %s", typecast_mxdatetime[i].name);
139-
t = (typecastObject *)typecast_from_c(&(typecast_mxdatetime[i]));
139+
t = (typecastObject *)typecast_from_c(&(typecast_mxdatetime[i]), dict);
140140
if (t == NULL) return -1;
141141
PyDict_SetItem(dict, t->name, (PyObject *)t);
142142
}
@@ -145,7 +145,7 @@ typecast_init(PyObject *dict)
145145
for (i = 0; typecast_pydatetime[i].name != NULL; i++) {
146146
typecastObject *t;
147147
Dprintf("typecast_init: initializing %s", typecast_pydatetime[i].name);
148-
t = (typecastObject *)typecast_from_c(&(typecast_pydatetime[i]));
148+
t = (typecastObject *)typecast_from_c(&(typecast_pydatetime[i]), dict);
149149
if (t == NULL) return -1;
150150
PyDict_SetItem(dict, t->name, (PyObject *)t);
151151
}
@@ -154,26 +154,6 @@ typecast_init(PyObject *dict)
154154
return 0;
155155
}
156156

157-
/* typecast_get_by_name - get a type object by name (slow!) */
158-
159-
static PyObject*
160-
typecast_get_by_name(unsigned char *name)
161-
{
162-
PyObject *value, *res = NULL;
163-
int ppos = 0;
164-
165-
while (PyDict_Next(psyco_types, &ppos, NULL, &value)) {
166-
if (strcmp(PyString_AsString(((typecastObject*)value)->name),
167-
name) == 0) {
168-
res = value;
169-
break;
170-
}
171-
}
172-
173-
/* borrowed reference */
174-
return res;
175-
}
176-
177157
/* typecast_add - add a type object to the dictionary */
178158
int
179159
typecast_add(PyObject *obj, int binary)
@@ -422,15 +402,16 @@ typecast_from_python(PyObject *self, PyObject *args, PyObject *keywds)
422402
}
423403

424404
PyObject *
425-
typecast_from_c(typecastObject_initlist *type)
405+
typecast_from_c(typecastObject_initlist *type, PyObject *dict)
426406
{
427407
PyObject *tuple, *base = NULL;
428408
typecastObject *obj;
429409
int i, len = 0;
430410

431411
/* before doing anything else we look for the base */
432412
if (type->base) {
433-
base = typecast_get_by_name(type->base);
413+
/* NOTE: base is a borrowed reference! */
414+
base = PyDict_GetItemString(dict, type->base);
434415
if (!base) {
435416
PyErr_Format(Error, "typecast base not found: %s", type->base);
436417
return NULL;

psycopg/typecast.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ extern int typecast_init(PyObject *dict);
7272
extern int typecast_add(PyObject *obj, int binary);
7373

7474
/* the C callable typecastObject creator function */
75-
extern PyObject *typecast_from_c(typecastObject_initlist *type);
75+
extern PyObject *typecast_from_c(typecastObject_initlist *type, PyObject *d);
7676

7777
/* the python callable typecast creator function */
7878
extern PyObject *typecast_from_python(

psycopg/typecast_array.c

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -203,12 +203,18 @@ typecast_GENERIC_ARRAY_cast(unsigned char *str, int len, PyObject *curs)
203203
return obj;
204204
}
205205

206-
/** LONGINTEGERARRAY and INTEGERARRAY - cast integers arrays **/
206+
/** almost all the basic array typecasters are derived from GENERIC **/
207207

208208
#define typecast_LONGINTEGERARRAY_cast typecast_GENERIC_ARRAY_cast
209209
#define typecast_INTEGERARRAY_cast typecast_GENERIC_ARRAY_cast
210-
211-
/** STRINGARRAY - cast integers arrays **/
212-
210+
#define typecast_FLOATARRAY_cast typecast_GENERIC_ARRAY_cast
211+
#define typecast_DECIMALARRAY_cast typecast_GENERIC_ARRAY_cast
213212
#define typecast_STRINGARRAY_cast typecast_GENERIC_ARRAY_cast
214-
213+
#define typecast_UNICODEARRAY_cast typecast_GENERIC_ARRAY_cast
214+
#define typecast_BOOLEANARRAY_cast typecast_GENERIC_ARRAY_cast
215+
#define typecast_DATETIMEARRAY_cast typecast_GENERIC_ARRAY_cast
216+
#define typecast_DATEARRAY_cast typecast_GENERIC_ARRAY_cast
217+
#define typecast_TIMEARRAY_cast typecast_GENERIC_ARRAY_cast
218+
#define typecast_INTERVALARRAY_cast typecast_GENERIC_ARRAY_cast
219+
#define typecast_BINARYARRAY_cast typecast_GENERIC_ARRAY_cast
220+
#define typecast_ROWIDARRAY_cast typecast_GENERIC_ARRAY_cast

psycopg/typecast_builtins.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,17 @@ static long int typecast_BINARY_types[] = {17, 0};
1414
static long int typecast_ROWID_types[] = {26, 0};
1515
static long int typecast_LONGINTEGERARRAY_types[] = {1016, 0};
1616
static long int typecast_INTEGERARRAY_types[] = {1005, 1006, 1007, 0};
17+
static long int typecast_FLOATARRAY_types[] = {1017, 1021, 1022, 0};
18+
static long int typecast_DECIMALARRAY_types[] = {1231, 0};
19+
static long int typecast_UNICODEARRAY_types[] = {1002, 1003, 1009, 1014, 1015, 0};
1720
static long int typecast_STRINGARRAY_types[] = {1002, 1003, 1009, 1014, 1015, 0};
21+
static long int typecast_BOOLEANARRAY_types[] = {1000, 0};
22+
static long int typecast_DATETIMEARRAY_types[] = {1115, 1185, 0};
23+
static long int typecast_TIMEARRAY_types[] = {1183, 1270, 0};
24+
static long int typecast_DATEARRAY_types[] = {1182, 0};
25+
static long int typecast_INTERVALARRAY_types[] = {1187, 0};
26+
static long int typecast_BINARYARRAY_types[] = {1001, 0};
27+
static long int typecast_ROWIDARRAY_types[] = {1028, 1013, 0};
1828

1929

2030
typecastObject_initlist typecast_builtins[] = {
@@ -34,7 +44,17 @@ typecastObject_initlist typecast_builtins[] = {
3444
{"ROWID", typecast_ROWID_types, typecast_ROWID_cast, NULL},
3545
{"LONGINTEGERARRAY", typecast_LONGINTEGERARRAY_types, typecast_LONGINTEGERARRAY_cast, "LONGINTEGER"},
3646
{"INTEGERARRAY", typecast_INTEGERARRAY_types, typecast_INTEGERARRAY_cast, "INTEGER"},
47+
{"FLOATARRAY", typecast_FLOATARRAY_types, typecast_FLOATARRAY_cast, "FLOAT"},
48+
{"DECIMALARRAY", typecast_DECIMALARRAY_types, typecast_DECIMALARRAY_cast, "DECIMAL"},
49+
{"UNICODEARRAY", typecast_UNICODEARRAY_types, typecast_UNICODEARRAY_cast, "UNICODE"},
3750
{"STRINGARRAY", typecast_STRINGARRAY_types, typecast_STRINGARRAY_cast, "STRING"},
51+
{"BOOLEANARRAY", typecast_BOOLEANARRAY_types, typecast_BOOLEANARRAY_cast, "BOOLEAN"},
52+
{"DATETIMEARRAY", typecast_DATETIMEARRAY_types, typecast_DATETIMEARRAY_cast, "DATETIME"},
53+
{"TIMEARRAY", typecast_TIMEARRAY_types, typecast_TIMEARRAY_cast, "TIME"},
54+
{"DATEARRAY", typecast_DATEARRAY_types, typecast_DATEARRAY_cast, "DATE"},
55+
{"INTERVALARRAY", typecast_INTERVALARRAY_types, typecast_INTERVALARRAY_cast, "INTERVAL"},
56+
{"BINARYARRAY", typecast_BINARYARRAY_types, typecast_BINARYARRAY_cast, "BINARY"},
57+
{"ROWIDARRAY", typecast_ROWIDARRAY_types, typecast_ROWIDARRAY_cast, "ROWID"},
3858
{NULL, NULL, NULL, NULL}
3959
};
4060

sandbox/array.py

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,18 @@
44
curs = conn.cursor()
55

66
curs.execute("SELECT ARRAY[1,2,3] AS foo")
7-
print curs.fetchone()
7+
print curs.fetchone()[0]
88

99
curs.execute("SELECT ARRAY['1','2','3'] AS foo")
10-
print curs.fetchone()
10+
print curs.fetchone()[0]
1111

1212
curs.execute("""SELECT ARRAY[',','"','\\\\'] AS foo""")
13-
d = curs.fetchone()
14-
print d, '->', d[0][0], d[0][1], d[0][2]
13+
d = curs.fetchone()[0]
14+
print d, '->', d[0], d[1], d[2]
1515

1616
curs.execute("SELECT ARRAY[ARRAY[1,2],ARRAY[3,4]] AS foo")
17-
print curs.fetchone()
17+
print curs.fetchone()[0]
18+
19+
curs.execute("SELECT ARRAY['20:00:01'::time] AS foo")
20+
print curs.description
21+
print curs.fetchone()[0]

scripts/buildtypes.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,17 @@
5353
# from postgresql headers; we'll have to do it hard-coding :/
5454
array_types = (['LONGINTEGER', [1016]],
5555
['INTEGER', [1005, 1006, 1007]],
56-
['STRING', [1002, 1003, 1009, 1014, 1015]])
56+
['FLOAT', [1017, 1021, 1022]],
57+
['DECIMAL', [1231]],
58+
['UNICODE', [1002, 1003, 1009, 1014, 1015]],
59+
['STRING', [1002, 1003, 1009, 1014, 1015]],
60+
['BOOLEAN', [1000]],
61+
['DATETIME', [1115, 1185]],
62+
['TIME', [1183, 1270]],
63+
['DATE', [1182]],
64+
['INTERVAL', [1187]],
65+
['BINARY', [1001]],
66+
['ROWID', [1028, 1013]])
5767

5868
# this is the header used to compile the data in the C module
5969
HEADER = """

0 commit comments

Comments
 (0)