From 12b2823c325ffad3f9a8c655a47454384ba02ef5 Mon Sep 17 00:00:00 2001 From: vimiix Date: Wed, 20 Sep 2023 17:01:16 +0800 Subject: [PATCH] fix:convert empty string to NULL in A compatibility mode --- psycopg/connection.h | 9 +++++++++ psycopg/connection_type.c | 20 ++++++++++++++++++++ psycopg/cursor_type.c | 14 ++++++++++++-- 3 files changed, 41 insertions(+), 2 deletions(-) diff --git a/psycopg/connection.h b/psycopg/connection.h index 6d61c2e..ff3894e 100644 --- a/psycopg/connection.h +++ b/psycopg/connection.h @@ -46,6 +46,13 @@ extern "C" { #define STATE_ON 1 #define STATE_DEFAULT 2 +/* sql_compatibility values */ +#define SQL_COMPATIBILITY_A 1 +#define SQL_COMPATIBILITY_OTHER 5 +// #define SQL_COMPATIBILITY_B 2 +// #define SQL_COMPATIBILITY_C 3 +// #define SQL_COMPATIBILITY_PG 4 + /* connection status */ #define CONN_STATUS_SETUP 0 #define CONN_STATUS_READY 1 @@ -148,6 +155,8 @@ struct connectionObject { /* inside a with block */ int entered; + + int sql_compatibility; }; /* map isolation level values into a numeric const */ diff --git a/psycopg/connection_type.c b/psycopg/connection_type.c index 92d5a86..5155c68 100644 --- a/psycopg/connection_type.c +++ b/psycopg/connection_type.c @@ -1268,6 +1268,9 @@ static struct PyMemberDef connectionObject_members[] = { {"server_version", T_INT, offsetof(connectionObject, server_version), READONLY, "Server version."}, + {"sql_compatibility", T_INT, + offsetof(connectionObject, sql_compatibility), READONLY, + "Server sql_compatibility param value."}, {NULL} }; @@ -1317,6 +1320,7 @@ static int connection_setup(connectionObject *self, const char *dsn, long int async) { int rv = -1; + char *sql_compatibility_value = NULL; Dprintf("connection_setup: init connection object at %p, " "async %ld, refcnt = " FORMAT_CODE_PY_SSIZE_T, @@ -1334,6 +1338,7 @@ connection_setup(connectionObject *self, const char *dsn, long int async) self->isolevel = ISOLATION_LEVEL_DEFAULT; self->readonly = STATE_DEFAULT; self->deferrable = STATE_DEFAULT; + self->sql_compatibility = SQL_COMPATIBILITY_A; #ifdef CONN_CHECK_PID self->procpid = getpid(); #endif @@ -1356,7 +1361,22 @@ connection_setup(connectionObject *self, const char *dsn, long int async) FORMAT_CODE_PY_SSIZE_T, self, Py_REFCNT(self)); + Py_BEGIN_ALLOW_THREADS; + pthread_mutex_lock(&self->lock); + sql_compatibility_value = pq_get_guc_locked(self, "sql_compatibility", &_save); + pthread_mutex_unlock(&self->lock); + Py_END_ALLOW_THREADS; + + if (strcmp(sql_compatibility_value, "A") == 0) { + self->sql_compatibility = SQL_COMPATIBILITY_A; + } else { + self->sql_compatibility = SQL_COMPATIBILITY_OTHER; + } + exit: + if (sql_compatibility_value){ + free(sql_compatibility_value); + } return rv; } diff --git a/psycopg/cursor_type.c b/psycopg/cursor_type.c index bbf867b..69c7cb0 100644 --- a/psycopg/cursor_type.c +++ b/psycopg/cursor_type.c @@ -684,7 +684,12 @@ curs_execute_prepared_batch(cursorObject *self, PyObject *args) if (!(argItem = psyco_ensure_bytes(argItem))) { goto exit; } - paramValues[rowIdx * nParams + colIdx] = Bytes_AsString(argItem); + // convert empty string to NULL in A compatibility mode + if (self->conn->sql_compatibility == SQL_COMPATIBILITY_A && PyObject_Length(argItem) == 0) { + paramValues[rowIdx * nParams + colIdx] = NULL; + } else { + paramValues[rowIdx * nParams + colIdx] = Bytes_AsString(argItem); + } } Py_XDECREF(argItem); } @@ -771,7 +776,12 @@ curs_execute_params_batch(cursorObject *self, PyObject *args) if (!(argItem = psyco_ensure_bytes(argItem))) { goto exit; } - paramValues[rowIdx * nParams + colIdx] = Bytes_AsString(argItem); + // convert empty string to NULL in A compatibility mode + if (self->conn->sql_compatibility == SQL_COMPATIBILITY_A && PyObject_Length(argItem) == 0) { + paramValues[rowIdx * nParams + colIdx] = NULL; + } else { + paramValues[rowIdx * nParams + colIdx] = Bytes_AsString(argItem); + } } Py_XDECREF(argItem); } -- Gitee