mirror of
https://github.com/psycopg/psycopg2.git
synced 2025-01-31 09:24:07 +03:00
Various fixes, now all examples work.
This commit is contained in:
parent
8274a032b1
commit
d6e232e2b9
10
ChangeLog
10
ChangeLog
|
@ -1,5 +1,15 @@
|
|||
2007-04-14 Federico Di Gregorio <fog@initd.org>
|
||||
|
||||
* psycopg/psycopg.h: fixed probable typo in definition of
|
||||
CONV_CODE_PY_SSIZE_T: d -> i for Python < 2.5.
|
||||
|
||||
* Fixed some of the examples.
|
||||
|
||||
2007-04-13 Federico Di Gregorio <fog@initd.org>
|
||||
|
||||
* Applied slighly modified patch from daniel (#176). Made
|
||||
buffer size a compile-time parameter.
|
||||
|
||||
* Applied patch from David Rushby: typecast_binary.c cleanup.
|
||||
|
||||
* Applied patch from David Rushby for int->size_t transition.
|
||||
|
|
19
NEWS
19
NEWS
|
@ -1,22 +1,21 @@
|
|||
What's new in psycopg 2.0.6
|
||||
---------------------------
|
||||
|
||||
* Full support for PostgreSQL 8.2, including NULLs in arrays.
|
||||
|
||||
* Full support for Python 2.5 and 64 bit architectures.
|
||||
|
||||
* Support for almost all PostgreSQL encodings.
|
||||
|
||||
* Better management of times and dates both from Python and in Zope.
|
||||
* Better support for PostgreSQL, Python and win32:
|
||||
- full support for PostgreSQL 8.2, including NULLs in arrays
|
||||
- support for almost all existing PostgreSQL encodings
|
||||
- full list of PostgreSQL error codes available by importing the
|
||||
psycopg2.errorcodes module
|
||||
- full support for Python 2.5 and 64 bit architectures
|
||||
- better build support on win32 platform
|
||||
|
||||
* Support for per-connection type-casters (used by ZPsycopgDA too, this
|
||||
fixes a long standing bug that made different connections use a random
|
||||
set of date/time type-casters instead of the configured one.)
|
||||
|
||||
* We now have a full list of PostgreSQL error codes available by
|
||||
importing the psycopg2.errorcodes module.
|
||||
* Better management of times and dates both from Python and in Zope.
|
||||
|
||||
* Better build support on win32 platform.
|
||||
* copy_to and copy_from now take an extra "columns" parameter.
|
||||
|
||||
* Fixed some small buglets and build glitches:
|
||||
- removed double mutex destroy
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
# See the LICENSE file for details.
|
||||
|
||||
|
||||
ALLOWED_PSYCOPG_VERSIONS = ('2.0.5', '2.0.6b2', '2.0.6')
|
||||
ALLOWED_PSYCOPG_VERSIONS = ('2.0.6',)
|
||||
|
||||
import sys
|
||||
import time
|
||||
|
|
|
@ -45,8 +45,8 @@ conn.commit()
|
|||
|
||||
io = open('copy_from.txt', 'wr')
|
||||
data = ['Tom\tJenkins\t37\n',
|
||||
'Madonna\t\N\t45\n',
|
||||
'Federico\tDi Gregorio\t\N\n']
|
||||
'Madonna\t\\N\t45\n',
|
||||
'Federico\tDi Gregorio\t\\N\n']
|
||||
io.writelines(data)
|
||||
io.close()
|
||||
|
||||
|
|
|
@ -63,6 +63,7 @@ typedef struct {
|
|||
PyObject *copyfile; /* file-like used during COPY TO/FROM ops */
|
||||
Py_ssize_t copysize; /* size of the copy buffer during COPY TO/FROM ops */
|
||||
#define DEFAULT_COPYSIZE 16384
|
||||
#define DEFAULT_COPYBUFF 1024
|
||||
|
||||
PyObject *tuple_factory; /* factory for result tuples */
|
||||
PyObject *tzinfo_factory; /* factory for tzinfo objects */
|
||||
|
|
|
@ -88,15 +88,6 @@ _mogrify(PyObject *var, PyObject *fmt, connectionObject *conn, PyObject **new)
|
|||
c = PyString_AsString(fmt);
|
||||
|
||||
while(*c) {
|
||||
/* check if some crazy guy mixed formats */
|
||||
if (kind == 2) {
|
||||
Py_XDECREF(n);
|
||||
psyco_set_error(ProgrammingError, (PyObject*)conn,
|
||||
"argument formats can't be mixed", NULL, NULL);
|
||||
return -1;
|
||||
}
|
||||
kind = 1;
|
||||
|
||||
/* handle plain percent symbol in format string */
|
||||
if (c[0] == '%' && c[1] == '%') {
|
||||
c+=2; force = 1;
|
||||
|
@ -110,6 +101,15 @@ _mogrify(PyObject *var, PyObject *fmt, connectionObject *conn, PyObject **new)
|
|||
*/
|
||||
else if (c[0] == '%' && c[1] == '(') {
|
||||
|
||||
/* check if some crazy guy mixed formats */
|
||||
if (kind == 2) {
|
||||
Py_XDECREF(n);
|
||||
psyco_set_error(ProgrammingError, (PyObject*)conn,
|
||||
"argument formats can't be mixed", NULL, NULL);
|
||||
return -1;
|
||||
}
|
||||
kind = 1;
|
||||
|
||||
/* let's have d point the end of the argument */
|
||||
for (d = c + 2; *d && *d != ')'; d++);
|
||||
|
||||
|
@ -1076,6 +1076,55 @@ psyco_curs_scroll(cursorObject *self, PyObject *args, PyObject *kwargs)
|
|||
|
||||
#ifdef PSYCOPG_EXTENSIONS
|
||||
|
||||
#define COPY_BUFFER_SIZE 1024
|
||||
|
||||
static int _psyco_curs_copy_columns(PyObject *columns, char *columnlist)
|
||||
{
|
||||
PyObject *col, *coliter;
|
||||
Py_ssize_t collen;
|
||||
char* colname;
|
||||
int offset = 1;
|
||||
|
||||
columnlist[0] = '\0';
|
||||
if (columns == NULL || columns == Py_None) return 0;
|
||||
|
||||
coliter = PyObject_GetIter(columns);
|
||||
if (coliter == NULL) return 0;
|
||||
|
||||
columnlist[0] = '(';
|
||||
|
||||
while ((col = PyIter_Next(coliter)) != NULL) {
|
||||
if (!PyString_Check(col)) {
|
||||
Py_DECREF(col);
|
||||
Py_DECREF(coliter);
|
||||
PyErr_SetString(PyExc_ValueError,
|
||||
"elements in column list must be strings");
|
||||
return -1;
|
||||
}
|
||||
PyString_AsStringAndSize(col, &colname, &collen);
|
||||
if (offset + collen > DEFAULT_COPYBUFF - 2) {
|
||||
Py_DECREF(col);
|
||||
Py_DECREF(coliter);
|
||||
PyErr_SetString(PyExc_ValueError, "column list too long");
|
||||
return -1;
|
||||
}
|
||||
strncpy(&columnlist[offset], colname, collen);
|
||||
offset += collen;
|
||||
columnlist[offset++] = ',';
|
||||
Py_DECREF(col);
|
||||
}
|
||||
Py_DECREF(coliter);
|
||||
|
||||
if (offset == 2) {
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
columnlist[offset - 1] = ')';
|
||||
columnlist[offset] = '\0';
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* extension: copy_from - implements COPY FROM */
|
||||
|
||||
#define psyco_curs_copy_from_doc \
|
||||
|
@ -1100,12 +1149,12 @@ _psyco_curs_has_read_check(PyObject* o, void* var)
|
|||
static PyObject *
|
||||
psyco_curs_copy_from(cursorObject *self, PyObject *args, PyObject *kwargs)
|
||||
{
|
||||
char query[1024];
|
||||
char query[DEFAULT_COPYBUFF];
|
||||
char *table_name;
|
||||
char *sep = "\t", *null = NULL;
|
||||
Py_ssize_t bufsize = DEFAULT_COPYSIZE;
|
||||
Py_ssize_t bufsize = DEFAULT_COPYBUFF;
|
||||
PyObject *file, *columns = NULL, *res = NULL;
|
||||
char columnlist[1024] = "";
|
||||
char columnlist[DEFAULT_COPYBUFF];
|
||||
|
||||
static char *kwlist[] = {"file", "table", "sep", "null", "size",
|
||||
"columns", NULL};
|
||||
|
@ -1119,58 +1168,19 @@ psyco_curs_copy_from(cursorObject *self, PyObject *args, PyObject *kwargs)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
if (columns != NULL && columns != Py_None) {
|
||||
PyObject* collistiter = PyObject_GetIter(columns);
|
||||
PyObject* col;
|
||||
Py_ssize_t collistlen = 2;
|
||||
Py_ssize_t colitemlen;
|
||||
char* colname;
|
||||
if (collistiter == NULL) {
|
||||
if (_psyco_curs_copy_columns(columns, columnlist) == -1)
|
||||
return NULL;
|
||||
}
|
||||
strcpy(columnlist, " (");
|
||||
while ((col = PyIter_Next(collistiter)) != NULL) {
|
||||
if (!PyString_Check(col)) {
|
||||
Py_DECREF(col);
|
||||
Py_DECREF(collistiter);
|
||||
PyErr_SetString(PyExc_ValueError,
|
||||
"Elements in column list must be strings");
|
||||
return NULL;
|
||||
}
|
||||
PyString_AsStringAndSize(col, &colname, &colitemlen);
|
||||
if (collistlen + colitemlen > 1022) {
|
||||
Py_DECREF(col);
|
||||
Py_DECREF(collistiter);
|
||||
PyErr_SetString(PyExc_ValueError, "Column list too long");
|
||||
return NULL;
|
||||
}
|
||||
strncpy(&columnlist[collistlen], colname, colitemlen);
|
||||
collistlen += colitemlen;
|
||||
columnlist[collistlen++] = ',';
|
||||
Py_DECREF(col);
|
||||
}
|
||||
Py_DECREF(collistiter);
|
||||
|
||||
if (collistlen == 2) { /* empty list; we printed no comma */
|
||||
collistlen++;
|
||||
}
|
||||
|
||||
columnlist[collistlen - 1] = ')';
|
||||
columnlist[collistlen] = '\0';
|
||||
}
|
||||
|
||||
if (PyErr_Occurred()) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
EXC_IF_CURS_CLOSED(self);
|
||||
|
||||
if (null) {
|
||||
PyOS_snprintf(query, 1023, "COPY %s%s FROM stdin USING DELIMITERS '%s'"
|
||||
PyOS_snprintf(query, DEFAULT_COPYBUFF-1,
|
||||
"COPY %s%s FROM stdin USING DELIMITERS '%s'"
|
||||
" WITH NULL AS '%s'", table_name, columnlist, sep, null);
|
||||
}
|
||||
else {
|
||||
PyOS_snprintf(query, 1023, "COPY %s%s FROM stdin USING DELIMITERS '%s'",
|
||||
PyOS_snprintf(query, DEFAULT_COPYBUFF-1,
|
||||
"COPY %s%s FROM stdin USING DELIMITERS '%s'",
|
||||
table_name, columnlist, sep);
|
||||
}
|
||||
Dprintf("psyco_curs_copy_from: query = %s", query);
|
||||
|
@ -1188,8 +1198,10 @@ psyco_curs_copy_from(cursorObject *self, PyObject *args, PyObject *kwargs)
|
|||
return res;
|
||||
}
|
||||
|
||||
/* extension: copy_to - implements COPY TO */
|
||||
|
||||
#define psyco_curs_copy_to_doc \
|
||||
"copy_to(file, table, sep='\\t', null='\\N') -- Copy table to file."
|
||||
"copy_to(file, table, sep='\\t', null='\\N', columns=None) -- Copy table to file."
|
||||
|
||||
static int
|
||||
_psyco_curs_has_write_check(PyObject* o, void* var)
|
||||
|
@ -1209,28 +1221,34 @@ _psyco_curs_has_write_check(PyObject* o, void* var)
|
|||
static PyObject *
|
||||
psyco_curs_copy_to(cursorObject *self, PyObject *args, PyObject *kwargs)
|
||||
{
|
||||
char query[256];
|
||||
char query[DEFAULT_COPYBUFF];
|
||||
char columnlist[DEFAULT_COPYBUFF];
|
||||
char *table_name;
|
||||
char *sep = "\t", *null = NULL;
|
||||
PyObject *file, *res = NULL;
|
||||
PyObject *file, *columns = NULL, *res = NULL;
|
||||
|
||||
static char *kwlist[] = {"file", "table", "sep", "null", NULL};
|
||||
static char *kwlist[] = {"file", "table", "sep", "null", "columns", NULL};
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&s|ss", kwlist,
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&s|ssO", kwlist,
|
||||
_psyco_curs_has_write_check, &file,
|
||||
&table_name, &sep, &null)) {
|
||||
&table_name, &sep, &null, &columns)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (_psyco_curs_copy_columns(columns, columnlist) == -1)
|
||||
return NULL;
|
||||
|
||||
EXC_IF_CURS_CLOSED(self);
|
||||
|
||||
if (null) {
|
||||
PyOS_snprintf(query, 255, "COPY %s TO stdout USING DELIMITERS '%s'"
|
||||
" WITH NULL AS '%s'", table_name, sep, null);
|
||||
PyOS_snprintf(query, DEFAULT_COPYBUFF-1,
|
||||
"COPY %s%s TO stdout USING DELIMITERS '%s'"
|
||||
" WITH NULL AS '%s'", table_name, columnlist, sep, null);
|
||||
}
|
||||
else {
|
||||
PyOS_snprintf(query, 255, "COPY %s TO stdout USING DELIMITERS '%s'",
|
||||
table_name, sep);
|
||||
PyOS_snprintf(query, DEFAULT_COPYBUFF-1,
|
||||
"COPY %s%s TO stdout USING DELIMITERS '%s'",
|
||||
table_name, columnlist, sep);
|
||||
}
|
||||
|
||||
self->copysize = 0;
|
||||
|
|
|
@ -48,7 +48,7 @@ extern "C" {
|
|||
#if PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION >= 5
|
||||
#define CONV_CODE_PY_SSIZE_T "n"
|
||||
#else
|
||||
#define CONV_CODE_PY_SSIZE_T "d"
|
||||
#define CONV_CODE_PY_SSIZE_T "i"
|
||||
|
||||
typedef int Py_ssize_t;
|
||||
#define PY_SSIZE_T_MIN INT_MIN
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
[build_ext]
|
||||
define=PSYCOPG_EXTENSIONS,PSYCOPG_DISPLAY_SIZE,PSYCOPG_NEW_BOOLEAN,HAVE_PQFREEMEM,HAVE_PQPROTOCOL3
|
||||
define=PSYCOPG_EXTENSIONS,PSYCOPG_DISPLAY_SIZE,PSYCOPG_NEW_BOOLEAN,HAVE_PQFREEMEM,HAVE_PQPROTOCOL3,PSYCOPG_DEBUG
|
||||
# PSYCOPG_EXTENSIONS enables extensions to PEP-249 (you really want this)
|
||||
# PSYCOPG_DISPLAY_SIZE enable display size calculation (a little slower)
|
||||
# HAVE_PQFREEMEM should be defined on PostgreSQL >= 7.4
|
||||
|
|
2
setup.py
2
setup.py
|
@ -54,7 +54,7 @@ from distutils.command.build_ext import build_ext
|
|||
from distutils.sysconfig import get_python_inc
|
||||
from distutils.ccompiler import get_default_compiler
|
||||
|
||||
PSYCOPG_VERSION = '2.0.6b2'
|
||||
PSYCOPG_VERSION = '2.0.6'
|
||||
version_flags = []
|
||||
|
||||
PLATFORM_IS_WINDOWS = sys.platform.lower().startswith('win')
|
||||
|
|
Loading…
Reference in New Issue
Block a user