static int setup_getdataclass()

in sql-odbc/src/sqlodbc/convert.c [659:848]


static int setup_getdataclass(SQLLEN *const length_return,
                              const char **const ptr_return,
                              int *needbuflen_return, GetDataClass *const esdc,
                              const char *neut_str, const OID field_type,
                              const SQLSMALLINT fCType, const SQLLEN cbValueMax,
                              const ConnectionClass *const conn) {
    SQLLEN len = (-2);
    const char *ptr = NULL;
    int needbuflen = 0;
    int result = COPY_OK;

    BOOL lf_conv = 0;
    int bytea_process_kind = 0;
    BOOL already_processed = FALSE;
    BOOL changed = FALSE;
    int len_for_wcs_term = 0;

#ifdef UNICODE_SUPPORT
    char *allocbuf = NULL;
    int unicode_count = -1;
    BOOL localize_needed = FALSE;
    BOOL hybrid = FALSE;
#endif /* UNICODE_SUPPORT */

    if (OPENSEARCH_TYPE_BYTEA == field_type) {
        if (SQL_C_BINARY == fCType)
            bytea_process_kind = BYTEA_PROCESS_BINARY;
        else if (0 == strnicmp(neut_str, "\\x", 2)) /* hex format */
            neut_str += 2;
        else
            bytea_process_kind = BYTEA_PROCESS_ESCAPE;
    }

#ifdef UNICODE_SUPPORT
    if (0 == bytea_process_kind) {
        if (get_convtype()
            > 0) /* coversion between the current locale is available */
        {
            BOOL wcs_debug = 0;
            BOOL same_encoding =
                (conn->ccsc == opensearch_CS_code(conn->locale_encoding));
            BOOL is_utf8 = (UTF8 == conn->ccsc);

            switch (field_type) {
                case OPENSEARCH_TYPE_UNKNOWN:
                case OPENSEARCH_TYPE_BPCHAR:
                case OPENSEARCH_TYPE_VARCHAR:
                case OPENSEARCH_TYPE_TEXT:
                case OPENSEARCH_TYPE_BPCHARARRAY:
                case OPENSEARCH_TYPE_VARCHARARRAY:
                case OPENSEARCH_TYPE_TEXTARRAY:
                    if (SQL_C_CHAR == fCType || SQL_C_BINARY == fCType)
                        localize_needed = (!same_encoding || wcs_debug);
                    if (SQL_C_WCHAR == fCType)
                        hybrid = (!is_utf8 || (same_encoding && wcs_debug));
            }
            MYLOG(OPENSEARCH_DEBUG,
                  "localize=%d hybrid=%d is_utf8=%d same_encoding=%d "
                  "wcs_debug=%d\n",
                  localize_needed, hybrid, is_utf8, same_encoding, wcs_debug);
        }
    }
    if (fCType == SQL_C_WCHAR) {
        if (BYTEA_PROCESS_ESCAPE == bytea_process_kind)
            unicode_count = (int)convert_from_opensearchbinary(neut_str, NULL, 0) * 2;
        else if (hybrid) {
            MYLOG(OPENSEARCH_DEBUG, "hybrid estimate\n");
            if ((unicode_count =
                     (int)bindcol_hybrid_estimate(neut_str, lf_conv, &allocbuf))
                < 0) {
                result = COPY_INVALID_STRING_CONVERSION;
                goto cleanup;
            }
        } else /* normally */
        {
            unicode_count = (int)utf8_to_ucs2_lf(neut_str, SQL_NTS, lf_conv,
                                                 NULL, 0, FALSE);
        }
        len = WCLEN * unicode_count;
        already_processed = changed = TRUE;
    } else if (localize_needed) {
        if ((len = bindcol_localize_estimate(neut_str, lf_conv, &allocbuf))
            < 0) {
            result = COPY_INVALID_STRING_CONVERSION;
            goto cleanup;
        }
        already_processed = changed = TRUE;
    }
#endif /* UNICODE_SUPPORT */

    if (already_processed) /* skip */
        ;
    else if (0 != bytea_process_kind) {
        len = convert_from_opensearchbinary(neut_str, NULL, 0);
        if (BYTEA_PROCESS_BINARY != bytea_process_kind)
            len *= 2;
        changed = TRUE;
    } else
        /* convert linefeeds to carriage-return/linefeed */
        len = convert_linefeeds(neut_str, NULL, 0, lf_conv, &changed);

    /* just returns length info */
    if (cbValueMax == 0) {
        result = COPY_RESULT_TRUNCATED;
        goto cleanup;
    }

    if (!esdc->ttlbuf)
        esdc->ttlbuflen = 0;
    needbuflen = (int)len + get_terminator_len(fCType);
    if (SQL_C_BINARY == fCType) {
        /*
         * Though Binary doesn't have NULL terminator,
         * bindcol_localize_exec() needs output buffer
         * for NULL terminator.
         */
        len_for_wcs_term = 1;
    }
    if (changed || needbuflen > cbValueMax) {
        if (needbuflen > (SQLLEN)esdc->ttlbuflen) {
            esdc->ttlbuf = realloc(esdc->ttlbuf, needbuflen + len_for_wcs_term);
            esdc->ttlbuflen = needbuflen;
        }

        already_processed = FALSE;
#ifdef UNICODE_SUPPORT
        if (fCType == SQL_C_WCHAR) {
            if (BYTEA_PROCESS_ESCAPE == bytea_process_kind) {
                len = convert_from_opensearchbinary(neut_str, esdc->ttlbuf,
                                            esdc->ttlbuflen);
                len = es_bin2whex(esdc->ttlbuf, (SQLWCHAR *)esdc->ttlbuf, len);
            } else {
                if (!hybrid) /* normally */
                    utf8_to_ucs2_lf(neut_str, SQL_NTS, lf_conv,
                                    (SQLWCHAR *)esdc->ttlbuf, unicode_count,
                                    FALSE);
                else /* hybrid */
                {
                    MYLOG(OPENSEARCH_DEBUG, "hybrid convert\n");
                    if (bindcol_hybrid_exec((SQLWCHAR *)esdc->ttlbuf, neut_str,
                                            unicode_count + 1, lf_conv,
                                            &allocbuf)
                        < 0) {
                        result = COPY_INVALID_STRING_CONVERSION;
                        goto cleanup;
                    }
                }
            }
            already_processed = TRUE;
        } else if (localize_needed) {
            if (bindcol_localize_exec(esdc->ttlbuf, len + 1, lf_conv, &allocbuf)
                < 0) {
                result = COPY_INVALID_STRING_CONVERSION;
                goto cleanup;
            }
            already_processed = TRUE;
        }
#endif /* UNICODE_SUPPORT */

        if (already_processed)
            ;
        else if (0 != bytea_process_kind) {
            len = convert_from_opensearchbinary(neut_str, esdc->ttlbuf,
                                                esdc->ttlbuflen);
            if (BYTEA_PROCESS_ESCAPE == bytea_process_kind)
                len = opensearch_bin2hex(esdc->ttlbuf, esdc->ttlbuf, len);
        } else
            convert_linefeeds(neut_str, esdc->ttlbuf, esdc->ttlbuflen, lf_conv,
                              &changed);
        ptr = esdc->ttlbuf;
        esdc->ttlbufused = len;
    } else {
        if (esdc->ttlbuf) {
            free(esdc->ttlbuf);
            esdc->ttlbuf = NULL;
        }
        ptr = neut_str;
    }
cleanup:
#ifdef UNICODE_SUPPORT
    if (allocbuf)
        free(allocbuf);
#endif /* UNICODE_SUPPORT */

    *length_return = len;
    *ptr_return = ptr;
    *needbuflen_return = needbuflen;

    return result;
}