Fix backend error of prepared statement including now() via JDBC in replication mode
authorYugo Nagata <nagata@sraoss.co.jp>
Mon, 24 Mar 2014 06:05:10 +0000 (15:05 +0900)
committerYugo Nagata <nagata@sraoss.co.jp>
Mon, 24 Mar 2014 09:11:41 +0000 (18:11 +0900)
With JDBC, when a prepared statement is executed more than PreparedThreshold times,
the statement is named, and pgpool rewrites now() to parameter in replication mode.
Hence, rewritten query has additonal parameter, so Bind message also should inclued
additional parameter format codes. However, when the number of original parameter was
one, pgpool didn't handle this. This caused a error like "incorrect binary data format
in bind parameter 2" on backend.

pool_timestamp.c

index 5ee7ccab4f931134888d6aa444b229d51f24ac65..b3797dc0c86b43a2e32bd1f90d0e48cf9fc0382d 100644 (file)
@@ -752,7 +752,8 @@ bind_rewrite_timestamp(POOL_CONNECTION_POOL *backend,
        int32            tmp4;
        int                      i,
                                 ts_len,
-                                copy_len;
+                                copy_len,
+                                num_org_params;
        const char      *copy_from;
        char            *ts,
                                *copy_to,
@@ -775,8 +776,11 @@ bind_rewrite_timestamp(POOL_CONNECTION_POOL *backend,
 
        ts_len = strlen(ts);
 
-       *len += (strlen(ts) + sizeof(int32)) * message->num_tsparams;
-       new_msg = copy_to = (char *) malloc(*len + message->num_tsparams * sizeof(int16));
+       /* enlarge length for timestamp parameters */
+       *len += (ts_len + sizeof(int32)) * message->num_tsparams;
+       /* allocate extra memory for parameter formats */
+       num_org_params = message->query_context->num_original_params;
+       new_msg = copy_to = (char *) malloc(*len + sizeof(int16) * (message->num_tsparams + num_org_params));
        copy_from = orig_msg;
 
        /* portal_name */
@@ -794,12 +798,20 @@ bind_rewrite_timestamp(POOL_CONNECTION_POOL *backend,
        copy_len = sizeof(int16);
        tmp2 = num_formats = ntohs(tmp2);
 
-       if (num_formats > 1)
+       if (num_formats >= 1)
        {
-               /* enlarge message length */
+               /* one means the specified format code is applied all original parameters */
+               if (num_formats == 1)
+               {
+                       *len += (num_org_params - 1) * sizeof(int16);
+                       tmp2 += num_org_params - 1;
+               }
+
+               /* enlarge message length for timestamp parameter's formats */
                *len += message->num_tsparams * sizeof(int16);
                tmp2 += message->num_tsparams;
        }
+
        tmp2 = htons(tmp2);
        memcpy(copy_to, &tmp2, copy_len);       /* copy number of format codes */
        copy_to += copy_len; copy_from += copy_len;
@@ -809,10 +821,17 @@ bind_rewrite_timestamp(POOL_CONNECTION_POOL *backend,
        memcpy(copy_to, copy_from, copy_len);           /* copy format codes */
        copy_to += copy_len; copy_from += copy_len;
 
-       if (num_formats > 1)
+       if (num_formats >= 1)
        {
-               /* set format codes to zero(text) */
-               memset(copy_to, 0, message->num_tsparams * 2);
+               /* copy the specified format code as numbers of original parameters */
+               if (num_formats == 1)
+               {
+                       memcpy(copy_to, copy_from, (num_org_params - 1) * sizeof(int16));
+                       copy_to += (num_org_params - 1) * sizeof(int16);
+               }
+
+               /* set additional format codes to zero(text) */
+               memset(copy_to, 0, message->num_tsparams * sizeof(int16));
                copy_to += sizeof(int16) * message->num_tsparams;
        }