~ubuntu-branches/ubuntu/trusty/psqlodbc/trusty

« back to all changes in this revision

Viewing changes to convert.c

  • Committer: Package Import Robot
  • Author(s): Christoph Berg
  • Date: 2011-12-30 19:09:04 UTC
  • mfrom: (1.1.9)
  • Revision ID: package-import@ubuntu.com-20111230190904-pmdip68ou7i4vzk8
Tags: 1:09.01.0100-1
New upgrade release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
20
20
#include "convert.h"
21
21
#ifdef  WIN32
22
22
#include <float.h>
 
23
#define HAVE_LOCALE_H
23
24
#endif /* WIN32 */
24
25
 
25
26
#include <stdio.h>
141
142
 
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 */
145
149
 
146
150
/*---------
147
151
 *                      A Guide for date/time/timestamp conversions
602
606
#endif /* ODBCVER */
603
607
 
604
608
 
 
609
#ifdef  HAVE_LOCALE_H
 
610
static char *current_locale = NULL;
 
611
static char *current_decimal_point = NULL;
 
612
static void current_numeric_locale()
 
613
{
 
614
        char *loc = setlocale(LC_NUMERIC, NULL);
 
615
        if (NULL == current_locale || 0 != stricmp(loc, current_locale))
 
616
        {
 
617
                struct lconv    *lc = localeconv();
 
618
 
 
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);
 
625
        }
 
626
}
 
627
 
 
628
static void set_server_decimal_point(char *num)
 
629
{
 
630
        char *str;
 
631
 
 
632
        current_numeric_locale();
 
633
        if ('.' == *current_decimal_point)
 
634
                return; 
 
635
        for (str = num; '\0' != *str; str++)
 
636
        {
 
637
                if (*str == *current_decimal_point)
 
638
                {
 
639
                        *str = '.';
 
640
                        break;
 
641
                }
 
642
        }
 
643
}
 
644
 
 
645
static void set_client_decimal_point(char *num)
 
646
{
 
647
        char *str;
 
648
 
 
649
        current_numeric_locale();
 
650
        if ('.' == *current_decimal_point)
 
651
                return;
 
652
        for (str = num; '\0' != *str; str++)
 
653
        {
 
654
                if (*str == '.')
 
655
                {
 
656
                        *str = *current_decimal_point;
 
657
                        break;
 
658
                }
 
659
        }
 
660
}
 
661
#else
 
662
static void set_server_decimal_point(char *num) {}
 
663
static void set_client_decimal_point(char *num, BOOL) {}
 
664
#endif /* HAVE_LOCALE_H */
 
665
 
605
666
/*      This is called by SQLFetch() */
606
667
int
607
668
copy_and_convert_field_bindinfo(StatementClass *stmt, OID field_type, int atttypmod, void *value, int col)
703
764
        SQLWCHAR        *allocbuf = NULL;
704
765
        ssize_t         wstrlen;        
705
766
#endif /* WIN_UNICODE_SUPPORT */
706
 
#ifdef HAVE_LOCALE_H
707
 
        char *saved_locale;
708
 
#endif /* HAVE_LOCALE_H */
709
767
#if (ODBCVER >= 0x0350)
710
768
        SQLGUID g;
711
769
#endif
1078
1136
        {
1079
1137
                /* Special character formatting as required */
1080
1138
 
 
1139
                BOOL    hex_bin_format = FALSE;
1081
1140
                /*
1082
1141
                 * These really should return error if cbValueMax is not big
1083
1142
                 * enough.
1149
1208
                                                                 * (i.e, 255 = "FF") */
1150
1209
 
1151
1210
                        default:
 
1211
                                switch (field_type)
 
1212
                                {
 
1213
                                        case PG_TYPE_FLOAT4:
 
1214
                                        case PG_TYPE_FLOAT8:
 
1215
                                        case PG_TYPE_NUMERIC:
 
1216
                                                set_client_decimal_point((char *) neut_str);
 
1217
                                                break;
 
1218
                                        case PG_TYPE_BYTEA:
 
1219
                                                if (0 == strnicmp(neut_str, "\\x", 2))
 
1220
                                                {
 
1221
                                                        hex_bin_format = TRUE;
 
1222
                                                        neut_str += 2;
 
1223
                                                }
 
1224
                                                break;
 
1225
                                }
 
1226
 
1152
1227
                                if (stmt->current_col < 0)
1153
1228
                                {
1154
1229
                                        pgdc = &(gdata->fdata);
1163
1238
                                if (pgdc->data_left < 0)
1164
1239
                                {
1165
1240
                                        BOOL lf_conv = conn->connInfo.lf_conversion;
 
1241
                                        if (PG_TYPE_BYTEA == field_type)
 
1242
                                        {
 
1243
                                                if (hex_bin_format)
 
1244
                                                        len = strlen(neut_str);
 
1245
                                                else
 
1246
                                                {
 
1247
                                                        len = convert_from_pgbinary(neut_str, NULL, 0);
 
1248
                                                        len *= 2;
 
1249
                                                }
 
1250
                                                changed = TRUE;
 
1251
#ifdef  UNICODE_SUPPORT
 
1252
                                                if (fCType == SQL_C_WCHAR)
 
1253
                                                        len *= WCLEN;
 
1254
#endif /* UNICODE_SUPPORT */
 
1255
                                        }
 
1256
                                        else
1166
1257
#ifdef  UNICODE_SUPPORT
1167
1258
                                        if (fCType == SQL_C_WCHAR)
1168
1259
                                        {
1172
1263
                                        }
1173
1264
                                        else
1174
1265
#endif /* UNICODE_SUPPORT */
1175
 
                                        if (PG_TYPE_BYTEA == field_type)
1176
 
                                        {
1177
 
                                                len = convert_from_pgbinary(neut_str, NULL, 0);
1178
 
                                                len *= 2;
1179
 
                                                changed = TRUE;
1180
 
                                        }
1181
 
                                        else
1182
1266
#ifdef  WIN_UNICODE_SUPPORT
1183
1267
                                        if (localize_needed)
1184
1268
                                        {
1227
1311
#ifdef  UNICODE_SUPPORT
1228
1312
                                                if (fCType == SQL_C_WCHAR)
1229
1313
                                                {
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)
 
1315
                                                        {
 
1316
                                                                len = convert_from_pgbinary(neut_str, pgdc->ttlbuf, pgdc->ttlbuflen);
 
1317
                                                                len = pg_bin2whex(pgdc->ttlbuf, (SQLWCHAR *) pgdc->ttlbuf, len);
 
1318
                                                        }
 
1319
                                                        else
 
1320
                                                                utf8_to_ucs2_lf(neut_str, SQL_NTS, lf_conv, (SQLWCHAR *) pgdc->ttlbuf, len / WCLEN);
1231
1321
                                                }
1232
1322
                                                else
1233
1323
#endif /* UNICODE_SUPPORT */
1234
1324
                                                if (PG_TYPE_BYTEA == field_type)
1235
1325
                                                {
1236
 
                                                        len = convert_from_pgbinary(neut_str, pgdc->ttlbuf, pgdc->ttlbuflen);
1237
 
                                                        pg_bin2hex(pgdc->ttlbuf, pgdc->ttlbuf, len);
1238
 
                                                        len *= 2; 
 
1326
                                                        if (hex_bin_format)
 
1327
                                                        {
 
1328
                                                                len = strlen(neut_str);
 
1329
                                                                strncpy_null(pgdc->ttlbuf, neut_str, pgdc->ttlbuflen);
 
1330
                                                        }
 
1331
                                                        else
 
1332
                                                        {
 
1333
                                                                len = convert_from_pgbinary(neut_str, pgdc->ttlbuf, pgdc->ttlbuflen);
 
1334
                                                                len = pg_bin2hex(pgdc->ttlbuf, pgdc->ttlbuf, len);
 
1335
                                                        } 
1239
1336
                                                }
1240
1337
                                                else
1241
1338
#ifdef  WIN_UNICODE_SUPPORT
1296
1393
                                                copy_len *= WCLEN;
1297
1394
                                        }
1298
1395
#endif /* UNICODE_SUPPORT */
1299
 
#ifdef HAVE_LOCALE_H
1300
 
                                        switch (field_type)
1301
 
                                        {
1302
 
                                                case PG_TYPE_FLOAT4:
1303
 
                                                case PG_TYPE_FLOAT8:
1304
 
                                                case PG_TYPE_NUMERIC:
1305
 
                                                {
1306
 
                                                        struct lconv    *lc;
1307
 
                                                        char            *new_string;
1308
 
                                                        int             i, j;
1309
 
 
1310
 
                                                        new_string = malloc(cbValueMax);
1311
 
                                                        lc = localeconv();
1312
 
                                                        for (i = 0, j = 0; ptr[i]; i++)
1313
 
                                                        {
1314
 
                                                                if (ptr[i] == '.')
1315
 
                                                                {
1316
 
                                                                        strncpy_null(&new_string[j], lc->decimal_point, cbValueMax - j);
1317
 
                                                                        j += strlen(lc->decimal_point);
1318
 
                                                                }
1319
 
                                                                else
1320
 
                                                                        new_string[j++] = ptr[i];
1321
 
                                                        }
1322
 
                                                        new_string[j] = '\0';
1323
 
                                                        strncpy_null(rgbValueBindRow, new_string, copy_len + 1);
1324
 
                                                        free(new_string);
1325
 
                                                        already_copied = TRUE;
1326
 
                                                        break;
1327
 
                                                }
1328
 
                                        }
1329
 
#endif /* HAVE_LOCALE_H */
1330
1396
                                        if (!already_copied)
1331
1397
                                        {
1332
1398
                                                /* Copy the data */
1498
1564
                                break;
1499
1565
 
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);
1505
1568
                                len = 4;
1506
1569
                                if (bind_size > 0)
1507
1570
                                        *((SFLOAT *) rgbValueBindRow) = (float) get_double_value(neut_str);
1508
1571
                                else
1509
1572
                                        *((SFLOAT *) rgbValue + bind_row) = (float) get_double_value(neut_str);
1510
 
#ifdef HAVE_LOCALE_H
1511
 
                                setlocale(LC_ALL, saved_locale);
1512
 
                                free(saved_locale);
1513
 
#endif /* HAVE_LOCALE_H */
1514
1573
                                break;
1515
1574
 
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);
1521
1577
                                len = 8;
1522
1578
                                if (bind_size > 0)
1523
1579
                                        *((SDOUBLE *) rgbValueBindRow) = get_double_value(neut_str);
1524
1580
                                else
1525
1581
                                        *((SDOUBLE *) rgbValue + bind_row) = get_double_value(neut_str);
1526
 
#ifdef HAVE_LOCALE_H
1527
 
                                setlocale(LC_ALL, saved_locale);
1528
 
                                free(saved_locale);
1529
 
#endif /* HAVE_LOCALE_H */
1530
1582
                                break;
1531
1583
 
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 */
1538
1586
                        {
1539
1587
                        SQL_NUMERIC_STRUCT      *ns;
1540
1588
                        int     i, nlen, bit, hval, tv, dig, sta, olen;
1607
1655
                        if (hval && olen < SQL_MAX_NUMERIC_LEN - 1)
1608
1656
                                ns->val[olen++] = hval;
1609
1657
                        }
1610
 
#ifdef HAVE_LOCALE_H
1611
 
                        /* setlocale(LC_ALL, saved_locale); */
1612
 
#endif /* HAVE_LOCALE_H */
1613
1658
                        break;
1614
1659
#endif /* ODBCVER */
1615
1660
 
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;
2006
2054
                
2007
2055
        if (stmt)
2008
2056
                qb->str_size_limit = stmt->stmt_size_limit;
2111
2159
                buf[c++] = qp->statement[qp->opos++]; \
2112
2160
        } \
2113
2161
        if (qp->statement[qp->opos] == '\0') \
2114
 
                return SQL_ERROR; \
 
2162
                {retval = SQL_ERROR; goto cleanup;} \
2115
2163
        buf[c] = '\0'; \
2116
2164
} while (0)
2117
2165
 
2191
2239
        if (newpos >= qb->str_alsize) \
2192
2240
        { \
2193
2241
                if (enlarge_query_statement(qb, newpos) <= 0) \
2194
 
                        return SQL_ERROR; \
 
2242
                        {retval = SQL_ERROR; goto cleanup;} \
2195
2243
        }
2196
2244
 
2197
2245
/*----------
2200
2248
 */
2201
2249
#define CVT_TERMINATE(qb) \
2202
2250
do { \
2203
 
        if (NULL == qb->query_statement) return SQL_ERROR; \
 
2251
        if (NULL == qb->query_statement) {retval = SQL_ERROR; goto cleanup;} \
2204
2252
        qb->query_statement[qb->npos] = '\0'; \
2205
2253
} while (0)
2206
2254
 
2244
2292
 */
2245
2293
#define CVT_APPEND_BINARY(qb, buf, used) \
2246
2294
do { \
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); \
2250
2298
} while (0)
2285
2333
QB_start_brace(QueryBuild *qb)
2286
2334
{
2287
2335
        BOOL    replace_by_parenthesis = TRUE;
 
2336
        RETCODE retval = SQL_ERROR;
2288
2337
 
2289
2338
        if (0 == qb->brace_level)
2290
2339
        {
2299
2348
        if (replace_by_parenthesis)
2300
2349
                CVT_APPEND_CHAR(qb, '(');
2301
2350
        qb->brace_level++;
2302
 
        return SQL_SUCCESS;
 
2351
        retval = SQL_SUCCESS;
 
2352
cleanup:
 
2353
        return retval;
2303
2354
}
2304
2355
 
2305
2356
static RETCODE
2306
2357
QB_end_brace(QueryBuild *qb)
2307
2358
{
2308
2359
        BOOL    replace_by_parenthesis = TRUE;
 
2360
        RETCODE retval = SQL_ERROR;
2309
2361
 
2310
2362
        if (qb->brace_level <= 1 &&
2311
2363
            !qb->parenthesize_the_first)
2313
2365
        if (replace_by_parenthesis)
2314
2366
                CVT_APPEND_CHAR(qb, ')');
2315
2367
        qb->brace_level--;
2316
 
        return SQL_SUCCESS;
 
2368
        retval = SQL_SUCCESS;
 
2369
cleanup:
 
2370
        return retval;
2317
2371
}
2318
2372
 
2319
2373
static RETCODE QB_append_space_to_separate_identifiers(QueryBuild *qb, const QueryParse *qp)
2321
2375
        unsigned char   tchar = F_OldChar(qp);
2322
2376
        encoded_str     encstr;
2323
2377
        BOOL            add_space = FALSE;
 
2378
        RETCODE         retval = SQL_ERROR;
2324
2379
 
2325
2380
        if (ODBC_ESCAPE_END != tchar)
2326
2381
                return SQL_SUCCESS;
2344
2399
        }
2345
2400
        if (add_space)
2346
2401
                CVT_APPEND_CHAR(qb, ' ');
 
2402
        retval = SQL_SUCCESS;
 
2403
cleanup:
2347
2404
 
2348
 
        return SQL_SUCCESS;
 
2405
        return retval;
2349
2406
}
2350
2407
 
2351
2408
/*----------
2528
2585
{
2529
2586
        CSTR func = "Prepare_and_convert";
2530
2587
        char    *exe_statement = NULL;
2531
 
        int     retval;
 
2588
        RETCODE retval;
2532
2589
        ConnectionClass *conn = SC_get_conn(stmt);
2533
2590
        ConnInfo        *ci = &(conn->connInfo);
2534
2591
        BOOL    discardOutput, outpara;
2573
2630
                {
2574
2631
                        SC_set_error(stmt, STMT_COUNT_FIELD_INCORRECT,
2575
2632
                                "The # of binded parameters < the # of parameter markers", func);
2576
 
                        return SQL_ERROR;
 
2633
                        retval = SQL_ERROR;
 
2634
                        goto cleanup;
2577
2635
                }
2578
2636
                if (marker_count > 0)
2579
2637
                {
2603
2661
                {
2604
2662
                        retval = inner_process_tokens(qp, qb);
2605
2663
                        if (SQL_ERROR == retval)
2606
 
                        {
2607
 
                                QB_replace_SC_error(stmt, qb, func);
2608
 
                                QB_Destructor(qb);
2609
 
                                return retval;
2610
 
                        }
 
2664
                                goto cleanup;
2611
2665
                }
2612
2666
                CVT_APPEND_CHAR(qb, ';');
2613
2667
                /* build the execute statement */
2638
2692
        {
2639
2693
                retval = inner_process_tokens(qp, qb);
2640
2694
                if (SQL_ERROR == retval)
 
2695
                        goto cleanup;
 
2696
        }
 
2697
        /* make sure new_statement is always null-terminated */
 
2698
        CVT_TERMINATE(qb);
 
2699
        retval = SQL_SUCCESS;
 
2700
 
 
2701
cleanup:
 
2702
        if (SQL_SUCCEEDED(retval))
 
2703
        {
 
2704
                if (exe_statement)
 
2705
                        SC_set_concat_prepare_exec(stmt);
 
2706
                stmt->stmt_with_params = qb->query_statement;
 
2707
                qb->query_statement = NULL;
 
2708
        }
 
2709
        else
 
2710
        {
 
2711
                QB_replace_SC_error(stmt, qb, func);
 
2712
                if (exe_statement)
2641
2713
                {
2642
 
                        QB_replace_SC_error(stmt, qb, func);
2643
 
                        if (exe_statement)
2644
 
                        {
2645
 
                                free(exe_statement);
2646
 
                                stmt->execute_statement = NULL;
2647
 
                        }
2648
 
                        QB_Destructor(qb);
2649
 
                        return retval;
 
2714
                        free(exe_statement);
 
2715
                        stmt->execute_statement = NULL;
2650
2716
                }
 
2717
                QB_Destructor(qb);
2651
2718
        }
2652
 
        /* make sure new_statement is always null-terminated */
2653
 
        CVT_TERMINATE(qb);
2654
 
 
2655
 
        if (exe_statement)
2656
 
                SC_set_concat_prepare_exec(stmt);
2657
 
        stmt->stmt_with_params = qb->query_statement;
2658
 
        qb->query_statement = NULL;
2659
 
        return SQL_SUCCESS;
 
2719
        return retval;
2660
2720
}
2661
2721
 
2662
2722
#define         my_strchr(conn, s1,c1) pg_mbschr(conn->ccsc, s1,c1)
2915
2975
        if (bPrepConv)
2916
2976
        {
2917
2977
                retval = Prepare_and_convert(stmt, qp, qb);
2918
 
                return retval;
 
2978
                goto cleanup;
2919
2979
        }
2920
2980
        SC_forget_unnamed(stmt);
2921
2981
        buildPrepareStatement = FALSE;
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)
2928
 
                return SQL_ERROR;
 
2988
        {
 
2989
                retval = SQL_ERROR;
 
2990
                goto cleanup;
 
2991
        }
2929
2992
        new_statement = qb->query_statement;
2930
2993
 
2931
2994
        /* For selects, prepend a declare cursor to the statement */
3084
3147
        }
3085
3148
 
3086
3149
        stmt->stmt_with_params = qb->query_statement;
3087
 
        return SQL_SUCCESS;
 
3150
        retval = SQL_SUCCESS;
 
3151
cleanup:
 
3152
        return retval;
3088
3153
}
3089
3154
 
3090
3155
static void
3571
3636
        if (SQL_SUCCESS_WITH_INFO == retval) /* means discarding output parameter */
3572
3637
        {
3573
3638
        }
3574
 
        return SQL_SUCCESS;
 
3639
        retval = SQL_SUCCESS;
 
3640
cleanup:
 
3641
        return retval;
3575
3642
}
3576
3643
 
3577
3644
#define MIN_ALC_SIZE    128
3868
3935
        SQLLEN          used;
3869
3936
        char            *buffer, *buf, *allocbuf, *lastadd = NULL;
3870
3937
        OID             lobj_oid;
3871
 
        int             lobj_fd, retval;
 
3938
        int             lobj_fd;
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;
3884
3952
 
3885
3953
        outputDiscard = (0 != (qb->flags & FLGB_DISCARD_OUTPUT));
3886
3954
        valueOutput = (0 == (qb->flags & (FLGB_PRE_EXECUTING | FLGB_BUILDING_PREPARE_STATEMENT)));
4159
4227
#ifdef  WIN32
4160
4228
                        if (_finite(dbv))
4161
4229
#endif /* WIN32 */
4162
 
                        sprintf(param_string, "%.15g", dbv);
 
4230
                        {
 
4231
                                sprintf(param_string, "%.15g", dbv);
 
4232
                                set_server_decimal_point(param_string);
 
4233
                        }
4163
4234
#ifdef  WIN32
4164
4235
                        else if (_isnan(dbv))
4165
4236
                                strcpy(param_string, NAN_STRING);
4175
4246
#ifdef  WIN32
4176
4247
                        if (_finite(flv))
4177
4248
#endif /* WIN32 */
4178
 
                        sprintf(param_string, "%.6g", flv);
 
4249
                        {
 
4250
                                sprintf(param_string, "%.6g", flv);
 
4251
                                set_server_decimal_point(param_string);
 
4252
                        }
4179
4253
#ifdef  WIN32
4180
4254
                        else if (_isnan(flv))
4181
4255
                                strcpy(param_string, NAN_STRING);
4354
4428
                        qb->errormsg = "Unrecognized C_parameter type in copy_statement_with_parameters";
4355
4429
                        qb->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
4356
4430
                        CVT_TERMINATE(qb);      /* just in case */
4357
 
                        return SQL_ERROR;
 
4431
                        retval = SQL_ERROR;
 
4432
                        goto cleanup;
4358
4433
        }
4359
4434
 
4360
4435
        /*
4377
4452
                }
4378
4453
                else
4379
4454
                        CVT_APPEND_STR(qb, "NULL");
4380
 
                return SQL_SUCCESS;
 
4455
                retval = SQL_SUCCESS;
 
4456
                goto cleanup;
4381
4457
        }
4382
4458
        if (!req_bind)
4383
4459
        {
4433
4509
                                                 '1' == param_string[1])
4434
4510
                                                strcpy(param_string, "1");
4435
4511
                                        break;
 
4512
                                case PG_TYPE_FLOAT4:
 
4513
                                case PG_TYPE_FLOAT8:
 
4514
                                case PG_TYPE_NUMERIC:
 
4515
                                        if (NULL != buf)
 
4516
                                                set_server_decimal_point(buf);
 
4517
                                        else
 
4518
                                                set_server_decimal_point(param_string);
 
4519
                                        break;
4436
4520
                        }
4437
4521
                        /* it was a SQL_C_CHAR */
4438
4522
                        if (buf)
4514
4598
                                case SQL_C_BINARY:
4515
4599
                                        break;
4516
4600
                                case SQL_C_CHAR:
 
4601
#ifdef  UNICODE_SUPPORT
 
4602
                                case SQL_C_WCHAR:
 
4603
#endif /* UNICODE_SUPPORT */
4517
4604
                                        switch (used)
4518
4605
                                        {
4519
4606
                                                case SQL_NTS:
4531
4618
                                default:
4532
4619
                                        qb->errormsg = "Could not convert the ctype to binary type";
4533
4620
                                        qb->errornumber = STMT_EXEC_ERROR;
4534
 
                                        return SQL_ERROR;
 
4621
                                        retval = SQL_ERROR;
 
4622
                                        goto cleanup;
4535
4623
                        }
4536
4624
                        if (param_pgtype == PG_TYPE_BYTEA)
4537
4625
                        {
4557
4645
                        {
4558
4646
                                qb->errormsg = "Could not convert binary other than LO type";
4559
4647
                                qb->errornumber = STMT_EXEC_ERROR;
4560
 
                                return SQL_ERROR;
 
4648
                                retval = SQL_ERROR;
 
4649
                                goto cleanup;
4561
4650
                        }
4562
4651
 
4563
4652
                        if (apara->data_at_exec)
4573
4662
                                        {
4574
4663
                                                qb->errormsg = "Could not begin (in-line) a transaction";
4575
4664
                                                qb->errornumber = STMT_EXEC_ERROR;
4576
 
                                                return SQL_ERROR;
 
4665
                                                retval = SQL_ERROR;
 
4666
                                                goto cleanup;
4577
4667
                                        }
4578
4668
                                }
4579
4669
 
4583
4673
                                {
4584
4674
                                        qb->errornumber = STMT_EXEC_ERROR;
4585
4675
                                        qb->errormsg = "Couldnt create (in-line) large object.";
4586
 
                                        return SQL_ERROR;
 
4676
                                        retval = SQL_ERROR;
 
4677
                                        goto cleanup;
4587
4678
                                }
4588
4679
 
4589
4680
                                /* store the fd */
4592
4683
                                {
4593
4684
                                        qb->errornumber = STMT_EXEC_ERROR;
4594
4685
                                        qb->errormsg = "Couldnt open (in-line) large object for writing.";
4595
 
                                        return SQL_ERROR;
 
4686
                                        retval = SQL_ERROR;
 
4687
                                        goto cleanup;
4596
4688
                                }
4597
4689
 
4598
4690
                                retval = odbc_lo_write(conn, lobj_fd, buffer, (Int4) used);
4606
4698
                                        {
4607
4699
                                                qb->errormsg = "Could not commit (in-line) a transaction";
4608
4700
                                                qb->errornumber = STMT_EXEC_ERROR;
4609
 
                                                return SQL_ERROR;
 
4701
                                                retval = SQL_ERROR;
 
4702
                                                goto cleanup;
4610
4703
                                        }
4611
4704
                                }
4612
4705
                        }
4631
4724
                case SQL_REAL:
4632
4725
                        if (buf)
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);
4636
4730
                        break;
4638
4732
                case SQL_DOUBLE:
4639
4733
                        if (buf)
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);
4643
4738
                        break;
4676
4771
                if (lastadd)
4677
4772
                        CVT_APPEND_STR(qb, lastadd);
4678
4773
        }
 
4774
        if (req_bind)
 
4775
        {
 
4776
                UInt4   slen = htonl((UInt4) (qb->npos - npos - 4));
 
4777
 
 
4778
                memcpy(qb->query_statement + npos, &slen, sizeof(slen));
 
4779
        }
 
4780
        retval = SQL_SUCCESS;
 
4781
cleanup:
4679
4782
        if (allocbuf)
4680
4783
                free(allocbuf);
4681
 
        if (req_bind)
4682
 
        {
4683
 
                UInt4   slen = htonl((UInt4) (qb->npos - npos - 4));
4684
 
 
4685
 
                memcpy(qb->query_statement + npos, &slen, sizeof(slen));
4686
 
        }
4687
 
        return SQL_SUCCESS;
 
4784
        return retval;
4688
4785
}
4689
4786
 
4690
4787
 
4819
4916
        char            buf[1024], buf_small[128], key[65];
4820
4917
        UCHAR   ucv;
4821
4918
        UInt4           prtlen;
 
4919
 
 
4920
        QueryBuild      nqb;
 
4921
        BOOL    nqb_is_valid = FALSE;
4822
4922
 
4823
4923
        if (F_OldChar(qp) == ODBC_ESCAPE_START) /* skip the first { */
4824
4924
                F_OldNext(qp);
4897
4997
                const char *nextdel;
4898
4998
 
4899
4999
                if (SQL_ERROR == QB_start_brace(qb))
4900
 
                        return SQL_ERROR;
 
5000
                {
 
5001
                        retval = SQL_ERROR;
 
5002
                        goto cleanup;
 
5003
                }
4901
5004
                if (qb->num_io_params > 1 ||
4902
5005
                    (0 == qb->proc_return &&
4903
5006
                     PG_VERSION_GE(conn, 7.3)))
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))
4913
 
                                return SQL_ERROR;
 
5016
                        {
 
5017
                                retval = SQL_ERROR;
 
5018
                                goto cleanup;
 
5019
                        }
4914
5020
                        /* positioned at } */
4915
5021
                        qp->opos += (nextdel - F_OldPtr(qp));
4916
5022
                }
4958
5064
                retval = QB_start_brace(qb);
4959
5065
                /* Continue at inner_process_tokens loop */
4960
5066
                F_OldPrior(qp);
4961
 
                return retval;
 
5067
                goto cleanup;
4962
5068
        }
4963
5069
        else if (stricmp(key, "escape") == 0) /* like escape syntax support for 7.1+ servers */
4964
5070
        {
4970
5076
        }
4971
5077
        else if (stricmp(key, "fn") == 0)
4972
5078
        {
4973
 
                QueryBuild      nqb;
4974
5079
                const char *mapExpr;
4975
5080
                int     i, param_count;
4976
5081
                SQLLEN  from, to;
4998
5103
                if (F_OldChar(qp) != '(')
4999
5104
                {
5000
5105
                        CVT_APPEND_STR(qb, key);
5001
 
                        return SQL_SUCCESS;
 
5106
                        goto cleanup;
5002
5107
                }
5003
5108
 
5004
5109
                /*
5008
5113
                 */
5009
5114
 
5010
5115
                QB_initialize_copy(&nqb, qb, 1024);
 
5116
                nqb_is_valid = TRUE;
5011
5117
                if (retval = processParameters(qp, &nqb, &param_consumed, param_pos), retval == SQL_ERROR)
5012
5118
                {
5013
5119
                        qb->errornumber = nqb.errornumber;
5014
5120
                        qb->errormsg = nqb.errormsg;
5015
 
                        QB_Destructor(&nqb);
5016
 
                        return retval;
 
5121
                        goto cleanup;
5017
5122
                }
5018
5123
 
5019
5124
                for (param_count = 0;; param_count++)
5155
5260
                        qb->param_number = nqb.param_number;
5156
5261
                        qb->flags = nqb.flags;
5157
5262
                }
 
5263
        }
 
5264
        else
 
5265
        {
 
5266
                /* Bogus key, leave untranslated */
 
5267
                retval = SQL_ERROR;
 
5268
        }
 
5269
 
 
5270
cleanup:
 
5271
        if (nqb_is_valid)
5158
5272
                QB_Destructor(&nqb);
5159
 
        }
5160
 
        else
5161
 
        {
5162
 
                /* Bogus key, leave untranslated */
5163
 
                return SQL_ERROR;
5164
 
        }
5165
 
 
5166
5273
        return retval;
5167
5274
}
5168
5275
 
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);
5580
5687
 
 
5688
        /* use hex format for 9.0 or later servers */
 
5689
        if (0 != (qb->flags & FLGB_HEX_BIN_FORMAT))
 
5690
        {
 
5691
                if (esc_double)
 
5692
                        out[o++] = escape_in_literal;
 
5693
                out[o++] = '\\';
 
5694
                out[o++] = 'x';
 
5695
                o += pg_bin2hex(in, (UCHAR *) out + o, len);
 
5696
                return o;
 
5697
        }
5581
5698
        for (i = 0; i < len; i++)
5582
5699
        {
5583
5700
                inc = in[i];
5605
5722
 
5606
5723
 
5607
5724
static const char *hextbl = "0123456789ABCDEF";
5608
 
static SQLLEN
5609
 
pg_bin2hex(UCHAR *src, UCHAR *dst, SQLLEN length)
5610
 
{
5611
 
        UCHAR           chr,
5612
 
                           *src_wk,
5613
 
                           *dst_wk;
5614
 
        BOOL            backwards;
5615
 
        int                     i;
5616
5725
 
5617
 
        backwards = FALSE;
5618
 
        if (dst < src)
5619
 
        {
5620
 
                if (dst + length > src + 1)
5621
 
                        return -1;
5622
 
        }
5623
 
        else if (dst < src + length)
5624
 
                backwards = TRUE;
5625
 
        if (backwards)
5626
 
        {
5627
 
                for (i = 0, src_wk = src + length - 1, dst_wk = dst + 2 * length - 1; i < length; i++, src_wk--)
5628
 
                {
5629
 
                        chr = *src_wk;
5630
 
                        *dst_wk-- = hextbl[chr % 16];
5631
 
                        *dst_wk-- = hextbl[chr >> 4];
5632
 
                }
5633
 
        }
5634
 
        else
5635
 
        {
5636
 
                for (i = 0, src_wk = src, dst_wk = dst; i < length; i++, src_wk++)
5637
 
                {
5638
 
                        chr = *src_wk;
5639
 
                        *dst_wk++ = hextbl[chr >> 4];
5640
 
                        *dst_wk++ = hextbl[chr % 16];
5641
 
                }
5642
 
        }
5643
 
        dst[2 * length] = '\0';
5644
 
        return length;
 
5726
#define def_bin2hex(type) \
 
5727
        (const UCHAR *src, type *dst, SQLLEN length) \
 
5728
{ \
 
5729
        const UCHAR     *src_wk; \
 
5730
        UCHAR           chr; \
 
5731
        type            *dst_wk; \
 
5732
        BOOL            backwards; \
 
5733
        int             i; \
 
5734
 \
 
5735
        backwards = FALSE; \
 
5736
        if ((UCHAR *)dst < src) \
 
5737
        { \
 
5738
                if ((UCHAR *) (dst + 2 * (length - 1)) > src + length - 1) \
 
5739
                        return -1; \
 
5740
        } \
 
5741
        else if ((UCHAR *) dst < src + length) \
 
5742
                backwards = TRUE; \
 
5743
        if (backwards) \
 
5744
        { \
 
5745
                for (i = 0, src_wk = src + length - 1, dst_wk = dst + 2 * length - 1; i < length; i++, src_wk--) \
 
5746
                { \
 
5747
                        chr = *src_wk; \
 
5748
                        *dst_wk-- = hextbl[chr % 16]; \
 
5749
                        *dst_wk-- = hextbl[chr >> 4]; \
 
5750
                } \
 
5751
        } \
 
5752
        else \
 
5753
        { \
 
5754
                for (i = 0, src_wk = src, dst_wk = dst; i < length; i++, src_wk++) \
 
5755
                { \
 
5756
                        chr = *src_wk; \
 
5757
                        *dst_wk++ = hextbl[chr >> 4]; \
 
5758
                        *dst_wk++ = hextbl[chr % 16]; \
 
5759
                } \
 
5760
        } \
 
5761
        dst[2 * length] = '\0'; \
 
5762
        return 2 * length * sizeof(type); \
5645
5763
}
 
5764
#ifdef  UNICODE_SUPPORT
 
5765
static SQLLEN
 
5766
pg_bin2whex def_bin2hex(SQLWCHAR)
 
5767
#endif /* UNICODE_SUPPORT */
 
5768
 
 
5769
static SQLLEN
 
5770
pg_bin2hex def_bin2hex(UCHAR)
5646
5771
 
5647
5772
SQLLEN
5648
5773
pg_hex2bin(const UCHAR *src, UCHAR *dst, SQLLEN length)