diff options
Diffstat (limited to 'dev-db/freetds/files')
-rw-r--r-- | dev-db/freetds/files/SQLGetData.utf8.odbc.c-r3.diff | 196 | ||||
-rw-r--r-- | dev-db/freetds/files/SQLGetData.utf8.odbc.c.diff | 199 | ||||
-rw-r--r-- | dev-db/freetds/files/SQLGetData_cvs.patch | 67 | ||||
-rw-r--r-- | dev-db/freetds/files/freetds-0.82-odbc-csa2.patch | 484 | ||||
-rw-r--r-- | dev-db/freetds/files/freetds-20080603-odbc-csa2.patch | 404 | ||||
-rw-r--r-- | dev-db/freetds/files/freetds-ds-connect_timeout.patch | 12 | ||||
-rw-r--r-- | dev-db/freetds/files/freetds-ds-odbc.patch | 222 |
7 files changed, 1584 insertions, 0 deletions
diff --git a/dev-db/freetds/files/SQLGetData.utf8.odbc.c-r3.diff b/dev-db/freetds/files/SQLGetData.utf8.odbc.c-r3.diff new file mode 100644 index 0000000..0039347 --- /dev/null +++ b/dev-db/freetds/files/SQLGetData.utf8.odbc.c-r3.diff @@ -0,0 +1,196 @@ +diff -dPNur freetds-0.82/src/odbc/odbc.c freetds-0.82-new-ds/src/odbc/odbc.c +--- freetds-0.82/src/odbc/odbc.c 2008-05-06 04:57:26.000000000 +0200 ++++ freetds-0.82-new-ds/src/odbc/odbc.c 2008-06-25 22:47:06.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,154 @@ + 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 >= 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 (fCType == SQL_C_BINARY) { ++ switch (nSybType) { ++ case SYBCHAR: ++ case SYBVARCHAR: ++ case SYBTEXT: ++ case XSYBCHAR: ++ case XSYBVARCHAR: ++ nread = (src[0] == '0' && toupper(src[1]) == 'X')? 2 : 0; ++ ++ while ((nread < colinfo->column_cur_size) && (src[nread] == ' ' || src[nread] == '\0')) ++ nread++; ++ ++ nread += colinfo->column_text_sqlgetdatapos * 2; ++ ++ if (nread && nread >= colinfo->column_cur_size) ++ ODBC_RETURN(stmt, SQL_NO_DATA); ++ ++ src += nread; ++ srclen = colinfo->column_cur_size - nread; ++ ++ if (converted_column_cur_size%2) ++ converted_column_cur_size = (converted_column_cur_size + 1) / 2; ++ else ++ 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 +4762,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 --git a/dev-db/freetds/files/SQLGetData.utf8.odbc.c.diff b/dev-db/freetds/files/SQLGetData.utf8.odbc.c.diff new file mode 100644 index 0000000..91a8fca --- /dev/null +++ b/dev-db/freetds/files/SQLGetData.utf8.odbc.c.diff @@ -0,0 +1,199 @@ +Index: src/odbc/odbc.c +=================================================================== +RCS file: /cvsroot/freetds/freetds/src/odbc/odbc.c,v +retrieving revision 1.481 +diff -u -r1.481 odbc.c +--- src/odbc/odbc.c 5 Jun 2008 16:21:54 -0000 1.481 ++++ src/odbc/odbc.c 12 Jun 2008 01:55:58 -0000 +@@ -4644,6 +4646,8 @@ + SQLLEN dummy_cb; + int nSybType; + ++ int extra_bytes = 0; ++ + INIT_HSTMT; + + tdsdump_log(TDS_DBG_FUNC, "SQLGetData(%p, %u, %d, %p, %d, %p)\n", +@@ -4684,42 +4688,140 @@ + 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 && colinfo->column_text_sqlgetdatapos) { ++ 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 (nread >= colinfo->column_cur_size) ++ ODBC_RETURN(stmt, SQL_NO_DATA); ++ } ++ ++ src += nread; ++ srclen = colinfo->column_cur_size - nread; ++ break; ++ default: ++ if (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 (fCType == SQL_C_BINARY) { ++ switch (nSybType) { ++ case SYBCHAR: ++ case SYBVARCHAR: ++ case SYBTEXT: ++ case XSYBCHAR: ++ case XSYBVARCHAR: ++ nread = (src[0] == '0' && toupper(src[1]) == 'X')? 2 : 0; ++ ++ while ((nread < colinfo->column_cur_size) && (src[nread] == ' ' || src[nread] == '\0')) ++ nread++; ++ ++ nread += colinfo->column_text_sqlgetdatapos * 2; ++ ++ if (nread && nread >= colinfo->column_cur_size) ++ ODBC_RETURN(stmt, SQL_NO_DATA); ++ ++ src += nread; ++ srclen = colinfo->column_cur_size - nread; ++ 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)) { + /* calculate how many bytes were read */ + int remaining = cbValueMax; +Index: src/odbc/unittests/getdata.c +=================================================================== +RCS file: /cvsroot/freetds/freetds/src/odbc/unittests/getdata.c,v +retrieving revision 1.6 +diff -u -r1.6 getdata.c +--- src/odbc/unittests/getdata.c 29 Jan 2008 14:30:48 -0000 1.6 ++++ src/odbc/unittests/getdata.c 12 Jun 2008 01:55:58 -0000 +@@ -11,7 +11,14 @@ + { + memset(odbc_err, 0, sizeof(odbc_err)); + memset(odbc_sqlstate, 0, sizeof(odbc_sqlstate)); +- if (!SQL_SUCCEEDED(SQLGetDiagRec(SQL_HANDLE_STMT, Statement, 1, (SQLCHAR *) odbc_sqlstate, NULL, (SQLCHAR *) odbc_err, sizeof(odbc_err), NULL))) { ++ if (!SQL_SUCCEEDED(SQLGetDiagRec(SQL_HANDLE_STMT ++ , Statement ++ , 1 ++ , (SQLCHAR *) odbc_sqlstate ++ , NULL ++ , (SQLCHAR *) odbc_err ++ , sizeof(odbc_err) ++ , NULL))) { + printf("SQLGetDiagRec should not fail\n"); + exit(1); + } diff --git a/dev-db/freetds/files/SQLGetData_cvs.patch b/dev-db/freetds/files/SQLGetData_cvs.patch new file mode 100644 index 0000000..5631c22 --- /dev/null +++ b/dev-db/freetds/files/SQLGetData_cvs.patch @@ -0,0 +1,67 @@ +diff -dPNur freetds-0.82-ds1/src/odbc/odbc.c freetds-0.82-ds2/src/odbc/odbc.c +--- freetds-0.82-ds1/src/odbc/odbc.c 2008-07-01 19:19:14.000000000 +0200 ++++ freetds-0.82-ds2/src/odbc/odbc.c 2008-07-01 19:19:25.000000000 +0200 +@@ -4564,6 +4564,7 @@ + SQLLEN dummy_cb; + int nSybType; + ++ TDS_INT converted_column_cur_size; + int extra_bytes = 0; + + INIT_HSTMT; +@@ -4599,6 +4600,7 @@ + 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; +@@ -4624,7 +4626,7 @@ + if (is_blob_type(colinfo->column_type)) + src = ((TDSBLOB *) src)->textvalue; + +- if (fCType == SQL_C_CHAR && colinfo->column_text_sqlgetdatapos) { ++ if (fCType == SQL_C_CHAR) { + TDS_CHAR buf[3]; + SQLLEN len; + +@@ -4667,12 +4669,15 @@ + } + } else { + nread = colinfo->column_text_sqlgetdatapos / 2; +- if (nread >= colinfo->column_cur_size) ++ ++ 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 >= colinfo->column_cur_size) +@@ -4701,6 +4706,12 @@ + + src += nread; + srclen = colinfo->column_cur_size - nread; ++ ++ if (converted_column_cur_size%2) ++ converted_column_cur_size = (converted_column_cur_size + 1) / 2; ++ else ++ converted_column_cur_size /= 2; ++ + break; + default: + if (colinfo->column_text_sqlgetdatapos > 0 +@@ -4751,7 +4762,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 --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"); diff --git a/dev-db/freetds/files/freetds-20080603-odbc-csa2.patch b/dev-db/freetds/files/freetds-20080603-odbc-csa2.patch new file mode 100644 index 0000000..1615ddd --- /dev/null +++ b/dev-db/freetds/files/freetds-20080603-odbc-csa2.patch @@ -0,0 +1,404 @@ +diff -dPNur freetds/include/tds.h freetds-ds/include/tds.h +--- freetds/include/tds.h 2008-06-18 11:06:26.000000000 +0200 ++++ freetds-ds/include/tds.h 2008-07-02 22:10:03.000000000 +0200 +@@ -1009,6 +1009,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/src/odbc/odbc.c freetds-ds/src/odbc/odbc.c +--- freetds/src/odbc/odbc.c 2008-06-18 11:06:26.000000000 +0200 ++++ freetds-ds/src/odbc/odbc.c 2008-07-02 22:10:03.000000000 +0200 +@@ -4652,6 +4652,7 @@ + SQLLEN dummy_cb; + int nSybType; + ++ TDS_INT converted_column_cur_size; + int extra_bytes = 0; + + INIT_HSTMT; +@@ -4690,6 +4691,7 @@ + ODBC_RETURN(stmt, SQL_ERROR); + } + colinfo = tds->current_results->columns[icol - 1]; ++ converted_column_cur_size = colinfo->column_cur_size; + + if (colinfo->column_cur_size < 0) { + *pcbValue = SQL_NULL_DATA; +@@ -4715,7 +4717,7 @@ + if (is_blob_type(colinfo->column_type)) + src = ((TDSBLOB *) src)->textvalue; + +- if (fCType == SQL_C_CHAR && colinfo->column_text_sqlgetdatapos) { ++ if (fCType == SQL_C_CHAR) { + TDS_CHAR buf[3]; + SQLLEN len; + +@@ -4758,40 +4760,15 @@ + } + } else { + nread = colinfo->column_text_sqlgetdatapos / 2; +- if (nread >= colinfo->column_cur_size) ++ ++ 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; +- break; +- default: +- if (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 (fCType == SQL_C_BINARY) { +- switch (nSybType) { +- case SYBCHAR: +- case SYBVARCHAR: +- case SYBTEXT: +- case XSYBCHAR: +- case XSYBVARCHAR: +- nread = (src[0] == '0' && toupper(src[1]) == 'X')? 2 : 0; +- +- while ((nread < colinfo->column_cur_size) && (src[nread] == ' ' || src[nread] == '\0')) +- nread++; +- +- nread += colinfo->column_text_sqlgetdatapos * 2; +- +- if (nread && 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 +@@ -4842,7 +4819,7 @@ + if (colinfo->column_text_sqlgetdatapos == 0 && cbValueMax > 0) + ++colinfo->column_text_sqlgetdatapos; + +- if (colinfo->column_text_sqlgetdatapos < colinfo->column_cur_size) { /* not all read ?? */ ++ if (colinfo->column_text_sqlgetdatapos < converted_column_cur_size) { /* not all read ?? */ + odbc_errs_add(&stmt->errs, "01004", "String data, right truncated"); + ODBC_RETURN(stmt, SQL_SUCCESS_WITH_INFO); + } +diff -dPNur freetds/src/odbc/prepare_query.c freetds-ds/src/odbc/prepare_query.c +--- freetds/src/odbc/prepare_query.c 2007-04-18 16:29:24.000000000 +0200 ++++ freetds-ds/src/odbc/prepare_query.c 2008-07-02 22:10:03.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/src/odbc/unittests/blob1.c freetds-ds/src/odbc/unittests/blob1.c +--- freetds/src/odbc/unittests/blob1.c 2008-01-12 01:14:11.000000000 +0100 ++++ freetds-ds/src/odbc/unittests/blob1.c 2008-07-02 22:09:28.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"); diff --git a/dev-db/freetds/files/freetds-ds-connect_timeout.patch b/dev-db/freetds/files/freetds-ds-connect_timeout.patch new file mode 100644 index 0000000..013764e --- /dev/null +++ b/dev-db/freetds/files/freetds-ds-connect_timeout.patch @@ -0,0 +1,12 @@ +diff -dPNur freetds-0.82/src/odbc/odbc.c freetds-0.82-ds/src/odbc/odbc.c +--- freetds-0.82/src/odbc/odbc.c 2008-05-06 04:57:26.000000000 +0200 ++++ freetds-0.82-ds/src/odbc/odbc.c 2008-06-26 12:20:43.000000000 +0200 +@@ -312,7 +312,7 @@ + + tds_fix_connection(connection); + +- connection->connect_timeout = dbc->attr.connection_timeout; ++ connection->connect_timeout = dbc->attr.login_timeout; + + if (tds_connect(dbc->tds_socket, connection) == TDS_FAIL) { + tds_free_socket(dbc->tds_socket); diff --git a/dev-db/freetds/files/freetds-ds-odbc.patch b/dev-db/freetds/files/freetds-ds-odbc.patch new file mode 100644 index 0000000..a7b6707 --- /dev/null +++ b/dev-db/freetds/files/freetds-ds-odbc.patch @@ -0,0 +1,222 @@ +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-06-09 13:12:51.000000000 +0200 +@@ -4564,6 +4564,8 @@ + SQLLEN dummy_cb; + int nSybType; + ++ int extra_bytes = 0; ++ + INIT_HSTMT; + + tdsdump_log(TDS_DBG_FUNC, "SQLGetData(%p, %u, %d, %p, %d, %p)\n", +@@ -4601,18 +4603,117 @@ + 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 readed = 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)&&(colinfo->column_text_sqlgetdatapos)) { ++ 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) { ++ readed = (colinfo->column_text_sqlgetdatapos - 1) / 2; ++ if (readed >= colinfo->column_cur_size) ++ ODBC_RETURN(stmt, SQL_NO_DATA); ++ ++ if (cbValueMax > 2) { ++ len = convert_tds2sql(context, nSybType, src + readed, 1, fCType, buf, 3, 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; ++ readed++; ++ ++ if (readed >= 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 { ++ readed = colinfo->column_text_sqlgetdatapos / 2; ++ if (readed >= colinfo->column_cur_size) ++ ODBC_RETURN(stmt, SQL_NO_DATA); ++ } ++ ++ src += readed; ++ srclen = colinfo->column_cur_size - readed; ++ break; ++ default: ++ if (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 (fCType == SQL_C_BINARY) { ++ switch (nSybType) { ++ case SYBCHAR: ++ case SYBVARCHAR: ++ case SYBTEXT: ++ case XSYBCHAR: ++ case XSYBVARCHAR: ++ if (src[0] == '0' && (src[1] == 'x' || src[1] == 'X')) readed = 2; ++ else readed = 0; ++ while ((readed < colinfo->column_cur_size) && (src[readed] == ' ' || src[readed] == '\0')) readed ++; ++ readed += colinfo->column_text_sqlgetdatapos * 2; ++ ++ if ((readed)&&(readed >= colinfo->column_cur_size)) ++ ODBC_RETURN(stmt, SQL_NO_DATA); ++ ++ src += readed; ++ srclen = colinfo->column_cur_size - readed; ++ 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) +@@ -4620,23 +4721,18 @@ + + 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; +@@ -4644,9 +4740,54 @@ + /* FIXME test on destination char ??? */ + if (stmt->dbc->env->attr.output_nts != SQL_FALSE && fCType == SQL_C_CHAR && readed > 0) + --readed; ++ + if (readed > *pcbValue) + readed = *pcbValue; ++ + colinfo->column_text_sqlgetdatapos += readed; ++ ++/* ++ if (fCType == SQL_C_CHAR) { ++ switch (nSybType) { ++ case SYBLONGBINARY: ++ case SYBBINARY: ++ case SYBVARBINARY: ++ case SYBIMAGE: ++ case XSYBBINARY: ++ case XSYBVARBINARY: ++ case TDS_CONVERT_BINARY: ++ if (readed%2) { ++ readed--; ++ *((TDS_CHAR *)rgbValue + readed) = 0; ++ } ++ colinfo->column_text_sqlgetdatapos += readed / 2; ++ break; ++ default: ++ colinfo->column_text_sqlgetdatapos += readed; ++ } ++ } else if (fCType == SQL_C_BINARY) { ++ switch (nSybType) { ++ case SYBCHAR: ++ case SYBVARCHAR: ++ case SYBTEXT: ++ case XSYBCHAR: ++ case XSYBVARCHAR: ++ if (!colinfo->column_text_sqlgetdatapos) { ++ if (src[0] == '0' && (src[1] == 'x' || src[1] == 'X')) ++ colinfo->column_text_sqlgetdatapos += 2; ++ ++ while ((colinfo->column_text_sqlgetdatapos < colinfo->column_cur_size) && (src[colinfo->column_text_sqlgetdatapos] == ' ' || src[colinfo->column_text_sqlgetdatapos] == '\0')) ++ colinfo->column_text_sqlgetdatapos ++; ++ } ++ colinfo->column_text_sqlgetdatapos += readed * 2; ++ break; ++ default: ++ colinfo->column_text_sqlgetdatapos += readed; ++ } ++ } else { ++ colinfo->column_text_sqlgetdatapos += readed; ++ }*/ ++ + /* avoid infinite SQL_SUCCESS on empty strings */ + if (colinfo->column_text_sqlgetdatapos == 0 && cbValueMax > 0) + ++colinfo->column_text_sqlgetdatapos; |