#include "dpiImpl.h"
#define DPI_MS_DAY 86400000
#define DPI_MS_HOUR 3600000
#define DPI_MS_MINUTE 60000
#define DPI_MS_SECOND 1000
#define DPI_MS_FSECOND 1000000
int dpiDataBuffer__fromOracleDate(dpiDataBuffer *data,
dpiOciDate *oracleValue)
{
dpiTimestamp *timestamp = &data->asTimestamp;
timestamp->year = oracleValue->year;
timestamp->month = oracleValue->month;
timestamp->day = oracleValue->day;
timestamp->hour = oracleValue->hour;
timestamp->minute = oracleValue->minute;
timestamp->second = oracleValue->second;
timestamp->fsecond = 0;
timestamp->tzHourOffset = 0;
timestamp->tzMinuteOffset = 0;
return DPI_SUCCESS;
}
int dpiDataBuffer__fromOracleDateAsDouble(dpiDataBuffer *data,
dpiEnv *env, dpiError *error, dpiOciDate *oracleValue)
{
void *timestamp;
int status;
if (dpiOci__descriptorAlloc(env->handle, ×tamp,
DPI_OCI_DTYPE_TIMESTAMP, "alloc timestamp", error) < 0)
return DPI_FAILURE;
if (dpiOci__dateTimeConstruct(env->handle, timestamp, oracleValue->year,
oracleValue->month, oracleValue->day, oracleValue->hour,
oracleValue->minute, oracleValue->second, 0, NULL, 0, error) < 0) {
dpiOci__descriptorFree(timestamp, DPI_OCI_DTYPE_TIMESTAMP);
return DPI_FAILURE;
}
status = dpiDataBuffer__fromOracleTimestampAsDouble(data,
DPI_ORACLE_TYPE_TIMESTAMP, env, error, timestamp);
dpiOci__descriptorFree(timestamp, DPI_OCI_DTYPE_TIMESTAMP);
return status;
}
int dpiDataBuffer__fromOracleIntervalDS(dpiDataBuffer *data, dpiEnv *env,
dpiError *error, void *oracleValue)
{
dpiIntervalDS *interval = &data->asIntervalDS;
return dpiOci__intervalGetDaySecond(env->handle, &interval->days,
&interval->hours, &interval->minutes, &interval->seconds,
&interval->fseconds, oracleValue, error);
}
int dpiDataBuffer__fromOracleIntervalYM(dpiDataBuffer *data, dpiEnv *env,
dpiError *error, void *oracleValue)
{
dpiIntervalYM *interval = &data->asIntervalYM;
return dpiOci__intervalGetYearMonth(env->handle, &interval->years,
&interval->months, oracleValue, error);
}
int dpiDataBuffer__fromOracleNumberAsDouble(dpiDataBuffer *data,
dpiError *error, void *oracleValue)
{
return dpiOci__numberToReal(&data->asDouble, oracleValue, error);
}
int dpiDataBuffer__fromOracleNumberAsInteger(dpiDataBuffer *data,
dpiError *error, void *oracleValue)
{
return dpiOci__numberToInt(oracleValue, &data->asInt64, sizeof(int64_t),
DPI_OCI_NUMBER_SIGNED, error);
}
int dpiDataBuffer__fromOracleNumberAsUnsignedInteger(dpiDataBuffer *data,
dpiError *error, void *oracleValue)
{
return dpiOci__numberToInt(oracleValue, &data->asUint64, sizeof(uint64_t),
DPI_OCI_NUMBER_UNSIGNED, error);
}
int dpiDataBuffer__fromOracleNumberAsText(dpiDataBuffer *data, dpiEnv *env,
dpiError *error, void *oracleValue)
{
uint8_t *target, numDigits, digits[DPI_NUMBER_MAX_DIGITS];
int16_t decimalPointIndex, i;
uint16_t *targetUtf16;
uint32_t numBytes;
dpiBytes *bytes;
int isNegative;
if (dpiUtils__parseOracleNumber(oracleValue, &isNegative,
&decimalPointIndex, &numDigits, digits, error) < 0)
return DPI_FAILURE;
numBytes = numDigits;
if (isNegative)
numBytes++;
if (decimalPointIndex <= 0)
numBytes += -decimalPointIndex + 2;
else if (decimalPointIndex < numDigits)
numBytes++;
else if (decimalPointIndex > numDigits)
numBytes += decimalPointIndex - numDigits;
if (env->charsetId == DPI_CHARSET_ID_UTF16)
numBytes *= 2;
bytes = &data->asBytes;
if (numBytes > bytes->length)
return dpiError__set(error, "check number to text size",
DPI_ERR_BUFFER_SIZE_TOO_SMALL, bytes->length);
bytes->length = numBytes;
if (env->charsetId == DPI_CHARSET_ID_UTF16) {
targetUtf16 = (uint16_t*) bytes->ptr;
if (isNegative)
*targetUtf16++ = '-';
if (decimalPointIndex <= 0) {
*targetUtf16++ = '0';
*targetUtf16++ = '.';
for (; decimalPointIndex < 0; decimalPointIndex++)
*targetUtf16++ = '0';
}
for (i = 0; i < numDigits; i++) {
if (i > 0 && i == decimalPointIndex)
*targetUtf16++ = '.';
*targetUtf16++ = '0' + digits[i];
}
if (decimalPointIndex > numDigits) {
for (i = numDigits; i < decimalPointIndex; i++)
*targetUtf16++ = '0';
}
} else {
target = (uint8_t*) bytes->ptr;
if (isNegative)
*target++ = '-';
if (decimalPointIndex <= 0) {
*target++ = '0';
*target++ = '.';
for (; decimalPointIndex < 0; decimalPointIndex++)
*target++ = '0';
}
for (i = 0; i < numDigits; i++) {
if (i > 0 && i == decimalPointIndex)
*target++ = '.';
*target++ = '0' + digits[i];
}
if (decimalPointIndex > numDigits) {
for (i = numDigits; i < decimalPointIndex; i++)
*target++ = '0';
}
}
return DPI_SUCCESS;
}
int dpiDataBuffer__fromOracleTimestamp(dpiDataBuffer *data, dpiEnv *env,
dpiError *error, void *oracleValue, int withTZ)
{
dpiTimestamp *timestamp = &data->asTimestamp;
if (dpiOci__dateTimeGetDate(env->handle, oracleValue, ×tamp->year,
×tamp->month, ×tamp->day, error) < 0)
return DPI_FAILURE;
if (dpiOci__dateTimeGetTime(env->handle, oracleValue, ×tamp->hour,
×tamp->minute, ×tamp->second, ×tamp->fsecond,
error) < 0)
return DPI_FAILURE;
if (withTZ) {
if (dpiOci__dateTimeGetTimeZoneOffset(env->handle, oracleValue,
×tamp->tzHourOffset, ×tamp->tzMinuteOffset,
error) < 0)
return DPI_FAILURE;
} else {
timestamp->tzHourOffset = 0;
timestamp->tzMinuteOffset = 0;
}
return DPI_SUCCESS;
}
int dpiDataBuffer__fromOracleTimestampAsDouble(dpiDataBuffer *data,
uint32_t dataType, dpiEnv *env, dpiError *error, void *oracleValue)
{
int32_t day, hour, minute, second, fsecond;
void *interval, *baseDate;
int status;
if (dpiEnv__getBaseDate(env, dataType, &baseDate, error) < 0)
return DPI_FAILURE;
if (dpiOci__descriptorAlloc(env->handle, &interval,
DPI_OCI_DTYPE_INTERVAL_DS, "alloc interval", error) < 0)
return DPI_FAILURE;
if (dpiOci__dateTimeSubtract(env->handle, oracleValue, baseDate, interval,
error) < 0) {
dpiOci__descriptorFree(interval, DPI_OCI_DTYPE_INTERVAL_DS);
return DPI_FAILURE;
}
status = dpiOci__intervalGetDaySecond(env->handle, &day, &hour, &minute,
&second, &fsecond, interval, error);
dpiOci__descriptorFree(interval, DPI_OCI_DTYPE_INTERVAL_DS);
if (status < 0)
return DPI_FAILURE;
data->asDouble = ((double) day) * DPI_MS_DAY + hour * DPI_MS_HOUR +
minute * DPI_MS_MINUTE + second * DPI_MS_SECOND +
fsecond / DPI_MS_FSECOND;
return DPI_SUCCESS;
}
int dpiDataBuffer__toOracleDate(dpiDataBuffer *data, dpiOciDate *oracleValue)
{
dpiTimestamp *timestamp = &data->asTimestamp;
oracleValue->year = timestamp->year;
oracleValue->month = timestamp->month;
oracleValue->day = timestamp->day;
oracleValue->hour = timestamp->hour;
oracleValue->minute = timestamp->minute;
oracleValue->second = timestamp->second;
return DPI_SUCCESS;
}
int dpiDataBuffer__toOracleDateFromDouble(dpiDataBuffer *data, dpiEnv *env,
dpiError *error, dpiOciDate *oracleValue)
{
uint32_t fsecond;
void *timestamp;
if (dpiOci__descriptorAlloc(env->handle, ×tamp,
DPI_OCI_DTYPE_TIMESTAMP, "alloc timestamp", error) < 0)
return DPI_FAILURE;
if (dpiDataBuffer__toOracleTimestampFromDouble(data,
DPI_ORACLE_TYPE_TIMESTAMP, env, error, timestamp) < 0) {
dpiOci__descriptorFree(timestamp, DPI_OCI_DTYPE_TIMESTAMP);
return DPI_FAILURE;
}
if (dpiOci__dateTimeGetDate(env->handle, timestamp, &oracleValue->year,
&oracleValue->month, &oracleValue->day, error) < 0) {
dpiOci__descriptorFree(timestamp, DPI_OCI_DTYPE_TIMESTAMP);
return DPI_FAILURE;
}
if (dpiOci__dateTimeGetTime(env->handle, timestamp, &oracleValue->hour,
&oracleValue->minute, &oracleValue->second, &fsecond, error) < 0) {
dpiOci__descriptorFree(timestamp, DPI_OCI_DTYPE_TIMESTAMP);
return DPI_FAILURE;
}
dpiOci__descriptorFree(timestamp, DPI_OCI_DTYPE_TIMESTAMP);
return DPI_SUCCESS;
}
int dpiDataBuffer__toOracleIntervalDS(dpiDataBuffer *data, dpiEnv *env,
dpiError *error, void *oracleValue)
{
dpiIntervalDS *interval = &data->asIntervalDS;
return dpiOci__intervalSetDaySecond(env->handle, interval->days,
interval->hours, interval->minutes, interval->seconds,
interval->fseconds, oracleValue, error);
}
int dpiDataBuffer__toOracleIntervalYM(dpiDataBuffer *data, dpiEnv *env,
dpiError *error, void *oracleValue)
{
dpiIntervalYM *interval = &data->asIntervalYM;
return dpiOci__intervalSetYearMonth(env->handle, interval->years,
interval->months, oracleValue, error);
}
int dpiDataBuffer__toOracleNumberFromDouble(dpiDataBuffer *data,
dpiError *error, void *oracleValue)
{
if (isnan(data->asDouble))
return dpiError__set(error, "convert double to Oracle number",
DPI_ERR_NAN);
return dpiOci__numberFromReal(data->asDouble, oracleValue, error);
}
int dpiDataBuffer__toOracleNumberFromInteger(dpiDataBuffer *data,
dpiError *error, void *oracleValue)
{
return dpiOci__numberFromInt(&data->asInt64, sizeof(int64_t),
DPI_OCI_NUMBER_SIGNED, oracleValue, error);
}
int dpiDataBuffer__toOracleNumberFromText(dpiDataBuffer *data, dpiEnv *env,
dpiError *error, void *oracleValue)
{
uint8_t numDigits, digits[DPI_NUMBER_AS_TEXT_CHARS], *source, *target, i;
int isNegative, prependZero, appendSentinel;
dpiBytes *value = &data->asBytes;
int16_t decimalPointIndex;
uint8_t byte, numPairs;
int8_t ociExponent;
if (dpiUtils__parseNumberString(value->ptr, value->length, env->charsetId,
&isNegative, &decimalPointIndex, &numDigits, digits, error) < 0)
return DPI_FAILURE;
prependZero = (decimalPointIndex > 0 && decimalPointIndex % 2 == 1) ||
(decimalPointIndex < 0 && decimalPointIndex % 2 == -1);
if (prependZero && numDigits != 0) {
digits[numDigits++] = 0;
decimalPointIndex++;
}
if (numDigits % 2 == 1)
digits[numDigits++] = 0;
numPairs = numDigits / 2;
appendSentinel = (isNegative && numDigits > 0 &&
numDigits < DPI_NUMBER_MAX_DIGITS);
target = (uint8_t*) oracleValue;
*target++ = (uint8_t) (numPairs + 1 + appendSentinel);
if (numDigits == 0) {
*target = 128;
return DPI_SUCCESS;
}
ociExponent = (int8_t) ((decimalPointIndex - 2) / 2 + 193);
if (isNegative)
ociExponent = ~ociExponent;
*target++ = (uint8_t) ociExponent;
source = digits;
for (i = 0; i < numPairs; i++) {
if (i == 0 && prependZero)
byte = *source++;
else {
byte = *source++ * 10;
byte += *source++;
}
if (isNegative)
byte = 101 - byte;
else byte++;
*target++ = byte;
}
if (appendSentinel)
*target = 102;
return DPI_SUCCESS;
}
int dpiDataBuffer__toOracleNumberFromUnsignedInteger(dpiDataBuffer *data,
dpiError *error, void *oracleValue)
{
return dpiOci__numberFromInt(&data->asUint64, sizeof(uint64_t),
DPI_OCI_NUMBER_UNSIGNED, oracleValue, error);
}
int dpiDataBuffer__toOracleTimestamp(dpiDataBuffer *data, dpiEnv *env,
dpiError *error, void *oracleValue, int withTZ)
{
dpiTimestamp *timestamp = &data->asTimestamp;
char tzOffsetBuffer[10], *tzOffset = NULL;
size_t tzOffsetLength = 0;
char sign;
if (withTZ) {
sign = (timestamp->tzHourOffset < 0 || timestamp->tzMinuteOffset < 0) ?
'-' : '+';
tzOffsetLength = (size_t) sprintf(tzOffsetBuffer, "%c%.2d:%.2d", sign,
abs(timestamp->tzHourOffset), abs(timestamp->tzMinuteOffset));
tzOffset = tzOffsetBuffer;
}
return dpiOci__dateTimeConstruct(env->handle, oracleValue, timestamp->year,
timestamp->month, timestamp->day, timestamp->hour,
timestamp->minute, timestamp->second, timestamp->fsecond, tzOffset,
tzOffsetLength, error);
}
int dpiDataBuffer__toOracleTimestampFromDouble(dpiDataBuffer *data,
uint32_t dataType, dpiEnv *env, dpiError *error, void *oracleValue)
{
int32_t day, hour, minute, second, fsecond;
void *interval, *baseDate;
int status;
double ms;
if (dpiEnv__getBaseDate(env, dataType, &baseDate, error) < 0)
return DPI_FAILURE;
if (dpiOci__descriptorAlloc(env->handle, &interval,
DPI_OCI_DTYPE_INTERVAL_DS, "alloc interval", error) < 0)
return DPI_FAILURE;
ms = data->asDouble;
day = (int32_t) (ms / DPI_MS_DAY);
ms = ms - ((double) day) * DPI_MS_DAY;
hour = (int32_t) (ms / DPI_MS_HOUR);
ms = ms - (hour * DPI_MS_HOUR);
minute = (int32_t) (ms / DPI_MS_MINUTE);
ms = ms - (minute * DPI_MS_MINUTE);
second = (int32_t) (ms / DPI_MS_SECOND);
ms = ms - (second * DPI_MS_SECOND);
fsecond = (int32_t)(ms * DPI_MS_FSECOND);
if (dpiOci__intervalSetDaySecond(env->handle, day, hour, minute, second,
fsecond, interval, error) < 0) {
dpiOci__descriptorFree(interval, DPI_OCI_DTYPE_INTERVAL_DS);
return DPI_FAILURE;
}
status = dpiOci__dateTimeIntervalAdd(env->handle, baseDate, interval,
oracleValue, error);
dpiOci__descriptorFree(interval, DPI_OCI_DTYPE_INTERVAL_DS);
return status;
}
int dpiData_getBool(dpiData *data)
{
return data->value.asBoolean;
}
dpiBytes *dpiData_getBytes(dpiData *data)
{
return &data->value.asBytes;
}
double dpiData_getDouble(dpiData *data)
{
return data->value.asDouble;
}
float dpiData_getFloat(dpiData *data)
{
return data->value.asFloat;
}
int64_t dpiData_getInt64(dpiData *data)
{
return data->value.asInt64;
}
dpiIntervalDS *dpiData_getIntervalDS(dpiData *data)
{
return &data->value.asIntervalDS;
}
dpiIntervalYM *dpiData_getIntervalYM(dpiData *data)
{
return &data->value.asIntervalYM;
}
int dpiData_getIsNull(dpiData *data)
{
return data->isNull;
}
dpiLob *dpiData_getLOB(dpiData *data)
{
return data->value.asLOB;
}
dpiJson *dpiData_getJson(dpiData *data)
{
return data->value.asJson;
}
dpiJsonArray *dpiData_getJsonArray(dpiData *data)
{
return &data->value.asJsonArray;
}
dpiJsonObject *dpiData_getJsonObject(dpiData *data)
{
return &data->value.asJsonObject;
}
dpiObject *dpiData_getObject(dpiData *data)
{
return data->value.asObject;
}
dpiStmt *dpiData_getStmt(dpiData *data)
{
return data->value.asStmt;
}
dpiTimestamp *dpiData_getTimestamp(dpiData *data)
{
return &data->value.asTimestamp;
}
uint64_t dpiData_getUint64(dpiData *data)
{
return data->value.asUint64;
}
dpiVector *dpiData_getVector(dpiData *data)
{
return data->value.asVector;
}
void dpiData_setBool(dpiData *data, int value)
{
data->isNull = 0;
data->value.asBoolean = value;
}
void dpiData_setBytes(dpiData *data, char *ptr, uint32_t length)
{
data->isNull = 0;
data->value.asBytes.ptr = ptr;
data->value.asBytes.length = length;
}
void dpiData_setDouble(dpiData *data, double value)
{
data->isNull = 0;
data->value.asDouble = value;
}
void dpiData_setFloat(dpiData *data, float value)
{
data->isNull = 0;
data->value.asFloat = value;
}
void dpiData_setInt64(dpiData *data, int64_t value)
{
data->isNull = 0;
data->value.asInt64 = value;
}
void dpiData_setIntervalDS(dpiData *data, int32_t days, int32_t hours,
int32_t minutes, int32_t seconds, int32_t fseconds)
{
dpiIntervalDS *interval = &data->value.asIntervalDS;
data->isNull = 0;
interval->days = days;
interval->hours = hours;
interval->minutes = minutes;
interval->seconds = seconds;
interval->fseconds = fseconds;
}
void dpiData_setIntervalYM(dpiData *data, int32_t years, int32_t months)
{
dpiIntervalYM *interval = &data->value.asIntervalYM;
data->isNull = 0;
interval->years = years;
interval->months = months;
}
void dpiData_setLOB(dpiData *data, dpiLob *lob)
{
data->isNull = 0;
data->value.asLOB = lob;
}
void dpiData_setNull(dpiData *data)
{
data->isNull = 1;
}
void dpiData_setObject(dpiData *data, dpiObject *obj)
{
data->isNull = 0;
data->value.asObject = obj;
}
void dpiData_setStmt(dpiData *data, dpiStmt *obj)
{
data->isNull = 0;
data->value.asStmt = obj;
}
void dpiData_setTimestamp(dpiData *data, int16_t year, uint8_t month,
uint8_t day, uint8_t hour, uint8_t minute, uint8_t second,
uint32_t fsecond, int8_t tzHourOffset, int8_t tzMinuteOffset)
{
dpiTimestamp *timestamp = &data->value.asTimestamp;
data->isNull = 0;
timestamp->year = year;
timestamp->month = month;
timestamp->day = day;
timestamp->hour = hour;
timestamp->minute = minute;
timestamp->second = second;
timestamp->fsecond = fsecond;
timestamp->tzHourOffset = tzHourOffset;
timestamp->tzMinuteOffset = tzMinuteOffset;
}
void dpiData_setUint64(dpiData *data, uint64_t value)
{
data->isNull = 0;
data->value.asUint64 = value;
}