mirror of
https://github.com/psycopg/psycopg2.git
synced 2025-01-31 17:34:08 +03:00
Applied COPY patch from Alejandro Dubrovsky
This commit is contained in:
parent
b9157c8ba1
commit
c1d6073531
|
@ -40,7 +40,7 @@
|
||||||
|
|
||||||
#ifndef PSYCOPG_OWN_QUOTING
|
#ifndef PSYCOPG_OWN_QUOTING
|
||||||
size_t
|
size_t
|
||||||
qstring_escape(char *to, char *from, size_t len, PGconn *conn)
|
qstring_escape(char *to, const char *from, size_t len, PGconn *conn)
|
||||||
{
|
{
|
||||||
#if PG_MAJOR_VERSION > 8 || \
|
#if PG_MAJOR_VERSION > 8 || \
|
||||||
(PG_MAJOR_VERSION == 8 && PG_MINOR_VERSION > 1) || \
|
(PG_MAJOR_VERSION == 8 && PG_MINOR_VERSION > 1) || \
|
||||||
|
@ -54,7 +54,7 @@ qstring_escape(char *to, char *from, size_t len, PGconn *conn)
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
size_t
|
size_t
|
||||||
qstring_escape(char *to, char *from, size_t len, PGconn *conn)
|
qstring_escape(char *to, const char *from, size_t len, PGconn *conn)
|
||||||
{
|
{
|
||||||
int i, j;
|
int i, j;
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,9 @@
|
||||||
#include "psycopg/typecast.h"
|
#include "psycopg/typecast.h"
|
||||||
#include "psycopg/microprotocols.h"
|
#include "psycopg/microprotocols.h"
|
||||||
#include "psycopg/microprotocols_proto.h"
|
#include "psycopg/microprotocols_proto.h"
|
||||||
|
#include "psycopg/utils.h"
|
||||||
#include "pgversion.h"
|
#include "pgversion.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
extern PyObject *pyPsycopgTzFixedOffsetTimezone;
|
extern PyObject *pyPsycopgTzFixedOffsetTimezone;
|
||||||
|
|
||||||
|
@ -1113,7 +1115,7 @@ psyco_curs_scroll(cursorObject *self, PyObject *args, PyObject *kwargs)
|
||||||
|
|
||||||
#ifdef PSYCOPG_EXTENSIONS
|
#ifdef PSYCOPG_EXTENSIONS
|
||||||
|
|
||||||
#define COPY_BUFFER_SIZE 1024
|
#define COPY_BUFFER_SIZE 8192
|
||||||
|
|
||||||
static int _psyco_curs_copy_columns(PyObject *columns, char *columnlist)
|
static int _psyco_curs_copy_columns(PyObject *columns, char *columnlist)
|
||||||
{
|
{
|
||||||
|
@ -1187,12 +1189,15 @@ _psyco_curs_has_read_check(PyObject* o, void* var)
|
||||||
static PyObject *
|
static PyObject *
|
||||||
psyco_curs_copy_from(cursorObject *self, PyObject *args, PyObject *kwargs)
|
psyco_curs_copy_from(cursorObject *self, PyObject *args, PyObject *kwargs)
|
||||||
{
|
{
|
||||||
char query[DEFAULT_COPYBUFF];
|
char query_buffer[COPY_BUFFER_SIZE];
|
||||||
|
size_t query_size;
|
||||||
|
char *query;
|
||||||
const char *table_name;
|
const char *table_name;
|
||||||
const char *sep = "\t", *null = NULL;
|
const char *sep = "\t", *null = NULL;
|
||||||
Py_ssize_t bufsize = DEFAULT_COPYBUFF;
|
Py_ssize_t bufsize = DEFAULT_COPYBUFF;
|
||||||
PyObject *file, *columns = NULL, *res = NULL;
|
PyObject *file, *columns = NULL, *res = NULL;
|
||||||
char columnlist[DEFAULT_COPYBUFF];
|
char columnlist[DEFAULT_COPYBUFF];
|
||||||
|
char *quoted_delimiter;
|
||||||
|
|
||||||
static char *kwlist[] = {"file", "table", "sep", "null", "size",
|
static char *kwlist[] = {"file", "table", "sep", "null", "size",
|
||||||
"columns", NULL};
|
"columns", NULL};
|
||||||
|
@ -1211,16 +1216,44 @@ psyco_curs_copy_from(cursorObject *self, PyObject *args, PyObject *kwargs)
|
||||||
|
|
||||||
EXC_IF_CURS_CLOSED(self);
|
EXC_IF_CURS_CLOSED(self);
|
||||||
|
|
||||||
|
quoted_delimiter = psycopg_internal_escape_string(self->conn, sep);
|
||||||
|
if (NULL == quoted_delimiter) {
|
||||||
|
PyErr_SetString(PyExc_ValueError, "Failed to quote delimiter");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
query = query_buffer;
|
||||||
if (null) {
|
if (null) {
|
||||||
PyOS_snprintf(query, DEFAULT_COPYBUFF-1,
|
char *quoted_null = psycopg_internal_escape_string(self->conn, null);
|
||||||
"COPY %s%s FROM stdin USING DELIMITERS '%s'"
|
if (NULL == quoted_null) {
|
||||||
" WITH NULL AS '%s'", table_name, columnlist, sep, null);
|
PyErr_SetString(PyExc_ValueError, "Failed to quote null-marker");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
query_size = PyOS_snprintf(query, COPY_BUFFER_SIZE,
|
||||||
|
"COPY %s%s FROM stdin WITH DELIMITER AS %s"
|
||||||
|
" NULL AS %s", table_name, columnlist, quoted_delimiter, quoted_null);
|
||||||
|
if (query_size >= COPY_BUFFER_SIZE) {
|
||||||
|
/* Got truncated, allocate dynamically */
|
||||||
|
query = (char *) malloc((query_size + 1) * sizeof(char));
|
||||||
|
PyOS_snprintf(query, query_size + 1,
|
||||||
|
"COPY %s%s FROM stdin WITH DELIMITER AS %s"
|
||||||
|
" NULL AS %s", table_name, columnlist, quoted_delimiter, quoted_null);
|
||||||
|
}
|
||||||
|
free(quoted_null);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
PyOS_snprintf(query, DEFAULT_COPYBUFF-1,
|
query_size = PyOS_snprintf(query, COPY_BUFFER_SIZE,
|
||||||
"COPY %s%s FROM stdin USING DELIMITERS '%s'",
|
"COPY %s%s FROM stdin WITH DELIMITER AS %s",
|
||||||
table_name, columnlist, sep);
|
table_name, columnlist, quoted_delimiter);
|
||||||
|
if (query_size >= COPY_BUFFER_SIZE) {
|
||||||
|
/* Got truncated, allocate dynamically */
|
||||||
|
query = (char *) malloc((query_size + 1) * sizeof(char));
|
||||||
|
PyOS_snprintf(query, query_size + 1,
|
||||||
|
"COPY %s%s FROM stdin WITH DELIMITER AS %s",
|
||||||
|
table_name, columnlist, quoted_delimiter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
free(quoted_delimiter);
|
||||||
Dprintf("psyco_curs_copy_from: query = %s", query);
|
Dprintf("psyco_curs_copy_from: query = %s", query);
|
||||||
|
|
||||||
self->copysize = bufsize;
|
self->copysize = bufsize;
|
||||||
|
@ -1231,6 +1264,9 @@ psyco_curs_copy_from(cursorObject *self, PyObject *args, PyObject *kwargs)
|
||||||
Py_INCREF(Py_None);
|
Py_INCREF(Py_None);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (query && (query != query_buffer)) {
|
||||||
|
free(query);
|
||||||
|
}
|
||||||
self->copyfile =NULL;
|
self->copyfile =NULL;
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
|
@ -1260,11 +1296,14 @@ _psyco_curs_has_write_check(PyObject* o, void* var)
|
||||||
static PyObject *
|
static PyObject *
|
||||||
psyco_curs_copy_to(cursorObject *self, PyObject *args, PyObject *kwargs)
|
psyco_curs_copy_to(cursorObject *self, PyObject *args, PyObject *kwargs)
|
||||||
{
|
{
|
||||||
char query[DEFAULT_COPYBUFF];
|
char *query = NULL;
|
||||||
|
char query_buffer[COPY_BUFFER_SIZE];
|
||||||
|
size_t query_size;
|
||||||
char columnlist[DEFAULT_COPYBUFF];
|
char columnlist[DEFAULT_COPYBUFF];
|
||||||
const char *table_name;
|
const char *table_name;
|
||||||
const char *sep = "\t", *null = NULL;
|
const char *sep = "\t", *null = NULL;
|
||||||
PyObject *file, *columns = NULL, *res = NULL;
|
PyObject *file, *columns = NULL, *res = NULL;
|
||||||
|
char *quoted_delimiter;
|
||||||
|
|
||||||
static char *kwlist[] = {"file", "table", "sep", "null", "columns", NULL};
|
static char *kwlist[] = {"file", "table", "sep", "null", "columns", NULL};
|
||||||
|
|
||||||
|
@ -1278,17 +1317,46 @@ psyco_curs_copy_to(cursorObject *self, PyObject *args, PyObject *kwargs)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
EXC_IF_CURS_CLOSED(self);
|
EXC_IF_CURS_CLOSED(self);
|
||||||
|
quoted_delimiter = psycopg_internal_escape_string(self->conn, sep);
|
||||||
|
if (NULL == quoted_delimiter) {
|
||||||
|
PyErr_SetString(PyExc_ValueError, "Failed to quote delimiter");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
query = query_buffer;
|
||||||
if (null) {
|
if (null) {
|
||||||
PyOS_snprintf(query, DEFAULT_COPYBUFF-1,
|
char *quoted_null = psycopg_internal_escape_string(self->conn, null);
|
||||||
"COPY %s%s TO stdout USING DELIMITERS '%s'"
|
if (NULL == quoted_null) {
|
||||||
" WITH NULL AS '%s'", table_name, columnlist, sep, null);
|
PyErr_SetString(PyExc_ValueError, "Failed to quote null-marker");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
query_size = PyOS_snprintf(query, COPY_BUFFER_SIZE,
|
||||||
|
"COPY %s%s TO stdout WITH DELIMITER AS %s"
|
||||||
|
" NULL AS %s", table_name, columnlist, quoted_delimiter, quoted_null);
|
||||||
|
|
||||||
|
if (query_size >= COPY_BUFFER_SIZE) {
|
||||||
|
/* Got truncated, allocate dynamically */
|
||||||
|
query = (char *) malloc((query_size + 1) * sizeof(char));
|
||||||
|
PyOS_snprintf(query, query_size + 1,
|
||||||
|
"COPY %s%s TO stdout WITH DELIMITER AS %s"
|
||||||
|
" NULL AS %s", table_name, columnlist, quoted_delimiter, quoted_null);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
PyOS_snprintf(query, DEFAULT_COPYBUFF-1,
|
query_size = PyOS_snprintf(query, COPY_BUFFER_SIZE,
|
||||||
"COPY %s%s TO stdout USING DELIMITERS '%s'",
|
"COPY %s%s TO stdout WITH DELIMITER AS %s",
|
||||||
table_name, columnlist, sep);
|
table_name, columnlist, quoted_delimiter);
|
||||||
|
if (query_size >= COPY_BUFFER_SIZE) {
|
||||||
|
/* Got truncated, allocate dynamically */
|
||||||
|
query = (char *) malloc((query_size + 1) * sizeof(char));
|
||||||
|
PyOS_snprintf(query, query_size + 1,
|
||||||
|
"COPY %s%s TO stdout WITH DELIMITER AS %s",
|
||||||
|
table_name, columnlist, quoted_delimiter);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
free(quoted_delimiter);
|
||||||
|
|
||||||
self->copysize = 0;
|
self->copysize = 0;
|
||||||
self->copyfile = file;
|
self->copyfile = file;
|
||||||
|
@ -1297,7 +1365,9 @@ psyco_curs_copy_to(cursorObject *self, PyObject *args, PyObject *kwargs)
|
||||||
res = Py_None;
|
res = Py_None;
|
||||||
Py_INCREF(Py_None);
|
Py_INCREF(Py_None);
|
||||||
}
|
}
|
||||||
|
if (query && (query != query_buffer)) {
|
||||||
|
free(query);
|
||||||
|
}
|
||||||
self->copyfile = NULL;
|
self->copyfile = NULL;
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
|
|
|
@ -143,7 +143,7 @@ HIDDEN PyObject *psyco_GetDecimalType(void);
|
||||||
HIDDEN void psyco_set_error(PyObject *exc, PyObject *curs, const char *msg,
|
HIDDEN void psyco_set_error(PyObject *exc, PyObject *curs, const char *msg,
|
||||||
const char *pgerror, const char *pgcode);
|
const char *pgerror, const char *pgcode);
|
||||||
|
|
||||||
HIDDEN size_t qstring_escape(char *to, char *from, size_t len, PGconn *conn);
|
HIDDEN size_t qstring_escape(char *to, const char *from, size_t len, PGconn *conn);
|
||||||
|
|
||||||
/* Exceptions docstrings */
|
/* Exceptions docstrings */
|
||||||
#define Error_doc \
|
#define Error_doc \
|
||||||
|
|
2
setup.py
2
setup.py
|
@ -330,7 +330,7 @@ sources = [
|
||||||
'connection_type.c', 'connection_int.c', 'cursor_type.c', 'cursor_int.c',
|
'connection_type.c', 'connection_int.c', 'cursor_type.c', 'cursor_int.c',
|
||||||
'lobject_type.c', 'lobject_int.c',
|
'lobject_type.c', 'lobject_int.c',
|
||||||
'adapter_qstring.c', 'adapter_pboolean.c', 'adapter_binary.c',
|
'adapter_qstring.c', 'adapter_pboolean.c', 'adapter_binary.c',
|
||||||
'adapter_asis.c', 'adapter_list.c']
|
'adapter_asis.c', 'adapter_list.c', 'utils.c']
|
||||||
|
|
||||||
parser = ConfigParser.ConfigParser()
|
parser = ConfigParser.ConfigParser()
|
||||||
parser.read('setup.cfg')
|
parser.read('setup.cfg')
|
||||||
|
|
Loading…
Reference in New Issue
Block a user