Changeset: d1b2fe5d87cd for MonetDB URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=d1b2fe5d87cd Modified Files: clients/odbc/driver/ODBCConvert.c clients/odbc/driver/ODBCUtil.c clients/odbc/driver/ODBCUtil.h gdk/gdk_bat.c Branch: default Log Message:
Merge with Aug2018 branch. diffs (truncated from 304 to 300 lines): diff --git a/clients/odbc/driver/ODBCConvert.c b/clients/odbc/driver/ODBCConvert.c --- a/clients/odbc/driver/ODBCConvert.c +++ b/clients/odbc/driver/ODBCConvert.c @@ -1236,25 +1236,44 @@ ODBCFetch(ODBCStmt *stmt, origlenp = lenp; if (type == SQL_C_WCHAR) { /* allocate temporary space */ - buflen = 511; /* should be enough for most types */ - if (data != NULL && - (sql_type == SQL_CHAR || - sql_type == SQL_VARCHAR || - sql_type == SQL_LONGVARCHAR || - sql_type == SQL_WCHAR || - sql_type == SQL_WVARCHAR || - sql_type == SQL_WLONGVARCHAR)) - buflen = (SQLLEN) datalen + 1; /* but this is certainly enough for strings */ - ptr = malloc(buflen); - if (ptr == NULL) { - /* Memory allocation error */ - addStmtError(stmt, "HY001", NULL, 0); - return SQL_ERROR; + switch (sql_type) { + case SQL_CHAR: + case SQL_VARCHAR: + case SQL_LONGVARCHAR: + case SQL_WCHAR: + case SQL_WVARCHAR: + case SQL_WLONGVARCHAR: + case SQL_BINARY: + case SQL_VARBINARY: + case SQL_LONGVARBINARY: + case SQL_GUID: + /* this is certainly enough for strings */ + buflen = (SQLLEN) datalen + 1; + ptr = NULL; + break; + default: + /* should be enough for most types */ + buflen = 511; + ptr = malloc(buflen); + if (ptr == NULL) { + /* Memory allocation error */ + addStmtError(stmt, "HY001", NULL, 0); + return SQL_ERROR; + } + break; } - lenp = NULL; } switch (sql_type) { + case SQL_BINARY: + case SQL_VARBINARY: + case SQL_LONGVARBINARY: + if (buflen > 0 && (buflen & 1) == 0) { + /* return even number of bytes + NULL + * (i.e. buflen must be odd) */ + buflen--; + } + /* fall through */ default: case SQL_CHAR: case SQL_VARCHAR: @@ -1265,71 +1284,22 @@ ODBCFetch(ODBCStmt *stmt, case SQL_GUID: if (irdrec->already_returned >= datalen) { /* no more data to return */ - if (type == SQL_C_WCHAR) - free(ptr); - return SQL_NO_DATA; - } - data += irdrec->already_returned; - datalen -= irdrec->already_returned; - copyString(data, datalen, ptr, buflen, lenp, SQLLEN, - addStmtError, stmt, return SQL_ERROR); - if (datalen < (size_t) buflen) - irdrec->already_returned += datalen; - else - irdrec->already_returned += buflen - 1; - break; - case SQL_BINARY: - case SQL_VARBINARY: - case SQL_LONGVARBINARY: { - size_t k; - int n; - unsigned char c = 0; - SQLLEN j; - unsigned char *p = ptr; - - if (irdrec->already_returned >= datalen) { - /* no more data to return */ - if (type == SQL_C_WCHAR) + if (type == SQL_C_WCHAR && ptr) free(ptr); return SQL_NO_DATA; } data += irdrec->already_returned; datalen -= irdrec->already_returned; - for (k = 0, j = 0; k < datalen && j < buflen; k++) { - if (isdigit((unsigned char) data[k])) - n = data[k] - '0'; - else if ('A' <= data[k] && data[k] <= 'F') - n = data[k] - 'A' + 10; - else if ('a' <= data[k] && data[k] <= 'f') - n = data[k] - 'a' + 10; - else { - /* should not happen */ - /* General error */ - addStmtError(stmt, "HY000", "Unexpected data from server", 0); - if (type == SQL_C_WCHAR) - free(ptr); - return SQL_ERROR; - } - if (k & 1) { - c |= n; - p[j] = c; - j++; - } else - c = n << 4; + if (ptr) { + copyString(data, datalen, ptr, buflen, lenp, + SQLLEN, addStmtError, stmt, + return SQL_ERROR); } - if (k & 1) { - /* should not happen: uneven length */ - /* General error */ - addStmtError(stmt, "HY000", "Unexpected data from server", 0); - if (type == SQL_C_WCHAR) - free(ptr); - return SQL_ERROR; - } - irdrec->already_returned += k; - if (lenp) - *lenp = datalen / 2; + if (datalen < (size_t) buflen) + irdrec->already_returned += datalen; + else + irdrec->already_returned += buflen - 1; break; - } case SQL_TINYINT: case SQL_SMALLINT: case SQL_INTEGER: @@ -1866,11 +1836,20 @@ ODBCFetch(ODBCStmt *stmt, } if (type == SQL_C_WCHAR) { SQLSMALLINT n; - SQLINTEGER i; + size_t i; - ODBCutf82wchar((SQLCHAR *) ptr, SQL_NTS, - (SQLWCHAR *) origptr, - origbuflen / sizeof(SQLWCHAR), &n, &i); + if (ptr) { + ODBCutf82wchar((SQLCHAR *) ptr, SQL_NTS, + (SQLWCHAR *) origptr, + origbuflen / sizeof(SQLWCHAR), + &n, &i); + free(ptr); + } else { + ODBCutf82wchar((SQLCHAR *) data, SQL_NTS, + (SQLWCHAR *) origptr, + origbuflen / sizeof(SQLWCHAR), + &n, &i); + } #ifdef ODBCDEBUG ODBCLOG("Writing %d bytes to %p\n", (int) (n * sizeof(SQLWCHAR)), @@ -1879,18 +1858,20 @@ ODBCFetch(ODBCStmt *stmt, if (origlenp) *origlenp = n * sizeof(SQLWCHAR); /* # of bytes, not chars */ - free(ptr); irdrec->already_returned -= datalen; irdrec->already_returned += i; + if (i < datalen) { + /* String data, right-truncated */ + addStmtError(stmt, "01004", NULL, 0); + } } #ifdef ODBCDEBUG else - ODBCLOG("Writing %d bytes to %p\n", - (int) strlen(ptr), ptr); + ODBCLOG("Writing %zu bytes to %p\n", strlen(ptr), ptr); #endif break; } - case SQL_C_BINARY: + case SQL_C_BINARY: { if (buflen < 0) { /* Invalid string or buffer length */ addStmtError(stmt, "HY090", NULL, 0); @@ -1933,8 +1914,63 @@ ODBCFetch(ODBCStmt *stmt, /* Restricted data type attribute violation */ addStmtError(stmt, "07006", NULL, 0); return SQL_ERROR; + case SQL_BINARY: + case SQL_VARBINARY: + case SQL_LONGVARBINARY: + break; } - /* break; -- not reached */ + if (irdrec->already_returned >= datalen) { + /* no more data to return */ + return SQL_NO_DATA; + } + data += irdrec->already_returned; + datalen -= irdrec->already_returned; + + size_t k; + SQLLEN j; + unsigned char *p = ptr; + + for (k = 0, j = 0; k < datalen && j < buflen; k++) { + unsigned int n; + + if (isdigit((unsigned char) data[k])) + n = data[k] - '0'; + else if ('A' <= data[k] && data[k] <= 'F') + n = data[k] - 'A' + 10; + else if ('a' <= data[k] && data[k] <= 'f') + n = data[k] - 'a' + 10; + else { + /* should not happen: not a hex character */ + /* General error */ + addStmtError(stmt, "HY000", "Unexpected data from server", 0); + if (type == SQL_C_WCHAR) + free(ptr); + return SQL_ERROR; + } + if (k & 1) { + p[j] |= n; + j++; + } else { + p[j] = n << 4; + } + } + if (k & 1) { + /* should not happen: uneven length */ + /* General error */ + addStmtError(stmt, "HY000", "Unexpected data from server", 0); + if (type == SQL_C_WCHAR) + free(ptr); + return SQL_ERROR; + } + irdrec->already_returned += k; + if (lenp) + *lenp = datalen / 2; + if (k < datalen) { + /* String data, right-truncated */ + addStmtError(stmt, "01004", NULL, 0); + } + break; + } case SQL_C_BIT: if (ardrec && row > 0) ptr = (SQLPOINTER) ((char *) ptr + row * (bind_type == SQL_BIND_BY_COLUMN ? (SQLINTEGER) sizeof(unsigned char) : bind_type)); diff --git a/clients/odbc/driver/ODBCUtil.c b/clients/odbc/driver/ODBCUtil.c --- a/clients/odbc/driver/ODBCUtil.c +++ b/clients/odbc/driver/ODBCUtil.c @@ -188,7 +188,7 @@ ODBCutf82wchar(const SQLCHAR *src, SQLWCHAR *buf, SQLLEN buflen, SQLSMALLINT *buflenout, - SQLINTEGER *consumed) + size_t *consumed) { SQLLEN i = 0; SQLINTEGER j = 0; @@ -263,7 +263,7 @@ ODBCutf82wchar(const SQLCHAR *src, if (buflen > 0) buf[i] = 0; if (consumed) - *consumed = j; + *consumed = (size_t) j; while (j < length && src[j]) { i++; if ((src[j+0] & 0x80) == 0) { diff --git a/clients/odbc/driver/ODBCUtil.h b/clients/odbc/driver/ODBCUtil.h --- a/clients/odbc/driver/ODBCUtil.h +++ b/clients/odbc/driver/ODBCUtil.h @@ -100,7 +100,7 @@ extern char *dupODBCstring(const SQLCHAR } while (0) extern SQLCHAR *ODBCwchar2utf8(const SQLWCHAR *s, SQLLEN length, const char **errmsg); -extern const char *ODBCutf82wchar(const SQLCHAR *s, SQLINTEGER length, SQLWCHAR *buf, SQLLEN buflen, SQLSMALLINT *buflenout, SQLINTEGER *consumed); +extern const char *ODBCutf82wchar(const SQLCHAR *s, SQLINTEGER length, SQLWCHAR *buf, SQLLEN buflen, SQLSMALLINT *buflenout, size_t *consumed); #define fixWcharIn(ws, wsl, t, s, errfunc, hdl, exit) \ do { \ diff --git a/gdk/gdk_bat.c b/gdk/gdk_bat.c --- a/gdk/gdk_bat.c +++ b/gdk/gdk_bat.c @@ -1007,7 +1007,7 @@ BUNappend(BAT *b, const void *t, bool fo BATcheck(b, "BUNappend", GDK_FAIL); - assert(!isVIEW(b)); _______________________________________________ checkin-list mailing list checkin-list@monetdb.org https://www.monetdb.org/mailman/listinfo/checkin-list