142
143
static const char *mapFunction(const char *func, int param_count);
143
144
static int conv_from_octal(const UCHAR *s);
144
static SQLLEN pg_bin2hex(UCHAR *src, UCHAR *dst, SQLLEN length);
145
static SQLLEN pg_bin2hex(const UCHAR *src, UCHAR *dst, SQLLEN length);
146
#ifdef UNICODE_SUPPORT
147
static SQLLEN pg_bin2whex(const UCHAR *src, SQLWCHAR *dst, SQLLEN length);
148
#endif /* UNICODE_SUPPORT */
147
151
* A Guide for date/time/timestamp conversions
602
606
#endif /* ODBCVER */
610
static char *current_locale = NULL;
611
static char *current_decimal_point = NULL;
612
static void current_numeric_locale()
614
char *loc = setlocale(LC_NUMERIC, NULL);
615
if (NULL == current_locale || 0 != stricmp(loc, current_locale))
617
struct lconv *lc = localeconv();
619
if (NULL != current_locale)
620
free(current_locale);
621
current_locale = strdup(loc);
622
if (NULL != current_decimal_point)
623
free(current_decimal_point);
624
current_decimal_point = strdup(lc->decimal_point);
628
static void set_server_decimal_point(char *num)
632
current_numeric_locale();
633
if ('.' == *current_decimal_point)
635
for (str = num; '\0' != *str; str++)
637
if (*str == *current_decimal_point)
645
static void set_client_decimal_point(char *num)
649
current_numeric_locale();
650
if ('.' == *current_decimal_point)
652
for (str = num; '\0' != *str; str++)
656
*str = *current_decimal_point;
662
static void set_server_decimal_point(char *num) {}
663
static void set_client_decimal_point(char *num, BOOL) {}
664
#endif /* HAVE_LOCALE_H */
605
666
/* This is called by SQLFetch() */
607
668
copy_and_convert_field_bindinfo(StatementClass *stmt, OID field_type, int atttypmod, void *value, int col)
1163
1238
if (pgdc->data_left < 0)
1165
1240
BOOL lf_conv = conn->connInfo.lf_conversion;
1241
if (PG_TYPE_BYTEA == field_type)
1244
len = strlen(neut_str);
1247
len = convert_from_pgbinary(neut_str, NULL, 0);
1251
#ifdef UNICODE_SUPPORT
1252
if (fCType == SQL_C_WCHAR)
1254
#endif /* UNICODE_SUPPORT */
1166
1257
#ifdef UNICODE_SUPPORT
1167
1258
if (fCType == SQL_C_WCHAR)
1174
1265
#endif /* UNICODE_SUPPORT */
1175
if (PG_TYPE_BYTEA == field_type)
1177
len = convert_from_pgbinary(neut_str, NULL, 0);
1182
1266
#ifdef WIN_UNICODE_SUPPORT
1183
1267
if (localize_needed)
1227
1311
#ifdef UNICODE_SUPPORT
1228
1312
if (fCType == SQL_C_WCHAR)
1230
utf8_to_ucs2_lf(neut_str, SQL_NTS, lf_conv, (SQLWCHAR *) pgdc->ttlbuf, len / WCLEN);
1314
if (PG_TYPE_BYTEA == field_type && !hex_bin_format)
1316
len = convert_from_pgbinary(neut_str, pgdc->ttlbuf, pgdc->ttlbuflen);
1317
len = pg_bin2whex(pgdc->ttlbuf, (SQLWCHAR *) pgdc->ttlbuf, len);
1320
utf8_to_ucs2_lf(neut_str, SQL_NTS, lf_conv, (SQLWCHAR *) pgdc->ttlbuf, len / WCLEN);
1233
1323
#endif /* UNICODE_SUPPORT */
1234
1324
if (PG_TYPE_BYTEA == field_type)
1236
len = convert_from_pgbinary(neut_str, pgdc->ttlbuf, pgdc->ttlbuflen);
1237
pg_bin2hex(pgdc->ttlbuf, pgdc->ttlbuf, len);
1328
len = strlen(neut_str);
1329
strncpy_null(pgdc->ttlbuf, neut_str, pgdc->ttlbuflen);
1333
len = convert_from_pgbinary(neut_str, pgdc->ttlbuf, pgdc->ttlbuflen);
1334
len = pg_bin2hex(pgdc->ttlbuf, pgdc->ttlbuf, len);
1241
1338
#ifdef WIN_UNICODE_SUPPORT
1296
1393
copy_len *= WCLEN;
1298
1395
#endif /* UNICODE_SUPPORT */
1299
#ifdef HAVE_LOCALE_H
1302
case PG_TYPE_FLOAT4:
1303
case PG_TYPE_FLOAT8:
1304
case PG_TYPE_NUMERIC:
1310
new_string = malloc(cbValueMax);
1312
for (i = 0, j = 0; ptr[i]; i++)
1316
strncpy_null(&new_string[j], lc->decimal_point, cbValueMax - j);
1317
j += strlen(lc->decimal_point);
1320
new_string[j++] = ptr[i];
1322
new_string[j] = '\0';
1323
strncpy_null(rgbValueBindRow, new_string, copy_len + 1);
1325
already_copied = TRUE;
1329
#endif /* HAVE_LOCALE_H */
1330
1396
if (!already_copied)
1332
1398
/* Copy the data */
1500
1566
case SQL_C_FLOAT:
1501
#ifdef HAVE_LOCALE_H
1502
saved_locale = strdup(setlocale(LC_ALL, NULL));
1503
setlocale(LC_ALL, "C");
1504
#endif /* HAVE_LOCALE_H */
1567
set_client_decimal_point((char *) neut_str);
1506
1569
if (bind_size > 0)
1507
1570
*((SFLOAT *) rgbValueBindRow) = (float) get_double_value(neut_str);
1509
1572
*((SFLOAT *) rgbValue + bind_row) = (float) get_double_value(neut_str);
1510
#ifdef HAVE_LOCALE_H
1511
setlocale(LC_ALL, saved_locale);
1513
#endif /* HAVE_LOCALE_H */
1516
1575
case SQL_C_DOUBLE:
1517
#ifdef HAVE_LOCALE_H
1518
saved_locale = strdup(setlocale(LC_ALL, NULL));
1519
setlocale(LC_ALL, "C");
1520
#endif /* HAVE_LOCALE_H */
1576
set_client_decimal_point((char *) neut_str);
1522
1578
if (bind_size > 0)
1523
1579
*((SDOUBLE *) rgbValueBindRow) = get_double_value(neut_str);
1525
1581
*((SDOUBLE *) rgbValue + bind_row) = get_double_value(neut_str);
1526
#ifdef HAVE_LOCALE_H
1527
setlocale(LC_ALL, saved_locale);
1529
#endif /* HAVE_LOCALE_H */
1532
1584
#if (ODBCVER >= 0x0300)
1533
1585
case SQL_C_NUMERIC:
1534
#ifdef HAVE_LOCALE_H
1535
/* strcpy(saved_locale, setlocale(LC_ALL, NULL));
1536
setlocale(LC_ALL, "C"); not needed currently */
1537
#endif /* HAVE_LOCALE_H */
1539
1587
SQL_NUMERIC_STRUCT *ns;
1540
1588
int i, nlen, bit, hval, tv, dig, sta, olen;
1926
1971
#define FLGB_DISCARD_OUTPUT (1L << 8)
1927
1972
#define FLGB_BINARY_AS_POSSIBLE (1L << 9)
1928
1973
#define FLGB_LITERAL_EXTENSION (1L << 10)
1974
#define FLGB_HEX_BIN_FORMAT (1L << 11)
1929
1975
typedef struct _QueryBuild {
1930
1976
char *query_statement;
1931
1977
size_t str_size_limit;
2003
2049
if (CC_get_escape(qb->conn) &&
2004
2050
PG_VERSION_GE(qb->conn, 8.1))
2005
2051
qb->flags |= FLGB_LITERAL_EXTENSION;
2052
if (PG_VERSION_GE(qb->conn, 9.0))
2053
qb->flags |= FLGB_HEX_BIN_FORMAT;
2008
2056
qb->str_size_limit = stmt->stmt_size_limit;
2245
2293
#define CVT_APPEND_BINARY(qb, buf, used) \
2247
size_t newlimit = qb->npos + 5 * used; \
2295
size_t newlimit = qb->npos + ((qb->flags & FLGB_HEX_BIN_FORMAT) ? 2 * used + 4 : 5 * used); \
2248
2296
ENLARGE_NEWSTATEMENT(qb, newlimit); \
2249
2297
qb->npos += convert_to_pgbinary(buf, &qb->query_statement[qb->npos], used, qb); \
2299
2348
if (replace_by_parenthesis)
2300
2349
CVT_APPEND_CHAR(qb, '(');
2301
2350
qb->brace_level++;
2351
retval = SQL_SUCCESS;
2306
2357
QB_end_brace(QueryBuild *qb)
2308
2359
BOOL replace_by_parenthesis = TRUE;
2360
RETCODE retval = SQL_ERROR;
2310
2362
if (qb->brace_level <= 1 &&
2311
2363
!qb->parenthesize_the_first)
2529
2586
CSTR func = "Prepare_and_convert";
2530
2587
char *exe_statement = NULL;
2532
2589
ConnectionClass *conn = SC_get_conn(stmt);
2533
2590
ConnInfo *ci = &(conn->connInfo);
2534
2591
BOOL discardOutput, outpara;
2604
2662
retval = inner_process_tokens(qp, qb);
2605
2663
if (SQL_ERROR == retval)
2607
QB_replace_SC_error(stmt, qb, func);
2612
2666
CVT_APPEND_CHAR(qb, ';');
2613
2667
/* build the execute statement */
2639
2693
retval = inner_process_tokens(qp, qb);
2640
2694
if (SQL_ERROR == retval)
2697
/* make sure new_statement is always null-terminated */
2699
retval = SQL_SUCCESS;
2702
if (SQL_SUCCEEDED(retval))
2705
SC_set_concat_prepare_exec(stmt);
2706
stmt->stmt_with_params = qb->query_statement;
2707
qb->query_statement = NULL;
2711
QB_replace_SC_error(stmt, qb, func);
2642
QB_replace_SC_error(stmt, qb, func);
2645
free(exe_statement);
2646
stmt->execute_statement = NULL;
2714
free(exe_statement);
2715
stmt->execute_statement = NULL;
2652
/* make sure new_statement is always null-terminated */
2656
SC_set_concat_prepare_exec(stmt);
2657
stmt->stmt_with_params = qb->query_statement;
2658
qb->query_statement = NULL;
2662
2722
#define my_strchr(conn, s1,c1) pg_mbschr(conn->ccsc, s1,c1)
2925
2985
if (prepare_dummy_cursor)
2926
2986
qp->flags |= FLGP_PREPARE_DUMMY_CURSOR;
2927
2987
if (QB_initialize(qb, qp->stmt_len, stmt, NULL) < 0)
2929
2992
new_statement = qb->query_statement;
2931
2994
/* For selects, prepend a declare cursor to the statement */
3869
3936
char *buffer, *buf, *allocbuf, *lastadd = NULL;
3871
int lobj_fd, retval;
3872
3939
SQLULEN offset = apdopts->param_offset_ptr ? *apdopts->param_offset_ptr : 0;
3873
3940
size_t current_row = qb->current_row, npos = 0;
3874
3941
BOOL handling_large_object = FALSE, req_bind, add_quote = FALSE;
3881
3948
SQL_INTERVAL_STRUCT *ivstruct;
3882
3949
const char *ivsign;
3883
3950
#endif /* ODBCVER */
3951
RETCODE retval = SQL_ERROR;
3885
3953
outputDiscard = (0 != (qb->flags & FLGB_DISCARD_OUTPUT));
3886
3954
valueOutput = (0 == (qb->flags & (FLGB_PRE_EXECUTING | FLGB_BUILDING_PREPARE_STATEMENT)));
4160
4228
if (_finite(dbv))
4161
4229
#endif /* WIN32 */
4162
sprintf(param_string, "%.15g", dbv);
4231
sprintf(param_string, "%.15g", dbv);
4232
set_server_decimal_point(param_string);
4164
4235
else if (_isnan(dbv))
4165
4236
strcpy(param_string, NAN_STRING);
4176
4247
if (_finite(flv))
4177
4248
#endif /* WIN32 */
4178
sprintf(param_string, "%.6g", flv);
4250
sprintf(param_string, "%.6g", flv);
4251
set_server_decimal_point(param_string);
4180
4254
else if (_isnan(flv))
4181
4255
strcpy(param_string, NAN_STRING);
4433
4509
'1' == param_string[1])
4434
4510
strcpy(param_string, "1");
4512
case PG_TYPE_FLOAT4:
4513
case PG_TYPE_FLOAT8:
4514
case PG_TYPE_NUMERIC:
4516
set_server_decimal_point(buf);
4518
set_server_decimal_point(param_string);
4437
4521
/* it was a SQL_C_CHAR */
4593
4684
qb->errornumber = STMT_EXEC_ERROR;
4594
4685
qb->errormsg = "Couldnt open (in-line) large object for writing.";
4598
4690
retval = odbc_lo_write(conn, lobj_fd, buffer, (Int4) used);
4633
4726
my_strcpy(param_string, sizeof(param_string), buf, used);
4727
set_server_decimal_point(param_string);
4634
4728
lastadd = "::float4";
4635
4729
CVT_APPEND_STR(qb, param_string);
4638
4732
case SQL_DOUBLE:
4640
4734
my_strcpy(param_string, sizeof(param_string), buf, used);
4735
set_server_decimal_point(param_string);
4641
4736
lastadd = "::float8";
4642
4737
CVT_APPEND_STR(qb, param_string);
4677
4772
CVT_APPEND_STR(qb, lastadd);
4776
UInt4 slen = htonl((UInt4) (qb->npos - npos - 4));
4778
memcpy(qb->query_statement + npos, &slen, sizeof(slen));
4780
retval = SQL_SUCCESS;
4680
4783
free(allocbuf);
4683
UInt4 slen = htonl((UInt4) (qb->npos - npos - 4));
4685
memcpy(qb->query_statement + npos, &slen, sizeof(slen));
4910
5013
CVT_APPEND_DATA(qb, F_OldPtr(qp), funclen);
4911
5014
CVT_APPEND_STR(qb, "()");
4912
5015
if (SQL_ERROR == QB_end_brace(qb))
4914
5020
/* positioned at } */
4915
5021
qp->opos += (nextdel - F_OldPtr(qp));
5010
5115
QB_initialize_copy(&nqb, qb, 1024);
5116
nqb_is_valid = TRUE;
5011
5117
if (retval = processParameters(qp, &nqb, ¶m_consumed, param_pos), retval == SQL_ERROR)
5013
5119
qb->errornumber = nqb.errornumber;
5014
5120
qb->errormsg = nqb.errormsg;
5015
QB_Destructor(&nqb);
5019
5124
for (param_count = 0;; param_count++)
5578
5685
char escape_in_literal = CC_get_escape(qb->conn);
5579
5686
BOOL esc_double = (0 == (qb->flags & FLGB_BUILDING_BIND_REQUEST) && 0 != escape_in_literal);
5688
/* use hex format for 9.0 or later servers */
5689
if (0 != (qb->flags & FLGB_HEX_BIN_FORMAT))
5692
out[o++] = escape_in_literal;
5695
o += pg_bin2hex(in, (UCHAR *) out + o, len);
5581
5698
for (i = 0; i < len; i++)
5607
5724
static const char *hextbl = "0123456789ABCDEF";
5609
pg_bin2hex(UCHAR *src, UCHAR *dst, SQLLEN length)
5620
if (dst + length > src + 1)
5623
else if (dst < src + length)
5627
for (i = 0, src_wk = src + length - 1, dst_wk = dst + 2 * length - 1; i < length; i++, src_wk--)
5630
*dst_wk-- = hextbl[chr % 16];
5631
*dst_wk-- = hextbl[chr >> 4];
5636
for (i = 0, src_wk = src, dst_wk = dst; i < length; i++, src_wk++)
5639
*dst_wk++ = hextbl[chr >> 4];
5640
*dst_wk++ = hextbl[chr % 16];
5643
dst[2 * length] = '\0';
5726
#define def_bin2hex(type) \
5727
(const UCHAR *src, type *dst, SQLLEN length) \
5729
const UCHAR *src_wk; \
5735
backwards = FALSE; \
5736
if ((UCHAR *)dst < src) \
5738
if ((UCHAR *) (dst + 2 * (length - 1)) > src + length - 1) \
5741
else if ((UCHAR *) dst < src + length) \
5745
for (i = 0, src_wk = src + length - 1, dst_wk = dst + 2 * length - 1; i < length; i++, src_wk--) \
5748
*dst_wk-- = hextbl[chr % 16]; \
5749
*dst_wk-- = hextbl[chr >> 4]; \
5754
for (i = 0, src_wk = src, dst_wk = dst; i < length; i++, src_wk++) \
5757
*dst_wk++ = hextbl[chr >> 4]; \
5758
*dst_wk++ = hextbl[chr % 16]; \
5761
dst[2 * length] = '\0'; \
5762
return 2 * length * sizeof(type); \
5764
#ifdef UNICODE_SUPPORT
5766
pg_bin2whex def_bin2hex(SQLWCHAR)
5767
#endif /* UNICODE_SUPPORT */
5770
pg_bin2hex def_bin2hex(UCHAR)
5648
5773
pg_hex2bin(const UCHAR *src, UCHAR *dst, SQLLEN length)