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 + -
显示快捷键?