informixdb-cvs Mailing List for InformixDB (Page 3)
Brought to you by:
chaese,
f-apolloner
You can subscribe to this list here.
2005 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
(36) |
Nov
(40) |
Dec
(6) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2006 |
Jan
(1) |
Feb
|
Mar
(6) |
Apr
(3) |
May
|
Jun
|
Jul
|
Aug
|
Sep
(13) |
Oct
(12) |
Nov
(10) |
Dec
(8) |
2007 |
Jan
|
Feb
(1) |
Mar
(1) |
Apr
|
May
|
Jun
(5) |
Jul
|
Aug
(1) |
Sep
(4) |
Oct
(15) |
Nov
|
Dec
(1) |
2008 |
Jan
|
Feb
(1) |
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
(2) |
Sep
(5) |
Oct
|
Nov
|
Dec
|
2011 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
(4) |
Dec
|
2012 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
(3) |
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: Carsten H. <ch...@us...> - 2006-12-02 01:50:47
|
Update of /cvsroot/informixdb/informixdb/doc In directory sc8-pr-cvs2.sourceforge.net:/tmp/cvs-serv1134 Modified Files: manual.txt Log Message: Doc update, set release date Index: manual.txt =================================================================== RCS file: /cvsroot/informixdb/informixdb/doc/manual.txt,v retrieving revision 1.15 retrieving revision 1.16 diff -C2 -d -r1.15 -r1.16 *** manual.txt 11 Nov 2006 22:36:39 -0000 1.15 --- manual.txt 2 Dec 2006 01:50:46 -0000 1.16 *************** *** 5,9 **** :Authors: Daniel Smertnig and Carsten Haese :Version: informixdb 2.4 ! :Date: TBD :Homepage: `InformixDB on Sourceforge`_ --- 5,9 ---- :Authors: Daniel Smertnig and Carsten Haese :Version: informixdb 2.4 ! :Date: 2006-12-02 :Homepage: `InformixDB on Sourceforge`_ *************** *** 293,296 **** --- 293,300 ---- >>> cursor.execute(cursor.command, params2) + `New in version 2.4`: You may pass `None` instead of `cursor.command` to + execute the previously prepared query. This reduces code clutter if your + cursor instances have long names. + Using named cursors ------------------- |
From: Carsten H. <ch...@us...> - 2006-11-13 15:47:53
|
Update of /cvsroot/informixdb/informixdb In directory sc8-pr-cvs2.sourceforge.net:/tmp/cvs-serv17595 Modified Files: informixdb.py Log Message: Implement mapping interface for Row objects so that they can be supplied as parameter packets for queries with named parameters. Index: informixdb.py =================================================================== RCS file: /cvsroot/informixdb/informixdb/informixdb.py,v retrieving revision 1.17 retrieving revision 1.18 diff -C2 -d -r1.17 -r1.18 *** informixdb.py 11 Nov 2006 22:36:39 -0000 1.17 --- informixdb.py 13 Nov 2006 15:47:44 -0000 1.18 *************** *** 54,57 **** --- 54,58 ---- def __repr__(self): return repr(self.__dict__) def __str__(self): return str(self.__dict__) + def __getitem__(self,k): return self.__dict__[k] class IntervalYearToMonth(object): |
From: Carsten H. <ch...@us...> - 2006-11-13 15:46:03
|
Update of /cvsroot/informixdb/informixdb/ext In directory sc8-pr-cvs2.sourceforge.net:/tmp/cvs-serv15691/ext Modified Files: _informixdb.ec Log Message: To allow duck-typing, named parameters should be allowed to come from any mapping, not just dictionaries. Also, only inspect the length of the parameter object when we actually need it, since it could be a mapping that doesn't specify a length, but for named parameters we don't care about how many there are as long as the right keys are there. Index: _informixdb.ec =================================================================== RCS file: /cvsroot/informixdb/informixdb/ext/_informixdb.ec,v retrieving revision 1.81 retrieving revision 1.82 diff -C2 -d -r1.81 -r1.82 *** _informixdb.ec 11 Nov 2006 22:36:39 -0000 1.81 --- _informixdb.ec 13 Nov 2006 15:45:59 -0000 1.82 *************** *** 491,495 **** 'command' attribute as the operation.\n\ \n\ ! 'parameters' is a sequence or dictionary of values to be bound to\n\ the placeholders in the SQL statement. For sequences, the number\n\ of values must exactly match the number of parameters required by\n\ --- 491,495 ---- 'command' attribute as the operation.\n\ \n\ ! 'parameters' is a sequence or mapping of values to be bound to\n\ the placeholders in the SQL statement. For sequences, the number\n\ of values must exactly match the number of parameters required by\n\ *************** *** 507,513 **** The 'operation' parameter is the same as for execute.\n\ 'seq_of_parameters' is an sequence of parameter sequences or\n\ ! dictionaries suitable for passing to execute(). The operation will\n\ be prepared once and then executes for all parameter sequences or\n\ ! dictionaries in 'seq_of_parameters'.\n\ \n\ For insert statements, executemany() will use an insert cursor\n\ --- 507,513 ---- The 'operation' parameter is the same as for execute.\n\ 'seq_of_parameters' is an sequence of parameter sequences or\n\ ! mappings suitable for passing to execute(). The operation will\n\ be prepared once and then executes for all parameter sequences or\n\ ! mappings in 'seq_of_parameters'.\n\ \n\ For insert statements, executemany() will use an insert cursor\n\ *************** *** 1575,1592 **** { struct sqlvar_struct *var = cur->daIn.sqlvar; - int n_vars = vars ? (int)PyObject_Length(vars) : 0; int i; - int maxp=0; if (PyList_Size(cur->named_params)) { /* If cur->named_params is not empty, the statement is using named ! parameters, so the vars must be supplied in a dictionary. ! Note that we allow the vars dictionary to contain more keys than the statement needs. This is analogous to string%dict interpolation, and it allows passing locals() as the parameter ! dictionary. */ ! if (vars && !PyDict_Check(vars)) { ! PyErr_SetString(PyExc_TypeError, "SQL parameters are not a dictionary"); return 0; } --- 1575,1590 ---- { struct sqlvar_struct *var = cur->daIn.sqlvar; int i; if (PyList_Size(cur->named_params)) { /* If cur->named_params is not empty, the statement is using named ! parameters, so the vars must be supplied in a mapping. ! Note that we allow the vars mapping to contain more keys than the statement needs. This is analogous to string%dict interpolation, and it allows passing locals() as the parameter ! mapping. */ ! if (vars && !PyMapping_Check(vars)) { ! PyErr_SetString(PyExc_TypeError, "SQL parameters are not a mapping"); return 0; } *************** *** 1596,1608 **** PyObject *parmname = PyList_GetItem(cur->named_params, cur->parmIdx[i]); /* Get the corresponding value from the dictionary. */ ! PyObject *item = PyDict_GetItem(vars, parmname); if (!item) { ! /* PyDict_GetItem doesn't set an exception, so we'll raise KeyError. */ ! PyErr_SetObject(PyExc_KeyError, parmname); ! /* PyList_GetItem and PyDict_GetItem borrow the references ! to their result, so no decref necessary here. */ return 0; } success = (*ibindFcn(item))(var++, item); if (!success) return 0; --- 1594,1605 ---- PyObject *parmname = PyList_GetItem(cur->named_params, cur->parmIdx[i]); /* Get the corresponding value from the dictionary. */ ! PyObject *item = PyObject_GetItem(vars, parmname); if (!item) { ! /* PyList_GetItem borrows the reference to its result, no decref ! on parmname necessary. */ return 0; } success = (*ibindFcn(item))(var++, item); + Py_DECREF(item); if (!success) return 0; *************** *** 1610,1613 **** --- 1607,1612 ---- } else { + int n_vars = vars ? (int)PyObject_Length(vars) : 0; + int maxp=0; /* The statement is using positional parameters */ if (vars && !PySequence_Check(vars)) { |
From: Carsten H. <ch...@us...> - 2006-11-11 22:36:41
|
Update of /cvsroot/informixdb/informixdb In directory sc8-pr-cvs2.sourceforge.net:/tmp/cvs-serv4691 Modified Files: README informixdb.py setup.py Log Message: Document new features; getting closer to version 2.4 Index: README =================================================================== RCS file: /cvsroot/informixdb/informixdb/README,v retrieving revision 1.15 retrieving revision 1.16 diff -C2 -d -r1.15 -r1.16 *** README 1 Oct 2006 03:22:48 -0000 1.15 --- README 11 Nov 2006 22:36:39 -0000 1.16 *************** *** 2,6 **** ============ ! This is informixdb 2.3, an Informix implementation of the Python Database API. This release implements version 2.0 of the DB-API: --- 2,6 ---- ============ ! This is informixdb 2.4, an Informix implementation of the Python Database API. This release implements version 2.0 of the DB-API: *************** *** 77,80 **** --- 77,85 ---- ==== + From 2.3 to 2.4: + - Implement 'named' parameter style to optionally bind query parameters + by name + - Implement option to retrieve opaque types in their binary representation + From 2.2 to 2.3: - Allow parameter list for executemany() to be arbitrary iterable objects. *************** *** 274,277 **** --- 279,283 ---- 2.2 2006-03-26 Carsten Haese 2.3 2006-10-01 Carsten Haese + 2.4 TBD Carsten Haese -- Index: setup.py =================================================================== RCS file: /cvsroot/informixdb/informixdb/setup.py,v retrieving revision 1.14 retrieving revision 1.15 diff -C2 -d -r1.14 -r1.15 *** setup.py 18 Sep 2006 18:53:40 -0000 1.14 --- setup.py 11 Nov 2006 22:36:39 -0000 1.15 *************** *** 217,222 **** setup (name = 'InformixDB', ! version = '2.3', ! description = 'InformixDB v2.3', long_description = \ "InformixDB is a DB-API 2.0 compliant interface for IBM Informix\n" --- 217,222 ---- setup (name = 'InformixDB', ! version = '2.4', ! description = 'InformixDB v2.4', long_description = \ "InformixDB is a DB-API 2.0 compliant interface for IBM Informix\n" Index: informixdb.py =================================================================== RCS file: /cvsroot/informixdb/informixdb/informixdb.py,v retrieving revision 1.16 retrieving revision 1.17 diff -C2 -d -r1.16 -r1.17 *** informixdb.py 13 Sep 2006 04:13:46 -0000 1.16 --- informixdb.py 11 Nov 2006 22:36:39 -0000 1.17 *************** *** 47,51 **** """ ! version = "2.3" class Row(object): --- 47,51 ---- """ ! version = "2.4" class Row(object): |
From: Carsten H. <ch...@us...> - 2006-11-11 22:36:41
|
Update of /cvsroot/informixdb/informixdb/ext In directory sc8-pr-cvs2.sourceforge.net:/tmp/cvs-serv4691/ext Modified Files: _informixdb.ec Log Message: Document new features; getting closer to version 2.4 Index: _informixdb.ec =================================================================== RCS file: /cvsroot/informixdb/informixdb/ext/_informixdb.ec,v retrieving revision 1.80 retrieving revision 1.81 diff -C2 -d -r1.80 -r1.81 *** _informixdb.ec 11 Nov 2006 21:19:57 -0000 1.80 --- _informixdb.ec 11 Nov 2006 22:36:39 -0000 1.81 *************** *** 484,499 **** Execute an arbitrary SQL statement.\n\n\ 'operation' is a string containing the SQL statements with optional\n\ ! placeholders, where either qmark-style\n\ ! (SELECT * FROM names WHERE name = ?) or numeric-style\n\ ! (SELECT * FROM names WHERE name = :1) may be used.\n\ \n\ To execute a previously prepared statement or to re-execute\n\ ! a previously executed statement, pass the cursor's 'command'\n\ ! attribute as the operation.\n\ \n\ ! 'parameters' is a sequence of values to be bound to the\n\ ! placeholders in the SQL statement. The number of values in the\n\ ! sequence must match the number of parameters required by the SQL\n\ ! statement exactly. The data types which are used for binding are\n\ automatically derived from the Python types. For strings and\n\ integers this is straightforward. For binding date, time, datetime,\n\ --- 484,498 ---- Execute an arbitrary SQL statement.\n\n\ 'operation' is a string containing the SQL statements with optional\n\ ! parameter placeholders, where either qmark, numeric, or named style\n\ ! may be used. Parameter styles must not be mixed in one statement.\n\ \n\ To execute a previously prepared statement or to re-execute\n\ ! a previously executed statement, pass None or the cursor's\n\ ! 'command' attribute as the operation.\n\ \n\ ! 'parameters' is a sequence or dictionary of values to be bound to\n\ ! the placeholders in the SQL statement. For sequences, the number\n\ ! of values must exactly match the number of parameters required by\n\ ! the SQL statement. The data types which are used for binding are\n\ automatically derived from the Python types. For strings and\n\ integers this is straightforward. For binding date, time, datetime,\n\ *************** *** 507,513 **** \n\ The 'operation' parameter is the same as for execute.\n\ ! 'seq_of_parameters' is a sequence of parameter sequences suitable\n\ ! for passing to execute(). The operation will be prepared once and\n\ ! then executes for all parameter sequences in 'seq_of_parameters'.\n\ \n\ For insert statements, executemany() will use an insert cursor\n\ --- 506,513 ---- \n\ The 'operation' parameter is the same as for execute.\n\ ! 'seq_of_parameters' is an sequence of parameter sequences or\n\ ! dictionaries suitable for passing to execute(). The operation will\n\ ! be prepared once and then executes for all parameter sequences or\n\ ! dictionaries in 'seq_of_parameters'.\n\ \n\ For insert statements, executemany() will use an insert cursor\n\ |
From: Carsten H. <ch...@us...> - 2006-11-11 22:36:41
|
Update of /cvsroot/informixdb/informixdb/doc In directory sc8-pr-cvs2.sourceforge.net:/tmp/cvs-serv4691/doc Modified Files: manual.txt Log Message: Document new features; getting closer to version 2.4 Index: manual.txt =================================================================== RCS file: /cvsroot/informixdb/informixdb/doc/manual.txt,v retrieving revision 1.14 retrieving revision 1.15 diff -C2 -d -r1.14 -r1.15 *** manual.txt 8 Oct 2006 04:42:42 -0000 1.14 --- manual.txt 11 Nov 2006 22:36:39 -0000 1.15 *************** *** 130,133 **** --- 130,149 ---- >>> cursor.callproc('lower', ('FOO',)) + `New in version 2.4`: Parameters may also be specified using ``named`` + style, in which case the arguments must be a dictionary whose keys + correspond to the parameter names:: + + >>> cursor.execute('INSERT INTO names VALUES(:first,:last,:age)', + ... dict(first='some', last='body', age=56) ) + + If a parameter name is not in the dictionary, a KeyError will be raised. + However, the dictionary may contain more keys than the statement needs. + This allows, for example, to simply pass ``locals()`` to bind all + parameters from correspondingly named variables. + + Note: While it is perfectly acceptable to execute different statements + with different parameter styles, mixing parameter styles in the same + statement is not allowed. + Getting results --------------- |
From: Carsten H. <ch...@us...> - 2006-11-11 22:35:26
|
Update of /cvsroot/informixdb/informixdb/doc In directory sc8-pr-cvs2.sourceforge.net:/tmp/cvs-serv3647/doc Modified Files: Makefile Log Message: Apparently rst2html.py is now just rst2html Index: Makefile =================================================================== RCS file: /cvsroot/informixdb/informixdb/doc/Makefile,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** Makefile 23 Oct 2005 02:28:55 -0000 1.1 --- Makefile 11 Nov 2006 22:35:24 -0000 1.2 *************** *** 2,4 **** # (requires docutils) manual.html: manual.txt ! rst2html.py --stylesheet-path=informixdb.css manual.txt >manual.html --- 2,4 ---- # (requires docutils) manual.html: manual.txt ! rst2html --stylesheet-path=informixdb.css manual.txt >manual.html |
From: Carsten H. <ch...@us...> - 2006-11-11 21:19:59
|
Update of /cvsroot/informixdb/informixdb/ext In directory sc8-pr-cvs2.sourceforge.net:/tmp/cvs-serv5771/ext Modified Files: _informixdb.ec Log Message: Make parsing logic for named parameters a bit clearer, prevent doParse from interpreting ::-casts as named parameters, and raise error for mixing named and positional parameters during the parse step instead of during the bind step. Index: _informixdb.ec =================================================================== RCS file: /cvsroot/informixdb/informixdb/ext/_informixdb.ec,v retrieving revision 1.79 retrieving revision 1.80 diff -C2 -d -r1.79 -r1.80 *** _informixdb.ec 11 Nov 2006 05:53:00 -0000 1.79 --- _informixdb.ec 11 Nov 2006 21:19:57 -0000 1.80 *************** *** 1153,1160 **** int parmCount; int parmIdx; - int isParm; char state; char prev; const char *parmName; } parseContext; --- 1153,1160 ---- int parmCount; int parmIdx; char state; char prev; const char *parmName; + int parmLen; } parseContext; *************** *** 1168,1171 **** --- 1168,1172 ---- ct->prev = '\0'; ct->parmName = 0; + ct->parmLen = 0; } *************** *** 1177,1181 **** register char ch; - ct->isParm = 0; while ( (ch = *in++) ) { if (ct->state == ch) { --- 1178,1181 ---- *************** *** 1187,1194 **** ct->parmIdx = ct->parmCount; ct->parmCount++; - ct->isParm = 1; rc = 1; break; ! } else if ((ch == ':') && !isalnum(ct->prev)) { const char *m = in; int n = 0; --- 1187,1193 ---- ct->parmIdx = ct->parmCount; ct->parmCount++; rc = 1; break; ! } else if ((ch == ':') && !isalnum(ct->prev) && ct->prev!=':') { const char *m = in; int n = 0; *************** *** 1203,1207 **** ct->parmCount++; in = m; - ct->isParm = 1; ct->prev = '0'; rc = 1; --- 1202,1205 ---- *************** *** 1209,1222 **** } } ! else { while (isalnum(*m) || *m=='_') { n++; m++; } if (n) { ! ct->parmIdx = -n; ct->parmName = in; ct->parmCount++; in = m; - ct->isParm = 1; ct->prev = '0'; rc = 1; --- 1207,1220 ---- } } ! if (isalpha(*m) || *m=='_') { while (isalnum(*m) || *m=='_') { n++; m++; } if (n) { ! ct->parmIdx = -1; ct->parmName = in; + ct->parmLen = n; ct->parmCount++; in = m; ct->prev = '0'; rc = 1; *************** *** 1521,1525 **** int i, n_slots; struct sqlvar_struct *var; ! short *ind; n_slots = PARM_COUNT_GUESS; --- 1519,1523 ---- int i, n_slots; struct sqlvar_struct *var; ! short *ind, have_named=0, have_positional=0; n_slots = PARM_COUNT_GUESS; *************** *** 1529,1541 **** while (doParse(&ctx)) { if (ctx.parmIdx >= 0) { cur->parmIdx[ctx.parmCount-1] = ctx.parmIdx; } else { PyObject *parmname; ! parmname = PyString_FromStringAndSize(ctx.parmName,-ctx.parmIdx); if (PyList_Append(cur->named_params, parmname)==-1) { return 0; } ! cur->parmIdx[ctx.parmCount-1] = -PyList_Size(cur->named_params); } if (ctx.parmCount == n_slots) { --- 1527,1545 ---- while (doParse(&ctx)) { if (ctx.parmIdx >= 0) { + /* non-negative parmIdx is a positional parameter (? or :<num>) */ cur->parmIdx[ctx.parmCount-1] = ctx.parmIdx; + have_positional = 1; } else { + /* negative parmIdx indicates a named parameter (:<name>), + the name is stored in parmName/parmLen of the parseContext. + */ PyObject *parmname; ! parmname = PyString_FromStringAndSize(ctx.parmName,ctx.parmLen); if (PyList_Append(cur->named_params, parmname)==-1) { return 0; } ! cur->parmIdx[ctx.parmCount-1] = ctx.parmCount-1; ! have_named = 1; } if (ctx.parmCount == n_slots) { *************** *** 1545,1548 **** --- 1549,1560 ---- } + if (have_positional && have_named) { + PyErr_SetString(PyExc_TypeError, + "can't mix named parameters and positional parameters"); + free(cur->parmIdx); + cur->parmIdx = NULL; + return 0; + } + if (ctx.parmCount == 0) { free(cur->parmIdx); *************** *** 1568,1571 **** --- 1580,1590 ---- if (PyList_Size(cur->named_params)) { + /* If cur->named_params is not empty, the statement is using named + parameters, so the vars must be supplied in a dictionary. + Note that we allow the vars dictionary to contain more keys + than the statement needs. This is analogous to string%dict + interpolation, and it allows passing locals() as the parameter + dictionary. + */ if (vars && !PyDict_Check(vars)) { PyErr_SetString(PyExc_TypeError, "SQL parameters are not a dictionary"); *************** *** 1573,1600 **** } for (i = 0; i < cur->daIn.sqld; ++i) { ! if (cur->parmIdx[i] >= 0) { ! PyErr_SetString(PyExc_TypeError, ! "can't mix named parameters and positional parameters"); ! return 0; ! } ! else { ! int success; ! PyObject *parmname = PyList_GetItem(cur->named_params, ! -cur->parmIdx[i]-1); ! PyObject *item = PyDict_GetItem(vars, parmname); /* PyList_GetItem and PyDict_GetItem borrow the references to their result, so no decref necessary here. */ ! if (!item) { ! /* PyDict_GetItem doesn't set an exception. */ ! PyErr_SetObject(PyExc_KeyError, parmname); ! return 0; ! } ! success = (*ibindFcn(item))(var++, item); ! if (!success) ! return 0; } } } else { if (vars && !PySequence_Check(vars)) { PyErr_SetString(PyExc_TypeError, "SQL parameters are not a sequence"); --- 1592,1614 ---- } for (i = 0; i < cur->daIn.sqld; ++i) { ! int success; ! /* Look up the i-th parameter name */ ! PyObject *parmname = PyList_GetItem(cur->named_params, cur->parmIdx[i]); ! /* Get the corresponding value from the dictionary. */ ! PyObject *item = PyDict_GetItem(vars, parmname); ! if (!item) { ! /* PyDict_GetItem doesn't set an exception, so we'll raise KeyError. */ ! PyErr_SetObject(PyExc_KeyError, parmname); /* PyList_GetItem and PyDict_GetItem borrow the references to their result, so no decref necessary here. */ ! return 0; } + success = (*ibindFcn(item))(var++, item); + if (!success) + return 0; } } else { + /* The statement is using positional parameters */ if (vars && !PySequence_Check(vars)) { PyErr_SetString(PyExc_TypeError, "SQL parameters are not a sequence"); |
From: Carsten H. <ch...@us...> - 2006-11-11 05:53:03
|
Update of /cvsroot/informixdb/informixdb/ext In directory sc8-pr-cvs2.sourceforge.net:/tmp/cvs-serv6484/ext Modified Files: _informixdb.ec Log Message: implement optional parameter binding by name Index: _informixdb.ec =================================================================== RCS file: /cvsroot/informixdb/informixdb/ext/_informixdb.ec,v retrieving revision 1.78 retrieving revision 1.79 diff -C2 -d -r1.78 -r1.79 *** _informixdb.ec 3 Nov 2006 05:04:27 -0000 1.78 --- _informixdb.ec 11 Nov 2006 05:53:00 -0000 1.79 *************** *** 448,451 **** --- 448,452 ---- PyObject *errorhandler; PyObject *binary_types; + PyObject *named_params; } Cursor; *************** *** 1081,1084 **** --- 1082,1087 ---- setConnectionName(NULL); + PyDict_Clear(self->binary_types); + Py_XDECREF(self->binary_types); Py_XDECREF(self->messages); Py_XDECREF(self->errorhandler); *************** *** 1153,1156 **** --- 1156,1160 ---- char state; char prev; + const char *parmName; } parseContext; *************** *** 1163,1166 **** --- 1167,1171 ---- ct->parmIdx = 0; ct->prev = '\0'; + ct->parmName = 0; } *************** *** 1188,1204 **** const char *m = in; int n = 0; ! while (isdigit(*m)) { ! n *= 10; ! n += *m - '0'; ! m++; } ! if (n) { ! ct->parmIdx = n-1; ! ct->parmCount++; ! in = m; ! ct->isParm = 1; ! ct->prev = '0'; ! rc = 1; ! break; } } --- 1193,1226 ---- const char *m = in; int n = 0; ! if (isdigit(*m)) { ! while (isdigit(*m)) { ! n *= 10; ! n += *m - '0'; ! m++; ! } ! if (n) { ! ct->parmIdx = n-1; ! ct->parmCount++; ! in = m; ! ct->isParm = 1; ! ct->prev = '0'; ! rc = 1; ! break; ! } } ! else { ! while (isalnum(*m) || *m=='_') { ! n++; m++; ! } ! if (n) { ! ct->parmIdx = -n; ! ct->parmName = in; ! ct->parmCount++; ! in = m; ! ct->isParm = 1; ! ct->prev = '0'; ! rc = 1; ! break; ! } } } *************** *** 1506,1510 **** initParseContext(&ctx, in, out); while (doParse(&ctx)) { ! cur->parmIdx[ctx.parmCount-1] = ctx.parmIdx; if (ctx.parmCount == n_slots) { n_slots += PARM_COUNT_INCREMENT; --- 1528,1542 ---- initParseContext(&ctx, in, out); while (doParse(&ctx)) { ! if (ctx.parmIdx >= 0) { ! cur->parmIdx[ctx.parmCount-1] = ctx.parmIdx; ! } ! else { ! PyObject *parmname; ! parmname = PyString_FromStringAndSize(ctx.parmName,-ctx.parmIdx); ! if (PyList_Append(cur->named_params, parmname)==-1) { ! return 0; ! } ! cur->parmIdx[ctx.parmCount-1] = -PyList_Size(cur->named_params); ! } if (ctx.parmCount == n_slots) { n_slots += PARM_COUNT_INCREMENT; *************** *** 1535,1566 **** int maxp=0; ! if (vars && !PySequence_Check(vars)) { ! PyErr_SetString(PyExc_TypeError, "SQL parameters are not a sequence"); ! return 0; } ! ! for (i = 0; i < cur->daIn.sqld; ++i) { ! if (cur->parmIdx[i] < n_vars) { ! int success; ! PyObject *item = PySequence_GetItem(vars, cur->parmIdx[i]); ! ! success = (*ibindFcn(item))(var++, item); ! Py_DECREF(item); /* PySequence_GetItem increments it */ ! if (!success) return 0; ! maxp = maxp > cur->parmIdx[i] ? maxp : cur->parmIdx[i]; ! } else { error_handle(cur->conn, cur, ExcInterfaceError, ! PyString_FromString("too few actual parameters")); return 0; } } - if (maxp+1 < n_vars) { - error_handle(cur->conn, cur, ExcInterfaceError, - PyString_FromString("too many actual parameters")); - return 0; - } - return 1; } --- 1567,1629 ---- int maxp=0; ! if (PyList_Size(cur->named_params)) { ! if (vars && !PyDict_Check(vars)) { ! PyErr_SetString(PyExc_TypeError, "SQL parameters are not a dictionary"); ! return 0; ! } ! for (i = 0; i < cur->daIn.sqld; ++i) { ! if (cur->parmIdx[i] >= 0) { ! PyErr_SetString(PyExc_TypeError, ! "can't mix named parameters and positional parameters"); ! return 0; ! } ! else { ! int success; ! PyObject *parmname = PyList_GetItem(cur->named_params, ! -cur->parmIdx[i]-1); ! PyObject *item = PyDict_GetItem(vars, parmname); ! /* PyList_GetItem and PyDict_GetItem borrow the references ! to their result, so no decref necessary here. */ ! if (!item) { ! /* PyDict_GetItem doesn't set an exception. */ ! PyErr_SetObject(PyExc_KeyError, parmname); ! return 0; ! } ! success = (*ibindFcn(item))(var++, item); ! if (!success) ! return 0; ! } ! } } ! else { ! if (vars && !PySequence_Check(vars)) { ! PyErr_SetString(PyExc_TypeError, "SQL parameters are not a sequence"); ! return 0; ! } ! ! for (i = 0; i < cur->daIn.sqld; ++i) { ! if (cur->parmIdx[i] < n_vars) { ! int success; ! PyObject *item = PySequence_GetItem(vars, cur->parmIdx[i]); ! ! success = (*ibindFcn(item))(var++, item); ! Py_DECREF(item); /* PySequence_GetItem increments it */ ! if (!success) ! return 0; ! maxp = maxp > cur->parmIdx[i] ? maxp : cur->parmIdx[i]; ! } else { ! error_handle(cur->conn, cur, ExcInterfaceError, ! PyString_FromString("too few actual parameters")); return 0; ! } ! } ! ! if (maxp+1 < n_vars) { error_handle(cur->conn, cur, ExcInterfaceError, ! PyString_FromString("too many actual parameters")); return 0; } } return 1; } *************** *** 2428,2431 **** --- 2491,2497 ---- cur->parmIdx = 0; } + if (cur->named_params) { + PySequence_DelSlice(cur->named_params,0,PyList_Size(cur->named_params)); + } } *************** *** 2522,2525 **** --- 2588,2595 ---- deleteOutputBinding(self); + PyDict_Clear(self->binary_types); + Py_XDECREF(self->binary_types); + PySequence_DelSlice(self->named_params,0,PyList_Size(self->named_params)); + Py_XDECREF(self->named_params); Py_XDECREF(self->conn); Py_XDECREF(self->messages); *************** *** 2615,2618 **** --- 2685,2689 ---- self->messages = PyList_New(0); self->binary_types = PyDict_Copy(conn->binary_types); + self->named_params = PyList_New(0); self->errorhandler = conn->errorhandler; Py_INCREF(self->errorhandler); |
From: Carsten H. <ch...@us...> - 2006-11-03 05:04:35
|
Update of /cvsroot/informixdb/informixdb/ext In directory sc8-pr-cvs2.sourceforge.net:/tmp/cvs-serv18033 Modified Files: _informixdb.ec Log Message: refactor redundant do_prepare parameters and allow cursor.execute and .executemany to pass None to signal usage of prepared statement. Index: _informixdb.ec =================================================================== RCS file: /cvsroot/informixdb/informixdb/ext/_informixdb.ec,v retrieving revision 1.77 retrieving revision 1.78 diff -C2 -d -r1.77 -r1.78 *** _informixdb.ec 3 Nov 2006 03:35:09 -0000 1.77 --- _informixdb.ec 3 Nov 2006 05:04:27 -0000 1.78 *************** *** 1778,1786 **** } ! static PyObject *do_prepare(Cursor *self, PyObject *op, const char *sql) { struct sqlda *tdaIn = &self->daIn; struct sqlda *tdaOut = self->daOut; int i; EXEC SQL BEGIN DECLARE SECTION; char *queryName = self->queryName; --- 1778,1787 ---- } ! static PyObject *do_prepare(Cursor *self, PyObject *op) { struct sqlda *tdaIn = &self->daIn; struct sqlda *tdaOut = self->daOut; int i; + const char *sql=NULL; EXEC SQL BEGIN DECLARE SECTION; char *queryName = self->queryName; *************** *** 1792,1795 **** --- 1793,1799 ---- require_cursor_open(self); + sql = PyString_AsString(op); + if (!sql) return NULL; + if (op == self->op) { doCloseCursor(self, 0); *************** *** 1859,1873 **** { PyObject *op; - const char *sql; static char* kwdlist[] = { "operation", 0 }; ! if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwdlist, &sql)) return NULL; - op = PyTuple_GET_ITEM(args, 0); /* Make sure we talk to the right database. */ if (setConnection(self->conn)) return NULL; ! if (do_prepare(self, op, sql)) { Py_INCREF(Py_None); return Py_None; --- 1863,1875 ---- { PyObject *op; static char* kwdlist[] = { "operation", 0 }; ! if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", kwdlist, &op)) return NULL; /* Make sure we talk to the right database. */ if (setConnection(self->conn)) return NULL; ! if (do_prepare(self, op)) { Py_INCREF(Py_None); return Py_None; *************** *** 1882,1886 **** struct sqlda *tdaIn = &self->daIn; PyObject *op, *inputvars=NULL; - const char *sql; int i; static char* kwdlist[] = { "operation", "parameters", 0 }; --- 1884,1887 ---- *************** *** 1893,1905 **** require_cursor_open(self); ! if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|O", kwdlist, ! &sql, &inputvars)) return NULL; ! op = PyTuple_GET_ITEM(args, 0); ! /* Make sure we talk to the right database. */ if (setConnection(self->conn)) return NULL; ! if (!do_prepare(self, op, sql)) { return NULL; } --- 1894,1907 ---- require_cursor_open(self); ! if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O", kwdlist, ! &op, &inputvars)) return NULL; ! if (op==Py_None) ! op = self->op; ! /* Make sure we talk to the right database. */ if (setConnection(self->conn)) return NULL; ! if (!do_prepare(self, op)) { return NULL; } *************** *** 1949,1953 **** struct sqlda *tdaIn = &self->daIn; PyObject *op, *params, *paramiter, *inputvars = 0; - const char *sql; int i; int rowcount = 0, inputDirty = 0, useInsertCursor; --- 1951,1954 ---- *************** *** 1961,1967 **** require_cursor_open(self); ! if (!PyArg_ParseTupleAndKeywords(args, kwds, "sO", kwdlist, &sql, ¶ms)) return NULL; ! op = PyTuple_GET_ITEM(args, 0); paramiter = PyObject_GetIter(params); if (paramiter == NULL) { --- 1962,1969 ---- require_cursor_open(self); ! if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO", kwdlist, &op, ¶ms)) return NULL; ! if (op==Py_None) ! op = self->op; paramiter = PyObject_GetIter(params); if (paramiter == NULL) { *************** *** 1972,1976 **** if (setConnection(self->conn)) return NULL; ! if (!do_prepare(self, op, sql)) { return NULL; } --- 1974,1978 ---- if (setConnection(self->conn)) return NULL; ! if (!do_prepare(self, op)) { return NULL; } |
From: Carsten H. <ch...@us...> - 2006-11-03 03:35:12
|
Update of /cvsroot/informixdb/informixdb/ext In directory sc8-pr-cvs2.sourceforge.net:/tmp/cvs-serv16910/ext Modified Files: _informixdb.ec Log Message: defer initializers that MinGW doesn't recognize as constants to allow compiling with MinGW Index: _informixdb.ec =================================================================== RCS file: /cvsroot/informixdb/informixdb/ext/_informixdb.ec,v retrieving revision 1.76 retrieving revision 1.77 diff -C2 -d -r1.76 -r1.77 *** _informixdb.ec 8 Oct 2006 04:10:39 -0000 1.76 --- _informixdb.ec 3 Nov 2006 03:35:09 -0000 1.77 *************** *** 400,406 **** 0, /* tp_dictoffset */ (initproc)Sblob_init, /* tp_init */ ! PyType_GenericAlloc, /* tp_alloc */ ! PyType_GenericNew, /* tp_new */ ! _PyObject_Del /* tp_free */ }; $endif; --- 400,406 ---- 0, /* tp_dictoffset */ (initproc)Sblob_init, /* tp_init */ ! DEFERRED_ADDRESS(PyType_GenericAlloc), /* tp_alloc */ ! DEFERRED_ADDRESS(PyType_GenericNew), /* tp_new */ ! DEFERRED_ADDRESS(_PyObject_Del) /* tp_free */ }; $endif; *************** *** 700,706 **** 0, /* tp_dictoffset */ (initproc)Cursor_init, /* tp_init */ ! PyType_GenericAlloc, /* tp_alloc */ ! PyType_GenericNew, /* tp_new */ ! _PyObject_Del /* tp_free */ }; --- 700,706 ---- 0, /* tp_dictoffset */ (initproc)Cursor_init, /* tp_init */ ! DEFERRED_ADDRESS(PyType_GenericAlloc), /* tp_alloc */ ! DEFERRED_ADDRESS(PyType_GenericNew), /* tp_new */ ! DEFERRED_ADDRESS(_PyObject_Del) /* tp_free */ }; *************** *** 960,966 **** 0, /* tp_dictoffset */ (initproc)Connection_init, /* tp_init */ ! PyType_GenericAlloc, /* tp_alloc */ ! PyType_GenericNew, /* tp_new */ ! _PyObject_Del /* tp_free */ }; --- 960,966 ---- 0, /* tp_dictoffset */ (initproc)Connection_init, /* tp_init */ ! DEFERRED_ADDRESS(PyType_GenericAlloc), /* tp_alloc */ ! DEFERRED_ADDRESS(PyType_GenericNew), /* tp_new */ ! DEFERRED_ADDRESS(_PyObject_Del) /* tp_free */ }; *************** *** 3318,3324 **** 0, /* tp_dictoffset */ (initproc)DBAPIType_init, /* tp_init */ ! PyType_GenericAlloc, /* tp_alloc */ ! PyType_GenericNew, /* tp_new */ ! _PyObject_Del /* tp_free */ }; --- 3318,3324 ---- 0, /* tp_dictoffset */ (initproc)DBAPIType_init, /* tp_init */ ! DEFERRED_ADDRESS(PyType_GenericAlloc), /* tp_alloc */ ! DEFERRED_ADDRESS(PyType_GenericNew), /* tp_new */ ! DEFERRED_ADDRESS(_PyObject_Del) /* tp_free */ }; *************** *** 3961,3966 **** --- 3961,3975 ---- Cursor_type.ob_type = &PyType_Type; + Cursor_type.tp_alloc = PyType_GenericAlloc; + Cursor_type.tp_new = PyType_GenericNew; + Cursor_type.tp_free = _PyObject_Del; Connection_type.ob_type = &PyType_Type; + Connection_type.tp_alloc = PyType_GenericAlloc; + Connection_type.tp_new = PyType_GenericNew; + Connection_type.tp_free = _PyObject_Del; DBAPIType_type.ob_type = &PyType_Type; + DBAPIType_type.tp_alloc = PyType_GenericAlloc; + DBAPIType_type.tp_new = PyType_GenericNew; + DBAPIType_type.tp_free = _PyObject_Del; Connection_getseters[0].closure = ExcWarning; *************** *** 3981,3984 **** --- 3990,3996 ---- $ifdef HAVE_ESQL9; Sblob_type.ob_type = &PyType_Type; + Sblob_type.tp_alloc = PyType_GenericAlloc; + Sblob_type.tp_new = PyType_GenericNew; + Sblob_type.tp_free = _PyObject_Del; PyType_Ready(&Sblob_type); Py_INCREF(&Sblob_type); |
From: Olavo S. <ola...@us...> - 2006-10-14 02:43:48
|
Update of /cvsroot/informixdb/zinformixda/dtml In directory sc8-pr-cvs2.sourceforge.net:/tmp/cvs-serv2000/zinformixda/dtml Added Files: browse.dtml connectionAdd.dtml connectionEdit.dtml connectionStatus.dtml Log Message: initial source commit --- NEW FILE: connectionAdd.dtml --- <dtml-var manage_page_header> <dtml-var "manage_form_title(this(), _, form_title='Add Z %s Database Connection' % database_type, )"> <br/> <form action="manage_addZDAConnection" method="post"> <table cellspacing="0" cellpadding="2" border="0"> <tr> <td align="left" valign="top" class="form-label"> Id </td> <td align="left" valign="top"> <input type="text" name="id" size="40" value="<dtml-var database_type>_database_connection" class="form-element" /> </td> </tr> <tr> <td align="left" valign="top" class="form-optional"> Title </td> <td align="left" valign="top"> <input type="text" name="title" size="40" value="Z <dtml-var database_type> Database Connection" class="form-element" /> </td> </tr> <tr> <td align="left" valign="top" class="form-label"> Enter a Database Connection String <a href="#1"><sup>[1]</sup></a> </td> <td align="left" valign="top"> <input type="text" name="connection_string" size="40" value="" class="form-element" /> </td> </tr> <tr> <td align="left" valign="top" class="form-label"> Connect immediately </td> <td align="left" valign="top"> <input name="check:boolean" type="checkbox" value="yes" class="form-element" checked /> </td> </tr> <tr> <td align="left" valign="top" class="form-label"> Use transactions </td> <td align="left" valign="top"> <input name="transactions:boolean" type="checkbox" value="yes" class="form-element" /> </td> </tr> <tr> <td align="left" valign="top" class="form-label"> Verbose mode <a href="#2"><sup>[2]</sup></a> </td> <td align="left" valign="top"> <input name="verbose:boolean" type="checkbox" value="yes" class="form-element" /> </td> </tr> <tr> <td></td> <td><input name="submit" type="submit" value=" Add " class="form-element" /></td> </tr> </table> </form> <hr width="90%"/> <a name="1"><sup>[1]</sup></a> <strong>Connection Strings</strong> <br/> <pre> The connection string used for Z <dtml-var database_type> Database Connection are of the form: database[@host [user [password ]]] or typically just: database user password to use the default server. </pre> <br/> <a name="1"><sup>[2]</sup></a> <strong>Verbose mode</strong> <br/> <pre> Verbose mode will output INFO level messages using the logging module. You can catch those messages by editing your zope.conf file and enabling INFO level somewhere in the LOGGER section. </pre> <dtml-var manage_page_footer> --- NEW FILE: connectionStatus.dtml --- <dtml-var manage_page_header> <dtml-var manage_tabs> <br/> <table cellspacing="2" cellpadding="2" border="0"> <tr> <td align="left" valign="top" class="form-label"> Id </td> <td align="left" valign="top" class="form-text"> <dtml-var id html_quote> </td> </tr> <tr> <td align="left" valign="top" class="form-optional"> Title </td> <td align="left" valign="top" class="form-text"> <dtml-var title html_quote> </td> </tr> <tr> <td align="left" valign="top" class="form-label"> Database connection string </td> <td align="left" valign="top" class="form-text"> <dtml-var connection_string html_quote> </td> </tr> <tr> <td align="left" valign="top" class="form-label"> Transactions are </td> <td align="left" valign="top" class="form-text"> <dtml-if transactions>enabled<dtml-else>disabled</dtml-if> </td> </tr> <tr> <td align="left" valign="top" class="form-label"> Verbose mode is </td> <td align="left" valign="top" class="form-text"> <dtml-if verbose>enabled<dtml-else>disabled</dtml-if> </td> </tr> <tr> <td align="left" valign="top" class="form-label"> The database connection is </td> <td align="left" valign="top" class="form-text"> <dtml-if connected>open<dtml-else>closed</dtml-if> </td> </tr> <tr> <td></td> <td> <dtml-if connected> <form action="manage_close_connection" method="get"> <input name="submit" type="submit" value=" Close Database Connection " class="form-element" /> </form> <dtml-else> <form action="manage_open_connection" method="get"> <input name="submit" type="submit" value=" Open Database Connection " class="form-element" /> </form> </dtml-if> </td> </tr> </table> <dtml-var manage_page_footer> --- NEW FILE: browse.dtml --- <dtml-var manage_page_header> <dtml-var manage_tabs> <dtml-if connected> <dtml-tree header=info> <img src="<dtml-var BASEPATH1>/misc_/Z<dtml-var database_type>DA/<dtml-var icon>" alt="<dtml-var Type spacify lower>" title="<dtml-var Type spacify lower>" border="0" /> <dtml-var Name><dtml-var Description> </dtml-tree> <dtml-else> <p class="form-help"> This database connection is currently closed. You must click on the <em>status</em> tab and open the connection before you can test it. </p> </dtml-if> <dtml-var manage_page_footer> --- NEW FILE: connectionEdit.dtml --- <dtml-var manage_page_header> <dtml-var manage_tabs> <br/> <form action="manage_edit" method="POST"> <table cellspacing="0" cellpadding="2" border="0"> <tr> <td align="left" valign="top" class="form-label"> Id </td> <td align="left" valign="top" class="form-text"> <dtml-var id html_quote> </td> </tr> <tr> <td align="left" valign="top" class="form-optional"> Title </td> <td align="left" valign="top"> <input type="text" name="title" size="40" value="<dtml-var title html_quote>" class="form-element" /> </td> </tr> <tr> <td align="left" valign="top" class="form-label"> Database connection string <a href="#1"><sup>[1]</sup> </td> <td align="left" valign="top"> <input type="text" name="connection_string" size="40" value="<dtml-var connection_string html_quote>" class="form-element"/> </td> </tr> <tr> <td align="left" valign="top" class="form-label"> Connect immediately </td> <td align="left" valign="top"> <input name="check:boolean" type="checkbox" value="yes" <dtml-if check>checked</dtml-if> class="form-element" /> </td> </tr> <tr> <td align="left" valign="top" class="form-label"> Use transactions </td> <td align="left" valign="top"> <input name="transactions:boolean" type="checkbox" value="yes" <dtml-if transactions>checked</dtml-if> class="form-element" /> </td> </tr> <tr> <td align="left" valign="top" class="form-label"> Verbose mode <a href="#2"><sup>[2]</sup></a> </td> <td align="left" valign="top"> <input name="verbose:boolean" type="checkbox" value="yes" <dtml-if verbose>checked</dtml-if> class="form-element" /> </td> </tr> <tr> <td></td> <td><input name="submit" type="submit" value=" Save Changes " class="form-element" /></td> </tr> </table> </form> <hr width="90%"/> <a name="1"><sup>[1]</sup></a> <strong>Connection Strings</strong> <br/> <pre> The connection string used for Z <dtml-var database_type> Database Connection are of the form: database[@host [user [password ]]] or typically just: database user password to use the default server. </pre> <br/> <a name="1"><sup>[2]</sup></a> <strong>Verbose mode</strong> <br/> <pre> Verbose mode will output INFO level messages using the logging module. You can catch those messages by editing your zope.conf file and enabling INFO level somewhere in the LOGGER section. </pre> <dtml-var manage_page_footer> |
From: Olavo S. <ola...@us...> - 2006-10-14 02:43:46
|
Update of /cvsroot/informixdb/zinformixda In directory sc8-pr-cvs2.sourceforge.net:/tmp/cvs-serv2000/zinformixda Added Files: CHANGES.txt COPYING.txt CREDITS.txt DA.py DABase.py DEPENDENCIES.txt INSTALL.txt TODO.txt VERSION.txt ZopePublicLicense.txt __init__.py db.py Log Message: initial source commit --- NEW FILE: TODO.txt --- Z Informix DA todo list ----------------------- - Advanced error handling ( display warnings ) - Implement Scroll Cursors and Cursors with Hold - Check Blob possible usage - Add test units - Release a Zope 3 Package version --- NEW FILE: DABase.py --- ############################################################################## # # Copyright (c) 2004, 2005, 2006 Zope Corporation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. ############################################################################## import Globals, Shared.DC.ZRDB.Connection, sys, string from ExtensionClass import Base import Acquisition from db import table_icons, field_icons from AccessControl import ClassSecurityInfo import AccessControl.Permissions __doc__ = '''Database Connection''' __revision__ = '$Id: DABase.py,v 1.1 2006/10/14 02:43:40 olavosantos Exp $' __version__ = string.split(__revision__)[2] class Connection(Shared.DC.ZRDB.Connection.Connection): _isAnSQLConnection = 1 security = ClassSecurityInfo() manage_options = Shared.DC.ZRDB.Connection.Connection.manage_options + ( { 'label':'Browse', 'action':'manage_browse' }, ) security.declareProtected(AccessControl.Permissions.view_management_screens, 'manage_browse') manage_browse = Globals.HTMLFile('dtml/browse',globals()) def tpValues(self): r = [] c = self._v_database_connection try: for d in c.tables(rdb=0): try: name = d['TABLE_NAME'] b = TableBrowser() b.__name__ = name b._d = d b._c = c b.icon = table_icons.get(d['TABLE_TYPE'],'text') r.append(b) except: pass finally: pass return r def __getitem__(self, name): if name == 'tableNamed': if not hasattr(self, '_v_tables'): self.tpValues() return self._v_tables.__of__(self) raise KeyError, name Globals.InitializeClass(Connection) class Browser(Base): def __getattr__(self, name): try: return self._d[name] except KeyError: raise AttributeError, name class values: def len(self): return 1 def __getitem__(self, i): try: return self._d[i] except AttributeError: pass self._d = self._f() return self._d[i] class TableBrowser(Browser, Acquisition.Implicit): icon = 'what' Description = check = '' def tpValues(self): v = values() v._f = self.tpValues_ return v def tpValues_(self): r = [] tname = self.__name__ for d in self._c.columns(tname): b = ColumnBrowser() b._d = d b.icon = field_icons.get(d['Type'], 'text') b.TABLE_NAME = tname r.append(b) return r def tpId(self): return self._d['TABLE_NAME'] def tpURL(self): return "Table/%s" % self._d['TABLE_NAME'] def Name(self): return self._d['TABLE_NAME'] def Type(self): return self._d['TABLE_TYPE'] class ColumnBrowser(Browser): icon = 'field' #def check(self): return ('\t<input type=checkbox name="%s.%s">' % (self.TABLE_NAME, self._d['Name'])) def tpId(self): return self._d['Name'] def tpURL(self): return "Column/%s" % self._d['Name'] def Description(self): d = self._d t = { True:'null', False:'not null' } d['Nullable'] = t.get(d['Nullable'],'') if d['Scale']: return " %(Type)s(%(Precision)s,%(Scale)s) %(Nullable)s" % d else: return " %(Type)s(%(Precision)s) %(Nullable)s" % d --- NEW FILE: VERSION.txt --- ZInformixDA 0.3 --- NEW FILE: CREDITS.txt --- ZInformixDA contributors ------------------------ Name: papa Link: http://www.zope.org/Members/papa/ Note: Very usefull modified ZInformixDA version Name: Isaac Salsberg ( isa...@ya... ) Link: http://www.zope.org/Members/isalsberg/ Note: How to compile/link ZInformixDA on win32 using MS VC 6.0 Name: Carsten Haese ( ch...@us... ) Link: http://informixdb.sourceforge.net/ Note: informixdb current maintainter & zinformixda project hosting Name: Stephen J. Turner ( sjt...@ix... ) Link: http://starship.python.net/crew/sturner/informixdb.html Note: old informixdb maintainer Name: Alexander Kuznetsov Link: http://thor.prohosting.com/~alexan/pub/Kinfxdb/ Note: Kinfxdb maintainer Name: Mark Rees Link: http://www.zope.org/Members/mark_rees/, http://hex-dump.blogspot.com/ Note: ZInformixDA version 0.2 Name: Andy Dustman ( an...@du... ) Link: http://www.zope.org/Members/adustman/, http://sourceforge.net/projects/mysql-python/ Note: MySQLdb and DA Thank you --------- - Zope Corporation for the ZOPE/ZEO environment. :) - Entire Zope Community for their big help. - Julio Silva ( aka zorton ) for findind the need to have and support ZInformixDA. :> --- NEW FILE: db.py --- ############################################################################## # # Copyright (c) 2004, 2005, 2006 Zope Corporation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. ############################################################################## # informix specific import informixdb import Shared.DC.ZRDB.TM import string, sys from DateTime import DateTime from string import strip, split, find, upper from time import time from UserDict import UserDict import logging database_type = 'Informix' __doc__ = '''%s Database Connection''' % database_type __revision__ = '$Id: db.py,v 1.1 2006/10/14 02:43:40 olavosantos Exp $' __version__ = string.split(__revision__)[2] logger = logging.getLogger('Product.Z%sDA' % database_type) logger.setLevel(logging.INFO) class Icons(UserDict): """icon values are registered in __init__.py""" def __init__(self): UserDict.__init__(self) self.update(self.icons) def get(self, i, x=None): i = upper(i) if i in self.keys(): return self[i] else: return x class TableIcons(Icons): icons = { 'TABLE':'table', 'VIEW':'view2', 'SYSTEM_TABLE':'stable', } table_icons = TableIcons() class FieldIcons(Icons): icons = { 'BLOB':'bin', 'BOOLEAN':'bin', 'BYTE':'text', 'CHAR':'text', 'CLOB':'bin', 'DATE':'date', 'DATETIME':'date', 'DECIMAL':'float', 'DOUBLE':'float', 'FLOAT':'float', 'INT':'int', 'INTEGER':'int', 'INTERVAL':'field', 'INT8':'int', 'INT24':'int', 'LONG':'int', 'LONGLONG':'int', 'LVARCHAR':'text', 'MONEY':'float', 'NCHAR':'text', 'NVARCHAR':'text', 'SERIAL':'int', 'SERIAL8':'int', 'SHORT':'int', 'SMALLFLOAT':'float', 'SMALLINT':'int', 'TEXT':'text', 'TIMESTAMP':'date', 'TINY':'int', 'VARCHAR':'text', 'YEAR':'int', } field_icons = FieldIcons() # Python Database API Specification v2.0 # http://www.python.org/dev/peps/pep-0249/ # apilevel_required = 2.0 _v = float(getattr(informixdb, 'apilevel', '0.0')) if _v < apilevel_required: _vp = (database_type, apilevel_required, _v) _msg = "Z%sDA requires at least python database api %s, level %s found.\nPlease upgrade your informixdb version.\n" % _vp raise RuntimeError, _msg class DB(Shared.DC.ZRDB.TM.TM): _p_oid = _p_changed = _registered = None def __init__(self, connection, transactions=None, verbose=None): self.connection = connection self.transactions = transactions self.verbose = verbose self.kwargs = self._parse_connection_string(self.connection) if self.verbose: logger.info('%s : open database connection.' % self.kwargs[0]) self.db = apply(informixdb.connect, self.kwargs) # autocommit = true when transactions are disabled by user if not transactions: if self.verbose: logger.info('%s : enabling autocommit.' % self.kwargs[0]) self.db.autocommit = True def _parse_connection_string(self, connection): kwargs = '' items = split(connection) if not items: return kwargs else: return items def tables(self, rdb=0, _care=('TABLE', 'VIEW')): r = [] a = r.append # Table Types: # # T - Table # V - View # # Table IDs: # # 100 -> nnn - user defined # 0 -> 24 - system defined # if self.verbose: logger.info('%s : listing database tables.' % self.kwargs[0]) result = self.query('SELECT tabname, owner, tabid, tabtype FROM systables WHERE tabtype IN ("T","V") ORDER BY owner, tabname', max_rows=9999999)[1] for row in result: ttype = 'VIEW' if row[3] == 'T': if int(row[2]) >= 100: ttype = 'TABLE' else: ttype = 'SYSTEM_TABLE' a({'TABLE_NAME': strip(row[1])+'.'+strip(row[0]), 'TABLE_TYPE': ttype, 'TABLE_OWNER': row[1]}) return r def columns(self, table_name): if self.transactions: self._register() if self.verbose: logger.info('%s : create cursor.' % self.kwargs[0]) c = self.db.cursor() if self.verbose: logger.info('%s : %s : listing table columns.' % (self.kwargs[0], table_name)) # get column description ( for some yet-to-know reason informixdb doesn't retrieve the correct value for null_ok ) rtype = {} c.execute('SELECT * FROM %s ' % table_name) desc = c.description for name, type, width, ds, p, scale, null_ok in desc: rtype[name] = type # get column details table_name = string.split(table_name,'.')[-1] r = [] a = r.append c.execute("SELECT * FROM syscolumns WHERE tabid = (SELECT tabid FROM systables WHERE tabname = '%s') ORDER BY colno" % table_name) while 1: row = c.fetchone() if not row: break null_ok = row[3] < 256 # if coltype >= 256, column don't allow null values a( { 'Name': row[0], 'Type': rtype.get(row[0]), 'Precision': row[4], 'Scale': None, 'Nullable': null_ok, } ) if c: if self.verbose: logger.info('%s : close cursor.' % self.kwargs[0]) c.close() return r def query(self, query_string, max_rows=1000): if self.transactions: self._register() desc = None result = () try: for qs in filter(None, map(strip,split(query_string, '\0'))): qtype = upper(split(qs, None, 1)[0]) if self.verbose: logger.info('%s : create cursor.' % self.kwargs[0]) c = self.db.cursor() if self.verbose: logger.info('%s : sql statement : %s' % ( self.kwargs[0], string.join(map(strip,split(qs))) ) ) c.execute(qs) if desc is not None: if c and (c.description != desc): raise 'Query Error', ( 'multiple select schema are not allowed' ) if c: desc = c.description if qtype == "SELECT" or qtype == "EXECUTE": result = c.fetchmany(max_rows) if self.verbose: logger.info('%s : close cursor.' % self.kwargs[0]) c.close() else: desc = None except informixdb.Error, m: raise if desc is None: return (),() r = [] a = r.append for name, type, width, ds, p, scale, null_ok in desc: a( { 'name': name, 'type': type, 'width': width, 'null': null_ok, } ) return r, result def string_literal(self, s): return "'" + s + "'" def _begin(self, *ignored): if self.verbose: logger.info('%s : begin work.' % self.kwargs[0]) pass def _finish(self, *ignored): if self.verbose: logger.info('%s : commit work.' % self.kwargs[0]) self.db.commit() def _abort(self, *ignored): if self.verbose: logger.info('%s : rollback work.' % self.kwargs[0]) self.db.rollback() def close(self): if self.verbose: logger.info('%s : close database connection.' % self.kwargs[0]) self.db.close() --- NEW FILE: COPYING.txt --- ZInformixDA is distributed under the provisions of the Zope Public License (ZPL) v2.1. See ZopePublicLicense.txt for the license text. Copyright (C) 2005 ZInformixDA Contributors. See CREDITS.txt for a list of ZInformixDA contributors. ZInformixDA contains source code derived from: - Zope 2, copyright (C) 2001-2006 by Zope Corporation. --- NEW FILE: INSTALL.txt --- Z Informix DA installation -------------------------- Supported Platforms ZInformixDA should work in any platform where you can run Zope, build the informixdb python package, or in other words in any IBM Informix supported platform. Prerequisites Please check DEPENDENCIES.txt for more information. Installation ( short version ) Fullfill the prerequesites. Unzip/Untar ZInformixDA into your "Products" folder and restart Zope. Installation ( long version ) Linux: I will try to describe an installation on a redhat-like linux. It should be similar in any other linux distro. step 1) Informix Client Software Development Kit (CSDK) Create a temp installation folder. # cd ~ # mkdir temp # cd temp Download the CSDK into temp. You may need to register at IBM to be able to download the file. # tar xvf clientsdk.2.90.UC4.LINUX.tar # chown -R root.root . # chmod -R 755 . Add a group and user for informix and prepare some needed environment values. We will use /opt/informix to install the csdk. # groupadd informix # useradd -g informix -d /dev/null informix # mkdir /opt/informix # INFORMIXDIR=/opt/informix # export INFORMIXDIR # ACCEPTLICENSE=yes # export ACCEPTLICENSE Install using the rpm installation method. Please read the doc/Client_install_guide.pdf. You have there plenty of options for your specific system. # rpm -ivh --prefix $INFORMIXDIR message.rpm # rpm -ivh --prefix $INFORMIXDIR gls.rpm # rpm -ivh --prefix $INFORMIXDIR clientsdkcontent.rpm step 2) InformixDB Python Module Download it. # tar xvfz InformixDB-2.2.tar.gz # chown -R root.root InformixDB-2.2 # chmod -R 755 InformixDB-2.2 # cd InformixDB-2.2 If you are using a binary package of Zope, you need run setup.py with the python executable that came with Zope. # /usr/local/bin/python2.4 setup.py build_ext # /usr/local/bin/python2.4 setup.py install Please read the InformixDB README.txt. You have there more usefull options that you can use in your system. step 3) System Configurations Don't forget to configure your dynamic linker run time bindings. :> # vi /etc/ld.so.conf /opt/informix/lib /opt/informix/lib/esql # ldconfig If you are going to use onsoctcp as the connectivity protocol, don't forget to add some network services into /etc/services. # vi /etc/services sqlexec 1525/tcp # Informix SQL sqlexec2 1526/tcp # Informix SQL And of course, edit the default sqlhosts to add your own informix servers. # vi /opt/informix/etc/sqlhosts dbinst2 onsoctcp 10.10.12.44 sqlexec2 ancdb01 onsoctcp 10.0.12.14 sqlexec At least two environment values have to exist in all profiles. Without them, informixdb won't work. # vi /etc/profile.d/informix.sh INFORMIXDIR=/opt/informix INFORMIXSERVER=ptdpt2000 export INFORMIXDIR INFORMIXSERVER # chmod 755 /etc/profile.d/informix.sh # reboot step 4) Test your informixdb installation # /usr/local/bin/python2.4 Python 2.4.3 (#1, Aug 23 2006, 15:28:44) [GCC 3.4.5 20051201 (Red Hat 3.4.5-2)] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> import informixdb >>> step 5) ZInformixDA Download ZInformixDA. I assume that you have your zope installation and/or instance in /usr/local/zope. # tar xvfz ZInformixDA-0.3.tar.gz # chown -R root.root ZInformixDA # chmod -R 755 ZInformixDA/ # mv ZInformixDA /usr/local/zope/Products/ # /usr/local/zope/bin/runzope If everything went well you will see a new Product in your Zope ControlPanel and the possibility to add a Z Informix Database Connection. Windows: This installation description should be similar in any windows release. step 1) Informix Client Software Development Kit (CSDK) Create a temp installation folder. c:\temp Download the CSDK into temp. You may need to register at IBM to be able to download the file. c:\temp\clientsdk.2.90.TC6.WIN.zip Unzip the file and run installation. c:\temp\clientsdk.2.90.TC6.WIN\IBM Informix Client-SDK.msi Use the custom installation mode and don't forget to "Set INFORMIXDIR to the newly chosen directory". Follow the instructions and reboot your system after installation. step 2) InformixDB Python Module Download into temp folder and run installation. c:\temp\InformixDB-2.3.win32-py2.4.exe If you are using a binary package of Zope, you probably have to copy informixdb.* files from a python installation into Zope lib folder. C:\Program Files\Zope-2.9.4\bin\Lib\site-packages Please read Isaac Salsberg tutorial on how to compile/link ZInformixDA on win32 if you need to compile informixdb module from scratch: http://www.zope.org/Members/isalsberg/InformixDA/How-ToZInformixDA step 3) System Configurations Use "Setnet32" program to setup informix hosts and environment variables. Set at least INFORMIXDIR and INFORMIXSERVER. step 4) Test your informixdb installation C:\Program Files\Zope-2.9.4\bin>python Python 2.4.3 (#69, Mar 29 2006, 17:35:34) [MSC v.1310 32 bit (Intel)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> import informixdb >>> step 5) ZInformixDA Download and unzip ZInformixDA into your Products folder. If everything went well you will see a new Product in your Zope ControlPanel and the possibility to add a Z Informix Database Connection. Database Adapter Usage Add a Z Informix Database Connection and start using ZSQL Methods to query your database. Upgrading I've tried to evolve the code without breaking nothing. So the upgrade process is ( or at least "should be" ) transparent. The only restriction is the need to use an informixdb that follows the Python Database API Specification v2.0. If you use the old informixdb module on your zope python version, your have to upgrade it too. Support/Bugs/Features/Future If you have some questions about this zope product, please drop me an email and i will be glad to help you. -- Olavo Santos <nb...@cy...> http://www.varkala.net/ --- NEW FILE: __init__.py --- ############################################################################## # # Copyright (c) 2004, 2005, 2006 Zope Corporation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. ############################################################################## import string, os from db import database_type import DA, Globals from App.ImageFile import ImageFile __doc__ = '''%s Database Adapter Package Registration''' % database_type __revision__ = '$Id: __init__.py,v 1.1 2006/10/14 02:43:40 olavosantos Exp $' __version__ = string.split(__revision__)[2] # generic database adapter icons misc_ = { 'conn':ImageFile(os.path.join('Shared','DC','ZRDB','www','DBAdapterFolder_icon.gif')), } for icon in ( 'table', 'view2', 'stable', 'what', 'field', 'text', 'bin', 'int', 'float', 'date', 'time', 'datetime'): misc_[icon] = ImageFile(os.path.join('www','%s.gif') % icon, globals()) # generic database adapter manage_add method manage_addZDAConnectionForm = Globals.HTMLFile( 'dtml/connectionAdd', globals(), database_type=database_type ) def manage_addZDAConnection( self, id, title, connection_string, check=None, transactions=None, verbose=None, REQUEST=None): """DA Connection Add Method""" self._setObject(id, DA.Connection(id, title, connection_string, check, transactions, verbose)) if REQUEST is not None: return self.manage_main(self, REQUEST) # initialization method def initialize(context): context.registerClass( instance_class = DA.Connection, permission = 'Add Z %s Database Connections' % database_type, constructors = ( manage_addZDAConnectionForm, manage_addZDAConnection ) ) --- NEW FILE: ZopePublicLicense.txt --- Zope Public License (ZPL) Version 2.1 ------------------------------------- A copyright notice accompanies this license document that identifies the copyright holders. This license has been certified as open source. It has also been designated as GPL compatible by the Free Software Foundation (FSF). Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions in source code must retain the accompanying copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the accompanying copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Names of the copyright holders must not be used to endorse or promote products derived from this software without prior written permission from the copyright holders. 4. The right to distribute this software or to use it for any purpose does not give you the right to use Servicemarks (sm) or Trademarks (tm) of the copyright holders. Use of them is covered by separate agreement with the copyright holders. 5. If any files are modified, you must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. Disclaimer THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --- NEW FILE: CHANGES.txt --- Z Informix DA releases ---------------------- 0.3 License update. Facelift to get rid of all Deprecation warnings in 2.9/2.10 zope trunk. Added "Verbose Mode". Minor changes to use informixdb api 2.0 python module. 0.2 "This was originally an alpha release of the DA so others can review it, help me improve it and give me feedback. But it has been used in a number of production environments over the last few months and has exhibited no bugs :-)" ( by Mark Rees ) 0.1 This is the first (alpha) version of the database adapter using Informix for Zope. This database adapter is based on the many Z DA's tht others have provided to the Zope distribution. --- NEW FILE: DEPENDENCIES.txt --- Z Informix DA dependencies -------------------------- * Informix Client Software Development Kit (CSDK) 2.90 or newer http://www.ibm.com/software/data/informix/downloads.html * Python 2.3.5 or newer http://www.python.org/ * InformixDB 2.2 or newer http://informixdb.sourceforge.net/ * Zope 2.7.0 or newer http://www.zope.org/ --- NEW FILE: DA.py --- ############################################################################## # # Copyright (c) 2004, 2005, 2006 Zope Corporation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. ############################################################################## from db import DB, database_type import Globals, DABase, string from App.Dialogs import MessageDialog from DateTime import DateTime from AccessControl import ClassSecurityInfo import AccessControl.Permissions import logging logger = logging.getLogger('Product.Z%sDA' % database_type) logger.setLevel(logging.INFO) __doc__ = '''%s Database Connection''' % database_type __revision__ = '$Id: DA.py,v 1.1 2006/10/14 02:43:40 olavosantos Exp $' __version__ = string.split(__revision__)[2] class Connection(DABase.Connection): """DA Connection Class""" database_type = database_type id = '%s_database_connection' % database_type meta_type = title = 'Z %s Database Connection' % database_type icon = 'misc_/Z%sDA/conn' % database_type check = True verbose = None transactions = None security = ClassSecurityInfo() security.declareProtected(AccessControl.Permissions.manage_properties, 'manage_properties') manage_properties = Globals.HTMLFile('dtml/connectionEdit', globals()) security.declareProtected(AccessControl.Permissions.view_management_screens, 'manage_main') manage_main = Globals.HTMLFile('dtml/connectionStatus', globals()) def __init__(self, id, title, connection_string, check=None, transactions=None, verbose=None): self.id = str(id) self.edit(title, connection_string, check, transactions, verbose) if self.verbose: logger.info('%s: running __init__ method.' % self.id) def factory(self): return DB def edit(self, title, connection_string, check=None, transactions=None, verbose=None): self.title = title self.connection_string = connection_string self.check = check self.transactions = transactions self.verbose = verbose if self.verbose: logger.info('%s: properties edited.' % self.id) if check: self.connect(connection_string) security.declareProtected(AccessControl.Permissions.manage_properties, 'manage_edit') def manage_edit(self, title, connection_string, check=None, transactions=None, verbose=None, REQUEST=None): """Change connection properties""" self.edit(title, connection_string, check, transactions, verbose) if REQUEST is not None: return MessageDialog( title='Edited', message='<strong>%s</strong> has been edited.' % self.id, action ='./manage_main', ) security.declareProtected(AccessControl.Permissions.open_close_database_connection, 'manage_open_connection') def manage_open_connection(self, REQUEST=None): """Open database connection""" if self.verbose: logger.info('%s: trying to open database connection...' % self.id) self.connect(self.connection_string) return self.manage_main(self, REQUEST) security.declareProtected(AccessControl.Permissions.open_close_database_connection, 'manage_close_connection') def manage_close_connection(self, REQUEST=None): """Close database connection""" if self.verbose: logger.info('%s: trying to close database connection...' % self.id) try: if hasattr(self,'_v_database_connection'): self._v_database_connection.close() self._v_connected = '' except: logger.error('Error closing relational database connection.', exc_info=True) if REQUEST is not None: return self.manage_main(self, REQUEST) def __setstate__(self, state): Globals.Persistent.__setstate__(self, state) if self.connection_string and self.check: try: self.connect(self.connection_string) except: logger.error('Error connecting to relational database.', exc_info=True) def connect(self, s): if self.verbose: logger.info('%s: running connect method.' % self.id) self.manage_close_connection() DB = self.factory() try: # some added properties if not hasattr(self, 'transactions'): self.transactions = None if not hasattr(self, 'verbose'): self.verbose = None ## No try. DO. if self.verbose: logger.info('%s: create db instance.' % self.id) self._v_database_connection = DB(s, self.transactions, self.verbose) self._v_connected = DateTime() except: raise return self def table_info(self): return self._v_database_connection.table_info() def sql_quote__(self, v, escapes={}): return self._v_database_connection.string_literal(v) Globals.InitializeClass(Connection) |
From: Olavo S. <ola...@us...> - 2006-10-14 02:43:45
|
Update of /cvsroot/informixdb/zinformixda/www In directory sc8-pr-cvs2.sourceforge.net:/tmp/cvs-serv2000/zinformixda/www Added Files: bin.gif date.gif datetime.gif field.gif float.gif int.gif stable.gif table.gif text.gif time.gif view2.gif what.gif Log Message: initial source commit --- NEW FILE: field.gif --- (This appears to be a binary file; contents omitted.) --- NEW FILE: time.gif --- (This appears to be a binary file; contents omitted.) --- NEW FILE: int.gif --- (This appears to be a binary file; contents omitted.) --- NEW FILE: stable.gif --- (This appears to be a binary file; contents omitted.) --- NEW FILE: float.gif --- (This appears to be a binary file; contents omitted.) --- NEW FILE: view2.gif --- (This appears to be a binary file; contents omitted.) --- NEW FILE: datetime.gif --- (This appears to be a binary file; contents omitted.) --- NEW FILE: table.gif --- (This appears to be a binary file; contents omitted.) --- NEW FILE: date.gif --- (This appears to be a binary file; contents omitted.) --- NEW FILE: text.gif --- (This appears to be a binary file; contents omitted.) --- NEW FILE: bin.gif --- (This appears to be a binary file; contents omitted.) --- NEW FILE: what.gif --- (This appears to be a binary file; contents omitted.) |
From: Olavo S. <ola...@us...> - 2006-10-14 02:42:58
|
Update of /cvsroot/informixdb/zinformixda/dtml In directory sc8-pr-cvs2.sourceforge.net:/tmp/cvs-serv1615/dtml Log Message: Directory /cvsroot/informixdb/zinformixda/dtml added to the repository |
From: Olavo S. <ola...@us...> - 2006-10-14 02:42:58
|
Update of /cvsroot/informixdb/zinformixda/www In directory sc8-pr-cvs2.sourceforge.net:/tmp/cvs-serv1615/www Log Message: Directory /cvsroot/informixdb/zinformixda/www added to the repository |
From: Olavo S. <ola...@us...> - 2006-10-14 02:41:32
|
Update of /cvsroot/informixdb/zinformixda In directory sc8-pr-cvs2.sourceforge.net:/tmp/cvs-serv1221/zinformixda Added Files: README.txt Log Message: initial source commit --- NEW FILE: README.txt --- Z Informix DA ------------- This is the Z Informix database adapter product for the Z Object Publishing Environment. ***** IMPORTANT ***** This product is distributed as a NON-BINARY release! This product requires compiled Python extensions that are NOT included as a binary with this release. You must build or install the required extensions using the instructions below before the product will work properly! Installation Please read INSTALL.txt for more details on how to install this database adapter and DEPENDENCIES.txt for the needed packages. Support/Bugs/Features/Future If you have some question about this zope product, please drop me an email and i will be glad to help you. -- Olavo Santos <nb...@cy...> http://www.varkala.net/ |
From: Carsten H. <ch...@us...> - 2006-10-08 04:42:46
|
Update of /cvsroot/informixdb/informixdb/doc In directory sc8-pr-cvs2.sourceforge.net:/tmp/cvs-serv30323 Modified Files: manual.txt Log Message: include documentation for reading opaque types in binary format Index: manual.txt =================================================================== RCS file: /cvsroot/informixdb/informixdb/doc/manual.txt,v retrieving revision 1.13 retrieving revision 1.14 diff -C2 -d -r1.13 -r1.14 *** manual.txt 1 Oct 2006 03:22:48 -0000 1.13 --- manual.txt 8 Oct 2006 04:42:42 -0000 1.14 *************** *** 4,9 **** :Authors: Daniel Smertnig and Carsten Haese ! :Version: informixdb 2.3 ! :Date: 2006-10-01 :Homepage: `InformixDB on Sourceforge`_ --- 4,9 ---- :Authors: Daniel Smertnig and Carsten Haese ! :Version: informixdb 2.4 ! :Date: TBD :Homepage: `InformixDB on Sourceforge`_ *************** *** 440,443 **** --- 440,457 ---- Distinct types are mapped like the type from which they are derived. + `New in version 2.4`: If desired, opaque types can be fetched in their + internal binary representation. The cursor attribute ``binary_types`` + is a dictionary that controls which opaque types are fetched in binary + format. + + When a query returns values of an opaque type, the type name is looked up + in the cursor's ``binary_types`` dictionary. If the type name is found + and has a true value, the contents will be read in binary format. + Otherwise, the contents will be read in text format. + + Connection objects have a ``binary_types`` dictionary that serves as the + default for the cursors that the connection creates. This dictionary is + empty by default. + ``NULL`` SQL ``NULL`` is represented by Python's ``None`` when binding parameters |
From: Carsten H. <ch...@us...> - 2006-10-08 04:10:42
|
Update of /cvsroot/informixdb/informixdb/ext In directory sc8-pr-cvs2.sourceforge.net:/tmp/cvs-serv17741/ext Modified Files: _informixdb.ec Log Message: allow reading and writing of opaque types in binary format Index: _informixdb.ec =================================================================== RCS file: /cvsroot/informixdb/informixdb/ext/_informixdb.ec,v retrieving revision 1.75 retrieving revision 1.76 diff -C2 -d -r1.75 -r1.76 *** _informixdb.ec 8 Oct 2006 01:16:22 -0000 1.75 --- _informixdb.ec 8 Oct 2006 04:10:39 -0000 1.76 *************** *** 447,450 **** --- 447,451 ---- PyObject *messages; PyObject *errorhandler; + PyObject *binary_types; } Cursor; *************** *** 619,622 **** --- 620,627 ---- ); + PyDoc_STRVAR(Cursor_binary_types_doc, + "Dictionary that controls if opaque types are read in binary format.\n\n\ + See also: Connection.binary_types"); + static PyMemberDef Cursor_members[] = { { "description", T_OBJECT_EX, offsetof(Cursor, description), READONLY, *************** *** 634,637 **** --- 639,644 ---- { "command", T_OBJECT_EX, offsetof(Cursor, op), READONLY, "Last prepared or executed command." }, + { "binary_types", T_OBJECT_EX, offsetof(Cursor, binary_types), READONLY, + Cursor_binary_types_doc }, { NULL } }; *************** *** 714,717 **** --- 721,725 ---- PyObject *errorhandler; int autocommit; + PyObject *binary_types; } Connection; *************** *** 845,848 **** --- 853,866 ---- a Warning."); + PyDoc_STRVAR(Connection_binary_types_doc, + "Dictionary that controls if opaque types are read in binary format.\n\n\ + When a query returns an opaque type, its type name is looked up in\n\ + this dictionary. If an entry is present and has a true value, the\n\ + values are fetched in binary (internal) format. Otherwise, values\n\ + are fetched in text (external) format.\n\n\ + By default, this dictionary is empty. Cursors make a copy of this\n\ + dictionary when they are created, which allows this setting to be\n\ + overridden on a per-cursor basis."); + static PyMemberDef Connection_members[] = { { "messages", T_OBJECT_EX, offsetof(Connection, messages), READONLY, *************** *** 850,853 **** --- 868,873 ---- { "errorhandler", T_OBJECT_EX, offsetof(Connection, errorhandler), 0, Connection_errorhandler_doc }, + { "binary_types", T_OBJECT_EX, offsetof(Connection, binary_types), READONLY, + Connection_binary_types_doc }, { NULL } }; *************** *** 1197,1201 **** char *buf; Py_ssize_t n; - loc_t *loc; if (PyObject_AsReadBuffer(item, (const void**)&buf, &n) == -1) { --- 1217,1220 ---- *************** *** 1203,1220 **** } ! loc = (loc_t*) malloc(sizeof(loc_t)); ! loc->loc_loctype = LOCMEMORY; ! loc->loc_buffer = malloc((int)n); ! loc->loc_bufsize = (int)n; ! loc->loc_size = (int)n; ! loc->loc_oflags = 0; ! loc->loc_mflags = 0; ! loc->loc_indicator = 0; ! memcpy(loc->loc_buffer, buf, (int)n); ! var->sqldata = (char *) loc; ! var->sqllen = sizeof(loc_t); ! var->sqltype = CLOCATORTYPE; ! *var->sqlind = 0; return 1; } --- 1222,1266 ---- } ! $ifdef HAVE_ESQL9; ! /* If the target column is an opaque type, bind the buffer contents ! as a var binary. This, in combination with the fact that the binary ! contents of opaque types are returned as a buffer, allows for ! seamless select-insert/update roundtrips of opaque types in binary ! format. */ ! if (ISUDTTYPE(var->sqltype)) { ! EXEC SQL BEGIN DECLARE SECTION; ! var binary *data; ! EXEC SQL END DECLARE SECTION; ! data = malloc(sizeof(void*)); ! *data = 0; ! ifx_var_flag(data, 0); ! ifx_var_alloc(data, n+1); ! ifx_var_setlen(data, n); ! ifx_var_setdata(data, (char *)buf, n); ! var->sqltype = CVARBINTYPE; ! var->sqldata = *data; ! var->sqllen = sizeof(void*); ! *var->sqlind = 0; ! free( data ); ! } ! else ! $endif; ! { ! loc_t *loc; ! loc = (loc_t*) malloc(sizeof(loc_t)); ! loc->loc_loctype = LOCMEMORY; ! loc->loc_buffer = malloc((int)n); ! loc->loc_bufsize = (int)n; ! loc->loc_size = (int)n; ! loc->loc_oflags = 0; ! loc->loc_mflags = 0; ! loc->loc_indicator = 0; ! memcpy(loc->loc_buffer, buf, (int)n); ! var->sqldata = (char *) loc; ! var->sqllen = sizeof(loc_t); ! var->sqltype = CLOCATORTYPE; ! *var->sqlind = 0; ! } return 1; } *************** *** 1639,1648 **** exec sql end declare section; ! var->sqltype = CLVCHARPTRTYPE; currentlvarcharptr = malloc(sizeof(void *)); *currentlvarcharptr = 0; ifx_var_flag(currentlvarcharptr,1); - var->sqlxid = 1; var->sqldata = *currentlvarcharptr; var->sqllen = sizeof(void *); --- 1685,1708 ---- exec sql end declare section; ! if (ISUDTTYPE(var->sqltype)) { ! /* For opaque types, check if the user wants them in binary ! format instead. */ ! PyObject *binflag = PyDict_GetItemString(cur->binary_types, ! var->sqltypename); ! if (binflag && (PyObject_IsTrue(binflag)==1)) { ! var->sqltype = CVARBINTYPE; ! } ! else { ! var->sqltype = CLVCHARPTRTYPE; ! } ! } ! else { ! /* Complex types are always read in text format.*/ ! var->sqltype = CLVCHARPTRTYPE; ! } currentlvarcharptr = malloc(sizeof(void *)); *currentlvarcharptr = 0; ifx_var_flag(currentlvarcharptr,1); var->sqldata = *currentlvarcharptr; var->sqllen = sizeof(void *); *************** *** 1993,1999 **** } ! static PyObject *doCopy(/* const */ void *data, int type, int4 xid, int4 sqllen, struct Cursor_t *cur) { switch(type & SQLTYPE){ case SQLDATE: --- 2053,2060 ---- } ! static PyObject *doCopy(struct sqlvar_struct *var, int type, int4 xid, int4 sqllen, struct Cursor_t *cur) { + void *data = var->sqldata; switch(type & SQLTYPE){ case SQLDATE: *************** *** 2205,2209 **** Py_ssize_t len = ifx_var_getlen(&data); char *lvcharbuf = ifx_var_getdata(&data); ! result = PyString_FromStringAndSize(lvcharbuf,len-1); ifx_var_dealloc(&data); return result; --- 2266,2287 ---- Py_ssize_t len = ifx_var_getlen(&data); char *lvcharbuf = ifx_var_getdata(&data); ! if ((var->sqltype&SQLTYPE)==CVARBINTYPE) { ! /* If the output was bound as var binary, build a buffer object. */ ! char *b_mem; ! Py_ssize_t b_len; ! result = PyBuffer_New(len); ! ! if (PyObject_AsWriteBuffer(result, (void**)&b_mem, &b_len) == -1) { ! Py_DECREF(result); ! result = NULL; ! } ! else { ! memcpy(b_mem, lvcharbuf, (int)b_len); ! } ! } ! else { ! /* Otherwise build a string. */ ! result = PyString_FromStringAndSize(lvcharbuf,len-1); ! } ifx_var_dealloc(&data); return result; *************** *** 2242,2246 **** Py_INCREF(v); } else { ! v = doCopy(var->sqldata, cur->originalType[pos], cur->originalXid[pos], cur->originalLen[pos], cur); } --- 2320,2324 ---- Py_INCREF(v); } else { ! v = doCopy(var, cur->originalType[pos], cur->originalXid[pos], cur->originalLen[pos], cur); } *************** *** 2534,2537 **** --- 2612,2616 ---- self->arraysize = 1; self->messages = PyList_New(0); + self->binary_types = PyDict_Copy(conn->binary_types); self->errorhandler = conn->errorhandler; Py_INCREF(self->errorhandler); *************** *** 2827,2830 **** --- 2906,2910 ---- self->messages = PyList_New(0); self->errorhandler = Py_None; + self->binary_types = PyDict_New(); Py_INCREF(self->errorhandler); |
From: Carsten H. <ch...@us...> - 2006-10-08 01:16:26
|
Update of /cvsroot/informixdb/informixdb/ext In directory sc8-pr-cvs2.sourceforge.net:/tmp/cvs-serv15861/ext Modified Files: _informixdb.ec Log Message: Use the size of the data buffer when reading out UDT buffer in case we're reading binary data with embedded NULs. Index: _informixdb.ec =================================================================== RCS file: /cvsroot/informixdb/informixdb/ext/_informixdb.ec,v retrieving revision 1.74 retrieving revision 1.75 diff -C2 -d -r1.74 -r1.75 *** _informixdb.ec 6 Oct 2006 14:14:12 -0000 1.74 --- _informixdb.ec 8 Oct 2006 01:16:22 -0000 1.75 *************** *** 2203,2208 **** if (ISCOMPLEXTYPE(type)||ISUDTTYPE(type)) { PyObject *result; char *lvcharbuf = ifx_var_getdata(&data); ! result = PyString_FromString(lvcharbuf); ifx_var_dealloc(&data); return result; --- 2203,2209 ---- if (ISCOMPLEXTYPE(type)||ISUDTTYPE(type)) { PyObject *result; + Py_ssize_t len = ifx_var_getlen(&data); char *lvcharbuf = ifx_var_getdata(&data); ! result = PyString_FromStringAndSize(lvcharbuf,len-1); ifx_var_dealloc(&data); return result; |
From: Carsten H. <ch...@us...> - 2006-10-06 14:14:21
|
Update of /cvsroot/informixdb/informixdb/ext In directory sc8-pr-cvs2.sourceforge.net:/tmp/cvs-serv13729/ext Modified Files: _informixdb.ec Log Message: Fixed inadvertently broken compilation on Python < 2.4 Index: _informixdb.ec =================================================================== RCS file: /cvsroot/informixdb/informixdb/ext/_informixdb.ec,v retrieving revision 1.73 retrieving revision 1.74 diff -C2 -d -r1.73 -r1.74 *** _informixdb.ec 23 Sep 2006 15:55:43 -0000 1.73 --- _informixdb.ec 6 Oct 2006 14:14:12 -0000 1.74 *************** *** 40,43 **** --- 40,47 ---- #undef loc_t + #ifndef Py_RETURN_NONE + #define Py_RETURN_NONE return Py_INCREF(Py_None), Py_None + #endif + /* Make sure that we can use Py_ssize_t the way Python 2.5 expects us to while remaining compatible with older Python versions. */ |
From: Carsten H. <ch...@us...> - 2006-10-01 03:22:51
|
Update of /cvsroot/informixdb/informixdb/doc In directory sc8-pr-cvs2.sourceforge.net:/tmp/cvs-serv2846/doc Modified Files: manual.txt Log Message: Set 2.3 release date, minor doc update. Index: manual.txt =================================================================== RCS file: /cvsroot/informixdb/informixdb/doc/manual.txt,v retrieving revision 1.12 retrieving revision 1.13 diff -C2 -d -r1.12 -r1.13 *** manual.txt 28 Sep 2006 01:26:00 -0000 1.12 --- manual.txt 1 Oct 2006 03:22:48 -0000 1.13 *************** *** 5,9 **** :Authors: Daniel Smertnig and Carsten Haese :Version: informixdb 2.3 ! :Date: TBD :Homepage: `InformixDB on Sourceforge`_ --- 5,9 ---- :Authors: Daniel Smertnig and Carsten Haese :Version: informixdb 2.3 ! :Date: 2006-10-01 :Homepage: `InformixDB on Sourceforge`_ |
From: Carsten H. <ch...@us...> - 2006-10-01 03:22:51
|
Update of /cvsroot/informixdb/informixdb In directory sc8-pr-cvs2.sourceforge.net:/tmp/cvs-serv2846 Modified Files: README Log Message: Set 2.3 release date, minor doc update. Index: README =================================================================== RCS file: /cvsroot/informixdb/informixdb/README,v retrieving revision 1.14 retrieving revision 1.15 diff -C2 -d -r1.14 -r1.15 *** README 23 Sep 2006 15:55:43 -0000 1.14 --- README 1 Oct 2006 03:22:48 -0000 1.15 *************** *** 63,70 **** ==================== ! A Windows installer for Python 2.4 is available for download at ! http://informixdb.sourceforge.net/. Download it and run it to install ! the InformixDB module. Note that you'll need the Informix Client SDK ! to use the InformixDB module. If you're using a different version of Python, you'll have to compile --- 63,70 ---- ==================== ! Windows installers for Python 2.4 and 2.5 are available for download at ! http://informixdb.sourceforge.net/. Download the appropriate installer ! and run it to install the InformixDB module. Note that you'll need the ! Informix Client SDK or Informix Connect to use the InformixDB module. If you're using a different version of Python, you'll have to compile *************** *** 273,277 **** 2.1 2005-11-21 Carsten Haese 2.2 2006-03-26 Carsten Haese ! 2.3 TBD Carsten Haese -- --- 273,277 ---- 2.1 2005-11-21 Carsten Haese 2.2 2006-03-26 Carsten Haese ! 2.3 2006-10-01 Carsten Haese -- |
From: Carsten H. <ch...@us...> - 2006-09-28 01:26:04
|
Update of /cvsroot/informixdb/informixdb/doc In directory sc8-pr-cvs2.sourceforge.net:/tmp/cvs-serv19242 Modified Files: manual.txt Log Message: Include documentation on 'with' block handling. Index: manual.txt =================================================================== RCS file: /cvsroot/informixdb/informixdb/doc/manual.txt,v retrieving revision 1.11 retrieving revision 1.12 diff -C2 -d -r1.11 -r1.12 *** manual.txt 13 Sep 2006 03:28:47 -0000 1.11 --- manual.txt 28 Sep 2006 01:26:00 -0000 1.12 *************** *** 61,64 **** --- 61,83 ---- the connection to be closed or deallocated first). + `New in version 2.3`: Connections and cursors support the context management + protocol for Python 2.5 `with` blocks. This allows code like this:: + + conn = informixdb.connect(...) + try: + cur = conn.cursor() + try: + # do something with cur + finally: + cur.close() + finally: + conn.close() + + to be written in Python 2.5 more concisely as:: + + with informixdb.connect(...) as conn: + with conn.cursor() as cur: + # do something with cur + Executing SQL statements ======================== |
From: Carsten H. <ch...@us...> - 2006-09-23 15:55:57
|
Update of /cvsroot/informixdb/informixdb/ext In directory sc8-pr-cvs2.sourceforge.net:/tmp/cvs-serv985/ext Modified Files: _informixdb.ec Log Message: Necessary changes for Python 2.5 compatibility Index: _informixdb.ec =================================================================== RCS file: /cvsroot/informixdb/informixdb/ext/_informixdb.ec,v retrieving revision 1.72 retrieving revision 1.73 diff -C2 -d -r1.72 -r1.73 *** _informixdb.ec 22 Sep 2006 00:12:09 -0000 1.72 --- _informixdb.ec 23 Sep 2006 15:55:43 -0000 1.73 *************** *** 2,6 **** * Copyright (c) 1997 by IV DocEye AB * Copyright (c) 1999 by Stephen J. Turner ! * Copyright (c) 2005 by Carsten Haese * * By obtaining, using, and/or copying this software and/or its --- 2,6 ---- * Copyright (c) 1997 by IV DocEye AB * Copyright (c) 1999 by Stephen J. Turner ! * Copyright (c) 2006 by Carsten Haese * * By obtaining, using, and/or copying this software and/or its *************** *** 40,43 **** --- 40,49 ---- #undef loc_t + /* Make sure that we can use Py_ssize_t the way Python 2.5 expects us to + while remaining compatible with older Python versions. */ + #if PY_VERSION_HEX < 0x02050000 + typedef int Py_ssize_t; + #endif + #define _da_free(x) free(x) #define _loc_free(x) free(x) *************** *** 1186,1190 **** { char *buf; ! int n; loc_t *loc; --- 1192,1196 ---- { char *buf; ! Py_ssize_t n; loc_t *loc; *************** *** 1195,1205 **** loc = (loc_t*) malloc(sizeof(loc_t)); loc->loc_loctype = LOCMEMORY; ! loc->loc_buffer = malloc(n); ! loc->loc_bufsize = n; ! loc->loc_size = n; loc->loc_oflags = 0; loc->loc_mflags = 0; loc->loc_indicator = 0; ! memcpy(loc->loc_buffer, buf, n); var->sqldata = (char *) loc; --- 1201,1211 ---- loc = (loc_t*) malloc(sizeof(loc_t)); loc->loc_loctype = LOCMEMORY; ! loc->loc_buffer = malloc((int)n); ! loc->loc_bufsize = (int)n; ! loc->loc_size = (int)n; loc->loc_oflags = 0; loc->loc_mflags = 0; loc->loc_indicator = 0; ! memcpy(loc->loc_buffer, buf, (int)n); var->sqldata = (char *) loc; *************** *** 1475,1479 **** { struct sqlvar_struct *var = cur->daIn.sqlvar; ! int n_vars = vars ? PyObject_Length(vars) : 0; int i; int maxp=0; --- 1481,1485 ---- { struct sqlvar_struct *var = cur->daIn.sqlvar; ! int n_vars = vars ? (int)PyObject_Length(vars) : 0; int i; int maxp=0; *************** *** 2159,2163 **** PyObject *buffer; char *b_mem; ! int b_len; loc_t *l = (loc_t*)data; --- 2165,2169 ---- PyObject *buffer; char *b_mem; ! Py_ssize_t b_len; loc_t *l = (loc_t*)data; *************** *** 2170,2174 **** } ! memcpy(b_mem, l->loc_buffer, b_len); return buffer; } /* case SQLTEXT */ --- 2176,2180 ---- } ! memcpy(b_mem, l->loc_buffer, (int)b_len); return buffer; } /* case SQLTEXT */ *************** *** 2261,2265 **** Py_INCREF(self); PyTuple_SET_ITEM(a, 0, (PyObject*)self); ! for (i = 0; i < PyTuple_Size(args); ++i) { PyObject *o = PyTuple_GetItem(args, i); Py_INCREF(o); --- 2267,2271 ---- Py_INCREF(self); PyTuple_SET_ITEM(a, 0, (PyObject*)self); ! for (i = 0; i < (int)PyTuple_Size(args); ++i) { PyObject *o = PyTuple_GetItem(args, i); Py_INCREF(o); *************** *** 2284,2288 **** PyTuple_SET_ITEM(a, 0, (PyObject*)self); PyTuple_SET_ITEM(a, 1, PyInt_FromLong(1)); ! for (i = 0; i < PyTuple_Size(args); ++i) { PyObject *o = PyTuple_GetItem(args, i); Py_INCREF(o); --- 2290,2294 ---- PyTuple_SET_ITEM(a, 0, (PyObject*)self); PyTuple_SET_ITEM(a, 1, PyInt_FromLong(1)); ! for (i = 0; i < (int)PyTuple_Size(args); ++i) { PyObject *o = PyTuple_GetItem(args, i); Py_INCREF(o); *************** *** 2761,2765 **** } ! p_count = PySequence_Length(params); p_str = malloc(p_count * 2); --- 2767,2771 ---- } ! p_count = (int)PySequence_Length(params); p_str = malloc(p_count * 2); *************** *** 2929,2933 **** f = PyString_FromString("%s: %s\n"); ! for (i = 0; i < PyList_Size(diags); ++i) { PyObject* d = PyList_GetItem(diags, i); a = Py_BuildValue("(OO)", PyDict_GetItemString(d, "sqlstate"), --- 2935,2939 ---- f = PyString_FromString("%s: %s\n"); ! for (i = 0; i < (int)PyList_Size(diags); ++i) { PyObject* d = PyList_GetItem(diags, i); a = Py_BuildValue("(OO)", PyDict_GetItemString(d, "sqlstate"), |