Fix to sort startup packet's parameters sent by client.
authorTakuma Hoshiai <hoshiai@sraoss.co.jp>
Wed, 21 Nov 2018 02:35:58 +0000 (11:35 +0900)
committerTakuma Hoshiai <hoshiai@sraoss.co.jp>
Wed, 21 Nov 2018 02:35:58 +0000 (11:35 +0900)
If order of startup packet's  parameters differ between cached connection pools and connection request, did't use connection pool ,and created new connection pool.
Per bug 444.

src/protocol/child.c

index 7f51232096e15d1979955c88c52105abeef3332b..ec8810c1b0e6225690c528e20cd6eb01de9a6886 100644 (file)
@@ -507,6 +507,12 @@ static StartupPacket *read_startup_packet(POOL_CONNECTION *cp)
        int protov;
        int len;
        char *p;
+       char **guc_options;
+       int opt_num = 0;
+       char *sp_sort;
+       char *tmpopt;
+       int i;
+       int j;
 
        sp = (StartupPacket *)palloc0(sizeof(*sp));
        enable_authentication_timeout();
@@ -533,7 +539,6 @@ static StartupPacket *read_startup_packet(POOL_CONNECTION *cp)
        memcpy(&protov, sp->startup_packet, sizeof(protov));
        sp->major = ntohl(protov)>>16;
        sp->minor = ntohl(protov) & 0x0000ffff;
-       p = sp->startup_packet;
     cp->protoVersion = sp->major;
 
        switch(sp->major)
@@ -550,6 +555,57 @@ static StartupPacket *read_startup_packet(POOL_CONNECTION *cp)
                        break;
 
                case PROTO_MAJOR_V3: /* V3 */
+                       /* copy startup_packet */
+                       sp_sort = palloc0(len);
+                       memcpy(sp_sort,sp->startup_packet,len);
+
+                       p = sp_sort;
+                       p += sizeof(int);       /* skip protocol version info */
+                       /* count the number of options */
+                       while(*p)
+                       {
+                               p += (strlen(p) + 1); /* skip option name */
+                               p += (strlen(p) + 1); /* skip option value */
+                               opt_num ++;
+                       }
+                       guc_options = (char **)palloc0(opt_num * sizeof(char *));
+                       /* get guc_option name list */
+                       p = sp_sort + sizeof(int);
+                       for(i = 0; i < opt_num; i++)
+                       {
+                               guc_options[i] = p;
+                               p += (strlen(p) + 1); /* skip option name */
+                               p += (strlen(p) + 1); /* skip option value */
+                       }
+                       /* sort option name using bubble sort */
+                       for (i = 0; i < opt_num - 1 ; i++)
+                       {
+                               for (j = i + 1; j < opt_num; j++)
+                               {
+                                       if (strcmp(guc_options[i], guc_options[j]) > 0)
+                                       {
+                                               tmpopt = guc_options[i];
+                                               guc_options[i] = guc_options[j];
+                                               guc_options[j] = tmpopt;
+                                       }
+                               }
+                       }
+
+                       p = sp->startup_packet + sizeof(int);   /* skip protocol version info */
+                       for (i = 0; i < opt_num; i++)
+                       {
+                               tmpopt = guc_options[i];
+                               memcpy(p, tmpopt ,strlen(tmpopt) + 1); /* memcpy option name */
+                               p += (strlen(tmpopt) + 1);
+                               tmpopt += (strlen(tmpopt) + 1);
+                               memcpy(p, tmpopt ,strlen(tmpopt) + 1); /* memcpy option value */
+                               p += (strlen(tmpopt) + 1);
+                       }
+
+                       pfree(guc_options);
+                       pfree(sp_sort);
+
+                       p = sp->startup_packet;
                        p += sizeof(int);       /* skip protocol version info */
 
                        while(*p)