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;
}
}
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);
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))
}
}
- 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)
const char *CurrCat(const ConnectionClass *conn)
{
- /*
if (conn->schema_support)
return conn->connInfo.database;
else
- */
return NULL;
}
#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
#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
*----------
*/
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;
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;
}
}
/* 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;
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);
}
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)
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,
ci->drivers.parse,
ci->drivers.cancel_as_freestmt,
ci->drivers.extra_systable_prefixes);
+
+ return found;
}
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)
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 *);
char rv = 1;
mylog("in EN_Destructor, self=%p\n", self);
+ if (!self)
+ return 0;
/*
* the error messages are static strings distributed throughout the
}
}
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)
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],
#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],
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);
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:
/*
* 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))
{
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);
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;
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);
}
}
- /* 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))
}
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);
/* 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))
{
{
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
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"); ***/
}
*/
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);
*/
#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 },
{ "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)
}
}
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;
if (CS_Table[i].code == characterset_code)
return CS_Table[i].name;
}
- return ("OTHER");
+ return (OTHER_STRING);
}
static int
switch (characterset_code)
{
case UTF8:
- case UNICODE_PODBC:
return 6;
case EUC_TW:
return 4;
switch (characterset_code)
{
case UTF8:
- case UNICODE_PODBC:
{
if (stat < 2 &&
character >= 0x80)
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);
* 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:
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;
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;
{
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;
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
,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
};
/* 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
{
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__ */
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)
{
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;
}
if (found)
goto cleanup;
- else
+ else if (0 != greloid || NAME_IS_VALID(wti->table_name))
{
RETCODE result;
StatementClass *col_stmt;
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);
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);
}
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, "e, &dquote, &numeric)) != NULL)
{
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"))
{
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
{
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 */
if (out_table && !in_table) /* new table */
{
in_dot = FALSE;
- maybe_outerj = FALSE;
+ maybe_join = 0;
if (!dquote)
{
if (token[0] == '(' ||
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 == ',')
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];
{
if (!dquote)
{
- if (stricmp(token, "INNER") == 0 ||
- stricmp(token, "ON") == 0)
+ if (stricmp(token, "ON") == 0)
{
in_table = FALSE;
continue;
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;
}
}
}
if (0 == stmt->ntab)
{
SC_set_parse_status(stmt, STMT_PARSE_FATAL);
- return FALSE;
+ goto cleanup;
}
for (i = 0; i < (int) irdflds->nfields; i++)
break;
}
if (STMT_PARSE_FATAL == SC_parsed_status(stmt))
- return FALSE;
+ {
+ goto cleanup;
+ }
mylog("Done PG_Columns\n");
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;
}
/*
if (fi[n + i] == NULL)
{
SC_set_parse_status(stmt, STMT_PARSE_FATAL);
- return FALSE;
+ goto cleanup;
}
reuse = FALSE;
}
}
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;
}
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)
{
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);
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;
}
STMT_TYPE_EXECUTE, "EXECUTE"
}
,{
- STMT_TYPE_EXECUTE, "DEALLOCATE"
+ STMT_TYPE_DEALLOCATE, "DEALLOCATE"
}
,{
STMT_TYPE_DROP, "DROP"
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;
#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