nanosecs precision for timestamp/interval datatypes
Project: http://git-wip-us.apache.org/repos/asf/trafodion/repo Commit: http://git-wip-us.apache.org/repos/asf/trafodion/commit/319abf81 Tree: http://git-wip-us.apache.org/repos/asf/trafodion/tree/319abf81 Diff: http://git-wip-us.apache.org/repos/asf/trafodion/diff/319abf81 Branch: refs/heads/master Commit: 319abf81860b6102658f48802172b6ea9aa607a0 Parents: 288ed21 Author: Anoop Sharma <[email protected]> Authored: Mon Jun 11 18:16:21 2018 +0000 Committer: Anoop Sharma <[email protected]> Committed: Mon Jun 11 18:16:21 2018 +0000 ---------------------------------------------------------------------- .../trafodion/jdbc/t4/InterfaceResultSet.java | 7 +- core/sql/bin/SqlciErrors.txt | 3 +- core/sql/cli/Descriptor.cpp | 4 +- core/sql/common/DateTimeType.cpp | 28 +- core/sql/common/DatetimeType.h | 5 +- core/sql/common/IntervalType.cpp | 17 +- core/sql/common/IntervalType.h | 3 +- core/sql/common/NAType.cpp | 2 +- core/sql/exp/ExpConvMxcs.cpp | 2 +- core/sql/exp/ExpErrorEnums.h | 1 + core/sql/exp/exp_arith.cpp | 444 +- core/sql/exp/exp_bignum.h | 17 +- core/sql/exp/exp_conv.cpp | 6 + core/sql/exp/exp_datetime.cpp | 243 +- core/sql/exp/exp_datetime.h | 12 +- core/sql/exp/exp_fixup.cpp | 6 +- core/sql/langman/LmLangManagerJava.cpp | 4 +- core/sql/optimizer/QRDescGenerator.cpp | 15 +- core/sql/parser/StmtDDLMisc.cpp | 10 + core/sql/regress/core/EXPECTED162 | 762 +-- core/sql/regress/core/TEST038 | 2 +- core/sql/regress/executor/EXPECTED022.SB | 6041 ++---------------- core/sql/regress/executor/TEST022 | 1083 ++-- core/sql/regress/hive/EXPECTED001 | 762 +-- core/sql/regress/hive/EXPECTED004 | 28 +- core/sql/regress/hive/EXPECTED005 | 130 +- core/sql/regress/seabase/EXPECTED002 | 250 +- core/sql/regress/udr/EXPECTED100.SB | 26 +- core/sql/regress/udr/TEST100 | 19 +- core/sql/regress/udr/t100.java | 4 + core/sql/sqlci/SqlCmd.cpp | 19 +- .../java/org/trafodion/sql/udr/TypeInfo.java | 18 +- 32 files changed, 2625 insertions(+), 7348 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/trafodion/blob/319abf81/core/conn/jdbcT4/src/main/java/org/trafodion/jdbc/t4/InterfaceResultSet.java ---------------------------------------------------------------------- diff --git a/core/conn/jdbcT4/src/main/java/org/trafodion/jdbc/t4/InterfaceResultSet.java b/core/conn/jdbcT4/src/main/java/org/trafodion/jdbc/t4/InterfaceResultSet.java index 7273338..7232009 100644 --- a/core/conn/jdbcT4/src/main/java/org/trafodion/jdbc/t4/InterfaceResultSet.java +++ b/core/conn/jdbcT4/src/main/java/org/trafodion/jdbc/t4/InterfaceResultSet.java @@ -253,6 +253,7 @@ class InterfaceResultSet { retObj = Date.valueOf(tmpStr); break; case SQLDTCODE_TIMESTAMP: + System.out.println("tmpStr = " + tmpStr); retObj = Timestamp.valueOf(tmpStr); break; case SQLDTCODE_TIME: @@ -448,9 +449,6 @@ class InterfaceResultSet { if (desc.sqlPrecision_ > 0) { nanoSeconds = Bytes.extractUInt(values, noNullValue + 7, swap); - if (nanoSeconds > 999999) // returned in microseconds - nanoSeconds = 0; - // apply leading 0's for string conversion tmpStr = "" + nanoSeconds; length = tmpStr.length(); @@ -489,9 +487,6 @@ class InterfaceResultSet { if (desc.sqlPrecision_ > 0) { nanoSeconds = Bytes.extractUInt(values, noNullValue + 3, swap); - if (nanoSeconds > 999999) // returned in microseconds - nanoSeconds = 0; - String formatStr = ""; for(int i=0;i<desc.sqlPrecision_;i++) formatStr += "0"; http://git-wip-us.apache.org/repos/asf/trafodion/blob/319abf81/core/sql/bin/SqlciErrors.txt ---------------------------------------------------------------------- diff --git a/core/sql/bin/SqlciErrors.txt b/core/sql/bin/SqlciErrors.txt index 23279fb..0053576 100644 --- a/core/sql/bin/SqlciErrors.txt +++ b/core/sql/bin/SqlciErrors.txt @@ -887,7 +887,7 @@ $1~String1 -------------------------------- 3131 0A000 99999 BEGINNER MAJOR DBADMIN The statement just entered is currently not supported. 3132 42000 99999 BEGINNER MAJOR DBADMIN The HEADING for column $0~ColumnName exceeds the maximum size of 128 characters. 3133 42000 99999 BEGINNER MAJOR DBADMIN PERFORM is valid only in COBOL programs. -3134 42000 99999 BEGINNER MAJOR DBADMIN The specified TIME or TIMESTAMP precision value, $0~int0, cannot exceed 6. +3134 42000 99999 BEGINNER MAJOR DBADMIN The specified TIME or TIMESTAMP precision value, $0~int0, cannot exceed 9. 3135 42000 99999 BEGINNER MAJOR DBADMIN The precision of float, $0~int0, cannot exceed 54. 3136 42000 99999 BEGINNER MAJOR DBADMIN Only LEFT, RIGHT, and FULL OUTER JOIN are valid in {oj ...} 3137 0A000 99999 BEGINNER MAJOR DBADMIN UNION JOIN is not yet supported. @@ -1589,6 +1589,7 @@ $1~String1 -------------------------------- 8450 ZZZZZ 99999 BEGINNER MINOR LOGONLY ESP number ($0~Int0) has processed ($1~Int1) transactions of the LRU operation on table $2~String0. 8451 ZZZZZ 99999 BEGINNER MINOR LOGONLY Error $0~String0 returned while retrieving region stats from hbase. 8452 ZZZZZ 99999 BEGINNER MINOR LOGONLY The regular expression is invalid. Cause: $0~String0 +8453 ZZZZZ 99999 BEGINNER MINOR LOGONLY This expression results in an invalid interval value '$0~String0' 8550 ZZZZZ 99999 ADVANCED MAJOR DBADMIN Error $0~NSKCode was returned by the Data Access Manager. 8551 ZZZZZ 99999 ADVANCED MAJOR DBADMIN Error $0~NSKCode was returned by the file system on $0~string0$1~string1. 8552 ZZZZZ 99999 ADVANCED MAJOR DBADMIN Error $0~int0 was returned by the file system while fetching the version of the system $0~string0. http://git-wip-us.apache.org/repos/asf/trafodion/blob/319abf81/core/sql/cli/Descriptor.cpp ---------------------------------------------------------------------- diff --git a/core/sql/cli/Descriptor.cpp b/core/sql/cli/Descriptor.cpp index a1a607f..47110c0 100644 --- a/core/sql/cli/Descriptor.cpp +++ b/core/sql/cli/Descriptor.cpp @@ -1501,7 +1501,7 @@ void Descriptor::DescItemDefaultsForDatetimeCode( case SQLINTCODE_HOUR_SECOND: case SQLINTCODE_DAY_SECOND: // 17.5 - GR 5-j-i - descItem.precision = 6; + descItem.precision = 9; break; default: @@ -1519,7 +1519,7 @@ void Descriptor::DescItemDefaultsForDatetimeCode( case SQLDTCODE_TIMESTAMP: // none with Timezone yet // 17.5 - GR 5-i-i - descItem.precision = 6; + descItem.precision = 9; break; case SQLDTCODE_TIME: http://git-wip-us.apache.org/repos/asf/trafodion/blob/319abf81/core/sql/common/DateTimeType.cpp ---------------------------------------------------------------------- diff --git a/core/sql/common/DateTimeType.cpp b/core/sql/common/DateTimeType.cpp index de67e74..be5a903 100644 --- a/core/sql/common/DateTimeType.cpp +++ b/core/sql/common/DateTimeType.cpp @@ -314,9 +314,13 @@ Int64 DatetimeType::julianTimestampValue(const char * value, const short valueLe { str_cpy_all((char *) &fraction, datetimeOpData, sizeof(fraction)); if (fractionPrec > 0) - // Adjust the fractional seconds part to be the number of microseconds. - fraction *= (Lng32)pow(10, (DatetimeType::MAX_FRACTION_PRECISION - - fractionPrec)); + { + if (fractionPrec > DatetimeType::MAX_FRACTION_PRECISION_MSEC) + // Adjust the fractional seconds part to be the number of microseconds + fraction /= (Lng32)pow(10, (fractionPrec - DatetimeType::MAX_FRACTION_PRECISION_MSEC)); + else + fraction *= (Lng32)pow(10, (DatetimeType::MAX_FRACTION_PRECISION_MSEC - fractionPrec)); + } } short timestamp[] = { year, month, day, hour, minute, second, (short)(fraction / 1000), (short)(fraction % 1000) @@ -584,7 +588,7 @@ const NAType* DatetimeType::synthesizeType(enum NATypeSynthRuleEnum synthRule, (datetime2->supportsSQLnull())) ? TRUE : FALSE); UInt32 fractionPrecision = MAXOF(datetime1->getFractionPrecision(), - datetime2->getFractionPrecision()); + datetime2->getFractionPrecision()); if ((modeSpecial4) && (fractionPrecision == 0) && @@ -597,8 +601,16 @@ const NAType* DatetimeType::synthesizeType(enum NATypeSynthRuleEnum synthRule, } else { - return new(h) SQLInterval(h, allowNulls, datetime1->getEndField(), - 12, datetime1->getEndField(), + Int32 leadingPrecision = IntervalType::computeLeadingPrecision + (datetime1->getEndField(), + SQLInterval::MAX_LEADING_PRECISION, + datetime1->getEndField(), + fractionPrecision); + + return new(h) SQLInterval(h, allowNulls, + datetime1->getEndField(), + leadingPrecision, + datetime1->getEndField(), fractionPrecision); } } @@ -1383,7 +1395,7 @@ DatetimeValue::DatetimeValue ComDiagsArea *diags = NULL; - Lng32 trueFP = 6; + Lng32 trueFP = DatetimeType::MAX_FRACTION_PRECISION; ULng32 flags = 0; flags |= CONV_NO_HADOOP_DATE_FIX; short rc = @@ -1399,7 +1411,7 @@ DatetimeValue::DatetimeValue if (endField == REC_DATE_SECOND) { Lng32 fp = trueFP; - for (; fp < 6; fp++) + for (; fp < DatetimeType::MAX_FRACTION_PRECISION; fp++) { if (startField == REC_DATE_YEAR) *(Lng32*)&dstValue[7] /= 10; http://git-wip-us.apache.org/repos/asf/trafodion/blob/319abf81/core/sql/common/DatetimeType.h ---------------------------------------------------------------------- diff --git a/core/sql/common/DatetimeType.h b/core/sql/common/DatetimeType.h index e948fd5..9aa5373 100644 --- a/core/sql/common/DatetimeType.h +++ b/core/sql/common/DatetimeType.h @@ -69,7 +69,10 @@ class DatetimeType : public DatetimeIntervalCommonType public: enum { DEFAULT_FRACTION_PRECISION = 0 }; // See ANSI 6.1 SR 25: zero - enum { MAX_FRACTION_PRECISION = 6 }; // See ANSI 6.1 SR 26: max is at least 6 + enum { MAX_FRACTION_PRECISION_MSEC = 6 }; // max microseconds fract precision + enum { MAX_FRACTION_PRECISION = 9 }; // See ANSI 6.1 SR 26: max is at least 6. + // Changed to 9 to support nano secs + // fractional precision enum Subtype { SUBTYPE_ILLEGAL, SUBTYPE_SQLDate, http://git-wip-us.apache.org/repos/asf/trafodion/blob/319abf81/core/sql/common/IntervalType.cpp ---------------------------------------------------------------------- diff --git a/core/sql/common/IntervalType.cpp b/core/sql/common/IntervalType.cpp index e10bf08..778505e 100644 --- a/core/sql/common/IntervalType.cpp +++ b/core/sql/common/IntervalType.cpp @@ -251,9 +251,9 @@ UInt32 IntervalType::getPrecision(rec_datetime_field startField, } // IntervalType::getPrecision UInt32 IntervalType::computeLeadingPrecision(rec_datetime_field startField, - UInt32 precision, - rec_datetime_field endField, - UInt32 fractionPrecision) + UInt32 precision, + rec_datetime_field endField, + UInt32 fractionPrecision) { UInt32 leadingPrecision; switch (getIntervalFSDatatype(startField, endField)) { @@ -298,10 +298,13 @@ Lng32 IntervalType::getStorageSize(rec_datetime_field startField, rec_datetime_field endField, UInt32 fractionPrecision) { - Lng32 size = getBinaryStorageSize(getPrecision(startField, - leadingPrecision, - endField, - fractionPrecision)); + Lng32 prec = getPrecision(startField, + leadingPrecision, + endField, + fractionPrecision); + + Lng32 size = getBinaryStorageSize(prec); + // interval datatypes are stored as 2(smallint),4(int) or 8(largeint) bytes. // If size is tinyint size based on precision, change it to smallint size. if (size == SQL_TINY_SIZE) http://git-wip-us.apache.org/repos/asf/trafodion/blob/319abf81/core/sql/common/IntervalType.h ---------------------------------------------------------------------- diff --git a/core/sql/common/IntervalType.h b/core/sql/common/IntervalType.h index 378ff76..3315524 100644 --- a/core/sql/common/IntervalType.h +++ b/core/sql/common/IntervalType.h @@ -325,7 +325,8 @@ public: enum { DEFAULT_LEADING_PRECISION = 2, // ANSI 10.1 SR 5: two MAX_LEADING_PRECISION = MAX_NUMERIC_PRECISION, // 10.1 SR 3: >=2 DEFAULT_FRACTION_PRECISION = 6, // ANSI 10.1 SR 6: six - MAX_FRACTION_PRECISION = 6 // ANSI 10.1 SR 4: >=6 + MAX_FRACTION_PRECISION_MSEC= 6, // ANSI 10.1 SR 4: >=6 + MAX_FRACTION_PRECISION = 9 // ANSI 10.1 SR 4: >=6 }; // --------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/trafodion/blob/319abf81/core/sql/common/NAType.cpp ---------------------------------------------------------------------- diff --git a/core/sql/common/NAType.cpp b/core/sql/common/NAType.cpp index 0271b0c..5845f89 100644 --- a/core/sql/common/NAType.cpp +++ b/core/sql/common/NAType.cpp @@ -997,7 +997,7 @@ NAType* NAType::getNATypeForHive(const char* hiveType, NAMemory* heap) return new (heap) SQLDoublePrecision(heap, TRUE /* allow NULL*/); if ( !strcmp(hiveType, "timestamp")) - return new (heap) SQLTimestamp(heap, TRUE /* allow NULL */ , 6); + return new (heap) SQLTimestamp(heap, TRUE /* allow NULL */ , DatetimeType::MAX_FRACTION_PRECISION); if ( !strcmp(hiveType, "date")) return new (heap) SQLDate(heap, TRUE /* allow NULL */); http://git-wip-us.apache.org/repos/asf/trafodion/blob/319abf81/core/sql/exp/ExpConvMxcs.cpp ---------------------------------------------------------------------- diff --git a/core/sql/exp/ExpConvMxcs.cpp b/core/sql/exp/ExpConvMxcs.cpp index 0f7d3ee..7b9d3fb 100644 --- a/core/sql/exp/ExpConvMxcs.cpp +++ b/core/sql/exp/ExpConvMxcs.cpp @@ -1329,7 +1329,7 @@ static short convAsciiToIntervalMxcs(char *target, } else { - *(UInt32 *)target = (UInt32) interm; + fraction = (UInt32) interm; } }; http://git-wip-us.apache.org/repos/asf/trafodion/blob/319abf81/core/sql/exp/ExpErrorEnums.h ---------------------------------------------------------------------- diff --git a/core/sql/exp/ExpErrorEnums.h b/core/sql/exp/ExpErrorEnums.h index 8227cb8..3b94897 100644 --- a/core/sql/exp/ExpErrorEnums.h +++ b/core/sql/exp/ExpErrorEnums.h @@ -164,6 +164,7 @@ enum ExeErrorCode EXE_ERROR_FROM_LOB_INTERFACE = 8442, EXE_INVALID_LOB_HANDLE = 8443, EXE_ERROR_HDFS_SCAN = 8447, + EXE_INVALID_INTERVAL_RESULT = 8453, EXE_LAST_EXPRESSIONS_ERROR = 8499, // --------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/trafodion/blob/319abf81/core/sql/exp/exp_arith.cpp ---------------------------------------------------------------------- diff --git a/core/sql/exp/exp_arith.cpp b/core/sql/exp/exp_arith.cpp index efe9b92..0e08354 100644 --- a/core/sql/exp/exp_arith.cpp +++ b/core/sql/exp/exp_arith.cpp @@ -48,14 +48,18 @@ #include "exp_ovfl_ptal.h" #include "exp_ieee.h" - -Int64 EXP_FIXED_OV_ADD(Int64 op1, Int64 op2, short * ov) +Int64 EXP_FIXED_ARITH_OV_OPER(short operation, + Int64 op1, Int64 op2, short * ov) { + if (NOT ((operation == ITM_PLUS) || (operation == ITM_MINUS) || + (operation == ITM_TIMES) || (operation == ITM_DIVIDE))) + return -1; // invalid operation + short rc = 0; *ov = 0; - BigNum op1BN(16, 20, 0, 0); - BigNum op2BN(16, 20, 0, 0); + BigNum op1BN(BigNum::BIGNUM_TEMP_LEN, BigNum::BIGNUM_TEMP_PRECISION, 0, 0); + BigNum op2BN(BigNum::BIGNUM_TEMP_LEN, BigNum::BIGNUM_TEMP_PRECISION, 0, 0); char op1BNdata[100]; char op2BNdata[100]; @@ -79,82 +83,46 @@ Int64 EXP_FIXED_OV_ADD(Int64 op1, Int64 op2, short * ov) op1BN.castFrom(&op1ST, op1_data, NULL, NULL); op2BN.castFrom(&op2ST, op2_data, NULL, NULL); - char * add_data[3]; - char addBNdata[100]; - add_data[0] = addBNdata; - add_data[1] = op1BNdata; - add_data[2] = op2BNdata; - - BigNum addBN(16, 20, 0, 0); - - rc = addBN.add(&op1BN, &op2BN, add_data); - if (rc) - { - *ov = 1; - return -1; - } - - SimpleType resultST(REC_BIN64_SIGNED, sizeof(Int64), 0, 0, - ExpTupleDesc::SQLMX_FORMAT, - 8, 0, 0, 0, Attributes::NO_DEFAULT, 0); - - Int64 result; - op1_data[0] = (char*)&result; - op1_data[1] = add_data[0]; + char * oper_data[3]; + char operBNdata[100]; + oper_data[0] = operBNdata; + oper_data[1] = op1BNdata; + oper_data[2] = op2BNdata; - // rc = addBN.castTo(&resultST, op1_data); - rc = convDoIt(op1_data[1], 16, REC_NUM_BIG_SIGNED, 20, 0, - op1_data[0], 8, REC_BIN64_SIGNED, 0, 0, - NULL, 0, NULL, NULL); + BigNum operBN(BigNum::BIGNUM_TEMP_LEN, BigNum::BIGNUM_TEMP_PRECISION, 0, 0); - if (rc) + switch (operation) { - *ov = 1; - return -1; - } - - return result; -} - -Int64 EXP_FIXED_OV_SUB(Int64 op1, Int64 op2, short * ov) -{ - short rc = 0; - *ov = 0; - - BigNum op1BN(16, 20, 0, 0); - BigNum op2BN(16, 20, 0, 0); - - char op1BNdata[100]; - char op2BNdata[100]; - - SimpleType op1ST(REC_BIN64_SIGNED, sizeof(Int64), 0, 0, - ExpTupleDesc::SQLMX_FORMAT, - 8, 0, 0, 0, Attributes::NO_DEFAULT, 0); - SimpleType op2ST(REC_BIN64_SIGNED, sizeof(Int64), 0, 0, - ExpTupleDesc::SQLMX_FORMAT, - 8, 0, 0, 0, Attributes::NO_DEFAULT, 0); - - char * op1_data[2]; - char * op2_data[2]; - - op1_data[0] = op1BNdata; - op1_data[1] = (char*)&op1; + case ITM_PLUS: + { + rc = operBN.add(&op1BN, &op2BN, oper_data); + } + break; - op2_data[0] = op2BNdata; - op2_data[1] = (char*)&op2; + case ITM_MINUS: + { + rc = operBN.sub(&op1BN, &op2BN, oper_data); + } + break; - op1BN.castFrom(&op1ST, op1_data, NULL, NULL); - op2BN.castFrom(&op2ST, op2_data, NULL, NULL); + case ITM_TIMES: + { + rc = operBN.mul(&op1BN, &op2BN, oper_data); + } + break; - char * sub_data[3]; - char subBNdata[100]; - sub_data[0] = subBNdata; - sub_data[1] = op1BNdata; - sub_data[2] = op2BNdata; + case ITM_DIVIDE: + { + char tempSpace[200]; + operBN.setTempSpaceInfo(ITM_DIVIDE, (ULong)tempSpace, 200); + rc = operBN.div(&op1BN, &op2BN, oper_data, NULL, NULL); + } + break; - BigNum subBN(16, 20, 0, 0); + default: + return -1; + } // switch - rc = subBN.sub(&op1BN, &op2BN, sub_data); if (rc) { *ov = 1; @@ -163,15 +131,15 @@ Int64 EXP_FIXED_OV_SUB(Int64 op1, Int64 op2, short * ov) SimpleType resultST(REC_BIN64_SIGNED, sizeof(Int64), 0, 0, ExpTupleDesc::SQLMX_FORMAT, - 8, 0, 0, 0, Attributes::NO_DEFAULT, 0); + sizeof(Int64), 0, 0, 0, Attributes::NO_DEFAULT, 0); Int64 result; op1_data[0] = (char*)&result; - op1_data[1] = sub_data[0]; + op1_data[1] = oper_data[0]; - // rc = subBN.castTo(&resultST, op1_data); - rc = convDoIt(op1_data[1], 16, REC_NUM_BIG_SIGNED, 20, 0, - op1_data[0], 8, REC_BIN64_SIGNED, 0, 0, + rc = convDoIt(op1_data[1], BigNum::BIGNUM_TEMP_LEN, REC_NUM_BIG_SIGNED, + BigNum::BIGNUM_TEMP_PRECISION, 0, + op1_data[0], sizeof(Int64), REC_BIN64_SIGNED, 0, 0, NULL, 0, NULL, NULL); if (rc) { @@ -182,159 +150,48 @@ Int64 EXP_FIXED_OV_SUB(Int64 op1, Int64 op2, short * ov) return result; } -Int64 EXP_FIXED_OV_MUL(Int64 op1, Int64 op2, short * ov) +Int64 EXP_FIXED_OV_ADD(Int64 op1,Int64 op2, short * ov) { - short rc = 0; - *ov = 0; - - BigNum op1BN(16, 38, 0, 0); - BigNum op2BN(16, 38, 0, 0); - - char op1BNdata[100]; - char op2BNdata[100]; - - SimpleType op1ST(REC_BIN64_SIGNED, sizeof(Int64), 0, 0, - ExpTupleDesc::SQLMX_FORMAT, - 8, 0, 0, 0, Attributes::NO_DEFAULT, 0); - SimpleType op2ST(REC_BIN64_SIGNED, sizeof(Int64), 0, 0, - ExpTupleDesc::SQLMX_FORMAT, - 8, 0, 0, 0, Attributes::NO_DEFAULT, 0); - - char * op1_data[2]; - char * op2_data[2]; - - op1_data[0] = op1BNdata; - op1_data[1] = (char*)&op1; - - op2_data[0] = op2BNdata; - op2_data[1] = (char*)&op2; - - op1BN.castFrom(&op1ST, op1_data, NULL, NULL); - op2BN.castFrom(&op2ST, op2_data, NULL, NULL); - - char * mul_data[3]; - char mulBNdata[100]; - mul_data[0] = mulBNdata; - mul_data[1] = op1BNdata; - mul_data[2] = op2BNdata; - - BigNum mulBN(16, 38, 0, 0); - - rc = mulBN.mul(&op1BN, &op2BN, mul_data); - if (rc) - { - *ov = 1; - return -1; - } - - SimpleType resultST(REC_BIN64_SIGNED, sizeof(Int64), 0, 0, - ExpTupleDesc::SQLMX_FORMAT, - 8, 0, 0, 0, Attributes::NO_DEFAULT, 0); - - Int64 result; - op1_data[0] = (char*)&result; - op1_data[1] = mul_data[0]; - - // rc = mulBN.castTo(&resultST, op1_data); - rc = convDoIt(op1_data[1], 16, REC_NUM_BIG_SIGNED, 38, 0, - op1_data[0], 8, REC_BIN64_SIGNED, 0, 0, - NULL, 0, NULL, NULL); - if (rc) - { - *ov = 1; - return -1; - } - - return result; + return EXP_FIXED_ARITH_OV_OPER(ITM_PLUS, op1, op2, ov); } -Int64 EXP_FIXED_OV_DIV(Int64 op1, Int64 op2, short * ov) +Int64 EXP_FIXED_OV_SUB(Int64 op1,Int64 op2, short * ov) { - short rc = 0; - *ov = 0; - - BigNum op1BN(16, 38, 0, 0); - BigNum op2BN(16, 38, 0, 0); - - char op1BNdata[100]; - char op2BNdata[100]; - - SimpleType op1ST(REC_BIN64_SIGNED, sizeof(Int64), 0, 0, - ExpTupleDesc::SQLMX_FORMAT, - 8, 0, 0, 0, Attributes::NO_DEFAULT, 0); - SimpleType op2ST(REC_BIN64_SIGNED, sizeof(Int64), 0, 0, - ExpTupleDesc::SQLMX_FORMAT, - 8, 0, 0, 0, Attributes::NO_DEFAULT, 0); - - char * op1_data[2]; - char * op2_data[2]; - - op1_data[0] = op1BNdata; - op1_data[1] = (char*)&op1; - - op2_data[0] = op2BNdata; - op2_data[1] = (char*)&op2; - - op1BN.castFrom(&op1ST, op1_data, NULL, NULL); - op2BN.castFrom(&op2ST, op2_data, NULL, NULL); - - char * div_data[3]; - char divBNdata[100]; - div_data[0] = divBNdata; - div_data[1] = op1BNdata; - div_data[2] = op2BNdata; - - BigNum divBN(16, 38, 0, 0); - char tempSpace[200]; - divBN.setTempSpaceInfo(ITM_DIVIDE, (ULong)tempSpace, 200); - rc = divBN.div(&op1BN, &op2BN, div_data, NULL, NULL); - if (rc) - { - *ov = 1; - return -1; - } - - SimpleType resultST(REC_BIN64_SIGNED, sizeof(Int64), 0, 0, - ExpTupleDesc::SQLMX_FORMAT, - 8, 0, 0, 0, Attributes::NO_DEFAULT, 0); - - Int64 result; - op1_data[0] = (char*)&result; - op1_data[1] = div_data[0]; - - //rc = divBN.castTo(&resultST, op1_data); - rc = convDoIt(op1_data[1], 16, REC_NUM_BIG_SIGNED, 38, 0, - op1_data[0], 8, REC_BIN64_SIGNED, 0, 0, - NULL, 0, NULL, NULL); - if (rc) - { - *ov = 1; - return -1; - } + return EXP_FIXED_ARITH_OV_OPER(ITM_MINUS, op1, op2, ov); +} - return result; +Int64 EXP_FIXED_OV_MUL(Int64 op1,Int64 op2, short * ov) +{ + return EXP_FIXED_ARITH_OV_OPER(ITM_TIMES, op1, op2, ov); } -//Int64 EXP_FIXED_OV_SUB(Int64 op1, Int64 op2, short * ov); -//Int64 EXP_FIXED_OV_MUL(Int64 op1, Int64 op2, short * ov); -//Int64 EXP_FIXED_OV_DIV(Int64 op1, Int64 op2, short * ov); +Int64 EXP_FIXED_OV_DIV(Int64 op1,Int64 op2, short * ov) +{ + return EXP_FIXED_ARITH_OV_OPER(ITM_DIVIDE, op1, op2, ov); +} -short EXP_FIXED_BIGN_OV_MUL(Attributes * op1, - Attributes * op2, - char * op_data[]) +/////////////////////////////////////////////////////////////// +short EXP_BIGN_ARITH_OPER(short operation, + Attributes * op1, + Attributes * op2, + char * op_data[]) { + if (NOT ((operation == ITM_PLUS) || (operation == ITM_MINUS) || + (operation == ITM_TIMES) || (operation == ITM_DIVIDE))) + return -1; // invalid operation + short rc = 0; - BigNum op1BN(16, 38, 0, 0); - BigNum op2BN(16, 38, 0, 0); + BigNum op1BN(BigNum::BIGNUM_TEMP_LEN, BigNum::BIGNUM_TEMP_PRECISION, 0, 0); + BigNum op2BN(BigNum::BIGNUM_TEMP_LEN, BigNum::BIGNUM_TEMP_PRECISION, 0, 0); char op1BNdata[100]; char op2BNdata[100]; - char * mul_data[3]; + char * oper_data[3]; //initialize result place holder. - mul_data[0] = op_data[0]; + oper_data[0] = op_data[0]; //convert op1 & op2 to bignum if not already bignum if(op1->isSimpleType()) @@ -345,10 +202,10 @@ short EXP_FIXED_BIGN_OV_MUL(Attributes * op1, rc = op1BN.castFrom(op1, op1_data, NULL, NULL); if(rc) return -1; - mul_data[1] = op1BNdata; + oper_data[1] = op1BNdata; } else - mul_data[1] = op_data[1]; + oper_data[1] = op_data[1]; if(op2->isSimpleType()) { @@ -358,84 +215,91 @@ short EXP_FIXED_BIGN_OV_MUL(Attributes * op1, rc = op2BN.castFrom(op2, op2_data, NULL, NULL); if(rc) return -1; - mul_data[2] = op2BNdata; + oper_data[2] = op2BNdata; } else - mul_data[2] = op_data[2]; + oper_data[2] = op_data[2]; - BigNum mulBN(16, 38, 0, 0); + BigNum operBN(BigNum::BIGNUM_TEMP_LEN, BigNum::BIGNUM_TEMP_PRECISION, 0, 0); - rc = mulBN.mul(&op1BN, &op2BN, mul_data); - if (rc) - return -1; - - return 0; -} - -short EXP_FIXED_BIGN_OV_DIV(Attributes * op1, - Attributes * op2, - char * op_data[]) -{ - short rc = 0; - - BigNum op1BN(16, 38, 0, 0); - BigNum op2BN(16, 38, 0, 0); + switch (operation) + { + case ITM_PLUS: + { + rc = operBN.add(&op1BN, &op2BN, oper_data); + } + break; - char op1BNdata[100]; - char op2BNdata[100]; + case ITM_MINUS: + { + rc = operBN.sub(&op1BN, &op2BN, oper_data); + } + break; - char * div_data[3]; + case ITM_TIMES: + { + rc = operBN.mul(&op1BN, &op2BN, oper_data); + } + break; - //initialize result place holder. - div_data[0] = op_data[0]; + case ITM_DIVIDE: + { + char tempSpace[200]; + operBN.setTempSpaceInfo(ITM_DIVIDE, (ULong)tempSpace, 200); - //convert op1 & op2 to bignum if not already bignum - if(op1->isSimpleType()) - { - char * op1_data[2]; - op1_data[0] = op1BNdata; - op1_data[1] = op_data[1]; - rc = op1BN.castFrom(op1, op1_data, NULL, NULL); - if(rc) - return -1; - div_data[1] = op1BNdata; - } - else - div_data[1] = op_data[1]; + rc = operBN.div(&op1BN, &op2BN, oper_data, NULL, NULL); + } + break; - if(op2->isSimpleType()) - { - char * op2_data[2]; - op2_data[0] = op2BNdata; - op2_data[1] = op_data[2]; - rc = op2BN.castFrom(op2, op2_data, NULL, NULL); - if(rc) + default: return -1; - div_data[2] = op2BNdata; - } - else - div_data[2] = op_data[2]; + } - BigNum divBN(16, 38, 0, 0); - char tempSpace[200]; - divBN.setTempSpaceInfo(ITM_DIVIDE, (ULong)tempSpace, 200); - rc = divBN.div(&op1BN, &op2BN, div_data, NULL, NULL); if (rc) return -1; return 0; } +short EXP_FIXED_BIGN_OV_ADD(Attributes * op1, + Attributes * op2, + char * op_data[]) +{ + return EXP_BIGN_ARITH_OPER(ITM_PLUS, op1, op2, op_data); +} + +short EXP_FIXED_BIGN_OV_SUB(Attributes * op1, + Attributes * op2, + char * op_data[]) +{ + return EXP_BIGN_ARITH_OPER(ITM_MINUS, op1, op2, op_data); +} + +short EXP_FIXED_BIGN_OV_MUL(Attributes * op1, + Attributes * op2, + char * op_data[]) +{ + return EXP_BIGN_ARITH_OPER(ITM_TIMES, op1, op2, op_data); +} + +short EXP_FIXED_BIGN_OV_DIV(Attributes * op1, + Attributes * op2, + char * op_data[]) +{ + return EXP_BIGN_ARITH_OPER(ITM_DIVIDE, op1, op2, op_data); +} + Int64 EXP_FIXED_BIGN_OV_MOD(Attributes * op1, - Attributes * op2, - char * op_data[], - short * ov) + Attributes * op2, + char * op_data[], + short * ov, + Int64 * quotient) { short rc = 0; *ov = 0; - BigNum op1BN(16, 38, 0, 0); - BigNum op2BN(16, 38, 0, 0); + BigNum op1BN(BigNum::BIGNUM_TEMP_LEN, BigNum::BIGNUM_TEMP_PRECISION, 0, 0); + BigNum op2BN(BigNum::BIGNUM_TEMP_LEN, BigNum::BIGNUM_TEMP_PRECISION, 0, 0); char op1BNdata[100]; char op2BNdata[100]; @@ -479,7 +343,7 @@ Int64 EXP_FIXED_BIGN_OV_MOD(Attributes * op1, //using basic operators: //z=MOD(x,y) then z = x - ((x/y)*(y)) - BigNum modBN(16, 38, 0, 0); + BigNum modBN(BigNum::BIGNUM_TEMP_LEN, BigNum::BIGNUM_TEMP_PRECISION, 0, 0); char * temp_data[3]; //calculate (x/y) @@ -496,6 +360,26 @@ Int64 EXP_FIXED_BIGN_OV_MOD(Attributes * op1, return -1; } + SimpleType resultST(REC_BIN64_SIGNED, sizeof(Int64), 0, 0, + ExpTupleDesc::SQLMX_FORMAT, + 8, 0, 0, 0, Attributes::NO_DEFAULT, 0); + + // if quotient(x/y) is to be returned, return it + if (quotient) + { + temp_data[0] = (char*)quotient; + temp_data[1] = xByY; //mod_data[0]; + + rc = convDoIt(temp_data[1], BigNum::BIGNUM_TEMP_LEN, REC_NUM_BIG_SIGNED, BigNum::BIGNUM_TEMP_PRECISION, 0, + temp_data[0], 8, REC_BIN64_SIGNED, 0, 0, + NULL, 0, NULL, NULL); + if (rc) + { + *ov = 1; + return -1; + } + } + //calculate (x/y) * y char xByYTimesY[100]; temp_data[0] = xByYTimesY; @@ -521,16 +405,12 @@ Int64 EXP_FIXED_BIGN_OV_MOD(Attributes * op1, return -1; } - SimpleType resultST(REC_BIN64_SIGNED, sizeof(Int64), 0, 0, - ExpTupleDesc::SQLMX_FORMAT, - 8, 0, 0, 0, Attributes::NO_DEFAULT, 0); - Int64 result; temp_data[0] = (char*)&result; temp_data[1] = mod_data[0]; //rc = divBN.castTo(&resultST, op1_data); - rc = convDoIt(temp_data[1], 16, REC_NUM_BIG_SIGNED, 38, 0, + rc = convDoIt(temp_data[1], BigNum::BIGNUM_TEMP_LEN, REC_NUM_BIG_SIGNED, BigNum::BIGNUM_TEMP_PRECISION, 0, temp_data[0], 8, REC_BIN64_SIGNED, 0, 0, NULL, 0, NULL, NULL); if (rc) @@ -1124,7 +1004,7 @@ ex_expr::exp_return_type ex_arith_clause::eval(char *op_data[], ExpTupleDesc::SQLMX_FORMAT, 8, 0, 0, 0, Attributes::NO_DEFAULT, 0); - BigNum opBN(16, 38, 0, 0); + BigNum opBN(BigNum::BIGNUM_TEMP_LEN, BigNum::BIGNUM_TEMP_PRECISION, 0, 0); while(!vGT5) { @@ -1132,8 +1012,8 @@ ex_expr::exp_return_type ex_arith_clause::eval(char *op_data[], op_data[1] = (char *) ÷nd; op_data[2] = (char *) &multiplier; rc = EXP_FIXED_BIGN_OV_MUL(&opST, - &opST, - op_data); + &opST, + op_data); if (rc) { //end of digits. @@ -1144,8 +1024,8 @@ ex_expr::exp_return_type ex_arith_clause::eval(char *op_data[], op_data[1] = result1; op_data[2] = (char *) &divisor; rc = EXP_FIXED_BIGN_OV_DIV(&opBN, - &opST, - op_data); + &opST, + op_data); if (rc) { //Something went wrong, lets consider http://git-wip-us.apache.org/repos/asf/trafodion/blob/319abf81/core/sql/exp/exp_bignum.h ---------------------------------------------------------------------- diff --git a/core/sql/exp/exp_bignum.h b/core/sql/exp/exp_bignum.h index 5ae29e0..2f228c9 100644 --- a/core/sql/exp/exp_bignum.h +++ b/core/sql/exp/exp_bignum.h @@ -65,6 +65,11 @@ class BigNum : public ComplexType { ULong tempSpacePtr_; // 24-31 //Put on 8-byte boundary public: + // some internal computation use bignum as temp storage. + // Use 38 digit precision and 16 bytes length for them. + enum {BIGNUM_TEMP_LEN = 16 }; + enum {BIGNUM_TEMP_PRECISION = 38 }; + BigNum(Lng32 length, Lng32 precision, short scale, short unSigned); BigNum(); @@ -181,10 +186,18 @@ short EXP_FIXED_BIGN_OV_DIV(Attributes * op1, char * op_data[]); Int64 EXP_FIXED_BIGN_OV_MOD(Attributes * op1, + Attributes * op2, + char * op_data[], + short * ov, + Int64 * quotient = NULL); + +short EXP_FIXED_BIGN_OV_ADD(Attributes * op1, Attributes * op2, - char * op_data[], - short * ov); + char * op_data[]); +short EXP_FIXED_BIGN_OV_SUB(Attributes * op1, + Attributes * op2, + char * op_data[]); http://git-wip-us.apache.org/repos/asf/trafodion/blob/319abf81/core/sql/exp/exp_conv.cpp ---------------------------------------------------------------------- diff --git a/core/sql/exp/exp_conv.cpp b/core/sql/exp/exp_conv.cpp index 41b0a67..f4265b7 100644 --- a/core/sql/exp/exp_conv.cpp +++ b/core/sql/exp/exp_conv.cpp @@ -11493,6 +11493,12 @@ ex_expr::exp_return_type ex_conv_clause::eval(char *op_data[], //move null to target if(tgt->getNullFlag()) { + // clear diags area since this error is not being returned + if (diagsArea && *diagsArea && ((*diagsArea)->getNumber(DgSqlCode::ERROR_) > 0)) + { + (*diagsArea)->clear(); + } + ExpTupleDesc::setNullValue( op_data[-2*MAX_OPERANDS], tgt->getNullBitIndex(), tgt->getTupleFormat() ); http://git-wip-us.apache.org/repos/asf/trafodion/blob/319abf81/core/sql/exp/exp_datetime.cpp ---------------------------------------------------------------------- diff --git a/core/sql/exp/exp_datetime.cpp b/core/sql/exp/exp_datetime.cpp index 3a899e7..af4ec03 100644 --- a/core/sql/exp/exp_datetime.cpp +++ b/core/sql/exp/exp_datetime.cpp @@ -45,7 +45,7 @@ #include "exp_interval.h" #include "exp_clause_derived.h" #include "NAAssert.h" - +#include "exp_bignum.h" #undef DllImport @@ -325,6 +325,9 @@ short ExpDatetime::getDatetimeFields(Lng32 datetimeCode, return 0; } +static const Lng32 powersOfTen[] = {1, 10 ,100, 1000, 10000, 100000, 1000000, + 10000000, 100000000, 1000000000}; + void ExpDatetime::convertDatetimeToInterval ( rec_datetime_field datetimeStartField , rec_datetime_field datetimeEndField @@ -332,8 +335,14 @@ void ExpDatetime::convertDatetimeToInterval , rec_datetime_field intervalEndField , char *datetimeOpData , Int64 &interval +, char * intervalBignum +, NABoolean &isBignum ) const { + short rc = 0; + + isBignum = FALSE; + interval = 0; short year; char month; @@ -375,18 +384,58 @@ void ExpDatetime::convertDatetimeToInterval break; case REC_DATE_SECOND: interval *= 60; + if (field <= datetimeEndField) { char second; str_cpy_all((char *) &second, datetimeOpData, sizeof(second)); datetimeOpData += sizeof(second); interval = interval + second; if (fractionPrecision > 0) { - do { - interval *= 10; - } while (--fractionPrecision > 0); Lng32 fraction; + Int64 fraction64; + str_cpy_all((char *) &fraction, datetimeOpData, sizeof(fraction)); - interval = interval + fraction; + + Int64 multiplicator = powersOfTen[fractionPrecision]; + if (fractionPrecision <= MAX_DATETIME_MICROS_FRACT_PREC) + { + interval *= multiplicator; + interval = interval + fraction; + } + else + { + // Int64 may run into an overflow if fract precision is > 6 + // Use bignum computation to do: + // interval = interval * multiplicator + // interval = interval + fraction + SimpleType op1ST(REC_BIN64_SIGNED, sizeof(Int64), 0, 0, + ExpTupleDesc::SQLMX_FORMAT, + 8, 0, 0, 0, Attributes::NO_DEFAULT, 0); + + char *op_data[3]; + char mulBignum[BigNum::BIGNUM_TEMP_LEN]; // 16 bytes bignum result length + + op_data[0] = mulBignum; // result + op_data[1] = (char*) &interval; + op_data[2] = (char*) &multiplicator; + rc = EXP_FIXED_BIGN_OV_MUL(&op1ST, &op1ST, op_data); + + BigNum op1BN(BigNum::BIGNUM_TEMP_LEN, BigNum::BIGNUM_TEMP_PRECISION, 0, 0); + + char addBignum[BigNum::BIGNUM_TEMP_LEN]; + fraction64 = fraction; + + op_data[0] = addBignum; + op_data[1] = mulBignum; + op_data[2] = (char*)&fraction64; + rc = EXP_FIXED_BIGN_OV_ADD(&op1BN, &op1ST, op_data); + + if (intervalBignum) + { + str_cpy_all(intervalBignum, addBignum, BigNum::BIGNUM_TEMP_LEN); + isBignum = TRUE; + } + } } } break; @@ -450,11 +499,14 @@ short ExpDatetime::getYearMonthDay(Int64 totalDays, } short ExpDatetime::convertIntervalToDatetime(Int64 interval, + char * intervalBignum, rec_datetime_field startField, rec_datetime_field endField, short fractionPrecision, char *datetimeOpData) const { + short rc = 0; + short year; char month; char day; @@ -467,22 +519,44 @@ short ExpDatetime::convertIntervalToDatetime(Int64 interval, switch (field) { case REC_DATE_SECOND: if (fractionPrecision > 0) { - Lng32 divisor = 1; - short fp = fractionPrecision; - do { - divisor *= 10; - } while (--fp > 0); - Int64 dividend = interval; - interval = dividend / (Int64) divisor; - dividend -= interval * (Int64) divisor; - // - // Underflow is allowed for time types, so wrap around if necessary. - // - if (dividend < 0) { - dividend += divisor; - interval -= 1; - } - fraction = int64ToInt32(dividend); + + //Int64 multiplicator = powersOfTen[fractionPrecision]; + Int64 divisor = powersOfTen[fractionPrecision]; + Int64 dividend = 0; + if (fractionPrecision <= MAX_DATETIME_MICROS_FRACT_PREC) + { + Int64 dividend = interval; + interval = dividend / divisor; + dividend = dividend - (interval * divisor); + // + // Underflow is allowed for time types, so wrap around if necessary. + // + if (dividend < 0) { + dividend += divisor; + interval -= 1; + } + fraction = int64ToInt32(dividend); + } + else + { + SimpleType opST(REC_BIN64_SIGNED, sizeof(Int64), 0, 0, + ExpTupleDesc::SQLMX_FORMAT, + 8, 0, 0, 0, Attributes::NO_DEFAULT, 0); + BigNum opBN(BigNum::BIGNUM_TEMP_LEN, BigNum::BIGNUM_TEMP_PRECISION, 0, 0); + + char *op_data[2]; + + op_data[0] = intervalBignum; + op_data[1] = (char*) &divisor; + Int64 quotient = -1; + short ov; + dividend = + EXP_FIXED_BIGN_OV_MOD(&opBN, &opST, op_data, &ov, "ient); + interval = quotient; + + fraction = int64ToInt32(dividend); + } + } // // Underflow is allowed for time types, so wrap around if necessary. @@ -935,6 +1009,7 @@ ExpDatetime::arithDatetimeInterval(arithOps operation, CollHeap *heap, ComDiagsArea** diagsArea) { + short rc = 0; if (operation != DATETIME_ADD && operation != DATETIME_SUB) { @@ -1016,33 +1091,39 @@ ExpDatetime::arithDatetimeInterval(arithOps operation, // (endField) as the Interval operand. We want to make sure we // add/subtract MONTHs to MONTHs, etc. // - Int64 value; + Int64 value = -1; + char intervalBignum[BigNum::BIGNUM_TEMP_LEN]; + char resultBignum[BigNum::BIGNUM_TEMP_LEN]; + NABoolean isBignum = FALSE; convertDatetimeToInterval(datetimeStartField, datetimeEndField, datetimeOpType->getScale(), intervalEndField, dateTimeValue, - value); + value, + intervalBignum, + isBignum); // Perform the arithmetic operation. // + Int64 interval64 = 0; switch (intervalOpType->getLength()) { case SQL_SMALL_SIZE: { short interval; str_cpy_all((char *) &interval, intervalOpData, sizeof(interval)); - value += ((operation == DATETIME_ADD) ? interval : -interval); + interval64 = interval; break; } case SQL_INT_SIZE: { Lng32 interval; str_cpy_all((char *) &interval, intervalOpData, sizeof(interval)); - value += ((operation == DATETIME_ADD) ? interval : -interval); + interval64 = interval; break; } case SQL_LARGE_SIZE: { Int64 interval; str_cpy_all((char *) &interval, intervalOpData, sizeof(interval)); - value += ((operation == DATETIME_ADD) ? interval : -interval); + interval64 = interval; break; } default: @@ -1050,20 +1131,43 @@ ExpDatetime::arithDatetimeInterval(arithOps operation, return -1; } + if (NOT isBignum) { // result is not a bignum + value += ((operation == DATETIME_ADD) ? interval64 : -interval64); + } else { + // result is a bignum + char *op_data[3]; + + BigNum op1BN(BigNum::BIGNUM_TEMP_LEN, BigNum::BIGNUM_TEMP_PRECISION, 0, 0); + SimpleType intST(REC_BIN64_SIGNED, sizeof(Int64), 0, 0, + ExpTupleDesc::SQLMX_FORMAT, + 8, 0, 0, 0, Attributes::NO_DEFAULT, 0); + + op_data[0] = resultBignum; + op_data[1] = intervalBignum; + op_data[2] = (char*)&interval64; + + if (operation == DATETIME_ADD) { + rc = EXP_FIXED_BIGN_OV_ADD(&op1BN, &intST, op_data); + } else { + rc = EXP_FIXED_BIGN_OV_SUB(&op1BN, &intST, op_data); + } + } + // Underflow is ok for time only datetime types. Arithmetic on the // hour field is computed modulo 24. For datetime types containing // a date portion, underflow is an error. // - if ((value < 0) && (datetimeStartField < REC_DATE_HOUR)) { + if ((NOT isBignum) && (value < 0) && + (datetimeStartField < REC_DATE_HOUR)) { ExRaiseSqlError(heap, diagsArea, EXE_DATETIME_FIELD_OVERFLOW); return -1; } - // Convert result back to datetime. Note that this is overlaying the // local copy of the datetime value. // if (convertIntervalToDatetime(value, + (isBignum ? resultBignum : NULL), datetimeStartField, intervalEndField, datetimeOpType->getScale(), @@ -1115,6 +1219,8 @@ short ExpDatetime::subDatetimeDatetime(Attributes *datetimeOpType, CollHeap *heap, ComDiagsArea** diagsArea) const { + short rc = 0; + rec_datetime_field datetimeStartField; rec_datetime_field datetimeEndField; if (getDatetimeFields(datetimeOpType->getPrecision(), @@ -1146,20 +1252,81 @@ short ExpDatetime::subDatetimeDatetime(Attributes *datetimeOpType, } Int64 value1; + char intervalBignum1[BigNum::BIGNUM_TEMP_LEN]; + NABoolean isBignum1 = FALSE; + NABoolean isBignum2 = FALSE; convertDatetimeToInterval(datetimeStartField, datetimeEndField, datetimeOpType->getScale(), intervalEndField, datetimeOpData1, - value1); + value1, + intervalBignum1, + isBignum1); + Int64 value2; + char intervalBignum2[BigNum::BIGNUM_TEMP_LEN]; convertDatetimeToInterval(datetimeStartField, datetimeEndField, datetimeOpType->getScale(), intervalEndField, datetimeOpData2, - value2); - Int64 result = value1 - value2; + value2, + intervalBignum2, + isBignum2); + + Int64 result = 0; + + if ((NOT isBignum1) && (NOT isBignum2)) // neither is bignum + result = value1 - value2; + else + { + BigNum opBN(BigNum::BIGNUM_TEMP_LEN, BigNum::BIGNUM_TEMP_PRECISION, 0, 0); + SimpleType opST(REC_BIN64_SIGNED, sizeof(Int64), 0, 0, + ExpTupleDesc::SQLMX_FORMAT, + 8, 0, 0, 0, Attributes::NO_DEFAULT, 0); + + char *op_data[3]; + + char resultBN[BigNum::BIGNUM_TEMP_LEN]; + op_data[0] = resultBN; + op_data[1] = (isBignum1 ? intervalBignum1 : (char*)&value1); + op_data[2] = (isBignum2 ? intervalBignum2 : (char*)&value2); + + rc = EXP_FIXED_BIGN_OV_SUB((isBignum1 ? (Attributes*)&opBN : (Attributes*)&opST), + (isBignum2 ? (Attributes*)&opBN : (Attributes*)&opST), + op_data); + if (rc) + { + ExRaiseSqlError(heap, diagsArea, EXE_INTERNAL_ERROR); + return -1; + } + + rc = convDoIt(op_data[0], BigNum::BIGNUM_TEMP_LEN, REC_NUM_BIG_SIGNED, BigNum::BIGNUM_TEMP_PRECISION, 0, + (char*)&result, 8, REC_BIN64_SIGNED, 0, 0, + NULL, 0, NULL, NULL); + if (rc) + { + // convert interval value to ascii format + char invalidVal[BigNum::BIGNUM_TEMP_PRECISION+1]; + Int32 len = BigNum::BIGNUM_TEMP_PRECISION; + memset(invalidVal, ' ', len); + convDoIt(op_data[0], BigNum::BIGNUM_TEMP_LEN, REC_NUM_BIG_SIGNED, BigNum::BIGNUM_TEMP_PRECISION, 0, + invalidVal, BigNum::BIGNUM_TEMP_PRECISION, REC_BYTE_F_ASCII, 0, 0, + NULL, 0, NULL, NULL); + len--; + while (invalidVal[len] == ' ') + len--; + len++; + invalidVal[len] = 0; + + ExRaiseSqlError(heap, diagsArea, EXE_INVALID_INTERVAL_RESULT, + NULL, NULL, NULL, NULL, + invalidVal); + return -1; + } + } + // // Scale the result to the interval qualifier's fractional precision. // @@ -1222,8 +1389,6 @@ scaleFraction(Int32 srcFractPrec, Lng32 fraction = 0; - static const Lng32 powersOfTen[] = {1, 10 ,100, 1000, 10000, 100000, 1000000}; - // If there is a fraction value in the destination and there is a // fraction value in the source, scale the fraction to the // destination precision. @@ -1546,7 +1711,6 @@ ExpDatetime::convDatetimeDatetime(char *srcData, return -1; } - // Skip over source fields that are not in the destination. // srcData += sizeofDatetimeFields(srcStartField, @@ -1841,9 +2005,9 @@ scanField(char *&src, // The maximum lengths of the various fields. Since the value of // REC_DATE_YEAR is 1, the first entry is just a place holder. // - static const Lng32 maxLens[] = { 0, 4, 2, 2, 2, 2, 2, 6 }; - static const Lng32 minValue[] = { 0, 0001, 01, 01, 00, 00, 00, 000000 }; - static const Lng32 maxValue[] = { 0, 9999, 12, 31, 23, 59, 59, 999999 }; + static const Lng32 maxLens[] = { 0, 4, 2, 2, 2, 2, 2, 9 }; + static const Lng32 minValue[] = { 0, 0001, 01, 01, 00, 00, 00, 000000000 }; + static const Lng32 maxValue[] = { 0, 9999, 12, 31, 23, 59, 59, 999999999 }; // The length of the scanned field. // @@ -2290,9 +2454,10 @@ ExpDatetime::convAsciiToDatetime(char *srcData, // timezone specified. Compute the new datetime value. // first, convert current datetime value to juliantimestamp + Lng32 jtsFraction = fraction / 1000; short timestamp[] = { year, month, day, hour, minute, second, - (short)(fraction / 1000), (short)(fraction % 1000) + (short)(jtsFraction / 1000), (short)(jtsFraction % 1000) }; short error; @@ -2340,7 +2505,7 @@ ExpDatetime::convAsciiToDatetime(char *srcData, second = (char) timestamp[5]; *dst++ = second; if (scale) { - fraction = timestamp[6] * 1000 + timestamp[7]; + //fraction = timestamp[6] * 1000 + timestamp[7]; str_cpy_all(dst, (char *)&fraction, sizeof(fraction)); dst += sizeof(fraction); } http://git-wip-us.apache.org/repos/asf/trafodion/blob/319abf81/core/sql/exp/exp_datetime.h ---------------------------------------------------------------------- diff --git a/core/sql/exp/exp_datetime.h b/core/sql/exp/exp_datetime.h index c665d21..7c3f7a7 100644 --- a/core/sql/exp/exp_datetime.h +++ b/core/sql/exp/exp_datetime.h @@ -120,7 +120,9 @@ public: enum { DATETIME_MAX_NUM_FIELDS = 7 }; enum { MAX_DATETIME_SIZE = 11 }; - enum { MAX_DATETIME_FRACT_PREC = 6 }; + enum { MAX_DATETIME_MICROS_FRACT_PREC = 6 }; + enum { MAX_DATETIME_NANOS_FRACT_PREC = 9 }; + enum { MAX_DATETIME_FRACT_PREC = 9 }; // MAX Length of Datetime string is 50 - // "DATE 'YYYY-MM-DD';" @@ -143,12 +145,17 @@ public: rec_datetime_field &startField, rec_datetime_field &endField); + static NABoolean fractionStoredAsNanos(rec_datetime_field endField, + short fractionPrecision); + void convertDatetimeToInterval(rec_datetime_field datetimeStartField, rec_datetime_field datetimeEndField, short fractionPrecision, rec_datetime_field intervalEndField, char *datetimeOpData, - Int64 &interval) const; + Int64 &interval, + char * intervalBignum, + NABoolean &isBignum) const; static short getYearMonthDay(Int64 totalDays, short &year, @@ -156,6 +163,7 @@ public: char &day); short convertIntervalToDatetime(Int64 interval, + char * intervalBignum, rec_datetime_field startField, rec_datetime_field endField, short fractionPrecision, http://git-wip-us.apache.org/repos/asf/trafodion/blob/319abf81/core/sql/exp/exp_fixup.cpp ---------------------------------------------------------------------- diff --git a/core/sql/exp/exp_fixup.cpp b/core/sql/exp/exp_fixup.cpp index 756612e..479ff44 100644 --- a/core/sql/exp/exp_fixup.cpp +++ b/core/sql/exp/exp_fixup.cpp @@ -536,9 +536,9 @@ const ArithInstruction ex_arith_clause::computeCaseIndex(OperatorTypeEnum op, { ArithInstruction instruction = ARITH_NOT_SUPPORTED; - short type_op1; - short type_op2; - short type_result; + short type_op1 = -1; + short type_op2 = -1; + short type_result = -1; getCaseDatatypes(attr1->getDatatype(), attr1->getLength(), type_op1, result->getDatatype(), result->getLength(), type_result, 0 /* don't need to take scale difference into account here */); http://git-wip-us.apache.org/repos/asf/trafodion/blob/319abf81/core/sql/langman/LmLangManagerJava.cpp ---------------------------------------------------------------------- diff --git a/core/sql/langman/LmLangManagerJava.cpp b/core/sql/langman/LmLangManagerJava.cpp index 58702a3..ca64d9d 100644 --- a/core/sql/langman/LmLangManagerJava.cpp +++ b/core/sql/langman/LmLangManagerJava.cpp @@ -3418,8 +3418,8 @@ LmResult LmLanguageManagerJava::convertToTimestamp( char *inputChars = ((char *)inputRow) + param->inDataOffset(); ComUInt32 len = param->actualInDataSize(inputRow); - // NOTE: jdbc only handles default timestamp: yyyy-mm-dd hh:mm:ss.msssss. - len = (len <= 26) ? len : 26; + // NOTE: jdbc only handles default timestamp: yyyy-mm-dd hh:mm:ss.nssssssss. + len = (len <= 29) ? len : 29; // First create the java.lang.String from the input bytes str_cpy_all(tempbuf, inputChars, (Lng32) len); http://git-wip-us.apache.org/repos/asf/trafodion/blob/319abf81/core/sql/optimizer/QRDescGenerator.cpp ---------------------------------------------------------------------- diff --git a/core/sql/optimizer/QRDescGenerator.cpp b/core/sql/optimizer/QRDescGenerator.cpp index 9071018..42719aa 100644 --- a/core/sql/optimizer/QRDescGenerator.cpp +++ b/core/sql/optimizer/QRDescGenerator.cpp @@ -252,11 +252,17 @@ NABoolean QRDescGenerator::typeSupported(const NAType* type) default: // All day-time interval values are expressed in terms of microseconds. + + // If fractional precision is greater than + // microsecs, disable rangespec transformation. + if (type->getScale() > SQLInterval::MAX_FRACTION_PRECISION_MSEC) + return FALSE; + return (SQLInterval::MAX_LEADING_PRECISION >= IntervalType::getPrecision(intvType->getStartField(), intvType->getLeadingPrecision(), REC_DATE_SECOND, - SQLInterval::MAX_FRACTION_PRECISION)); + SQLInterval::MAX_FRACTION_PRECISION_MSEC)); } } @@ -267,6 +273,13 @@ NABoolean QRDescGenerator::typeSupported(const NAType* type) //case NA_USER_SUPPLIED_TYPE: //case NA_RECORD_TYPE: //case NA_ROWSET_TYPE: + + // datetime values are currently converted to Int64 microseconds value + // for rangespec constants. If fractional precision is greater than + // microsecs, disable rangespec transformation. + if (type->getScale() > DatetimeType::MAX_FRACTION_PRECISION_MSEC) + return FALSE; + return TRUE; default: http://git-wip-us.apache.org/repos/asf/trafodion/blob/319abf81/core/sql/parser/StmtDDLMisc.cpp ---------------------------------------------------------------------- diff --git a/core/sql/parser/StmtDDLMisc.cpp b/core/sql/parser/StmtDDLMisc.cpp index af2c9d4..ff078e0 100644 --- a/core/sql/parser/StmtDDLMisc.cpp +++ b/core/sql/parser/StmtDDLMisc.cpp @@ -112,6 +112,16 @@ StmtDDLCleanupObjects::bindNode(BindWA * pBindWA) // remember the original table name specified by user origTableQualName_ = *tableQualName_; + if ((type_ == HIVE_TABLE_) || + (type_ == HIVE_VIEW_)) + { + // add hive catalog/schema names if not specified + if (tableQualName_->getCatalogName().isNull()) + tableQualName_->setCatalogName(HIVE_SYSTEM_CATALOG); + if (tableQualName_->getSchemaName().isNull()) + tableQualName_->setCatalogName(HIVE_SYSTEM_SCHEMA); + } + if (applyDefaultsAndValidateObject(pBindWA, tableQualName_)) { pBindWA->setErrStatus();
