diff options
Diffstat (limited to 'dev-db/freetds/files/freetds-0.82-odbc-csa2.patch')
-rw-r--r-- | dev-db/freetds/files/freetds-0.82-odbc-csa2.patch | 484 |
1 files changed, 484 insertions, 0 deletions
diff --git a/dev-db/freetds/files/freetds-0.82-odbc-csa2.patch b/dev-db/freetds/files/freetds-0.82-odbc-csa2.patch new file mode 100644 index 0000000..7487c7e --- /dev/null +++ b/dev-db/freetds/files/freetds-0.82-odbc-csa2.patch @@ -0,0 +1,484 @@ +diff -dPNur freetds-0.82/include/tds.h freetds-0.82-new/include/tds.h +--- freetds-0.82/include/tds.h 2007-12-27 14:45:22.000000000 +0100 ++++ freetds-0.82-new/include/tds.h 2008-07-02 22:32:56.000000000 +0200 +@@ -1005,6 +1005,7 @@ + TDS_INT *column_lenbind; + TDS_INT column_textpos; + TDS_INT column_text_sqlgetdatapos; ++ TDS_CHAR column_text_sqlputdatainfo; + + BCPCOLDATA *bcp_column_data; + /** +diff -dPNur freetds-0.82/src/odbc/odbc.c freetds-0.82-new/src/odbc/odbc.c +--- freetds-0.82/src/odbc/odbc.c 2008-05-06 04:57:26.000000000 +0200 ++++ freetds-0.82-new/src/odbc/odbc.c 2008-07-02 22:32:56.000000000 +0200 +@@ -4564,6 +4564,9 @@ + SQLLEN dummy_cb; + int nSybType; + ++ TDS_INT converted_column_cur_size; ++ int extra_bytes = 0; ++ + INIT_HSTMT; + + tdsdump_log(TDS_DBG_FUNC, "SQLGetData(%p, %u, %d, %p, %d, %p)\n", +@@ -4597,46 +4600,120 @@ + ODBC_RETURN(stmt, SQL_ERROR); + } + colinfo = resinfo->columns[icol - 1]; ++ converted_column_cur_size = colinfo->column_cur_size; + + if (colinfo->column_cur_size < 0) { + *pcbValue = SQL_NULL_DATA; + } else { ++ nSybType = tds_get_conversion_type(colinfo->column_type, colinfo->column_size); ++ if (fCType == SQL_C_DEFAULT) ++ fCType = odbc_sql_to_c_type_default(stmt->ird->records[icol - 1].sql_desc_concise_type); ++ if (fCType == SQL_ARD_TYPE) { ++ if (icol > stmt->ard->header.sql_desc_count) { ++ odbc_errs_add(&stmt->errs, "07009", NULL); ++ ODBC_RETURN(stmt, SQL_ERROR); ++ } ++ fCType = stmt->ard->records[icol - 1].sql_desc_concise_type; ++ } ++ assert(fCType); ++ + src = (TDS_CHAR *) colinfo->column_data; + if (is_variable_type(colinfo->column_type)) { +- if (colinfo->column_text_sqlgetdatapos > 0 +- && colinfo->column_text_sqlgetdatapos >= colinfo->column_cur_size) +- ODBC_RETURN(stmt, SQL_NO_DATA); +- ++ int nread = 0; ++ + /* 2003-8-29 check for an old bug -- freddy77 */ + assert(colinfo->column_text_sqlgetdatapos >= 0); + if (is_blob_type(colinfo->column_type)) + src = ((TDSBLOB *) src)->textvalue; +- src += colinfo->column_text_sqlgetdatapos; +- srclen = colinfo->column_cur_size - colinfo->column_text_sqlgetdatapos; ++ ++ if (fCType == SQL_C_CHAR) { ++ TDS_CHAR buf[3]; ++ SQLLEN len; ++ ++ switch (nSybType) { ++ case SYBLONGBINARY: ++ case SYBBINARY: ++ case SYBVARBINARY: ++ case SYBIMAGE: ++ case XSYBBINARY: ++ case XSYBVARBINARY: ++ case TDS_CONVERT_BINARY: ++ if (colinfo->column_text_sqlgetdatapos % 2) { ++ nread = (colinfo->column_text_sqlgetdatapos - 1) / 2; ++ if (nread >= colinfo->column_cur_size) ++ ODBC_RETURN(stmt, SQL_NO_DATA); ++ ++ if (cbValueMax > 2) { ++ len = convert_tds2sql(context, nSybType, src + nread, 1, fCType, buf, sizeof(buf), NULL); ++ if (len < 2) { ++ if (len < 0) ++ odbc_convert_err_set(&stmt->errs, len); ++ ODBC_RETURN(stmt, SQL_ERROR); ++ } ++ *(TDS_CHAR *) rgbValue = buf[1]; ++ *((TDS_CHAR *) rgbValue + 1) = 0; ++ ++ rgbValue++; ++ cbValueMax--; ++ ++ extra_bytes = 1; ++ nread++; ++ ++ if (nread >= colinfo->column_cur_size) ++ ODBC_RETURN_(stmt); ++ } else { ++ if (cbValueMax) ++ *(TDS_CHAR *) rgbValue = 0; ++ odbc_errs_add(&stmt->errs, "01004", "String data, right truncated"); ++ ODBC_RETURN(stmt, SQL_SUCCESS_WITH_INFO); ++ } ++ } else { ++ nread = colinfo->column_text_sqlgetdatapos / 2; ++ ++ if (colinfo->column_text_sqlgetdatapos > 0 ++ && nread >= colinfo->column_cur_size) ++ ODBC_RETURN(stmt, SQL_NO_DATA); ++ } ++ ++ src += nread; ++ srclen = colinfo->column_cur_size - nread; ++ converted_column_cur_size *= 2; ++ break; ++ default: ++ if (colinfo->column_text_sqlgetdatapos > 0 ++ && colinfo->column_text_sqlgetdatapos >= colinfo->column_cur_size) ++ ODBC_RETURN(stmt, SQL_NO_DATA); ++ ++ src += colinfo->column_text_sqlgetdatapos; ++ srclen = colinfo->column_cur_size - colinfo->column_text_sqlgetdatapos; ++ } ++ } else { ++ if (colinfo->column_text_sqlgetdatapos > 0 ++ && colinfo->column_text_sqlgetdatapos >= colinfo->column_cur_size) ++ ODBC_RETURN(stmt, SQL_NO_DATA); ++ ++ src += colinfo->column_text_sqlgetdatapos; ++ srclen = colinfo->column_cur_size - colinfo->column_text_sqlgetdatapos; ++ } + } else { + if (colinfo->column_text_sqlgetdatapos > 0 +- && colinfo->column_text_sqlgetdatapos >= colinfo->column_cur_size) ++ && colinfo->column_text_sqlgetdatapos >= colinfo->column_cur_size) + ODBC_RETURN(stmt, SQL_NO_DATA); + + srclen = colinfo->column_cur_size; + } +- nSybType = tds_get_conversion_type(colinfo->column_type, colinfo->column_size); +- if (fCType == SQL_C_DEFAULT) +- fCType = odbc_sql_to_c_type_default(stmt->ird->records[icol - 1].sql_desc_concise_type); +- if (fCType == SQL_ARD_TYPE) { +- if (icol > stmt->ard->header.sql_desc_count) { +- odbc_errs_add(&stmt->errs, "07009", NULL); +- ODBC_RETURN(stmt, SQL_ERROR); +- } +- fCType = stmt->ard->records[icol - 1].sql_desc_concise_type; +- } +- assert(fCType); ++ + *pcbValue = convert_tds2sql(context, nSybType, src, srclen, fCType, (TDS_CHAR *) rgbValue, cbValueMax, NULL); + if (*pcbValue < 0) { + odbc_convert_err_set(&stmt->errs, *pcbValue); + ODBC_RETURN(stmt, SQL_ERROR); + } +- ++ ++ if (extra_bytes) { ++ colinfo->column_text_sqlgetdatapos += extra_bytes; ++ *pcbValue += extra_bytes; ++ } ++ + if (is_variable_type(colinfo->column_type) && (fCType == SQL_C_CHAR || fCType == SQL_C_BINARY)) { + /* calc how many bytes was readed */ + int readed = cbValueMax; +@@ -4651,7 +4728,7 @@ + if (colinfo->column_text_sqlgetdatapos == 0 && cbValueMax > 0) + ++colinfo->column_text_sqlgetdatapos; + /* not all readed ?? */ +- if (colinfo->column_text_sqlgetdatapos < colinfo->column_cur_size) { ++ if (colinfo->column_text_sqlgetdatapos < converted_column_cur_size) { + odbc_errs_add(&stmt->errs, "01004", "String data, right truncated"); + ODBC_RETURN(stmt, SQL_SUCCESS_WITH_INFO); + } +diff -dPNur freetds-0.82/src/odbc/prepare_query.c freetds-0.82-new/src/odbc/prepare_query.c +--- freetds-0.82/src/odbc/prepare_query.c 2007-04-18 16:29:24.000000000 +0200 ++++ freetds-0.82-new/src/odbc/prepare_query.c 2008-07-02 22:32:56.000000000 +0200 +@@ -275,21 +275,110 @@ + /* copy to destination */ + if (blob) { + TDS_CHAR *p; ++ int dest_type, src_type, sql_src_type, res; ++ CONV_RESULT ores; ++ TDS_DBC * dbc = stmt->dbc; ++ void *free_ptr = NULL; ++ int start = 0; ++ SQLPOINTER extradata = NULL; ++ SQLLEN extralen = 0; ++ ++ ++ dest_type = odbc_sql_to_server_type(dbc->tds_socket, drec_ipd->sql_desc_concise_type); ++ if (dest_type == TDS_FAIL) ++ return SQL_ERROR; ++ ++ /* get C type */ ++ sql_src_type = drec_apd->sql_desc_concise_type; ++ if (sql_src_type == SQL_C_DEFAULT) ++ sql_src_type = odbc_sql_to_c_type_default(drec_ipd->sql_desc_concise_type); ++ ++ /* test source type */ ++ /* TODO test intervals */ ++ src_type = odbc_c_to_server_type(sql_src_type); ++ if (src_type == TDS_FAIL) ++ return SQL_ERROR; ++ ++ if (sql_src_type == SQL_C_CHAR) { ++ switch (tds_get_conversion_type(curcol->column_type, curcol->column_size)) { ++ case SYBBINARY: ++ case SYBVARBINARY: ++ case XSYBBINARY: ++ case XSYBVARBINARY: ++ case SYBLONGBINARY: ++ case SYBIMAGE: ++ if (!*((char*)DataPtr+len-1)) ++ --len; ++ ++ if (!len) ++ return SQL_SUCCESS; ++ ++ if (curcol->column_cur_size > 0 ++ && curcol->column_text_sqlputdatainfo) { ++ TDS_CHAR data[2]; ++ data[0] = curcol->column_text_sqlputdatainfo; ++ data[1] = *(char*)DataPtr; ++ ++ res = tds_convert(dbc->env->tds_ctx, src_type, data, 2, dest_type, &ores); ++ if (res < 0) ++ return SQL_ERROR; ++ ++ extradata = ores.ib; ++ extralen = res; ++ ++ start = 1; ++ --len; ++ } ++ ++ if (len&1) { ++ --len; ++ curcol->column_text_sqlputdatainfo = *((char*)DataPtr+len); ++ } ++ ++ res = tds_convert(dbc->env->tds_ctx, src_type, DataPtr+start, len, dest_type, &ores); ++ if (res < 0) { ++ if (extradata) ++ free(extradata); ++ ++ return SQL_ERROR; ++ } ++ ++ DataPtr = free_ptr = ores.ib; ++ len = res; ++ break; ++ } ++ } + + if (blob->textvalue) +- p = (TDS_CHAR *) realloc(blob->textvalue, len + curcol->column_cur_size); ++ p = (TDS_CHAR *) realloc(blob->textvalue, len + extralen + curcol->column_cur_size); + else { + assert(curcol->column_cur_size == 0); +- p = (TDS_CHAR *) malloc(len); ++ p = (TDS_CHAR *) malloc(len + extralen); + } +- if (!p) ++ if (!p) { ++ if (free_ptr) ++ free(free_ptr); ++ if (extradata) ++ free(extradata); + return SQL_ERROR; ++ } + blob->textvalue = p; ++ if (extralen) { ++ memcpy(blob->textvalue + curcol->column_cur_size, extradata, extralen); ++ curcol->column_cur_size += extralen; ++ } + memcpy(blob->textvalue + curcol->column_cur_size, DataPtr, len); ++ ++ if (extradata) ++ free(extradata); ++ if (free_ptr) ++ free(free_ptr); + } else { + memcpy(curcol->column_data + curcol->column_cur_size, DataPtr, len); + } ++ + curcol->column_cur_size += len; ++ + if (blob && curcol->column_cur_size > curcol->column_size) + curcol->column_size = curcol->column_cur_size; + +diff -dPNur freetds-0.82/src/odbc/unittests/blob1.c freetds-0.82-new/src/odbc/unittests/blob1.c +--- freetds-0.82/src/odbc/unittests/blob1.c 2008-01-12 01:21:39.000000000 +0100 ++++ freetds-0.82-new/src/odbc/unittests/blob1.c 2008-07-02 22:32:56.000000000 +0200 +@@ -47,6 +47,16 @@ + buf[n] = 'a' + ((start+n) * step % ('z' - 'a' + 1)); + } + ++static void ++fill_hex(char *buf, size_t len, unsigned int start, unsigned int step) ++{ ++ size_t n; ++ ++ for (n = 0; n < len; ++n) ++ sprintf(buf + 2*n, "%2x", (unsigned int)('a' + ((start+n) * step % ('z' - 'a' + 1)))); ++} ++ ++ + static int + check_chars(const char *buf, size_t len, unsigned int start, unsigned int step) + { +@@ -60,6 +70,21 @@ + } + + static int ++check_hex(const char *buf, size_t len, unsigned int start, unsigned int step) ++{ ++ size_t n; ++ char symbol[3]; ++ ++ for (n = 0; n < len; ++n) { ++ sprintf(symbol, "%2x", (unsigned int)('a' + ((start+n) / 2 * step % ('z' - 'a' + 1)))); ++ if (buf[n] != symbol[(start+n) % 2]) ++ return 0; ++ } ++ ++ return 1; ++} ++ ++static int + readBlob(SQLHSTMT * stmth, SQLUSMALLINT pos) + { + SQLRETURN rcode; +@@ -93,6 +118,43 @@ + return rcode; + } + ++static int ++readBlobAsChar(SQLHSTMT * stmth, SQLUSMALLINT pos, int step) ++{ ++ SQLRETURN rcode = SQL_SUCCESS_WITH_INFO; ++ char buf[8192]; ++ SQLLEN len, total = 0; ++ int i = 0; ++ int check; ++ int bufsize; ++ ++ if (step%2) bufsize = sizeof(buf) - 1; ++ else bufsize = sizeof(buf); ++ ++ printf(">> readBlobAsChar field %d\n", pos); ++ while (rcode == SQL_SUCCESS_WITH_INFO) { ++ i++; ++ rcode = SQLGetData(stmth, pos, SQL_C_CHAR, (SQLPOINTER) buf, (SQLINTEGER) bufsize, &len); ++ if (!SQL_SUCCEEDED(rcode) || len <= 0) ++ break; ++ if (len > (SQLLEN) bufsize) ++ len = (SQLLEN) bufsize - 1; ++ printf(">> step %d: %d bytes readed\n", i, (int) len); ++ ++ check = check_hex(buf, len, 2*987 + total, 25); ++ if (!check) { ++ fprintf(stderr, "Wrong buffer content\n"); ++ failed = 1; ++ } ++ total += len; ++ } ++ printf(">> total bytes read = %d \n", (int) total); ++ if (total != 20000) ++ failed = 1; ++ return rcode; ++} ++ ++ + int + main(int argc, char **argv) + { +@@ -106,12 +168,14 @@ + SQLLEN vind1; + char buf2[NBYTES]; + SQLLEN vind2; ++ char buf3[NBYTES*2 + 1]; ++ SQLLEN vind3; + int cnt = 2; + + use_odbc_version3 = 1; + Connect(); + +- Command(Statement, "CREATE TABLE #tt ( k INT, t TEXT, b IMAGE, v INT )"); ++ Command(Statement, "CREATE TABLE #tt ( k INT, t TEXT, b1 IMAGE, b2 IMAGE, v INT )"); + + /* Insert rows ... */ + +@@ -121,7 +185,7 @@ + rcode = SQLAllocHandle(SQL_HANDLE_STMT, Connection, &m_hstmt); + CHECK_RCODE(SQL_HANDLE_DBC, Connection, "SQLAllocHandle StmtH"); + +- rcode = SQLPrepare(m_hstmt, (SQLCHAR *) "INSERT INTO #tt VALUES ( ?, ?, ?, ? )", SQL_NTS); ++ rcode = SQLPrepare(m_hstmt, (SQLCHAR *) "INSERT INTO #tt VALUES ( ?, ?, ?, ?, ? )", SQL_NTS); + CHECK_RCODE(SQL_HANDLE_STMT, m_hstmt, "SQLPrepare"); + + SQLBindParameter(m_hstmt, 1, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER, 0, 0, &key, 0, &vind0); +@@ -133,9 +197,12 @@ + SQLBindParameter(m_hstmt, 3, SQL_PARAM_INPUT, SQL_C_BINARY, SQL_LONGVARBINARY, 0x10000000, 0, buf2, 0, &vind2); + CHECK_RCODE(SQL_HANDLE_STMT, m_hstmt, "SQLBindParameter 3"); + +- SQLBindParameter(m_hstmt, 4, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER, 0, 0, &key, 0, &vind0); ++ SQLBindParameter(m_hstmt, 4, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_LONGVARBINARY, 0x10000000, 0, buf3, 0, &vind3); + CHECK_RCODE(SQL_HANDLE_STMT, m_hstmt, "SQLBindParameter 4"); + ++ SQLBindParameter(m_hstmt, 5, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER, 0, 0, &key, 0, &vind0); ++ CHECK_RCODE(SQL_HANDLE_STMT, m_hstmt, "SQLBindParameter 5"); ++ + key = i; + vind0 = 0; + +@@ -144,6 +211,10 @@ + + fill_chars(buf2, NBYTES, 987, 25); + vind2 = SQL_LEN_DATA_AT_EXEC(NBYTES); ++ ++ memset(buf3, 0, sizeof(buf3)); ++ vind3 = SQL_LEN_DATA_AT_EXEC(2*NBYTES+1); ++ + + printf(">> insert... %d\n", i); + rcode = SQLExecute(m_hstmt); +@@ -155,10 +226,25 @@ + CHECK_RCODE(SQL_HANDLE_STMT, m_hstmt, "SQLParamData StmtH"); + printf(">> SQLParamData: ptr = %p rcode = %d\n", (void *) p, rcode); + if (rcode == SQL_NEED_DATA) { +- SQLRETURN rcode = SQLPutData(m_hstmt, p, NBYTES); ++ SQLRETURN rcode; ++ if (p == buf3) { ++ fill_hex(buf3, NBYTES, 987, 25); ++ ++ rcode = SQLPutData(m_hstmt, p, NBYTES - (i&1)); + +- CHECK_RCODE(SQL_HANDLE_STMT, m_hstmt, "SQLPutData StmtH"); +- printf(">> param %p: total bytes written = %d\n", (void *) p, NBYTES); ++ CHECK_RCODE(SQL_HANDLE_STMT, m_hstmt, "SQLPutData StmtH"); ++ printf(">> param %p: total bytes written = %d\n", (void *) p, NBYTES - (i&1)); ++ ++ rcode = SQLPutData(m_hstmt, p + NBYTES - (i&1), NBYTES + (i&1)); ++ ++ CHECK_RCODE(SQL_HANDLE_STMT, m_hstmt, "SQLPutData StmtH"); ++ printf(">> param %p: total bytes written = %d\n", (void *) p, NBYTES + (i&1)); ++ } else { ++ rcode = SQLPutData(m_hstmt, p, NBYTES); ++ ++ CHECK_RCODE(SQL_HANDLE_STMT, m_hstmt, "SQLPutData StmtH"); ++ printf(">> param %p: total bytes written = %d\n", (void *) p, NBYTES); ++ } + } + } + +@@ -182,7 +268,7 @@ + CHECK_RCODE(SQL_HANDLE_STMT, m_hstmt, "SQLSetStmtAttr SQL_ATTR_CURSOR_SENSITIVITY"); + } + +- rcode = SQLPrepare(m_hstmt, (SQLCHAR *) "SELECT t, b, v FROM #tt WHERE k = ?", SQL_NTS); ++ rcode = SQLPrepare(m_hstmt, (SQLCHAR *) "SELECT t, b1, b2, v FROM #tt WHERE k = ?", SQL_NTS); + CHECK_RCODE(SQL_HANDLE_STMT, m_hstmt, "SQLPrepare"); + + SQLBindParameter(m_hstmt, 1, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER, 0, 0, &i, 0, &vind0); +@@ -192,7 +278,9 @@ + CHECK_RCODE(SQL_HANDLE_STMT, m_hstmt, "SQLBindCol 2"); + SQLBindCol(m_hstmt, 2, SQL_C_BINARY, NULL, 0, &vind2); + CHECK_RCODE(SQL_HANDLE_STMT, m_hstmt, "SQLBindCol 3"); +- SQLBindCol(m_hstmt, 3, SQL_C_LONG, &key, 0, &vind0); ++ SQLBindCol(m_hstmt, 3, SQL_C_BINARY, NULL, 0, &vind3); ++ CHECK_RCODE(SQL_HANDLE_STMT, m_hstmt, "SQLBindCol 4"); ++ SQLBindCol(m_hstmt, 4, SQL_C_LONG, &key, 0, &vind0); + CHECK_RCODE(SQL_HANDLE_STMT, m_hstmt, "SQLBindCol 1"); + + vind0 = 0; +@@ -210,6 +298,8 @@ + CHECK_RCODE(SQL_HANDLE_STMT, m_hstmt, "readBlob 1"); + rcode = readBlob(m_hstmt, 2); + CHECK_RCODE(SQL_HANDLE_STMT, m_hstmt, "readBlob 2"); ++ rcode = readBlobAsChar(m_hstmt, 3, i); ++ CHECK_RCODE(SQL_HANDLE_STMT, m_hstmt, "readBlob 3 as SQL_C_CHAR"); + + rcode = SQLCloseCursor(m_hstmt); + CHECK_RCODE(SQL_HANDLE_STMT, m_hstmt, "SQLCloseCursor StmtH"); |