odbcconvert.c
来自「这个是内存数据库的客户端」· C语言 代码 · 共 2,426 行 · 第 1/5 页
C
2,426 行
if (lenp && offset) lenp = (SQLINTEGER *) ((char *) lenp + offset + row * (bind_type == SQL_BIND_BY_COLUMN ? sizeof(SQLINTEGER) : bind_type)); if (nullp && offset) nullp = (SQLINTEGER *) ((char *) nullp + offset + row * (bind_type == SQL_BIND_BY_COLUMN ? sizeof(SQLINTEGER) : bind_type)); /* translate default type */ /* note, type can't be SQL_ARD_TYPE since when this function is called from SQLFetch, type is already the ARD concise type, and when it is called from SQLGetData, it has already been translated */ if (type == SQL_C_DEFAULT) type = ODBCDefaultType(irdrec); if (precision == UNAFFECTED || scale == UNAFFECTED || datetime_interval_precision == UNAFFECTED) { if (ardrec) { if (precision == UNAFFECTED) precision = ardrec->sql_desc_precision; if (scale == UNAFFECTED) scale = ardrec->sql_desc_scale; if (datetime_interval_precision == UNAFFECTED) datetime_interval_precision = ardrec->sql_desc_datetime_interval_precision; } else { if (precision == UNAFFECTED) precision = type == SQL_C_NUMERIC ? 10 : 6; if (scale == UNAFFECTED) scale = 0; if (datetime_interval_precision == UNAFFECTED) datetime_interval_precision = 2; } } i = datetime_interval_precision; maxdatetimeval = 1; while (i-- > 0) maxdatetimeval *= 10; data = mapi_fetch_field(stmt->hdl, col - 1); if (mapi_error(stmt->Dbc->mid)) { /* General error */ addStmtError(stmt, "HY000", NULL, 0); return SQL_ERROR; } if (nullp) *nullp = SQL_NULL_DATA; if (lenp) *lenp = SQL_NULL_DATA; if (data == NULL) { if (nullp == NULL) { /* Indicator variable required but not supplied */ addStmtError(stmt, "22002", NULL, 0); return SQL_ERROR; } return SQL_SUCCESS; } /* first convert to internal (binary) format */ /* see SQLExecute.c for possible types */ switch (sql_type) { case SQL_CHAR: break; case SQL_DECIMAL: case SQL_TINYINT: case SQL_SMALLINT: case SQL_INTEGER: case SQL_BIGINT: case SQL_INTERVAL_MONTH: case SQL_INTERVAL_SECOND: if (!parseint(data, &nval)) { /* shouldn't happen: getting here means SQL server told us a value was of a certain type, but in reality it wasn't. */ /* Invalid character value for cast specification */ addStmtError(stmt, "22018", NULL, 0); return SQL_ERROR; } /* interval types are transferred as ints but need to be converted to the internal interval formats */ if (sql_type == SQL_INTERVAL_SECOND) ivalprec = parsesecondinterval(&nval, &ival, sql_type); else if (sql_type == SQL_INTERVAL_MONTH) parsemonthinterval(&nval, &ival, sql_type); break; case SQL_DOUBLE: case SQL_REAL: if (!parsedouble(data, &fval)) { /* Invalid character value for cast specification */ addStmtError(stmt, "22018", NULL, 0); return SQL_ERROR; } break; case SQL_BIT: nval.precision = 1; nval.scale = 0; nval.sign = 1; while (space(*data)) data++; if (strncasecmp(data, "true", 4) == 0) { data += 4; nval.val = 1; } else if (strncasecmp(data, "false", 5) == 0) { data += 5; nval.val = 0; } else { /* Invalid character value for cast specification */ addStmtError(stmt, "22018", NULL, 0); return SQL_ERROR; } while (space(*data)) data++; if (*data) { /* Invalid character value for cast specification */ addStmtError(stmt, "22018", NULL, 0); return SQL_ERROR; } break; case SQL_TYPE_DATE: if (!parsedate(data, &dval)) { /* Invalid character value for cast specification */ addStmtError(stmt, "22018", NULL, 0); return SQL_ERROR; } break; case SQL_TYPE_TIME: if (!parsetime(data, &tval)) { /* Invalid character value for cast specification */ addStmtError(stmt, "22018", NULL, 0); return SQL_ERROR; } break; case SQL_TYPE_TIMESTAMP: if (!parsetimestamp(data, &tsval)) { /* Invalid character value for cast specification */ addStmtError(stmt, "22018", NULL, 0); return SQL_ERROR; } break; default: /* any other type can only be converted to SQL_C_CHAR */ break; } /* then convert to desired format */ switch (type) { case SQL_C_CHAR:#ifdef WITH_WCHAR case SQL_C_WCHAR:#endif { SQLPOINTER origptr; SQLINTEGER origbuflen; SQLINTEGER *origlenp; if (buflen < 0) { /* Invalid string or buffer length */ addStmtError(stmt, "HY090", NULL, 0); return SQL_ERROR; } if (ardrec && row > 0) ptr = (SQLPOINTER) ((char *) ptr +row * (bind_type == SQL_BIND_BY_COLUMN ? ardrec->sql_desc_octet_length : bind_type)); /* if SQL_C_WCHAR is requested, first convert to UTF-8 * (SQL_C_CHAR), and at the end convert to UTF-16 */ origptr = ptr; origbuflen = buflen; origlenp = lenp;#ifdef WITH_WCHAR if (type == SQL_C_WCHAR) { /* allocate temporary space */ buflen *= 4; ptr = malloc(buflen + 1); lenp = NULL; }#endif switch (sql_type) { int sz; default: case SQL_CHAR: copyString(data, ptr, buflen, lenp, SQLINTEGER, addStmtError, stmt); break; case SQL_DECIMAL: case SQL_TINYINT: case SQL_SMALLINT: case SQL_INTEGER: case SQL_BIGINT: case SQL_BIT: { int f, n; data = (char *) ptr; for (n = 0, f = 1; n < nval.scale; n++) f *= 10; sz = snprintf(data, buflen, "%s%" O_ULLFMT, nval.sign ? "" : "-", nval.val / f); if (sz < 0 || sz >= buflen) { /* Numeric value out of range */ addStmtError(stmt, "22003", NULL, 0);#ifdef WITH_WCHAR if (type == SQL_C_WCHAR) free(ptr);#endif return SQL_ERROR; } if (lenp) *lenp = sz; if (nval.scale > 0) { data += sz; buflen -= sz; if (lenp) *lenp += nval.scale + 1; if (buflen > 2) sz = snprintf(data, buflen, ".%0*" O_ULLFMT, nval.scale, nval.val % f); if (buflen <= 2 || sz < 0 || sz >= buflen) { data[buflen - 1] = 0; /* String data, right-truncated */ addStmtError(stmt, "01004", NULL, 0); } } break; } case SQL_DOUBLE: case SQL_REAL: { data = (char *) ptr; for (i = 0; i < 18; i++) { sz = snprintf(data, buflen, "%.*g", i, fval); if (sz < 0 || sz >= buflen) { data[buflen - 1] = 0; if (i == 0) { /* Numeric value out of range */ addStmtError(stmt, "22003", NULL, 0);#ifdef WITH_WCHAR if (type == SQL_C_WCHAR) free(ptr);#endif return SQL_ERROR; } /* current precision (i) doesn't fit, but previous did, so use that */ snprintf(data, buflen, "%.*g", i - 1, fval); /* max space that would have been needed */ sz = (int) strlen(data) + 17 - i; /* String data, right-truncated */ addStmtError(stmt, "01004", NULL, 0); break; } if (fval == strtod(data, NULL)) break; } if (lenp) *lenp = sz; break; } case SQL_TYPE_DATE: if (buflen < 11) { /* Numeric value out of range */ addStmtError(stmt, "22003", NULL, 0);#ifdef WITH_WCHAR if (type == SQL_C_WCHAR) free(ptr);#endif return SQL_ERROR; } data = (char *) ptr; sz = snprintf(data, buflen, "%04hu-%02hu-%02hu", dval.year, dval.month, dval.day); if (sz < 0 || sz >= buflen) { data[buflen - 1] = 0; /* String data, right-truncated */ addStmtError(stmt, "01004", NULL, 0); } if (lenp) *lenp = sz; break; case SQL_TYPE_TIME: if (buflen < 9) { /* Numeric value out of range */ addStmtError(stmt, "22003", NULL, 0);#ifdef WITH_WCHAR if (type == SQL_C_WCHAR) free(ptr);#endif return SQL_ERROR; } data = (char *) ptr; sz = snprintf(data, buflen, "%02hu:%02hu:%02hu", tval.hour, tval.minute, tval.second); if (sz < 0 || sz >= buflen) { data[buflen - 1] = 0; /* String data, right-truncated */ addStmtError(stmt, "01004", NULL, 0); } if (lenp) *lenp = sz; break; case SQL_TYPE_TIMESTAMP: data = (char *) ptr; sz = snprintf(data, buflen, "%04hu-%02hu-%02hu %02hu:%02hu:%02hu", tsval.year, tsval.month, tsval.day, tsval.hour, tsval.minute, tsval.second); if (sz < 0 || sz >= buflen) { /* Numeric value out of range */ addStmtError(stmt, "22003", NULL, 0);#ifdef WITH_WCHAR if (type == SQL_C_WCHAR) free(ptr);#endif return SQL_ERROR; } if (lenp) *lenp = sz; if (tsval.fraction) { int fscale = 9; data += sz; buflen += sz; while (tsval.fraction % 10 == 0) { tsval.fraction /= 10; fscale--; } if (lenp) *lenp += fscale + 1; if (buflen > 2) sz = snprintf(data, buflen, ".%0*u", fscale, tsval.fraction); if (buflen <= 2 || sz < 0 || sz >= buflen) { data[buflen - 1] = 0; /* String data, right-truncated */ addStmtError(stmt, "01004", NULL, 0); } } break; case SQL_INTERVAL_MONTH: { unsigned f; for (i = 1, f = 10; ival.intval.year_month.year >= f; f *= 10, i++) ; sz = snprintf((char *) ptr, buflen, "INTERVAL %s'%u-%02u' YEAR(%d) TO MONTH", ival.interval_sign ? "-" : "", ival.intval.year_month.year, ival.intval.year_month.month, i); if (sz < 0 || sz >= buflen) { /* Numeric value out of range */ addStmtError(stmt, "22003", NULL, 0);#ifdef WITH_WCHAR if (type == SQL_C_WCHAR) free(ptr);#endif return SQL_ERROR; } if (lenp) *lenp = sz; break; } case SQL_INTERVAL_SECOND: { unsigned f; int w; data = (char *) ptr; for (i = 1, f = 10; ival.intval.day_second.day >= f; f *= 10, i++) ; if (i < 10) w = 17; /* space needed for "'DAY(n) TO SECOND" */ else w = 18; /* space needed for "'DAY(nn) TO SECOND" */ if (ivalprec < 10) w += 3; /* space for additional (n) */ else w += 4; /* space for additional (nn) */ sz = snprintf(data, buflen, "INTERVAL %s'%u %02u:%02u:%02u", ival.interval_sign ? "-" : "", ival.intval.day_second.day, ival.intval.day_second.hour, ival.intval.day_second.minute, ival.intval.day_second.second); if (sz < 0 || sz + w >= buflen) { /* Numeric value out of range */ addStmtError(stmt, "22003", NULL, 0);#ifdef WITH_WCHAR if (type == SQL_C_WCHAR) free(ptr);#endif return SQL_ERROR; } data += sz; buflen -= sz; if (lenp) *lenp = sz; if (ival.intval.day_second.fraction) { if (lenp) *lenp += ivalprec + 1; if (buflen > w + 2) sz = snprintf(data, buflen, ".%0*u", ivalprec, ival.intval.day_second.fraction); if (buflen <= w + 2 || sz < 0 || sz + w >= buflen) { sz = buflen - w - 1; /* String data, right-truncated */ addStmtError(stmt, "01004", NULL, 0); } data += sz; buflen -= sz; } /* this should now fit */ sz = snprintf(data, buflen, "' DAY(%d) TO SECOND(%d)", i, ivalprec); if (lenp && sz > 0) *lenp += sz; break; } }#ifdef WITH_WCHAR if (type == SQL_C_WCHAR) { SQLSMALLINT n; ODBCutf82wchar((SQLCHAR *) ptr, SQL_NTS, (SQLWCHAR *) origptr, origbuflen, &n); if (origlenp) *origlenp = n * 2; /* # of bytes, not chars */ free(ptr); }#endif break; } case SQL_C_BINARY: if (buflen < 0) { /* Invalid string or buffer length */ addStmtError(stmt, "HY090", NULL, 0); return SQL_ERROR; } if (ardrec && row > 0) ptr = (SQLPOINTER) ((char *) ptr +row * (bind_type == SQL_BIND_BY_COLUMN ? ardrec->sql_desc_octet_length : bind_type)); switch (sql_type) { case SQL_CHAR: case SQL_DECIMAL: case SQL_TINYINT: case SQL_SMALLINT: case SQL_INTEGER: case SQL_BIGINT: case SQL_REAL: case SQL_DOUBLE: case SQL_BIT: case SQL_TYPE_DATE: case SQL_TYPE_TIME: case SQL_TYPE_TIMESTAMP: case SQL_INTERVAL_MONTH: case SQL_INTERVAL_SECOND: default: /* Restricted data type attribute violation */ addStmtError(stmt, "07006", NULL, 0); return SQL_ERROR; } break; case SQL_C_BIT: if (ardrec && row > 0) ptr = (SQLPOINTER) ((char *) ptr +row * (bind_type == SQL_BIND_BY_COLUMN ? sizeof(unsigned char) : bind_type)); if (lenp) *lenp = 1; switch (sql_type) { case SQL_CHAR: if (!parsedouble(data, &fval)) { /* Invalid character value for cast specification */ addStmtError(stmt, "22018", NULL, 0); return SQL_ERROR; } /* fall through */ case SQL_REAL: case SQL_DOUBLE: if (fval < 0 || fval >= 2) {
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?