The version is now 8.2.0203.
authorHiroshi Inoue <inoue@tpf.co.jp>
Sat, 16 Dec 2006 12:02:54 +0000 (12:02 +0000)
committerHiroshi Inoue <inoue@tpf.co.jp>
Sat, 16 Dec 2006 12:02:54 +0000 (12:02 +0000)
1. Fix a bug which forgets unnamed plans too early especially
   when handling large objects.
2. Don't treat charcters whose value >= 128 as alphanumeric in case
   of conversion of binary data to bytea.
3. Change ConfigDSN() so that it takes the options in Setup Dialog
   page 1 into account.
4. Simplify the memory management of statements'columns info
   so as to prevent memory leaks or a crash in parse_statement etc.
5. SQLTables("", SQL_ALL_SCHEMAS. "", ..) now returns a list of
   valid schemas.
6. SQLTables("", "", "", SQL_ALL_TABLE_TYPES) now returns a list
   of valid table types.
7. SQLGetInfo SQL_DATABASE_NAME now returns the database name.
8. Improve the automatic setting mechanism of the client_encoding
   for Windows code page 125x (ANSI drivers only) .

16 files changed:
connection.c
connection.h
convert.c
descriptor.c
dlg_specific.c
dlg_specific.h
environ.c
execute.c
info.c
multibyte.c
multibyte.h
parse.c
results.c
setup.c
statement.c
version.h

index 2b07307407dd7fc0c115b879b6b961ff9695f7e9..639780baf6a1a8a6ab430356cb7a42afa615a8ad 100644 (file)
@@ -1067,9 +1067,10 @@ static int   protocol3_opts_array(ConnectionClass *self, const char *opts[][2], BO
        else
            opts[cnt++][1] = "on";
        /* client_encoding */
-       enc = get_environment_encoding(self, "other", NULL);
+       enc = get_environment_encoding(self, self->original_client_encoding, NULL, TRUE);
        if (enc)
        {
+           mylog("startup client_encoding=%s\n", enc);
            opts[cnt][0] = "client_encoding"; opts[cnt++][1] = enc;
        }
    }
@@ -1221,13 +1222,13 @@ static char CC_initial_log(ConnectionClass *self, const char *func)
         TABLE_NAME_STORAGE_LEN);
 
    encoding = check_client_encoding(ci->conn_settings);
-   if (encoding && strcmp(encoding, "OTHER"))
-       self->original_client_encoding = strdup(encoding);
+   if (encoding)
+       self->original_client_encoding = encoding;
    else
    {
        encoding = check_client_encoding(ci->drivers.conn_settings);
-       if (encoding && strcmp(encoding, "OTHER"))
-           self->original_client_encoding = strdup(encoding);
+       if (encoding)
+           self->original_client_encoding = encoding;
    }
    if (self->original_client_encoding)
        self->ccsc = pg_CS_code(self->original_client_encoding);
@@ -1682,14 +1683,13 @@ inolog("CC_send_settings\n");
    if (PG_VERSION_GE(self, 6.4))
    {
        CC_lookup_characterset(self);
-       if (CC_get_errornumber(self) != 0)
+       if (CC_get_errornumber(self) > 0)
            return 0;
 #ifdef UNICODE_SUPPORT
        if (CC_is_in_unicode_driver(self))
        {
            if (!self->original_client_encoding ||
-               (stricmp(self->original_client_encoding, "UNICODE") &&
-               stricmp(self->original_client_encoding, "UTF8")))
+               UTF8 != self->ccsc)
            {
                QResultClass    *res;
                if (PG_VERSION_LT(self, 7.1))
@@ -1733,7 +1733,8 @@ inolog("CC_send_settings\n");
        }
    }
 
-   CC_clear_error(self);       /* clear any initial command errors */
+   if (CC_get_errornumber(self) > 0)
+       CC_clear_error(self);       /* clear any initial command errors */
    self->status = CONN_CONNECTED;
    if (CC_is_in_unicode_driver(self)
        && 0 < ci->bde_environment)
@@ -3422,11 +3423,9 @@ LIBPQ_send_cancel_request(const ConnectionClass *conn)
 
 const char *CurrCat(const ConnectionClass *conn)
 {
-   /*
    if (conn->schema_support)
        return conn->connInfo.database;
    else
-   */
        return NULL;
 }
 
index b2c265dd18693f01456060954d18fba1a0fe2576..3b9480d88b32efbafa6fbe4fd6f88e66ca8a2d28 100644 (file)
@@ -54,6 +54,8 @@ enum
 #define CONNECTION_NEED_PASSWORD               112
 #define CONNECTION_COMMUNICATION_ERROR             113
 
+#define CONN_TRUNCATED                         (-2)
+#define CONN_OPTION_VALUE_CHANGED                  (-1)
 /* These errors correspond to specific SQL states */
 #define CONN_INIREAD_ERROR                     201
 #define CONN_OPENDB_ERROR                      202 
@@ -70,10 +72,8 @@ enum
 #define CONN_AUTH_TYPE_UNSUPPORTED                 211
 #define CONN_UNABLE_TO_LOAD_DLL                        212
 
-#define CONN_OPTION_VALUE_CHANGED                  213
 #define CONN_VALUE_OUT_OF_RANGE                        214
 
-#define CONN_TRUNCATED                         215
 #define CONN_OPTION_NOT_FOR_THE_DRIVER                 216
 #define CONN_EXEC_ERROR                            217
 
index 096150e3ba975432418c56c75cd93ee54c30ce03..638dfa1e1816416c4a8095775bae08adf3d61d7f 100644 (file)
--- a/convert.c
+++ b/convert.c
@@ -2003,10 +2003,10 @@ table_for_update(const char *stmt, int *endpos)
  *----------
  */
 static BOOL
-check_join(StatementClass *stmt, const char *curptr, int curpos)
+check_join(StatementClass *stmt, const char *curptr, size_t curpos)
 {
    const char *wstmt;
-   int stapos, endpos, tokenwd;
+   ssize_t stapos, endpos, tokenwd;
    const int   backstep = 5;
    BOOL    outerj = TRUE;
 
@@ -4672,24 +4672,26 @@ static size_t
 convert_to_pgbinary(const UCHAR *in, char *out, size_t len, QueryBuild *qb)
 {
    CSTR    func = "convert_to_pgbinary";
+   UCHAR   inc;
    size_t          i, o = 0;
    char    escape_in_literal = CC_get_escape(qb->conn);
    BOOL    esc_double = (0 == (qb->flags & FLGB_BUILDING_BIND_REQUEST) && 0 != escape_in_literal);
 
    for (i = 0; i < len; i++)
    {
-       mylog("%s: in[%d] = %d, %c\n", func, i, in[i], in[i]);
-       if (isalnum(in[i]) || in[i] == ' ')
-           out[o++] = in[i];
+       inc = in[i];
+       mylog("%s: in[%d] = %d, %c\n", func, i, inc, inc);
+       if (inc < 128 && (isalnum(inc) || inc == ' '))
+           out[o++] = inc;
        else
        {
            if (esc_double)
            {
-               o += conv_to_octal(in[i], &out[o], escape_in_literal);
+               o += conv_to_octal(inc, &out[o], escape_in_literal);
            }
            else
            {
-               conv_to_octal2(in[i], &out[o]);
+               conv_to_octal2(inc, &out[o]);
                o += 4;
            }
        }
index e41740f436b4f09d5be2d749083c3a8e14b6845a..b70d2a3ffb59b1ad02c494d1a723d5771d920804 100644 (file)
@@ -133,7 +133,7 @@ static void IRDFields_free(IRDFields * self)
    /* Free the parsed field information */
    if (self->fi)
    {
-       FI_Destructor(self->fi, self->nfields, TRUE);
+       FI_Destructor(self->fi, self->allocated, TRUE);
        self->fi = NULL;
    }
    self->allocated = 0;
index 4a96717d90536842283ab99d0a408b7446c06c50..6257a58007426c2c695b6bf1964beea6e3bd66fb 100644 (file)
@@ -412,9 +412,12 @@ unfoldCXAttribute(ConnInfo *ci, const char *value)
    ci->use_server_side_prepare = (char)((flag & BIT_USESERVERSIDEPREPARE) != 0);
    ci->lower_case_identifier = (char)((flag & BIT_LOWERCASEIDENTIFIER) != 0);
 }
-void
+BOOL
 copyAttributes(ConnInfo *ci, const char *attribute, const char *value)
 {
+   CSTR    func = "copyAttributes";
+   BOOL    found = TRUE;
+
    if (stricmp(attribute, "DSN") == 0)
        strcpy(ci->dsn, value);
 
@@ -536,13 +539,20 @@ copyAttributes(ConnInfo *ci, const char *attribute, const char *value)
        }
        mylog("force_abbrev=%d bde=%d cvt_null_date=%x\n", ci->force_abbrev_connstr, ci->bde_environment, ci->cvt_null_date_string);
    }
+   else
+       found = FALSE;
 
-   mylog("copyAttributes: DSN='%s',server='%s',dbase='%s',user='%s',passwd='%s',port='%s',onlyread='%s',protocol='%s',conn_settings='%s',disallow_premature=%d)\n", ci->dsn, ci->server, ci->database, ci->username, ci->password ? "xxxxx" : "", ci->port, ci->onlyread, ci->protocol, ci->conn_settings, ci->disallow_premature);
+   mylog("%s: DSN='%s',server='%s',dbase='%s',user='%s',passwd='%s',port='%s',onlyread='%s',protocol='%s',conn_settings='%s',disallow_premature=%d)\n", func, ci->dsn, ci->server, ci->database, ci->username, ci->password ? "xxxxx" : "", ci->port, ci->onlyread, ci->protocol, ci->conn_settings, ci->disallow_premature);
+
+   return found;
 }
 
-void
+BOOL
 copyCommonAttributes(ConnInfo *ci, const char *attribute, const char *value)
 {
+   CSTR    func = "copyCommonAttributes";
+   BOOL    found = TRUE;
+
    if (stricmp(attribute, INI_FETCH) == 0 || stricmp(attribute, ABBR_FETCH) == 0)
        ci->drivers.fetch_max = atoi(value);
    else if (stricmp(attribute, INI_SOCKET) == 0 || stricmp(attribute, ABBR_SOCKET) == 0)
@@ -583,7 +593,10 @@ copyCommonAttributes(ConnInfo *ci, const char *attribute, const char *value)
        ci->drivers.bools_as_char = atoi(value);
    else if (stricmp(attribute, INI_EXTRASYSTABLEPREFIXES) == 0 || stricmp(attribute, ABBR_EXTRASYSTABLEPREFIXES) == 0)
        strcpy(ci->drivers.extra_systable_prefixes, value);
-   mylog("CopyCommonAttributes: A7=%d;A8=%d;A9=%d;B0=%d;B1=%d;B2=%d;B3=%d;B4=%d;B5=%d;B6=%d;B7=%d;B8=%d;B9=%d;C0=%d;C1=%d;C2=%s",
+   else
+       found = FALSE;
+
+   mylog("%s: A7=%d;A8=%d;A9=%d;B0=%d;B1=%d;B2=%d;B3=%d;B4=%d;B5=%d;B6=%d;B7=%d;B8=%d;B9=%d;C0=%d;C1=%d;C2=%s", func,
          ci->drivers.fetch_max,
          ci->drivers.socket_buffersize,
          ci->drivers.unknown_sizes,
@@ -600,6 +613,8 @@ copyCommonAttributes(ConnInfo *ci, const char *attribute, const char *value)
          ci->drivers.parse,
          ci->drivers.cancel_as_freestmt,
          ci->drivers.extra_systable_prefixes);
+
+   return found;
 }
 
 
@@ -858,13 +873,18 @@ getDSNinfo(ConnInfo *ci, char overwrite)
         ci->fake_oid_index,
         ci->show_system_tables);
 
-   check_client_encoding(ci->conn_settings);
-   qlog("          conn_settings='%s',conn_encoding='%s'\n",
-        ci->conn_settings,
-        check_client_encoding(ci->conn_settings));
-   qlog("          translation_dll='%s',translation_option='%s'\n",
-        ci->translation_dll,
-        ci->translation_option);
+   if (get_qlog())
+   {
+       UCHAR   *enc = check_client_encoding(ci->conn_settings);
+
+       qlog("          conn_settings='%s',conn_encoding='%s'\n",
+           ci->conn_settings, enc ? enc : "(null)");
+       if (enc)
+           free(enc);
+       qlog("          translation_dll='%s',translation_option='%s'\n",
+           ci->translation_dll,
+           ci->translation_option);
+   }
 }
 /*
  * This function writes any global parameters (that can be manipulated)
index 63c07e1ab313072523718cd7f6ad08d98f030fc4..ff213aa52b9044396c6e26dc0e79a023ef850ad5 100644 (file)
@@ -271,8 +271,8 @@ void        writeDSNinfo(const ConnInfo *ci);
 void       getDSNdefaults(ConnInfo *ci);
 void       getDSNinfo(ConnInfo *ci, char overwrite);
 void       makeConnectString(char *connect_string, const ConnInfo *ci, UWORD);
-void       copyAttributes(ConnInfo *ci, const char *attribute, const char *value);
-void       copyCommonAttributes(ConnInfo *ci, const char *attribute, const char *value);
+BOOL       copyAttributes(ConnInfo *ci, const char *attribute, const char *value);
+BOOL       copyCommonAttributes(ConnInfo *ci, const char *attribute, const char *value);
 int    getDriverNameFromDSN(const char *dsn, char *driver_name, int namelen);
 int     changeDriverNameOfaDSN(const char *dsn, const char *driver_name, DWORD *errcode);
 UInt4  getExtraOptions(const ConnInfo *);
index fb22846e7616976e5415fee197f69047a7cd380e..4c5d4fb0365f2917500d23e7245557b36de53319 100644 (file)
--- a/environ.c
+++ b/environ.c
@@ -510,6 +510,8 @@ EN_Destructor(EnvironmentClass *self)
    char        rv = 1;
 
    mylog("in EN_Destructor, self=%p\n", self);
+   if (!self)
+       return 0;
 
    /*
     * the error messages are static strings distributed throughout the
index e1a9cea277237c3cf9fb77565790da8de514256d..b99b8fccd949984f6ea9f2dc02c4a29e559eabf5 100644 (file)
--- a/execute.c
+++ b/execute.c
@@ -673,7 +673,8 @@ inolog("ret=%d\n", ret);
        }
    }
 cleanup:
-   SC_forget_unnamed(stmt); /* unnamed plan is no longer reliable */
+   if (SQL_NEED_DATA != ret)
+       SC_forget_unnamed(stmt); /* unnamed plan is no longer reliable */
    if (!SC_is_prepare_statement(stmt) && ONCE_DESCRIBED == stmt->prepared)
        SC_set_prepared(stmt, NOT_YET_PREPARED);
    if (start_stmt || SQL_ERROR == ret)
diff --git a/info.c b/info.c
index 0bc8c9399a5faa5cbcd16e047497041794cb65a3..5ac1ec4958a89942bad0be9d9c5e7ccf9fb84518 100644 (file)
--- a/info.c
+++ b/info.c
@@ -1483,7 +1483,7 @@ PGAPI_Tables(
    HSTMT       htbl_stmt = NULL;
    RETCODE     ret = SQL_ERROR, result;
    int     result_cols;
-   char       *tableType;
+   char        *tableType = NULL;
    char        tables_query[INFO_INQUIRY_LEN];
    char        table_name[MAX_INFO_STRING],
                table_owner[MAX_INFO_STRING],
@@ -1493,7 +1493,7 @@ PGAPI_Tables(
 #endif /* HAVE_STRTOK_R */
    ConnectionClass *conn;
    ConnInfo   *ci;
-   char    *escSchemaName = NULL, *escTableName = NULL;
+   char    *escCatName = NULL, *escSchemaName = NULL, *escTableName = NULL;
    char       *prefix[32],
                prefixes[MEDIUM_REGISTRY_LEN];
    char       *table_type[32],
@@ -1508,8 +1508,9 @@ PGAPI_Tables(
    SQLSMALLINT     internal_asis_type = SQL_C_CHAR, cbSchemaName;
    const char  *like_or_eq;
    const char  *szSchemaName;
-   BOOL    search_pattern, list_schemas = FALSE;
-   SQLLEN      cbRelname, cbRelkind;
+   BOOL        search_pattern;
+   BOOL        list_cat = FALSE, list_schemas = FALSE, list_table_types = FALSE, list_some = FALSE;
+   SQLLEN      cbRelname, cbRelkind, cbSchName;
 
    mylog("%s: entering...stmt=%p scnm=%p len=%d\n", func, stmt, NULL_IF_NULL(szTableOwner), cbTableOwner);
 
@@ -1534,11 +1535,13 @@ PGAPI_Tables(
    if (search_pattern) 
    {
        like_or_eq = likeop;
+       escCatName = adjustLikePattern(szTableQualifier, cbTableQualifier, SEARCH_PATTERN_ESCAPE, NULL, conn);
        escTableName = adjustLikePattern(szTableName, cbTableName, SEARCH_PATTERN_ESCAPE, NULL, conn);
    }
    else
    {
        like_or_eq = eqop;
+       escCatName = simpleCatalogEscape(szTableQualifier, cbTableQualifier, NULL, conn);
        escTableName = simpleCatalogEscape(szTableName, cbTableName, NULL, conn);
    }
 retry_public_schema:
@@ -1551,27 +1554,45 @@ retry_public_schema:
    /*
     * Create the query to find out the tables
     */
-   if (conn->schema_support)
+   /* make_string mallocs memory */
+   tableType = make_string(szTableType, cbTableType, NULL, 0);
+   if (search_pattern &&
+       escTableName && '\0' == escTableName[0] &&
+       escCatName && escSchemaName)
    {
-       if (search_pattern &&
-           escSchemaName &&
-           stricmp(escSchemaName, SQL_ALL_SCHEMAS) == 0 &&
-           escTableName &&
-           '\0' == escTableName[0]
-          )
-           list_schemas = TRUE;
-       if (list_schemas)
+       if ('\0' == escSchemaName[0])
        {
-           strcpy(tables_query, "select NULL, nspname, NULL"
-           " from pg_catalog.pg_namespace n");
+           if (stricmp(escCatName, SQL_ALL_CATALOGS) == 0)
+               list_cat = TRUE;
+           else if ('\0' == escCatName[0] &&
+                stricmp(tableType, SQL_ALL_TABLE_TYPES) == 0)
+               list_table_types = TRUE;
        }
+       else if ('\0' == escCatName[0] &&
+            stricmp(escSchemaName, SQL_ALL_SCHEMAS) == 0)
+           list_schemas = TRUE;
+   }
+   list_some = (list_cat || list_schemas || list_table_types);
+
+   tables_query[0] = '\0';
+   if (list_cat)
+       strncpy(tables_query, "select NULL, NULL, NULL", sizeof(tables_query));
+   else if (list_table_types)
+       strncpy(tables_query, "select NULL, NULL, relkind from (select 'r' as relkind union select 'v') as a", sizeof(tables_query));
+   else if (list_schemas)
+   {
+       if (conn->schema_support)
+           strncpy(tables_query, "select NULL, nspname, NULL"
+           " from pg_catalog.pg_namespace n where true", sizeof(tables_query));
        else
-       {
-           /* view is represented by its relkind since 7.1 */
-           strcpy(tables_query, "select relname, nspname, relkind"
+           strncpy(tables_query, "select NULL, NULL as nspname, NULL", sizeof(tables_query));
+   }
+   else if (conn->schema_support)
+   {
+       /* view is represented by its relkind since 7.1 */
+       strcpy(tables_query, "select relname, nspname, relkind"
            " from pg_catalog.pg_class c, pg_catalog.pg_namespace n");
-           strcat(tables_query, " where relkind in ('r', 'v')");
-       }
+       strcat(tables_query, " where relkind in ('r', 'v')");
    }
    else if (PG_VERSION_GE(conn, 7.1))
    {
@@ -1586,19 +1607,17 @@ retry_public_schema:
        strcat(tables_query, " where relkind = 'r'");
    }
 
-   if (list_schemas)
-   {
-       schema_strcat1(tables_query, " where nspname %s '%.*s'", like_or_eq, escSchemaName, SQL_NTS, szTableName, cbTableName, conn);
-   }
-   else if (conn->schema_support)
+   if (!list_some)
    {
-       schema_strcat1(tables_query, " and nspname %s '%.*s'", like_or_eq, escSchemaName, SQL_NTS, szTableName, cbTableName, conn);
-       /* strcat(tables_query, " and pg_catalog.pg_table_is_visible(c.oid)"); */
-   }
-   else
-       my_strcat1(tables_query, " and usename %s '%.*s'", like_or_eq, escSchemaName, SQL_NTS);
-   if (!list_schemas)
+       if (conn->schema_support)
+       {
+           schema_strcat1(tables_query, " and nspname %s '%.*s'", like_or_eq, escSchemaName, SQL_NTS, szTableName, cbTableName, conn);
+           /* strcat(tables_query, " and pg_catalog.pg_table_is_visible(c.oid)"); */
+       }
+       else
+           my_strcat1(tables_query, " and usename %s '%.*s'", like_or_eq, escSchemaName, SQL_NTS);
        my_strcat1(tables_query, " and relname %s '%.*s'", like_or_eq, escTableName, SQL_NTS);
+   }
 
    /* Parse the extra systable prefix  */
    strcpy(prefixes, ci->drivers.extra_systable_prefixes);
@@ -1620,14 +1639,13 @@ retry_public_schema:
    show_regular_tables = FALSE;
    show_views = FALSE;
 
-   /* make_string mallocs memory */
-   tableType = make_string(szTableType, cbTableType, NULL, 0);
+   /* TABLE_TYPE */
    if (!tableType)
    {
        show_regular_tables = TRUE;
        show_views = TRUE;
    }
-   else if (stricmp(tableType, SQL_ALL_TABLE_TYPES) == 0)
+   else if (list_some || stricmp(tableType, SQL_ALL_TABLE_TYPES) == 0)
    {
        show_regular_tables = TRUE;
        show_views = TRUE;
@@ -1667,19 +1685,17 @@ retry_public_schema:
            i++;
        }
    }
-   if (tableType)
-       free(tableType);
 
    /*
     * If not interested in SYSTEM TABLES then filter them out to save
     * some time on the query.  If treating system tables as regular
     * tables, then dont filter either.
     */
-   if (!atoi(ci->show_system_tables) && !show_system_tables)
+   if ((list_schemas || !list_some) && !atoi(ci->show_system_tables) && !show_system_tables)
    {
        if (conn->schema_support)
            strcat(tables_query, " and nspname not in ('pg_catalog', 'information_schema', 'pg_toast', 'pg_temp_1')");
-       else
+       else if (!list_schemas)
        {
            strcat(tables_query, " and relname !~ '^" POSTGRES_SYS_PREFIX);
 
@@ -1693,17 +1709,20 @@ retry_public_schema:
        }
    }
 
-   /* match users */
-   if (PG_VERSION_LT(conn, 7.1))
-       /* filter out large objects in older versions */
-       strcat(tables_query, " and relname !~ '^xinv[0-9]+'");
-
    if (list_schemas)
        strcat(tables_query, " order by nspname");
+   else if (list_some)
+       ;
    else if (conn->schema_support)
        strcat(tables_query, " and n.oid = relnamespace order by nspname, relname");
    else
+   {
+       /* match users */
+       if (PG_VERSION_LT(conn, 7.1))
+           /* filter out large objects in older versions */
+           strcat(tables_query, " and relname !~ '^xinv[0-9]+'");
        strcat(tables_query, " and usesysid = relowner order by relname");
+   }
 
    result = PGAPI_ExecDirect(htbl_stmt, tables_query, SQL_NTS, 0);
    if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
@@ -1748,7 +1767,7 @@ retry_public_schema:
    }
 
    result = PGAPI_BindCol(htbl_stmt, 2, internal_asis_type,
-                          table_owner, MAX_INFO_STRING, NULL);
+                          table_owner, MAX_INFO_STRING, &cbSchName);
    if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
    {
        SC_error_copy(stmt, tbl_stmt, TRUE);
@@ -1789,6 +1808,7 @@ retry_public_schema:
 
    /* add the tuples */
    table_name[0] = '\0';
+   table_owner[0] = '\0';
    result = PGAPI_Fetch(htbl_stmt);
    while ((result == SQL_SUCCESS) || (result == SQL_SUCCESS_WITH_INFO))
    {
@@ -1842,8 +1862,10 @@ retry_public_schema:
        {
            tuple = QR_AddNew(res);
 
-           /* set_tuplefield_null(&tuple[TABLES_CATALOG_NAME]); */
-           set_tuplefield_string(&tuple[TABLES_CATALOG_NAME], CurrCat(conn));
+           if (list_cat || !list_some)
+               set_tuplefield_string(&tuple[TABLES_CATALOG_NAME], CurrCat(conn));
+           else
+               set_tuplefield_null(&tuple[TABLES_CATALOG_NAME]);
 
            /*
             * I have to hide the table owner from Access, otherwise it
@@ -1856,15 +1878,18 @@ retry_public_schema:
 
            mylog("%s: table_name = '%s'\n", func, table_name);
 
-           if (conn->schema_support)
+           if (list_schemas || (conn->schema_support && !list_some))
                set_tuplefield_string(&tuple[TABLES_SCHEMA_NAME], GET_SCHEMA_NAME(table_owner));
            else
                set_tuplefield_null(&tuple[TABLES_SCHEMA_NAME]);
-           set_nullfield_string(&tuple[TABLES_TABLE_NAME], table_name);
-           if (list_schemas)
-               set_tuplefield_null(&tuple[TABLES_TABLE_TYPE]);
+           if (list_some)
+               set_tuplefield_null(&tuple[TABLES_TABLE_NAME]);
            else
+               set_nullfield_string(&tuple[TABLES_TABLE_NAME], table_name);
+           if (list_table_types || !list_some)
                set_tuplefield_string(&tuple[TABLES_TABLE_TYPE], systable ? "SYSTEM TABLE" : (view ? "VIEW" : "TABLE"));
+           else
+               set_tuplefield_null(&tuple[TABLES_TABLE_TYPE]);
            set_tuplefield_string(&tuple[TABLES_REMARKS], NULL_STRING);
            /*** set_tuplefield_string(&tuple[TABLES_REMARKS], "TABLE"); ***/
        }
@@ -1885,10 +1910,14 @@ cleanup:
     */
    stmt->status = STMT_FINISHED;
 
+   if (escCatName)
+       free(escCatName);
    if (escSchemaName)
        free(escSchemaName);
    if (escTableName)
        free(escTableName);
+   if (tableType)
+       free(tableType);
    /* set up the current tuple pointer for SQLFetch */
    stmt->currTuple = -1;
    SC_set_rowset_start(stmt, -1, FALSE);
index db8063d50d1289cced6cb4f9cb4bec93578cc8fc..cd5a34c022dd079219348ba3d82f29139b94aa48 100644 (file)
@@ -9,6 +9,7 @@
  */
 
 #include "multibyte.h"
+#include "misc.h"
 #include "connection.h"
 #include "pgapifunc.h"
 #include <string.h>
 #define    TRUE    1
 #endif
 
-pg_CS CS_Table[] =
+static pg_CS CS_Table[] =
 {
    { "SQL_ASCII",  SQL_ASCII },
    { "EUC_JP", EUC_JP },
    { "EUC_CN", EUC_CN },
    { "EUC_KR", EUC_KR },
    { "EUC_TW", EUC_TW },
-   { "JOHAB",  JOHAB },
-   { "UTF8",   UTF8 },
+   { "JOHAB",  JOHAB },    /* since 7.3 */
+   { "UTF8",   UTF8 },     /* since 7.2 */
    { "MULE_INTERNAL",MULE_INTERNAL },
    { "LATIN1", LATIN1 },
    { "LATIN2", LATIN2 },
@@ -39,32 +40,41 @@ pg_CS CS_Table[] =
    { "LATIN8", LATIN8 },
    { "LATIN9", LATIN9 },
    { "LATIN10",    LATIN10 },
-   { "WIN1256",    WIN1256 },
-   { "WIN1258",    WIN1258 },  /* since 8.1 */
-   { "WIN874", WIN874 },
-   { "KOI8",   KOI8R },
-   { "WIN1251",    WIN1251 },
+   { "WIN1256",    WIN1256 },  /* Arabic since 7.3 */
+   { "WIN1258",    WIN1258 },  /* Vietnamese since 8.1 */
    { "WIN866", WIN866 },   /* since 8.1 */
+   { "WIN874", WIN874 },   /* Thai since 7.3 */
+   { "KOI8",   KOI8R },
+   { "WIN1251",    WIN1251 },  /* Cyrillic */
+   { "WIN1252",    WIN1252 },  /* Western Europe since 8.1 */
    { "ISO_8859_5", ISO_8859_5 },
    { "ISO_8859_6", ISO_8859_6 },
    { "ISO_8859_7", ISO_8859_7 },
    { "ISO_8859_8", ISO_8859_8 },
-
+   { "WIN1250",    WIN1250 },  /* Central Europe */
+   { "WIN1253",    WIN1253 },  /* Greek since 8.2 */
+   { "WIN1254",    WIN1254 },  /* Turkish since 8.2 */
+   { "WIN1255",    WIN1255 },  /* Hebrew since 8.2 */
+   { "WIN1257",    WIN1257 },  /* Baltic(North Europe) since 8.2 */
 
    { "SJIS",   SJIS },
    { "BIG5",   BIG5 },
-   { "GBK",    GBK },
-   { "UHC",    UHC },
-   { "WIN1250",    WIN1250 },
-   { "GB18030",    GB18030 },
-   { "UNICODE",    UNICODE_PODBC },
-   { "TCVN",   TCVN },
-   { "ALT",    ALT },
-   { "WIN",    WIN },
-   { "WIN1252",    WIN1252 },
+   { "GBK",    GBK },      /* since 7.3 */
+   { "UHC",    UHC },      /* since 7.3 */ 
+   { "GB18030",    GB18030 },  /* since 7.3 */
+   { "OTHER",  OTHER }
+};
+
+static pg_CS CS_Alias[] =
+{
+   { "UNICODE",    UTF8 },
+   { "TCVN",   WIN1258 },
+   { "ALT",    WIN866 },
+   { "WIN",    WIN1251 },
    { "OTHER",  OTHER }
 };
 
+CSTR   OTHER_STRING = "OTHER";
 
 int
 pg_CS_code(const UCHAR *characterset_string)
@@ -81,23 +91,101 @@ pg_CS_code(const UCHAR *characterset_string)
        }
    }
    if (c < 0)
-       for(i = 0; CS_Table[i].code != OTHER; i++)
+   {
+       for(i = 0; CS_Alias[i].code != OTHER; i++)
        {
-           if (strstr(characterset_string, CS_Table[i].name))
+           if (0 == stricmp(characterset_string, CS_Alias[i].name))
            {
-                       if(strlen(CS_Table[i].name) >= len)
-               {
-                               len = strlen(CS_Table[i].name);
-                               c = CS_Table[i].code;
-                           }
+                               c = CS_Alias[i].code;
+               break;
            }
        }
+   }
    if (c < 0)
-       c = i;
+       c = OTHER;
    return (c);
 }
 
-UCHAR *
+UCHAR *check_client_encoding(const UCHAR *conn_settings)
+{
+   const UCHAR *cptr, *sptr = NULL;
+   UCHAR   *rptr;
+   BOOL    allowed_cmd = TRUE, in_quote = FALSE;
+   int step = 0;
+   size_t  len = 0;
+
+        for (cptr = conn_settings; *cptr; cptr++)
+        {
+       if (in_quote)
+           if (LITERAL_QUOTE == *cptr)
+           {
+               in_quote = FALSE;
+               continue;
+           }
+       if (';' == *cptr)
+       {
+           allowed_cmd = TRUE;
+           step = 0;
+           continue;
+       }
+       if (!allowed_cmd)
+           continue;
+       if (isspace(*cptr))
+           continue;
+       switch (step)
+       {
+           case 0:
+               if (0 != strnicmp(cptr, "set", 3))
+               {
+                   allowed_cmd = FALSE;
+                   continue;
+               }
+               step++;
+               cptr += 3;
+               break;
+           case 1:
+               if (0 != strnicmp(cptr, "client_encoding", 15))
+               {
+                   allowed_cmd = FALSE;
+                   continue;
+               }
+               step++;
+               cptr += 15;
+               break;
+           case 2:
+               if (0 != strnicmp(cptr, "to", 2))
+               {
+                   allowed_cmd = FALSE;
+                   continue;
+               }
+               step++;
+               cptr += 2;
+               break;
+           case 3:
+               if (LITERAL_QUOTE == *cptr)
+               {
+                   cptr++;
+                   for (sptr = cptr; *cptr && *cptr != LITERAL_QUOTE; cptr++) ;
+               }
+               else
+               {
+                   for (sptr = cptr; *cptr && !isspace(*cptr); cptr++) ;
+               }
+               len = cptr - sptr;
+               step++;
+               break;
+       }
+   }
+   if (!sptr)
+       return NULL;
+   rptr = malloc(len + 1);
+   memcpy(rptr, sptr, len);
+   rptr[len] = '\0';
+   mylog("extracted a client_encoding '%s' from conn_settings\n", rptr);
+   return rptr;
+}
+
+const UCHAR *
 pg_CS_name(int characterset_code)
 {
    int i;
@@ -106,7 +194,7 @@ pg_CS_name(int characterset_code)
        if (CS_Table[i].code == characterset_code)
            return CS_Table[i].name;
    }
-   return ("OTHER");
+   return (OTHER_STRING);
 }
 
 static int
@@ -115,7 +203,6 @@ pg_mb_maxlen(characterset_code)
    switch (characterset_code)
    {
        case UTF8:
-       case UNICODE_PODBC:
            return 6;
        case EUC_TW:
            return 4;
@@ -143,7 +230,6 @@ pg_CS_stat(int stat,unsigned int character,int characterset_code)
    switch (characterset_code)
    {
        case UTF8:
-       case UNICODE_PODBC:
            {
                if (stat < 2 &&
                    character >= 0x80)
@@ -358,7 +444,7 @@ CC_lookup_cs_new(ConnectionClass *self)
    res = CC_send_query(self, "select pg_client_encoding()", NULL, IGNORE_ABORT_ON_CONN | ROLLBACK_ON_ERROR, NULL);
    if (QR_command_maybe_successful(res))
    {
-       char    *enc = QR_get_value_backend_row(res, 0, 0);
+       const char  *enc = QR_get_value_backend_row(res, 0, 0);
 
        if (enc)
            encstr = strdup(enc);
@@ -395,26 +481,36 @@ CC_lookup_cs_old(ConnectionClass *self)
  * This function works under Windows or Unicode case only.
  * Simply returns NULL under other OSs.
  */
-const char * get_environment_encoding(const ConnectionClass *conn, const char *setenc, const char *currenc)
+const char * get_environment_encoding(const ConnectionClass *conn, const char *setenc, const char *currenc, BOOL bStartup)
 {
    const char *wenc = NULL;
+   int acp;
 
 #ifdef UNICODE_SUPPORT
    if (CC_is_in_unicode_driver(conn))
        return "UTF8";
 #endif /* UNICODE_SUPPORT */
+   if (setenc && stricmp(setenc, OTHER_STRING))
+       return setenc;
 #ifdef WIN32
-   switch (GetACP())
+   acp = GetACP();
+   if (acp >= 1251 && acp <= 1258)
+   {
+       if (bStartup ||
+           stricmp(currenc, "SQL_ASCII") == 0)
+           return wenc;
+   }
+   switch (acp)
    {
        case 932:
            wenc = "SJIS";
            break;
        case 936:
-           if (!setenc && PG_VERSION_GT(conn, 7.2))
+           if (!bStartup && PG_VERSION_GT(conn, 7.2))
                wenc = "GBK";
            break;
        case 949:
-           if (!setenc || (PG_VERSION_GT(conn, 7.2) && stricmp(setenc, "EUC_KR")))  
+           if (!bStartup && PG_VERSION_GT(conn, 7.2))  
                wenc = "UHC";
            break;
        case 950:
@@ -423,18 +519,41 @@ const char * get_environment_encoding(const ConnectionClass *conn, const char *s
        case 1250:
            wenc = "WIN1250";
            break;
+       case 1251:
+           wenc = "WIN1251";
+           break;
+       case 1256:
+           if (PG_VERSION_GE(conn, 7.3))
+               wenc = "WIN1256";
+           break;
        case 1252:
-           if (setenc)
-               ;
-           else if (stricmp(currenc, "LATIN1") == 0 ||
-                stricmp(currenc, "LATIN9") == 0 ||
-                stricmp(currenc, "SQL_ASCII") == 0)
-               ;
-           else if (PG_VERSION_GE(conn, 8.1))
+           if (strnicmp(currenc, "LATIN", 5) == 0)
+               break;
+           if (PG_VERSION_GE(conn, 8.1))
                wenc = "WIN1252";
            else
                wenc = "LATIN1";
            break;
+       case 1258:
+           if (PG_VERSION_GE(conn, 8.1))
+               wenc = "WIN1258";
+           break;
+       case 1253:
+           if (PG_VERSION_GE(conn, 8.2))
+               wenc = "WIN1253";
+           break;
+       case 1254:
+           if (PG_VERSION_GE(conn, 8.2))
+               wenc = "WIN1254";
+           break;
+       case 1255:
+           if (PG_VERSION_GE(conn, 8.2))
+               wenc = "WIN1255";
+           break;
+       case 1257:
+           if (PG_VERSION_GE(conn, 8.2))
+               wenc = "WIN1257";
+           break;
    }
 #endif /* WIN32 */
    return wenc;
@@ -443,23 +562,34 @@ const char * get_environment_encoding(const ConnectionClass *conn, const char *s
 void
 CC_lookup_characterset(ConnectionClass *self)
 {
-   char    *encstr = NULL, *currenc = NULL, *tencstr;
+   char    *encspec = NULL, *currenc = NULL, *tencstr;
    CSTR func = "CC_lookup_characterset";
 
    mylog("%s: entering...\n", func);
+   if (self->original_client_encoding)
+       encspec = strdup(self->original_client_encoding);
    if (self->current_client_encoding)
-       encstr = strdup(self->current_client_encoding);
+       currenc = strdup(self->current_client_encoding);
    else if (PG_VERSION_LT(self, 7.2))
        currenc = CC_lookup_cs_old(self);
    else
        currenc = CC_lookup_cs_new(self);
-   tencstr = encstr ? encstr : currenc;
+   tencstr = encspec ? encspec : currenc;
    if (self->original_client_encoding)
+   {
+       if (stricmp(self->original_client_encoding, tencstr))
+       {
+           char msg[256];
+
+           snprintf(msg, sizeof(msg), "The client_encoding '%s' was changed to '%s'", self->original_client_encoding, tencstr);
+           CC_set_error(self, CONN_OPTION_VALUE_CHANGED, msg, func);
+       }
        free(self->original_client_encoding);
+   }
 #ifndef    UNICODE_SUPPORT
    else
    {
-       const char *wenc = get_environment_encoding(self, encstr, currenc);
+       const char *wenc = get_environment_encoding(self, encspec, currenc, FALSE);
        if (wenc && (!tencstr || stricmp(tencstr, wenc)))
        {
            QResultClass    *res;
@@ -476,8 +606,8 @@ CC_lookup_characterset(ConnectionClass *self)
            {
                self->original_client_encoding = strdup(wenc);
                self->ccsc = pg_CS_code(self->original_client_encoding);
-               if (encstr)
-                   free(encstr);
+               if (encspec)
+                   free(encspec);
                if (currenc)
                    free(currenc);
                return;
@@ -488,12 +618,16 @@ CC_lookup_characterset(ConnectionClass *self)
    if (tencstr)
    {
        self->original_client_encoding = tencstr;
+       if (encspec && currenc)
+           free(currenc);
        self->ccsc = pg_CS_code(tencstr);
        qlog("    [ Client encoding = '%s' (code = %d) ]\n", self->original_client_encoding, self->ccsc);
-       if (stricmp(pg_CS_name(self->ccsc), tencstr))
+       if (self->ccsc < 0)
        {
-           qlog(" Client encoding = '%s' and %s\n", self->original_client_encoding, pg_CS_name(self->ccsc));
-           CC_set_error(self, CONN_VALUE_OUT_OF_RANGE, "client encoding mismatch", func); 
+           char msg[256];
+
+           snprintf(msg, sizeof(msg), "would handle the encoding '%s' like ASCII", tencstr); 
+           CC_set_error(self, CONN_OPTION_VALUE_CHANGED, msg, func); 
        }
    }
    else
index 1d6e831c4a3e2562867eee7e4cbf21568c299a7d..479117988450d3cb1a565a4a6fbb1fd225693eb0 100644 (file)
@@ -30,25 +30,25 @@ enum {
    ,LATIN10        /* ISO-8859 Latin 10 */
    ,WIN1256        /* Arabic Windows */
    ,WIN1258        /* Vietnamese Windows */
+   ,WIN866         /* Alternativny Variant (MS-DOS CP866) */
    ,WIN874         /* Thai Windows */
    ,KOI8R          /* KOI8-R/U */
-   ,WIN1251        /* windows-1251 */
-   ,WIN866         /* Alternativny Variant (MS-DOS CP866) */
+   ,WIN1251        /* Cyrillic Windows */
+   ,WIN1252        /* Western Europe Windows */
    ,ISO_8859_5     /* ISO-8859-5 */
    ,ISO_8859_6     /* ISO-8859-6 */
    ,ISO_8859_7     /* ISO-8859-7 */
    ,ISO_8859_8     /* ISO-8859-8 */
+   ,WIN1250        /* Central Europe Windows */
+   ,WIN1253        /* Greek Windows */
+   ,WIN1254        /* Turkish Windows */
+   ,WIN1255        /* Hebrew Windows */
+   ,WIN1257        /* Baltic(North Europe) Windows */
    ,SJIS           /* Shift JIS */
    ,BIG5           /* Big5 */
    ,GBK            /* GBK */
    ,UHC            /* UHC */
-   ,WIN1250        /* windows-1250 */
    ,GB18030        /* GB18030 */
-   ,UNICODE_PODBC      /* same as Unicode UTF-8 */
-   ,TCVN           /* TCVN ( < Ver8.1) */
-   ,ALT            /* ALT ( < Var8.1) */
-   ,WIN            /* WIN ( < Ver8.1) */
-   ,WIN1252        /* WIN1252 */
    ,OTHER      =   -1
 };
 
@@ -67,11 +67,11 @@ enum {
 /* New Type */
 
 extern void CC_lookup_characterset(ConnectionClass *self);
-extern const char *get_environment_encoding(const ConnectionClass *conn, const char *oldenc, const char *svrenc);
+extern const char *get_environment_encoding(const ConnectionClass *conn, const char *setenc, const char *svrenc, BOOL bStartup);
 
 extern int pg_CS_stat(int stat,unsigned int charcter,int characterset_code);
 extern int pg_CS_code(const UCHAR *stat_string);
-extern UCHAR *pg_CS_name(int code);
+extern const UCHAR *pg_CS_name(int code);
 
 typedef struct pg_CS
 {
@@ -97,5 +97,6 @@ void encoded_str_constr(encoded_str *encstr, int ccsc, const char *str);
 extern int encoded_nextchar(encoded_str *encstr);
 extern ssize_t encoded_position_shift(encoded_str *encstr, size_t shift);
 extern int encoded_byte_check(encoded_str *encstr, size_t abspos);
-#define check_client_encoding(X) pg_CS_name(pg_CS_code(X))
+/* #define check_client_encoding(X) pg_CS_name(pg_CS_code(X)) */
+UCHAR *check_client_encoding(const UCHAR *sql_string);
 #endif /* __MULTIBUYTE_H__ */
diff --git a/parse.c b/parse.c
index bdc63a62d3c672ff634daef787dec67c38ef74f6..5c4c7d58a4f7d4c7054056041d61b77a23180cc7 100644 (file)
--- a/parse.c
+++ b/parse.c
@@ -451,6 +451,50 @@ static BOOL increaseNtab(StatementClass *stmt, const char *func)
    stmt->ntab++;
    return TRUE;
 }
+   
+static void setNumFields(IRDFields *irdflds, size_t numFields)
+{
+   FIELD_INFO  **fi = irdflds->fi;
+   size_t      nfields = irdflds->nfields;
+
+   if (numFields < nfields)
+   {
+       int i;
+
+       for (i = (int) numFields; i < (int) nfields; i++)
+       {
+           if (fi[i])
+               fi[i]->flag = 0;
+       }
+   }
+   irdflds->nfields = (UInt4) numFields;
+}
+
+static BOOL allocateFields(IRDFields *irdflds, size_t sizeRequested)
+{
+   FIELD_INFO  **fi = irdflds->fi;
+   size_t      alloc_size, incr_size;
+
+   if (sizeRequested <= irdflds->allocated)
+       return TRUE;
+   alloc_size = (0 != irdflds->allocated ? irdflds->allocated : FLD_INCR);
+   for (; alloc_size < sizeRequested; alloc_size *= 2)
+           ;
+   incr_size = sizeof(FIELD_INFO *) * (alloc_size - irdflds->allocated);
+
+   fi = (FIELD_INFO **) realloc(fi, alloc_size * sizeof(FIELD_INFO *));
+   if (!fi)
+   {
+       irdflds->fi = NULL;
+       irdflds->allocated = irdflds->nfields = 0;
+       return FALSE;
+   }
+   memset(&fi[irdflds->allocated], 0, incr_size);
+   irdflds->fi = fi;
+   irdflds->allocated = (SQLSMALLINT) alloc_size;
+
+   return TRUE;
+}
 
 static void xxxxx(FIELD_INFO *fi, QResultClass *res, int i)
 {
@@ -512,25 +556,19 @@ mylog("ColAttSet in\n");
    fi = irdflds->fi;
    if (num_fields > (int) irdflds->allocated)
    {
-       fi = (FIELD_INFO **) realloc(fi, num_fields * sizeof(FIELD_INFO *));
-       if (!fi)
-       {
-           irdflds->fi = NULL;
-           irdflds->allocated = irdflds->nfields = 0;
+       if (!allocateFields(irdflds, num_fields))
            return FALSE;
-       }
-       irdflds->fi = fi;
-       irdflds->allocated = num_fields;
-       for (i = irdflds->nfields; i < num_fields; i++)
-           fi[i] = NULL;
-       irdflds->nfields = num_fields;
+       fi = irdflds->fi;
    }
+   setNumFields(irdflds, num_fields);
    updatable = rti ? TI_is_updatable(rti) : FALSE;
 mylog("updatable=%d tab=%d fields=%d", updatable, stmt->ntab, num_fields);
    if (updatable)
    {
        if (1 != stmt->ntab)
            updatable = FALSE;
+       else if (SC_has_join(stmt))
+           updatable = FALSE;
        else
        {
            OID greloid;
@@ -749,7 +787,7 @@ inolog("fi=%p greloid=%d col_info=%p\n", wti, greloid, wti->col_info);
    }
    if (found)
        goto cleanup;
-   else
+   else if (0 != greloid || NAME_IS_VALID(wti->table_name))
    {
        RETCODE     result;
        StatementClass  *col_stmt;
@@ -920,13 +958,13 @@ parse_statement(StatementClass *stmt, BOOL check_hasoids)
                k = 0,
                n,
                blevel = 0, old_blevel, subqlevel = 0,
-               nfields_old, allocated_size, new_size;
+               allocated_size, new_size;
    FIELD_INFO **fi, *wfi;
    TABLE_INFO **ti, *wti;
-   char        parse;
+   char        parse, maybe_join = 0;
    ConnectionClass *conn = SC_get_conn(stmt);
    IRDFields   *irdflds = SC_get_IRDF(stmt);
-   BOOL        updatable = TRUE, maybe_outerj = FALSE;
+   BOOL        updatable = TRUE;
 
    mylog("%s: entering...\n", func);
 
@@ -942,8 +980,7 @@ parse_statement(StatementClass *stmt, BOOL check_hasoids)
    ti = stmt->ti;
 
    allocated_size = irdflds->allocated;
-   nfields_old = irdflds->nfields;
-   irdflds->nfields = 0;
+   setNumFields(irdflds, 0);
    if (stmt->ntab > 0)
    {
        TI_Destructor(stmt->ti, stmt->ntab);
@@ -953,6 +990,7 @@ parse_statement(StatementClass *stmt, BOOL check_hasoids)
    }
    stmt->from_pos = -1;
    stmt->where_pos = -1;
+#define    return  DONT_CALL_RETURN_FROM_HERE???
 
    while (pptr = ptr, (ptr = getNextToken(conn->ccsc, CC_get_escape(conn), pptr, token, sizeof(token), &delim, &quote, &dquote, &numeric)) != NULL)
    {
@@ -979,7 +1017,7 @@ parse_statement(StatementClass *stmt, BOOL check_hasoids)
                    mylog("INTO\n");
                    stmt->statement_type = STMT_TYPE_CREATE;
                    SC_set_parse_status(stmt, STMT_PARSE_FATAL);
-                   return FALSE;
+                   goto cleanup;
                }
                else if (!stricmp(token, "from"))
                {
@@ -1126,22 +1164,18 @@ parse_statement(StatementClass *stmt, BOOL check_hasoids)
                if (irdflds->nfields >= allocated_size)
                {
                    mylog("reallocing at nfld=%d\n", irdflds->nfields);
-                   new_size = (irdflds->nfields / FLD_INCR + 1) * FLD_INCR;
-                   fi = (FIELD_INFO **) realloc(fi, new_size * sizeof(FIELD_INFO *));
-                   if (!fi)
+                   new_size = irdflds->nfields + 1;
+                   if (!allocateFields(irdflds, new_size))
                    {
                        SC_set_parse_status(stmt, STMT_PARSE_FATAL);
                        SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "PGAPI_AllocStmt failed in parse_statement for FIELD_INFO.", func);
-                       return FALSE;
+                       goto cleanup;
                    }
-                   allocated_size = new_size;
-                   irdflds->fi = fi;
-                   irdflds->allocated = allocated_size;
+                   fi = irdflds->fi;
+                   allocated_size = irdflds->allocated;
                }
 
-               wfi = NULL;
-               if (irdflds->nfields < nfields_old)
-                   wfi = fi[irdflds->nfields];
+               wfi = fi[irdflds->nfields];
                if (wfi)
                    fi_reuse = TRUE;
                else
@@ -1150,7 +1184,7 @@ parse_statement(StatementClass *stmt, BOOL check_hasoids)
                {
                    SC_set_parse_status(stmt, STMT_PARSE_FATAL);
                    SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "PGAPI_AllocStmt failed in parse_statement for FIELD_INFO(2).", func);
-                   return FALSE;
+                   goto cleanup;
                }
 
                /* Initialize the field info */
@@ -1283,7 +1317,7 @@ parse_statement(StatementClass *stmt, BOOL check_hasoids)
            if (out_table && !in_table) /* new table */
            {
                in_dot = FALSE;
-               maybe_outerj = FALSE;
+               maybe_join = 0;
                if (!dquote)
                {
                    if (token[0] == '(' ||
@@ -1294,13 +1328,21 @@ parse_statement(StatementClass *stmt, BOOL check_hasoids)
                if (!increaseNtab(stmt, func))
                {
                    SC_set_parse_status(stmt, STMT_PARSE_FATAL);
-                   return FALSE;
+                   goto cleanup;
                }
 
                ti = stmt->ti;
                wti = ti[stmt->ntab - 1];
-               STR_TO_NAME(wti->table_name, token);
-               lower_the_name(GET_NAME(wti->table_name), conn, dquote);
+               if (dquote || stricmp(token, "select"))
+               {
+                   STR_TO_NAME(wti->table_name, token);
+                   lower_the_name(GET_NAME(wti->table_name), conn, dquote);
+               }
+               else
+               {
+                   NULL_THE_NAME(wti->table_name);
+                   TI_no_updatable(wti);
+               }
                mylog("got table = '%s'\n", PRINT_NAME(wti->table_name));
 
                if (0 == blevel && delim == ',')
@@ -1327,24 +1369,35 @@ parse_statement(StatementClass *stmt, BOOL check_hasoids)
                        stricmp(token, "OUTER") == 0 ||
                        stricmp(token, "FULL") == 0)
                {
+                   maybe_join = 1;
+                   in_table = FALSE;
+                   continue;
+               }
+               else if (stricmp(token, "INNER") == 0 ||
+                    stricmp(token, "CROSS") == 0)
+               {
+                   maybe_join = 2;
                    in_table = FALSE;
-                   maybe_outerj = TRUE;
                    continue;
                }
                else if (stricmp(token, "JOIN") == 0)
                {
                    in_table = FALSE;
                    out_table = TRUE;
-                   if (maybe_outerj)
+                   switch (maybe_join)
                    {
-                       SC_set_outer_join(stmt);
-                       maybe_outerj = FALSE;
+                       case 1:
+                           SC_set_outer_join(stmt);
+                           break;
+                       case 2:
+                           SC_set_inner_join(stmt);
+                           break;
                    }
+                   maybe_join = 0;
                    continue;
                }
-               else
-                   maybe_outerj = FALSE;
            }
+           maybe_join = 0;
            if (in_table)
            {
                wti = ti[stmt->ntab - 1];
@@ -1365,8 +1418,7 @@ parse_statement(StatementClass *stmt, BOOL check_hasoids)
                {
                    if (!dquote)
                    {
-                       if (stricmp(token, "INNER") == 0 ||
-                           stricmp(token, "ON") == 0)
+                       if (stricmp(token, "ON") == 0)
                        {
                            in_table = FALSE;
                            continue;
@@ -1443,7 +1495,7 @@ parse_statement(StatementClass *stmt, BOOL check_hasoids)
                            SC_set_parse_status(stmt, STMT_PARSE_FATAL);
                            SC_set_error(stmt, STMT_EXEC_ERROR, "duplicated Table name", func);
                            stmt->updatable = FALSE;
-                           return FALSE;
+                           goto cleanup;
                        }
                    }
                }
@@ -1478,7 +1530,7 @@ parse_statement(StatementClass *stmt, BOOL check_hasoids)
    if (0 == stmt->ntab)
    {
        SC_set_parse_status(stmt, STMT_PARSE_FATAL);
-       return  FALSE;
+       goto cleanup;
    }
 
    for (i = 0; i < (int) irdflds->nfields; i++)
@@ -1513,7 +1565,9 @@ parse_statement(StatementClass *stmt, BOOL check_hasoids)
            break;
    }
    if (STMT_PARSE_FATAL == SC_parsed_status(stmt))
-       return FALSE;
+   {
+       goto cleanup;
+   }
 
    mylog("Done PG_Columns\n");
 
@@ -1559,25 +1613,22 @@ parse_statement(StatementClass *stmt, BOOL check_hasoids)
            increased_cols = total_cols - 1;
 
            /* Allocate some more field pointers if necessary */
-           /* allocated_size = ((irdflds->nfields - 1) / FLD_INCR + 1) * FLD_INCR; */
            new_size = irdflds->nfields + increased_cols;
 
            mylog("k=%d, increased_cols=%d, allocated_size=%d, new_size=%d\n", k, increased_cols, allocated_size, new_size);
 
            if (new_size > allocated_size)
            {
-               int         new_alloc = ((new_size / FLD_INCR) + 1) * FLD_INCR;
+               int new_alloc = new_size;
 
                mylog("need more cols: new_alloc = %d\n", new_alloc);
-               fi = (FIELD_INFO **) realloc(fi, new_alloc * sizeof(FIELD_INFO *));
-               if (!fi)
+               if (!allocateFields(irdflds, new_alloc))
                {
                    SC_set_parse_status(stmt, STMT_PARSE_FATAL);
-                   return FALSE;
+                   goto cleanup;
                }
-               allocated_size = new_alloc;
-               irdflds->fi = fi;
-               irdflds->allocated = allocated_size;
+               fi = irdflds->fi;
+               allocated_size = irdflds->allocated;
            }
 
            /*
@@ -1620,7 +1671,7 @@ parse_statement(StatementClass *stmt, BOOL check_hasoids)
                        if (fi[n + i] == NULL)
                        {
                            SC_set_parse_status(stmt, STMT_PARSE_FATAL);
-                           return FALSE;
+                           goto cleanup;
                        }
                        reuse = FALSE;
                    }
@@ -1689,6 +1740,18 @@ parse_statement(StatementClass *stmt, BOOL check_hasoids)
    }
 
    stmt->updatable = updatable;
+cleanup:
+#undef return
+   if (STMT_PARSE_FATAL == SC_parsed_status(stmt))
+   {
+       setNumFields(irdflds, 0);
+       TI_Destructor(stmt->ti, stmt->ntab);
+       free(stmt->ti);
+       stmt->ti = NULL;
+       stmt->ntab = 0;
+       parse = FALSE;
+   }
+
    mylog("done parse_statement: parse=%d, parse_status=%d\n", parse, SC_parsed_status(stmt));
    return parse;
 }
index be11940c8322d2da2fc0f893032166869723b652..4ba6780afb31f0c7eebd192c4258fe5e80f4ba32 100644 (file)
--- a/results.c
+++ b/results.c
@@ -889,7 +889,7 @@ PGAPI_GetData(
    ConnInfo   *ci;
    SQLSMALLINT target_type;
 
-   mylog("%s: enter, stmt=%p\n", func, stmt);
+   mylog("%s: enter, stmt=%p icol=%d\n", func, stmt, icol);
 
    if (!stmt)
    {
diff --git a/setup.c b/setup.c
index fca852f1e7eb0fc6040670ff824801b196346a3e..37b67e902185bcb64396bb55a6c003a77c24aa78 100644 (file)
--- a/setup.c
+++ b/setup.c
@@ -302,19 +302,24 @@ ConfigDlgProc(HWND hdlg,
                        if (conn)
                        {
                            char *emsg;
+                           int errnum;
 
                            EN_add_connection(env, conn);
                            memcpy(&conn->connInfo, &lpsetupdlg->ci, sizeof(ConnInfo));
                            CC_initialize_pg_version(conn);
                            if (CC_connect(conn, AUTH_REQ_OK, NULL) > 0)
                            {
-                               strncpy(szMsg, "Connection successful", sizeof(szMsg));
+                               if (CC_get_errornumber(conn) != 0)
+                               {
+                                   CC_get_error(conn, &errnum, &emsg);
+                                   snprintf(szMsg, sizeof(szMsg), "Warning: %s", emsg);
+                               }
+                               else
+                                   strncpy(szMsg, "Connection successful", sizeof(szMsg));
                                emsg = szMsg;
                            }
                            else
                            {
-                               int errnum;
-
                                CC_get_error(conn, &errnum, &emsg);
                            }
                            MessageBox(lpsetupdlg->hwndParent, emsg, "Connection Test", MB_ICONEXCLAMATION | MB_OK);
@@ -416,7 +421,8 @@ ParseAttributes(LPCSTR lpszAttributes, LPSETUPDLG lpsetupdlg)
        mylog("aszKey='%s', value='%s'\n", aszKey, value);
 
        /* Copy the appropriate value to the conninfo  */
-       copyAttributes(&lpsetupdlg->ci, aszKey, value);
+       if (!copyAttributes(&lpsetupdlg->ci, aszKey, value))
+           copyCommonAttributes(&lpsetupdlg->ci, aszKey, value);
    }
    return;
 }
index 216d80d1758edccc7d67477e39020a9b691c1abd..4ffb585b3e61a846064863c103cf1a0ef56390ef 100644 (file)
@@ -84,7 +84,7 @@ static struct
        STMT_TYPE_EXECUTE, "EXECUTE"
    }
    ,{
-       STMT_TYPE_EXECUTE, "DEALLOCATE"
+       STMT_TYPE_DEALLOCATE, "DEALLOCATE"
    }
    ,{
        STMT_TYPE_DROP, "DROP"
@@ -1629,7 +1629,7 @@ SC_execute(StatementClass *self)
        switch (SC_get_prepare_method(self))
        {
 #ifndef    BYPASS_ONESHOT_PLAN_EXECUTION
-       case PARSE_TO_EXEC_ONCE:
+           case PARSE_TO_EXEC_ONCE:
 #endif /* BYPASS_ONESHOT_PLAN_EXECUTION */
            case NAMED_PARSE_REQUEST:
                use_extended_protocol = TRUE;
index 8ac83b14ad40928eb0e4a1b9cada51fef5693bbc..8ed970c5cf9b594bbf6f8b9447c9adc51ba84288 100644 (file)
--- a/version.h
+++ b/version.h
@@ -9,8 +9,8 @@
 #ifndef __VERSION_H__
 #define __VERSION_H__
 
-#define POSTGRESDRIVERVERSION      "08.02.0202"
-#define POSTGRES_RESOURCE_VERSION  "08.02.0202\0"
-#define PG_DRVFILE_VERSION     8,2,02,02
+#define POSTGRESDRIVERVERSION      "08.02.0203"
+#define POSTGRES_RESOURCE_VERSION  "08.02.0203\0"
+#define PG_DRVFILE_VERSION     8,2,02,03
 
 #endif