convert.c

来自「postgresql-odbc,跨平台应用」· C语言 代码 · 共 2,560 行 · 第 1/5 页

C
2,560
字号
	if (bind_size > 0)		pcbValueOffset = rgbValueOffset = (bind_size * bind_row);	else	{		pcbValueOffset = bind_row * sizeof(SQLLEN);		rgbValueOffset = bind_row * cbValueMax;	}	/*	 *	The following is applicable in case bind_size > 0	 *	or the fCType is of variable length. 	 */	if (rgbValue)		rgbValueBindRow = (char *) rgbValue + rgbValueOffset;	if (pcbValue)		pcbValueBindRow = LENADDR_SHIFT(pcbValue, pcbValueOffset);	if (pIndicator)	{		pIndicatorBindRow = LENADDR_SHIFT(pIndicator, pcbValueOffset);		*pIndicatorBindRow = 0;	}	memset(&std_time, 0, sizeof(SIMPLE_TIME));	/* Initialize current date */#ifdef	HAVE_LOCALTIME_R	tim = localtime_r(&stmt_t, &tm);#else	tim = localtime(&stmt_t);#endif /* HAVE_LOCALTIME_R */	std_time.m = tim->tm_mon + 1;	std_time.d = tim->tm_mday;	std_time.y = tim->tm_year + 1900;	mylog("copy_and_convert: field_type = %d, fctype = %d, value = '%s', cbValueMax=%d\n", field_type, fCType, (value == NULL) ? "<NULL>" : value, cbValueMax);	if (!value)	{mylog("null_cvt_date_string=%d\n", conn->connInfo.cvt_null_date_string);		/* a speicial handling for FOXPRO NULL -> NULL_STRING */		if (conn->connInfo.cvt_null_date_string > 0 &&		    PG_TYPE_DATE == field_type &&		    (SQL_C_CHAR == fCType ||		     SQL_C_TYPE_DATE == fCType ||		     SQL_C_DEFAULT == fCType))		{			if (pcbValueBindRow)				*pcbValueBindRow = 0;			switch (fCType)			{				case SQL_C_CHAR:					if (rgbValueBindRow && cbValueMax > 0)						rgbValueBindRow = '\0';					else						result = COPY_RESULT_TRUNCATED;					break;				case SQL_C_TYPE_DATE:				case SQL_C_DEFAULT:					if (rgbValueBindRow && cbValueMax >= sizeof(DATE_STRUCT))					{						memset(rgbValueBindRow, 0, cbValueMax);						if (pcbValueBindRow)							*pcbValueBindRow = sizeof(DATE_STRUCT);					}					else						result = COPY_RESULT_TRUNCATED;					break;#ifdef	UNICODE_SUPPORT				case SQL_C_WCHAR:					if (rgbValueBindRow && cbValueMax >= WCLEN)						memset(rgbValueBindRow, 0, WCLEN);					else						result = COPY_RESULT_TRUNCATED;					break;#endif /* UNICODE_SUPPORT */			}			return result; 		}		/*		 * handle a null just by returning SQL_NULL_DATA in pcbValue, and		 * doing nothing to the buffer.		 */		else if (pIndicator)		{			*pIndicatorBindRow = SQL_NULL_DATA;			return COPY_OK;		}		else		{			SC_set_error(stmt, STMT_RETURN_NULL_WITHOUT_INDICATOR, "StrLen_or_IndPtr was a null pointer and NULL data was retrieved", func);				return	SQL_ERROR;		}	}	if (stmt->hdbc->DataSourceToDriver != NULL)	{		size_t			length = strlen(value);		stmt->hdbc->DataSourceToDriver(stmt->hdbc->translation_option,						SQL_CHAR, valuei, (SDWORD) length,						valuei, (SDWORD) length, NULL,						NULL, 0, NULL);	}	/*	 * First convert any specific postgres types into more useable data.	 *	 * NOTE: Conversions from PG char/varchar of a date/time/timestamp value	 * to SQL_C_DATE,SQL_C_TIME, SQL_C_TIMESTAMP not supported	 */	switch (field_type)	{			/*			 * $$$ need to add parsing for date/time/timestamp strings in			 * PG_TYPE_CHAR,VARCHAR $$$			 */		case PG_TYPE_DATE:			sscanf(value, "%4d-%2d-%2d", &std_time.y, &std_time.m, &std_time.d);			break;		case PG_TYPE_TIME:			sscanf(value, "%2d:%2d:%2d", &std_time.hh, &std_time.mm, &std_time.ss);			break;		case PG_TYPE_ABSTIME:		case PG_TYPE_DATETIME:		case PG_TYPE_TIMESTAMP_NO_TMZONE:		case PG_TYPE_TIMESTAMP:			std_time.fr = 0;			std_time.infinity = 0;			if (strnicmp(value, INFINITY_STRING, 8) == 0)			{				std_time.infinity = 1;				std_time.m = 12;				std_time.d = 31;				std_time.y = 9999;				std_time.hh = 23;				std_time.mm = 59;				std_time.ss = 59;			}			if (strnicmp(value, MINFINITY_STRING, 9) == 0)			{				std_time.infinity = -1;				std_time.m = 0;				std_time.d = 0;				std_time.y = 0;				std_time.hh = 0;				std_time.mm = 0;				std_time.ss = 0;			}			if (strnicmp(value, "invalid", 7) != 0)			{				BOOL		bZone = (field_type != PG_TYPE_TIMESTAMP_NO_TMZONE && PG_VERSION_GE(conn, 7.2));				int			zone;				/*				 * sscanf(value, "%4d-%2d-%2d %2d:%2d:%2d", &std_time.y, &std_time.m,				 * &std_time.d, &std_time.hh, &std_time.mm, &std_time.ss);				 */				bZone = FALSE;	/* time zone stuff is unreliable */				timestamp2stime(value, &std_time, &bZone, &zone);inolog("2stime fr=%d\n", std_time.fr);			}			else			{				/*				 * The timestamp is invalid so set something conspicuous,				 * like the epoch				 */				time_t	t = 0;#ifdef	HAVE_LOCALTIME_R				tim = localtime_r(&t, &tm);#else				tim = localtime(&t);#endif /* HAVE_LOCALTIME_R */				std_time.m = tim->tm_mon + 1;				std_time.d = tim->tm_mday;				std_time.y = tim->tm_year + 1900;				std_time.hh = tim->tm_hour;				std_time.mm = tim->tm_min;				std_time.ss = tim->tm_sec;			}			break;		case PG_TYPE_BOOL:			{					/* change T/F to 1/0 */				char	   *s;				s = midtemp[mtemp_cnt];				switch (((char *)value)[0])				{					case 'f':					case 'F':					case 'n':					case 'N':					case '0':						strcpy(s, "0");						break;					default:						if (true_is_minus1)							strcpy(s, "-1");						else							strcpy(s, "1");				}				neut_str = midtemp[mtemp_cnt];				mtemp_cnt++;			}			break;			/* This is for internal use by SQLStatistics() */		case PG_TYPE_INT2VECTOR:			if (SQL_C_DEFAULT == fCType)			{				int	i, nval, maxc;				const char *vp;				/* this is an array of eight integers */				short	   *short_array = (short *) rgbValueBindRow, shortv;				maxc = 0;				if (NULL != short_array)					maxc = (int) cbValueMax / sizeof(short);				vp = value;				nval = 0;				mylog("index=(");				for (i = 0;; i++)				{					if (sscanf(vp, "%hi", &shortv) != 1)						break;					mylog(" %hi", shortv);					if (0 == shortv && PG_VERSION_LT(conn, 7.2))						break;					nval++;					if (nval < maxc)						short_array[i + 1] = shortv;					/* skip the current token */					while ((*vp != '\0') && (!isspace((UCHAR) *vp)))						vp++;					/* and skip the space to the next token */					while ((*vp != '\0') && (isspace((UCHAR) *vp)))						vp++;					if (*vp == '\0')						break;				}				mylog(") nval = %i\n", nval);				if (maxc > 0)					short_array[0] = nval;				/* There is no corresponding fCType for this. */				len = (nval + 1) * sizeof(short);				if (pcbValue)					*pcbValueBindRow = len;				if (len <= cbValueMax)					return COPY_OK; /* dont go any further or the data will be								 * trashed */				else					return COPY_RESULT_TRUNCATED;			}			break;			/*			 * This is a large object OID, which is used to store			 * LONGVARBINARY objects.			 */		case PG_TYPE_LO_UNDEFINED:			return convert_lo(stmt, value, fCType, rgbValueBindRow, cbValueMax, pcbValueBindRow);		default:			if (field_type == stmt->hdbc->lobj_type	/* hack until permanent type available */			   || (PG_TYPE_OID == field_type && SQL_C_BINARY == fCType && conn->lo_is_domain)			   )				return convert_lo(stmt, value, fCType, rgbValueBindRow, cbValueMax, pcbValueBindRow);	}	/* Change default into something useable */	if (fCType == SQL_C_DEFAULT)	{		fCType = pgtype_to_ctype(stmt, field_type);		if (fCType == SQL_C_WCHAR		    && CC_default_is_c(conn))			fCType = SQL_C_CHAR;		mylog("copy_and_convert, SQL_C_DEFAULT: fCType = %d\n", fCType);	}	text_handling = localize_needed = FALSE;	switch (fCType)	{		case INTERNAL_ASIS_TYPE:#ifdef	UNICODE_SUPPORT	    	case SQL_C_WCHAR:#endif /* UNICODE_SUPPORT */	    	case SQL_C_CHAR:			text_handling = TRUE;			break;		case SQL_C_BINARY:			switch (field_type)			{ 		 		case PG_TYPE_UNKNOWN:		  		case PG_TYPE_BPCHAR:		  		case PG_TYPE_VARCHAR:		  		case PG_TYPE_TEXT:		  		case PG_TYPE_BPCHARARRAY:		  		case PG_TYPE_VARCHARARRAY:		  		case PG_TYPE_TEXTARRAY:					text_handling = TRUE;					break;			}			break;	}	if (text_handling)	{#ifdef	WIN_UNICODE_SUPPORT		if (SQL_C_CHAR == fCType		    || SQL_C_BINARY == fCType)			localize_needed = TRUE;#endif /* WIN_UNICODE_SUPPORT */	}	if (text_handling)	{		/* Special character formatting as required */		/*		 * These really should return error if cbValueMax is not big		 * enough.		 */		switch (field_type)		{			case PG_TYPE_DATE:				len = 10;				if (cbValueMax > len)					sprintf(rgbValueBindRow, "%.4d-%.2d-%.2d", std_time.y, std_time.m, std_time.d);				break;			case PG_TYPE_TIME:				len = 8;				if (cbValueMax > len)					sprintf(rgbValueBindRow, "%.2d:%.2d:%.2d", std_time.hh, std_time.mm, std_time.ss);				break;			case PG_TYPE_ABSTIME:			case PG_TYPE_DATETIME:			case PG_TYPE_TIMESTAMP_NO_TMZONE:			case PG_TYPE_TIMESTAMP:				len = 19;				if (cbValueMax > len)					sprintf(rgbValueBindRow, "%.4d-%.2d-%.2d %.2d:%.2d:%.2d",							std_time.y, std_time.m, std_time.d, std_time.hh, std_time.mm, std_time.ss);				break;			case PG_TYPE_BOOL:				len = strlen(neut_str);				if (cbValueMax > len)				{					strcpy(rgbValueBindRow, neut_str);					mylog("PG_TYPE_BOOL: rgbValueBindRow = '%s'\n", rgbValueBindRow);				}				break;				/*				 * Currently, data is SILENTLY TRUNCATED for BYTEA and				 * character data types if there is not enough room in				 * cbValueMax because the driver can't handle multiple				 * calls to SQLGetData for these, yet.	Most likely, the				 * buffer passed in will be big enough to handle the				 * maximum limit of postgres, anyway.				 *				 * LongVarBinary types are handled correctly above, observing				 * truncation and all that stuff since there is				 * essentially no limit on the large object used to store				 * those.				 */			case PG_TYPE_BYTEA:/* convert binary data to hex strings								 * (i.e, 255 = "FF") */			default:				if (stmt->current_col < 0)				{					pgdc = &(gdata->fdata);					pgdc->data_left = -1;				}				else					pgdc = &gdata->gdata[stmt->current_col];#ifdef	UNICODE_SUPPORT				if (fCType == SQL_C_WCHAR)					wconverted = TRUE;#endif /* UNICODE_SUPPORT */				if (pgdc->data_left < 0)				{					BOOL lf_conv = conn->connInfo.lf_conversion;#ifdef	UNICODE_SUPPORT					if (fCType == SQL_C_WCHAR)					{						len = utf8_to_ucs2_lf(neut_str, SQL_NTS, lf_conv, NULL, 0);						len *= WCLEN;						changed = TRUE;					}					else#endif /* UNICODE_SUPPORT */					if (PG_TYPE_BYTEA == field_type)					{						len = convert_from_pgbinary(neut_str, NULL, 0);						len *= 2;						changed = TRUE;					}					else#ifdef	WIN_UNICODE_SUPPORT					if (localize_needed)					{						wstrlen = utf8_to_ucs2_lf(neut_str, SQL_NTS, lf_conv, NULL, 0);						allocbuf = (SQLWCHAR *) malloc(WCLEN * (wstrlen + 1));						wstrlen = utf8_to_ucs2_lf(neut_str, SQL_NTS, lf_conv, allocbuf, wstrlen + 1);						len = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR) allocbuf, (int) wstrlen, NULL, 0, NULL, NULL);						changed = TRUE;					}					else#endif /* WIN_UNICODE_SUPPORT */						/* convert linefeeds to carriage-return/linefeed */						len = convert_linefeeds(neut_str, NULL, 0, lf_conv, &changed);					if (cbValueMax == 0)		/* just returns length												 * info */					{						result = COPY_RESULT_TRUNCATED;#ifdef	WIN_UNICODE_SUPPORT						if (allocbuf)							free(allocbuf);#endif /* WIN_UNICODE_SUPPORT */						break;					}					if (!pgdc->ttlbuf)						pgdc->ttlbuflen = 0;					needbuflen = len;					switch (fCType)					{#ifdef	UNICODE_SUPPORT						case SQL_C_WCHAR:							needbuflen += WCLEN;							break;#endif /* UNICODE_SUPPORT */						case SQL_C_BINARY:							break;						default:							needbuflen++;					}					if (changed || needbuflen > cbValueMax)					{						if (needbuflen > (SQLLEN) pgdc->ttlbuflen)						{							pgdc->ttlbuf = realloc(pgdc->ttlbuf, needbuflen);							pgdc->ttlbuflen = needbuflen;						}#ifdef	UNICODE_SUPPORT						if (fCType == SQL_C_WCHAR)						{							utf8_to_ucs2_lf(neut_str, SQL_NTS, lf_conv, (SQLWCHAR *) pgdc->ttlbuf, len / WCLEN);						}						else#endif /* UNICODE_SUPPORT */						if (PG_TYPE_BYTEA == field_type)						{							len = convert_from_pgbinary(neut_str, pgdc->ttlbuf, pgdc->ttlbuflen);							pg_bin2hex(pgdc->ttlbuf, pgdc->ttlbuf, len);							len *= 2; 						}						else#ifdef	WIN_UNICODE_SUPPORT						if (localize_needed)						{							len = WideCharToMultiByte(CP_ACP, 0, allocbuf, (int) wstrlen, pgdc->ttlbuf, (int) pgdc->ttlbuflen, NULL, NULL);							free(allocbuf);							allocbuf = NULL;						}						else#endif /* WIN_UNICODE_SUPPORT */							convert_linefeeds(neut_str, pgdc->ttlbuf, pgdc->ttlbuflen, lf_conv, &changed);						ptr = pgdc->ttlbuf;						pgdc->ttlbufused = len;					}					else					{						if (pgdc->ttlbuf)						{							free(pgdc->ttlbuf);							pgdc->ttlbuf = NULL;						}						ptr = neut_str;					}				}				else				{					ptr = pgdc->ttlbuf;					len = pgdc->ttlbufused;				}				mylog("DEFAULT: len = %d, ptr = '%.*s'\n", len, len, ptr);				if (stmt->current_col >= 0)				{					if (pgdc->data_left > 0)					{						ptr += len - pgdc->data_left;						len = pgdc->data_left;						needbuflen = len + (pgdc->ttlbuflen - pgdc->ttlbufused);					}					else						pgdc->data_left = len;				}				if (cbValueMax > 0)

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?