Browse Source

Pass parmeter types to PQexecParams() explicitly, otherwise PostgreSQL
will be guessing them based on field type and in the case of mismatch
may bail with cryptic error message:

"ERROR: dbase.c:783: Error: ERROR: insufficient data left in message"

Particularly, this happens easily with integers - SER is packing 4 bytes,
while PG expects 8 bytes.

Sponsored by: Sippy Software, Inc. ( http://www.sippysoft.com/ )

Maxim Sobolev 18 years ago
parent
commit
e698c560e6
1 changed files with 12 additions and 1 deletions
  1. 12 1
      modules/db_postgres/dbase.c

+ 12 - 1
modules/db_postgres/dbase.c

@@ -68,6 +68,7 @@ struct pg_params {
 	const char** data;
 	const char** data;
 	int* len;
 	int* len;
 	int* formats;
 	int* formats;
+	Oid* types;
 };
 };
 
 
 
 
@@ -77,6 +78,7 @@ static void free_pg_params(struct pg_params* ptr)
 	if (ptr->data) pkg_free(ptr->data);
 	if (ptr->data) pkg_free(ptr->data);
 	if (ptr->len) pkg_free(ptr->len);
 	if (ptr->len) pkg_free(ptr->len);
 	if (ptr->formats) pkg_free(ptr->formats);
 	if (ptr->formats) pkg_free(ptr->formats);
+	if (ptr->types) pkg_free(ptr->types);
 	pkg_free(ptr);
 	pkg_free(ptr);
 }
 }
 
 
@@ -96,9 +98,13 @@ static struct pg_params* new_pg_params(int n)
 
 
 	ptr->len = (int*)pkg_malloc(sizeof(int) * n);
 	ptr->len = (int*)pkg_malloc(sizeof(int) * n);
 	if (!ptr->len) goto error;
 	if (!ptr->len) goto error;
+
+	ptr->types = (int*)pkg_malloc(sizeof(Oid) * n);
+	if (!ptr->types) goto error;
 	
 	
 	memset((char*)ptr->data, 0, sizeof(const char*) * n);
 	memset((char*)ptr->data, 0, sizeof(const char*) * n);
 	memset(ptr->len, 0, sizeof(int) * n);
 	memset(ptr->len, 0, sizeof(int) * n);
+	memset(ptr->types, 0, sizeof(Oid) * n);
 	ptr->n = n;
 	ptr->n = n;
 	ptr->cur = 0;
 	ptr->cur = 0;
 	return ptr;
 	return ptr;
@@ -141,6 +147,7 @@ static inline int params_add(struct pg_params* p, db_con_t* con, db_val_t* vals,
 			val->val.int_val = ntohl(val->val.int_val);
 			val->val.int_val = ntohl(val->val.int_val);
 			p->data[p->cur] = (const char*)&val->val.int_val;
 			p->data[p->cur] = (const char*)&val->val.int_val;
 			p->len[p->cur] = 4;
 			p->len[p->cur] = 4;
+			p->types[p->cur] = INT4OID;
 			break;
 			break;
 
 
 		case DB_FLOAT:
 		case DB_FLOAT:
@@ -150,6 +157,7 @@ static inline int params_add(struct pg_params* p, db_con_t* con, db_val_t* vals,
 			val->val.int_val = htonl(val->val.int_val);
 			val->val.int_val = htonl(val->val.int_val);
 			p->data[p->cur] = (const char*)&val->val.int_val;
 			p->data[p->cur] = (const char*)&val->val.int_val;
 			p->len[p->cur] = 4;
 			p->len[p->cur] = 4;
+			p->types[p->cur] = FLOAT4OID;
 			break;
 			break;
 			
 			
 		case DB_DOUBLE:
 		case DB_DOUBLE:
@@ -162,6 +170,7 @@ static inline int params_add(struct pg_params* p, db_con_t* con, db_val_t* vals,
 			(&val->val.int_val)[1] = i2;
 			(&val->val.int_val)[1] = i2;
 			p->data[p->cur] = (const char*)&val->val.int_val;
 			p->data[p->cur] = (const char*)&val->val.int_val;
 			p->len[p->cur] = 8;
 			p->len[p->cur] = 8;
+			p->types[p->cur] = FLOAT8OID;
 			break;
 			break;
 			
 			
 		case DB_STRING:
 		case DB_STRING:
@@ -187,6 +196,7 @@ static inline int params_add(struct pg_params* p, db_con_t* con, db_val_t* vals,
 			(&val->val.int_val)[1] = i2;
 			(&val->val.int_val)[1] = i2;
 			p->data[p->cur] = (const char*)&val->val.int_val;
 			p->data[p->cur] = (const char*)&val->val.int_val;
 			p->len[p->cur] = 8;
 			p->len[p->cur] = 8;
+			p->types[p->cur] = TIMESTAMPOID;
 			break;
 			break;
 			
 			
 		case DB_BLOB:
 		case DB_BLOB:
@@ -199,6 +209,7 @@ static inline int params_add(struct pg_params* p, db_con_t* con, db_val_t* vals,
 			val->val.int_val = htonl(32);
 			val->val.int_val = htonl(32);
 			p->data[p->cur] = (const char*)&val->val.int_val;
 			p->data[p->cur] = (const char*)&val->val.int_val;
 			p->len[p->cur] = 8;
 			p->len[p->cur] = 8;
+			p->types[p->cur] = BITOID;
 			break;
 			break;
 		}
 		}
 		
 		
@@ -756,7 +767,7 @@ static int submit_query(db_res_t** res, db_con_t* con, const char* query, struct
 	DBG("Executing '%s'\n", query);
 	DBG("Executing '%s'\n", query);
 	if (params && params->cur) {
 	if (params && params->cur) {
 	        pgres = PQexecParams(CON_CONNECTION(con), query,
 	        pgres = PQexecParams(CON_CONNECTION(con), query,
-				     params->cur, 0,
+				     params->cur, params->types,
 				     params->data, params->len,
 				     params->data, params->len,
 				     params->formats, 1);
 				     params->formats, 1);
 	} else {
 	} else {