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