mirror of
https://github.com/mariadb-corporation/mariadb-connector-cpp.git
synced 2025-08-15 20:45:46 +00:00
CONCPP-35, CONCPP-36, CONCPP-37, CONCPP-40 Fixes and testcases covering
these and previous couple of commits(without specific test)
This commit is contained in:
@ -1048,7 +1048,13 @@ namespace capi
|
||||
uint32_t SelectResultSetCapi::getUInt(int32_t columnIndex)
|
||||
{
|
||||
checkObjectRange(columnIndex);
|
||||
return static_cast<uint32_t>(row->getInternalULong(columnsInformation[columnIndex - 1].get()));
|
||||
|
||||
ColumnDefinition* columnInfo= columnsInformation[columnIndex - 1].get();
|
||||
int64_t value= row->getInternalLong(columnInfo);
|
||||
|
||||
row->rangeCheck("uint32_t", 0, UINT32_MAX, value, columnInfo);
|
||||
|
||||
return static_cast<uint32_t>(value);
|
||||
}
|
||||
|
||||
|
||||
|
@ -175,10 +175,6 @@ namespace capi
|
||||
}
|
||||
case MYSQL_TYPE_NEWDECIMAL:
|
||||
case MYSQL_TYPE_DECIMAL:
|
||||
{
|
||||
std::unique_ptr<BigDecimal> bigDecimal= getInternalBigDecimal(columnInfo);
|
||||
return !bigDecimal ? nullptr : new SQLString(zeroFillingIfNeeded(*bigDecimal, columnInfo));
|
||||
}
|
||||
case MYSQL_TYPE_GEOMETRY:
|
||||
return new SQLString(asChar);
|
||||
case MYSQL_TYPE_NULL:
|
||||
@ -240,7 +236,7 @@ namespace capi
|
||||
return *static_cast<int32_t*>(bind[index].buffer);
|
||||
}
|
||||
else {
|
||||
return *static_cast<uint32_t*>(bind[index].buffer);
|
||||
value= *static_cast<uint32_t*>(bind[index].buffer);
|
||||
}
|
||||
break;
|
||||
case MYSQL_TYPE_LONGLONG:
|
||||
@ -259,7 +255,17 @@ namespace capi
|
||||
case MYSQL_TYPE_VAR_STRING:
|
||||
case MYSQL_TYPE_VARCHAR:
|
||||
case MYSQL_TYPE_STRING:
|
||||
value= std::stoi(static_cast<char*>(bind[index].buffer));
|
||||
try {
|
||||
value = std::stoll(static_cast<char*>(bind[index].buffer));
|
||||
}
|
||||
// Common parent for std::invalid_argument and std::out_of_range
|
||||
catch (std::logic_error&) {
|
||||
|
||||
throw SQLException(
|
||||
"Out of range value for column '" + columnInfo->getName() + "' : value " + sql::SQLString(static_cast<char*>(bind[index].buffer), length),
|
||||
"22003",
|
||||
1264);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw SQLException(
|
||||
@ -286,83 +292,168 @@ namespace capi
|
||||
|
||||
int64_t value;
|
||||
|
||||
try {
|
||||
switch (columnInfo->getColumnType().getType()) {
|
||||
|
||||
case MYSQL_TYPE_BIT:
|
||||
return parseBit();
|
||||
case MYSQL_TYPE_TINY:
|
||||
value = getInternalTinyInt(columnInfo);
|
||||
break;
|
||||
case MYSQL_TYPE_SHORT:
|
||||
case MYSQL_TYPE_YEAR:
|
||||
{
|
||||
value = getInternalSmallInt(columnInfo);
|
||||
|
||||
break;
|
||||
}
|
||||
case MYSQL_TYPE_LONG:
|
||||
case MYSQL_TYPE_INT24:
|
||||
{
|
||||
value = getInternalMediumInt(columnInfo);
|
||||
|
||||
break;
|
||||
}
|
||||
case MYSQL_TYPE_LONGLONG:
|
||||
{
|
||||
value = *static_cast<uint64_t*>(bind[index].buffer);
|
||||
|
||||
if (columnInfo->isSigned()) {
|
||||
return value;
|
||||
}
|
||||
uint64_t unsignedValue = *static_cast<uint64_t*>(bind[index].buffer);
|
||||
|
||||
if (unsignedValue > static_cast<uint64_t>(INT64_MAX)) {
|
||||
throw SQLException(
|
||||
"Out of range value for column '"
|
||||
+ columnInfo->getName()
|
||||
+ "' : value "
|
||||
+ std::to_string(unsignedValue)
|
||||
+ " is not in int64_t range",
|
||||
"22003",
|
||||
1264);
|
||||
}
|
||||
return unsignedValue;
|
||||
}
|
||||
case MYSQL_TYPE_FLOAT:
|
||||
{
|
||||
float floatValue = getInternalFloat(columnInfo);
|
||||
if (floatValue > static_cast<float>(INT64_MAX)) {
|
||||
throw SQLException(
|
||||
"Out of range value for column '"
|
||||
+ columnInfo->getName()
|
||||
+ "' : value "
|
||||
+ std::to_string(floatValue)
|
||||
+ " is not in int64_t range",
|
||||
"22003",
|
||||
1264);
|
||||
}
|
||||
return static_cast<int64_t>(floatValue);
|
||||
}
|
||||
case MYSQL_TYPE_DOUBLE:
|
||||
{
|
||||
long double doubleValue = getInternalDouble(columnInfo);
|
||||
if (doubleValue > static_cast<long double>(INT64_MAX)) {
|
||||
throw SQLException(
|
||||
"Out of range value for column '"
|
||||
+ columnInfo->getName()
|
||||
+ "' : value "
|
||||
+ std::to_string(doubleValue)
|
||||
+ " is not in int64_t range",
|
||||
"22003",
|
||||
1264);
|
||||
}
|
||||
return static_cast<int64_t>(doubleValue);
|
||||
}
|
||||
case MYSQL_TYPE_NEWDECIMAL:
|
||||
case MYSQL_TYPE_DECIMAL:
|
||||
{
|
||||
std::unique_ptr<BigDecimal> bigDecimal = getInternalBigDecimal(columnInfo);
|
||||
//rangeCheck("BigDecimal", static_cast<int64_t>(buf));
|
||||
|
||||
return std::stoll(StringImp::get(*bigDecimal));
|
||||
}
|
||||
case MYSQL_TYPE_VAR_STRING:
|
||||
case MYSQL_TYPE_VARCHAR:
|
||||
case MYSQL_TYPE_STRING:
|
||||
return std::stoll(static_cast<char*>(bind[index].buffer));
|
||||
default:
|
||||
throw SQLException(
|
||||
"getLong not available for data field type "
|
||||
+ columnInfo->getColumnType().getCppTypeName());
|
||||
}
|
||||
}
|
||||
// stoll may throw. Catching common parent for std::invalid_argument and std::out_of_range
|
||||
catch (std::logic_error&) {
|
||||
throw SQLException(
|
||||
"Out of range value for column '" + columnInfo->getName() + "' : value " + value,
|
||||
"22003",
|
||||
1264);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
uint64_t BinRowProtocolCapi::getInternalULong(ColumnDefinition* columnInfo)
|
||||
{
|
||||
if (lastValueWasNull()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int64_t value;
|
||||
|
||||
switch (columnInfo->getColumnType().getType()) {
|
||||
|
||||
case MYSQL_TYPE_BIT:
|
||||
return parseBit();
|
||||
return static_cast<int64_t>(parseBit());
|
||||
case MYSQL_TYPE_TINY:
|
||||
value= getInternalTinyInt(columnInfo);
|
||||
break;
|
||||
case MYSQL_TYPE_SHORT:
|
||||
case MYSQL_TYPE_YEAR:
|
||||
{
|
||||
int16_t shortVal= getInternalSmallInt(columnInfo);
|
||||
if (columnInfo->isSigned()) {
|
||||
value= shortVal;
|
||||
}
|
||||
else {
|
||||
value= static_cast<uint16_t>(shortVal);
|
||||
}
|
||||
value= getInternalSmallInt(columnInfo);
|
||||
|
||||
break;
|
||||
}
|
||||
case MYSQL_TYPE_LONG:
|
||||
case MYSQL_TYPE_INT24:
|
||||
{
|
||||
int32_t value32= getInternalMediumInt(columnInfo);
|
||||
if (columnInfo->isSigned()) {
|
||||
value= value32;
|
||||
}
|
||||
else {
|
||||
value= static_cast<uint32_t>(value32);
|
||||
}
|
||||
value= getInternalMediumInt(columnInfo);
|
||||
|
||||
break;
|
||||
}
|
||||
case MYSQL_TYPE_LONGLONG:
|
||||
{
|
||||
value= *static_cast<uint64_t*>(bind[index].buffer);
|
||||
value = *static_cast<int64_t*>(bind[index].buffer);
|
||||
|
||||
if (columnInfo->isSigned()) {
|
||||
return value;
|
||||
}
|
||||
uint64_t unsignedValue= *static_cast<uint64_t*>(bind[index].buffer);
|
||||
|
||||
if (unsignedValue > static_cast<uint64_t>(INT64_MAX)) {
|
||||
throw SQLException(
|
||||
"Out of range value for column '"
|
||||
+columnInfo->getName()
|
||||
+"' : value "
|
||||
+ std::to_string(unsignedValue)
|
||||
+" is not in int64_t range",
|
||||
"22003",
|
||||
1264);
|
||||
}
|
||||
return unsignedValue;
|
||||
break;
|
||||
}
|
||||
case MYSQL_TYPE_FLOAT:
|
||||
{
|
||||
float floatValue= getInternalFloat(columnInfo);
|
||||
if (floatValue > static_cast<float>(INT64_MAX)) {
|
||||
float floatValue = getInternalFloat(columnInfo);
|
||||
if (floatValue < 0 || floatValue > static_cast<long double>(UINT64_MAX)) {
|
||||
throw SQLException(
|
||||
"Out of range value for column '"
|
||||
+columnInfo->getName()
|
||||
+"' : value "
|
||||
+ columnInfo->getName()
|
||||
+ "' : value "
|
||||
+ std::to_string(floatValue)
|
||||
+" is not in int64_t range",
|
||||
+ " is not in int64_t range",
|
||||
"22003",
|
||||
1264);
|
||||
}
|
||||
return static_cast<int64_t>(floatValue);
|
||||
return static_cast<uint64_t>(floatValue);
|
||||
}
|
||||
case MYSQL_TYPE_DOUBLE:
|
||||
{
|
||||
long double doubleValue= getInternalDouble(columnInfo);
|
||||
if (doubleValue > static_cast<long double>(INT64_MAX)) {
|
||||
long double doubleValue = getInternalDouble(columnInfo);
|
||||
if (doubleValue < 0 || doubleValue > static_cast<long double>(UINT64_MAX)) {
|
||||
throw SQLException(
|
||||
"Out of range value for column '"
|
||||
+columnInfo->getName()
|
||||
+"' : value "
|
||||
+ columnInfo->getName()
|
||||
+ "' : value "
|
||||
+ std::to_string(doubleValue)
|
||||
+" is not in int64_t range",
|
||||
+ " is not in int64_t range",
|
||||
"22003",
|
||||
1264);
|
||||
}
|
||||
@ -371,32 +462,49 @@ namespace capi
|
||||
case MYSQL_TYPE_NEWDECIMAL:
|
||||
case MYSQL_TYPE_DECIMAL:
|
||||
{
|
||||
std::unique_ptr<BigDecimal> bigDecimal= getInternalBigDecimal(columnInfo);
|
||||
std::unique_ptr<BigDecimal> bigDecimal = getInternalBigDecimal(columnInfo);
|
||||
//rangeCheck("BigDecimal", static_cast<int64_t>(buf));
|
||||
|
||||
return std::stoll(StringImp::get(*bigDecimal));
|
||||
return sql::mariadb::stoull(*bigDecimal);
|
||||
}
|
||||
case MYSQL_TYPE_VAR_STRING:
|
||||
case MYSQL_TYPE_VARCHAR:
|
||||
case MYSQL_TYPE_STRING:
|
||||
return std::stoll(static_cast<char*>(bind[index].buffer));
|
||||
{
|
||||
char* charValue = static_cast<char*>(bind[index].buffer);
|
||||
try {
|
||||
return sql::mariadb::stoull(charValue);
|
||||
}
|
||||
// Common parent for std::invalid_argument and std::out_of_range
|
||||
catch (std::logic_error&) {
|
||||
throw SQLException(
|
||||
"Out of range value for column '"
|
||||
+ columnInfo->getName()
|
||||
+ "' : value "
|
||||
+ charValue
|
||||
+ " is not in int64_t range",
|
||||
"22003",
|
||||
1264);
|
||||
}
|
||||
}
|
||||
default:
|
||||
throw SQLException(
|
||||
"getLong not available for data field type "
|
||||
+columnInfo->getColumnType().getCppTypeName());
|
||||
+ columnInfo->getColumnType().getCppTypeName());
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
uint64_t BinRowProtocolCapi::getInternalULong(ColumnDefinition* columnInfo)
|
||||
{
|
||||
if (columnInfo->getColumnType().getType() == MYSQL_TYPE_LONGLONG ) {
|
||||
// getInternalLong may throw, when it should not if application fetches unsigned value
|
||||
return *static_cast<uint64_t*>(bind[index].buffer);
|
||||
if (columnInfo->isSigned() && value < 0) {
|
||||
throw SQLException(
|
||||
"Out of range value for column '"
|
||||
+ columnInfo->getName()
|
||||
+ "' : value "
|
||||
+ std::to_string(value)
|
||||
+ " is not in int64_t range",
|
||||
"22003",
|
||||
1264);
|
||||
}
|
||||
// For other cases getInternalLong is good
|
||||
return static_cast<uint64_t>(getInternalLong(columnInfo));
|
||||
|
||||
return static_cast<uint64_t>(value);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -450,7 +558,8 @@ namespace capi
|
||||
return std::strtof(static_cast<char*>(bind[index].buffer), &end);
|
||||
// if (errno == ERANGE) ?
|
||||
}
|
||||
catch (std::invalid_argument& nfe) {
|
||||
// Common parent for std::invalid_argument and std::out_of_range
|
||||
catch (std::logic_error& nfe) {
|
||||
throw SQLException(
|
||||
"Incorrect format for getFloat for data field with type "
|
||||
+columnInfo->getColumnType().getCppTypeName(),
|
||||
@ -463,19 +572,7 @@ namespace capi
|
||||
"getFloat not available for data field type "
|
||||
+columnInfo->getColumnType().getCppTypeName());
|
||||
}
|
||||
try {
|
||||
return static_cast<float>(value);
|
||||
}
|
||||
catch (std::invalid_argument& nfe) {
|
||||
SQLException sqlException=
|
||||
SQLException(
|
||||
"Incorrect format for getFloat for data field with type "
|
||||
+columnInfo->getColumnType().getCppTypeName(),
|
||||
"22003",
|
||||
1264,
|
||||
&nfe);
|
||||
throw sqlException;
|
||||
}
|
||||
return static_cast<float>(value);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -518,10 +615,10 @@ namespace capi
|
||||
case MYSQL_TYPE_STRING:
|
||||
case MYSQL_TYPE_DECIMAL:
|
||||
try {
|
||||
char* end;
|
||||
return strtold(static_cast<char*>(bind[index].buffer), &end);
|
||||
return std::stold(static_cast<char*>(bind[index].buffer));
|
||||
}
|
||||
catch (std::invalid_argument& nfe) {
|
||||
// Common parent for std::invalid_argument and std::out_of_range
|
||||
catch (std::logic_error& nfe) {
|
||||
throw SQLException(
|
||||
"Incorrect format for getDouble for data field with type "
|
||||
+columnInfo->getColumnType().getCppTypeName(),
|
||||
@ -615,10 +712,11 @@ namespace capi
|
||||
case MYSQL_TYPE_TIMESTAMP:
|
||||
case MYSQL_TYPE_DATETIME:
|
||||
case MYSQL_TYPE_DATE:
|
||||
out << mt->year << "-" << (mt->month < 10 ? "0" : "") << mt->month << "-" << (mt->day < 10 ? "0" : "") << mt->day << " ";
|
||||
out << mt->year << "-" << (mt->month < 10 ? "0" : "") << mt->month << "-" << (mt->day < 10 ? "0" : "") << mt->day;
|
||||
if (type == MYSQL_TYPE_DATE) {
|
||||
break;
|
||||
}
|
||||
out << " ";
|
||||
case MYSQL_TYPE_TIME:
|
||||
out << (mt->hour < 10 ? "0" : "") << mt->hour << ":" << (mt->minute < 10 ? "0" : "") << mt->minute << ":" << (mt->second < 10 ? "0" : "") << mt->second;
|
||||
|
||||
@ -682,6 +780,21 @@ namespace capi
|
||||
|
||||
return Date(rawValue);
|
||||
}
|
||||
case MYSQL_TYPE_YEAR:
|
||||
{
|
||||
int32_t year = *static_cast<int16_t*>(bind[index].buffer);
|
||||
if (length == 2 && columnInfo->getLength() == 2) {
|
||||
if (year < 70) {
|
||||
year += 2000;
|
||||
}
|
||||
else {
|
||||
year += 1900;
|
||||
}
|
||||
}
|
||||
std::ostringstream result;
|
||||
result << year << "-01-01";
|
||||
return result.str();
|
||||
}
|
||||
default:
|
||||
throw SQLException(
|
||||
"getDate not available for data field type "
|
||||
@ -837,7 +950,12 @@ namespace capi
|
||||
case MYSQL_TYPE_INT24:
|
||||
return getInternalMediumInt(columnInfo)!=0;
|
||||
case MYSQL_TYPE_LONGLONG:
|
||||
return getInternalLong(columnInfo)!=0;
|
||||
if (columnInfo->isSigned()) {
|
||||
return getInternalLong(columnInfo) != 0;
|
||||
}
|
||||
else {
|
||||
return getInternalULong(columnInfo) != 0;
|
||||
}
|
||||
case MYSQL_TYPE_FLOAT:
|
||||
return getInternalFloat(columnInfo)!=0;
|
||||
case MYSQL_TYPE_DOUBLE:
|
||||
|
@ -323,6 +323,7 @@ namespace capi
|
||||
int32_t nanoBegin= -1;
|
||||
std::vector<int32_t> timestampsPart{ 0,0,0,0,0,0,0 };
|
||||
int32_t partIdx= 0;
|
||||
|
||||
for (uint32_t begin= pos; begin <pos +length; begin++) {
|
||||
int8_t b= fieldBuf[begin];
|
||||
if (b == '-'||b == ' '||b == ':') {
|
||||
@ -334,7 +335,7 @@ namespace capi
|
||||
nanoBegin= begin;
|
||||
continue;
|
||||
}
|
||||
if (b <'0'||b >'9') {
|
||||
if (b <'0' || b >'9') {
|
||||
throw SQLException(
|
||||
"cannot parse data in timestamp string '"
|
||||
+ SQLString(fieldBuf.arr + pos, length)
|
||||
@ -351,14 +352,14 @@ namespace capi
|
||||
&& timestampsPart[5] == 0
|
||||
&& timestampsPart[6] == 0)
|
||||
{
|
||||
lastValueNull |=BIT_LAST_ZERO_DATE;
|
||||
lastValueNull|= BIT_LAST_ZERO_DATE;
|
||||
return nullTs;
|
||||
}
|
||||
|
||||
|
||||
// fix non leading tray for nanoseconds
|
||||
if (nanoBegin > 0) {
|
||||
for (uint32_t begin= 0; begin <6 -(pos +length -nanoBegin -1); begin++) {
|
||||
timestampsPart[6]= timestampsPart[6] *10;
|
||||
timestampsPart[6]= timestampsPart[6]*10;
|
||||
}
|
||||
}
|
||||
|
||||
@ -370,8 +371,11 @@ namespace capi
|
||||
timestamp << (timestampsPart[2] < 10 ? "0" : "") << timestampsPart[2] << " ";
|
||||
timestamp << (timestampsPart[3] < 10 ? "0" : "") << timestampsPart[3] << ":";
|
||||
timestamp << (timestampsPart[4] < 10 ? "0" : "") << timestampsPart[4] << ":";
|
||||
timestamp << (timestampsPart[5] < 10 ? "0" : "") << timestampsPart[5] << ".";
|
||||
timestamp << (nanosStr.length() < 9 ? std::string(9 - nanosStr.length(), '0') : "") << nanosStr;
|
||||
timestamp << (timestampsPart[5] < 10 ? "0" : "") << timestampsPart[5];
|
||||
|
||||
if (timestampsPart[6] > 0) {
|
||||
timestamp << "." << (nanosStr.length() < 9 ? std::string(9 - nanosStr.length(), '0') : "") << nanosStr;
|
||||
}
|
||||
|
||||
return std::unique_ptr<Timestamp>(new Timestamp(timestamp.str()));
|
||||
}
|
||||
@ -725,6 +729,7 @@ namespace capi
|
||||
if (lastValueWasNull()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
try {
|
||||
switch (columnInfo->getColumnType().getType()) {
|
||||
case MYSQL_TYPE_FLOAT:
|
||||
@ -751,38 +756,97 @@ namespace capi
|
||||
case MYSQL_TYPE_LONG:
|
||||
case MYSQL_TYPE_INT24:
|
||||
case MYSQL_TYPE_LONGLONG:
|
||||
if (columnInfo->isSigned()) {
|
||||
return std::stoll(fieldBuf.arr);
|
||||
}
|
||||
else {
|
||||
return std::stoull(fieldBuf.arr);
|
||||
}
|
||||
return std::stoll(fieldBuf.arr);
|
||||
case MYSQL_TYPE_TIMESTAMP:
|
||||
case MYSQL_TYPE_DATETIME:
|
||||
case MYSQL_TYPE_TIME:
|
||||
case MYSQL_TYPE_DATE:
|
||||
throw SQLException(
|
||||
"Conversion to integer not available for data field type "
|
||||
+ columnInfo->getColumnType().getCppTypeName());
|
||||
default:
|
||||
return std::stoll(std::string(fieldBuf.arr + pos, length));
|
||||
}
|
||||
|
||||
}
|
||||
catch (std::invalid_argument&) {
|
||||
// Common parent for std::invalid_argument and std::out_of_range
|
||||
catch (std::logic_error&) {
|
||||
|
||||
std::string value(fieldBuf.arr + pos, length);
|
||||
if (std::regex_match(value, isIntegerRegex)) {
|
||||
try {
|
||||
return std::stoll(value.substr(0, value.find_first_of(".")));
|
||||
}
|
||||
catch (std::invalid_argument&) {
|
||||
|
||||
}
|
||||
}
|
||||
throw SQLException(
|
||||
"Out of range value for column '"+columnInfo->getName()+"' : value "+value,
|
||||
"Out of range value for column '"+columnInfo->getName()+"' : value " + SQLString(fieldBuf.arr, length),
|
||||
"22003",
|
||||
1264);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uint64_t TextRowProtocolCapi::getInternalULong(ColumnDefinition * columnInfo)
|
||||
{
|
||||
return static_cast<uint64_t>(getInternalLong(columnInfo));
|
||||
if (lastValueWasNull()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64_t value= 0;
|
||||
|
||||
try {
|
||||
switch (columnInfo->getColumnType().getType()) {
|
||||
case MYSQL_TYPE_FLOAT:
|
||||
case MYSQL_TYPE_DOUBLE:
|
||||
{
|
||||
long double doubleValue = std::stold(fieldBuf.arr);
|
||||
if (doubleValue < 0 || doubleValue > static_cast<long double>(UINT64_MAX)) {
|
||||
throw SQLException(
|
||||
"Out of range value for column '"
|
||||
+ columnInfo->getName()
|
||||
+ "' : value "
|
||||
+ SQLString(fieldBuf.arr, length)
|
||||
+ " is not in uint64_t range",
|
||||
"22003",
|
||||
1264);
|
||||
}
|
||||
return static_cast<uint64_t>(doubleValue);
|
||||
}
|
||||
case MYSQL_TYPE_BIT:
|
||||
return static_cast<uint64_t>(parseBit());
|
||||
case MYSQL_TYPE_TINY:
|
||||
case MYSQL_TYPE_SHORT:
|
||||
case MYSQL_TYPE_YEAR:
|
||||
case MYSQL_TYPE_LONG:
|
||||
case MYSQL_TYPE_INT24:
|
||||
case MYSQL_TYPE_LONGLONG:
|
||||
value= sql::mariadb::stoull(fieldBuf.arr);
|
||||
break;
|
||||
case MYSQL_TYPE_TIMESTAMP:
|
||||
case MYSQL_TYPE_DATETIME:
|
||||
case MYSQL_TYPE_TIME:
|
||||
case MYSQL_TYPE_DATE:
|
||||
throw SQLException(
|
||||
"Conversion to integer not available for data field type "
|
||||
+ columnInfo->getColumnType().getCppTypeName());
|
||||
default:
|
||||
value= sql::mariadb::stoull(fieldBuf.arr + pos, length);
|
||||
}
|
||||
|
||||
}
|
||||
// Common parent for std::invalid_argument and std::out_of_range
|
||||
catch (std::logic_error&) {
|
||||
/*std::stoll and std::stoull take care of */
|
||||
/*std::string value(fieldBuf.arr + pos, length);
|
||||
if (std::regex_match(value, isIntegerRegex)) {
|
||||
try {
|
||||
return std::stoull(value.substr(0, value.find_first_of(".")));
|
||||
}
|
||||
catch (std::exception&) {
|
||||
|
||||
}
|
||||
}*/
|
||||
throw SQLException(
|
||||
"Out of range value for column '" + columnInfo->getName() + "' : value " + value,
|
||||
"22003",
|
||||
1264);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -817,7 +881,8 @@ namespace capi
|
||||
try {
|
||||
return std::stof(std::string(fieldBuf.arr+pos, length));
|
||||
}
|
||||
catch (std::invalid_argument& nfe) {
|
||||
// Common parent for std::invalid_argument and std::out_of_range
|
||||
catch (std::logic_error& nfe) {
|
||||
throw SQLException(
|
||||
"Incorrect format \""
|
||||
+SQLString(fieldBuf.arr + pos, length)
|
||||
@ -864,7 +929,8 @@ namespace capi
|
||||
try {
|
||||
return std::stold(std::string(fieldBuf.arr + pos, length));
|
||||
}
|
||||
catch (std::invalid_argument& nfe) {
|
||||
// Common parent for std::invalid_argument and std::out_of_range
|
||||
catch (std::logic_error& nfe) {
|
||||
throw SQLException(
|
||||
"Incorrect format \""
|
||||
+ SQLString(fieldBuf.arr + pos, length)
|
||||
|
@ -94,6 +94,7 @@ namespace mariadb
|
||||
return replace(str, substr, subst);
|
||||
}
|
||||
|
||||
|
||||
bool equalsIgnoreCase(const SQLString& str1, const SQLString& str2)
|
||||
{
|
||||
SQLString localStr1(str1), localStr2(str2);
|
||||
@ -101,5 +102,32 @@ namespace mariadb
|
||||
return (localStr1.toLowerCase().compare(localStr2.toLowerCase()) == 0);
|
||||
}
|
||||
|
||||
|
||||
uint64_t stoull(const SQLString& str, std::size_t* pos)
|
||||
{
|
||||
bool negative= false;
|
||||
std::string::const_iterator ci= str.begin();
|
||||
while (std::isblank(*ci) && ci < str.end()) ++ci;
|
||||
|
||||
if (*str == '-')
|
||||
{
|
||||
negative= true;
|
||||
}
|
||||
|
||||
uint64_t result= std::stoull(StringImp::get(str), pos);
|
||||
|
||||
if (negative && result != 0)
|
||||
{
|
||||
throw std::out_of_range("String represents number beyond uint64_t range");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
uint64_t stoull(const char* str, std::size_t len, std::size_t* pos)
|
||||
{
|
||||
len= len == static_cast<std::size_t>(-1) ? strlen(str) : len;
|
||||
return stoull(sql::SQLString(str, len), pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -45,5 +45,7 @@ namespace mariadb
|
||||
|
||||
bool equalsIgnoreCase(const SQLString& str1, const SQLString& str2);
|
||||
|
||||
uint64_t stoull(const SQLString& str, std::size_t* pos= nullptr);
|
||||
uint64_t stoull(const char* str, std::size_t len= -1, std::size_t* pos = nullptr);
|
||||
}
|
||||
}
|
||||
|
@ -68,10 +68,6 @@ TARGET_LINK_LIBRARIES(static_test ${LIBRARY_NAME} ${PLATFORM_DEPENDENCIES} ${MY_
|
||||
ADD_TEST(static_test ${EXECUTABLE_OUTPUT_PATH}/static_test)
|
||||
SET_TESTS_PROPERTIES(static_test PROPERTIES TIMEOUT 120)
|
||||
|
||||
#SET_TARGET_PROPERTIES(static_test PROPERTIES
|
||||
# LINK_FLAGS "${} "
|
||||
# COMPILE_FLAGS "${}")
|
||||
|
||||
ADD_EXECUTABLE(driver_test driver_test.cpp)
|
||||
TARGET_LINK_LIBRARIES(driver_test ${LIBRARY_NAME} ${PLATFORM_DEPENDENCIES} ${MY_GCOV_LINK_LIBRARIES})
|
||||
|
||||
@ -87,6 +83,8 @@ ADD_TEST(test_preparedstatement preparedstatement)
|
||||
ADD_TEST(test_resultsetmetadata resultsetmetadata)
|
||||
ADD_TEST(test_connection connection)
|
||||
ADD_TEST(test_databasemetadata databasemetadata)
|
||||
ADD_TEST(test_resultset resultset)
|
||||
|
||||
|
||||
SET_TESTS_PROPERTIES(test_parametermetadata test_preparedstatement test_resultsetmetadata test_connection PROPERTIES TIMEOUT 120 WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
||||
# With remote SkySQL server, compliance tend to timeout
|
||||
|
@ -98,8 +98,7 @@ void assertEquals(const String& expected, const char* result
|
||||
// These are needed because blobs may contain \0, and const char* won't work for them
|
||||
void assertEquals(const sql::SQLString & result, const String& expected
|
||||
, const char* file, int line);
|
||||
void assertEquals(const sql::SQLString& expected, const char* result
|
||||
, const char* file, int line);
|
||||
|
||||
void assertEquals(const sql::SQLString& expected, const char* result
|
||||
, const char* file, int line);
|
||||
// Needed to avoid ambiguity
|
||||
|
@ -87,44 +87,44 @@ void connection::getClientOption()
|
||||
input=(static_cast<bool *> (&input_value));
|
||||
output=(static_cast<bool *> (&output_value));
|
||||
|
||||
//con->setClientOption("metadataUseInfoSchema", input);
|
||||
//con->getClientOption("metadataUseInfoSchema", output);
|
||||
con->setClientOption("metadataUseInfoSchema", input);
|
||||
con->getClientOption("metadataUseInfoSchema", output);
|
||||
ASSERT_EQUALS(input_value, output_value);
|
||||
|
||||
//con->setClientOption("metadataUseInfoSchema", input);
|
||||
//con->getClientOption("metadataUseInfoSchema", output);
|
||||
con->setClientOption("metadataUseInfoSchema", input);
|
||||
con->getClientOption("metadataUseInfoSchema", output);
|
||||
ASSERT_EQUALS(input_value, output_value);
|
||||
|
||||
input_value=false;
|
||||
output_value=true;
|
||||
//con->setClientOption("metadataUseInfoSchema", input);
|
||||
//con->getClientOption("metadataUseInfoSchema", output);
|
||||
con->setClientOption("metadataUseInfoSchema", input);
|
||||
con->getClientOption("metadataUseInfoSchema", output);
|
||||
ASSERT_EQUALS(input_value, output_value);
|
||||
}
|
||||
|
||||
{
|
||||
int input_value=sql::ResultSet::TYPE_SCROLL_INSENSITIVE;
|
||||
int output_value=sql::ResultSet::TYPE_FORWARD_ONLY;
|
||||
int input_value= sql::ResultSet::TYPE_SCROLL_INSENSITIVE;
|
||||
int output_value= sql::ResultSet::TYPE_FORWARD_ONLY;
|
||||
void * input;
|
||||
void * output;
|
||||
|
||||
input=(static_cast<int *> (&input_value));
|
||||
output=(static_cast<int *> (&output_value));
|
||||
|
||||
//con->setClientOption("defaultStatementResultType", input);
|
||||
//con->getClientOption("defaultStatementResultType", output);
|
||||
con->setClientOption("defaultStatementResultType", input);
|
||||
con->getClientOption("defaultStatementResultType", output);
|
||||
ASSERT_EQUALS(input_value, output_value);
|
||||
|
||||
input_value=sql::ResultSet::TYPE_FORWARD_ONLY;
|
||||
output_value=sql::ResultSet::TYPE_SCROLL_INSENSITIVE;
|
||||
//con->setClientOption("defaultStatementResultType", input);
|
||||
//con->getClientOption("defaultStatementResultType", output);
|
||||
input_value= sql::ResultSet::TYPE_FORWARD_ONLY;
|
||||
output_value= sql::ResultSet::TYPE_SCROLL_INSENSITIVE;
|
||||
con->setClientOption("defaultStatementResultType", input);
|
||||
con->getClientOption("defaultStatementResultType", output);
|
||||
ASSERT_EQUALS(input_value, output_value);
|
||||
|
||||
try
|
||||
{
|
||||
input_value=sql::ResultSet::TYPE_SCROLL_SENSITIVE;
|
||||
//con->setClientOption("defaultStatementResultType", input);
|
||||
con->setClientOption("defaultStatementResultType", input);
|
||||
FAIL("API Change or bug, please check");
|
||||
}
|
||||
catch (sql::InvalidArgumentException &)
|
||||
@ -135,7 +135,7 @@ void connection::getClientOption()
|
||||
try
|
||||
{
|
||||
input_value=sql::ResultSet::TYPE_SCROLL_SENSITIVE + sql::ResultSet::TYPE_SCROLL_INSENSITIVE + sql::ResultSet::TYPE_FORWARD_ONLY;
|
||||
//con->setClientOption("defaultStatementResultType", input);
|
||||
con->setClientOption("defaultStatementResultType", input);
|
||||
FAIL("API Change or bug, please check");
|
||||
}
|
||||
catch (sql::InvalidArgumentException &)
|
||||
@ -154,14 +154,14 @@ void connection::getClientOption()
|
||||
input=(static_cast<bool *> (&input_value));
|
||||
output=(static_cast<bool *> (&output_value));
|
||||
|
||||
//con->setClientOption("defaultPreparedStatementResultType", input);
|
||||
//con->getClientOption("defaultPreparedStatementResultType", output);
|
||||
con->setClientOption("defaultPreparedStatementResultType", input);
|
||||
con->getClientOption("defaultPreparedStatementResultType", output);
|
||||
ASSERT_EQUALS(input_value, output_value);
|
||||
|
||||
input_value=false;
|
||||
output_value=true;
|
||||
//con->setClientOption("defaultPreparedStatementResultType", input);
|
||||
//con->getClientOption("defaultPreparedStatementResultType", output);
|
||||
con->setClientOption("defaultPreparedStatementResultType", input);
|
||||
con->getClientOption("defaultPreparedStatementResultType", output);
|
||||
ASSERT_EQUALS(input_value, output_value);
|
||||
|
||||
}
|
||||
@ -175,9 +175,9 @@ void connection::getClientOption()
|
||||
sql::SQLString input_value("latin1");
|
||||
sql::SQLString output_value;
|
||||
|
||||
//con->setClientOption("characterSetResults", input_value);
|
||||
con->setClientOption("characterSetResults", input_value);
|
||||
|
||||
//output_value=con->getClientOption("characterSetResults");
|
||||
output_value=con->getClientOption("characterSetResults");
|
||||
ASSERT_EQUALS(input_value, output_value);
|
||||
}
|
||||
catch (sql::SQLException &e)
|
||||
|
@ -33,17 +33,21 @@
|
||||
#include "Warning.h"
|
||||
|
||||
#include <sstream>
|
||||
#include <cstdlib>
|
||||
#include <stdlib.h>
|
||||
#include "ResultSet.h"
|
||||
#include "Types.h"
|
||||
#include "Connection.h"
|
||||
#include "resultsettest.h"
|
||||
|
||||
|
||||
namespace testsuite
|
||||
{
|
||||
namespace classes
|
||||
{
|
||||
|
||||
static const sql::SQLString id("id");
|
||||
|
||||
void resultset::getInt()
|
||||
{
|
||||
bool on_off=true;
|
||||
@ -182,7 +186,7 @@ void resultset::getTypes()
|
||||
stmt.reset(con->createStatement());
|
||||
logMsg("... looping over all kinds of column types");
|
||||
|
||||
for (it=columns.begin(); it != columns.end(); it++)
|
||||
for (it = columns.begin(); it != columns.end(); it++)
|
||||
{
|
||||
stmt->execute("DROP TABLE IF EXISTS test");
|
||||
msg.str("");
|
||||
@ -194,7 +198,7 @@ void resultset::getTypes()
|
||||
msg << "... testing " << it->sqldef << ", value = '" << it->value << "'";
|
||||
logMsg(msg.str());
|
||||
}
|
||||
catch (sql::SQLException &)
|
||||
catch (sql::SQLException&)
|
||||
{
|
||||
msg.str("");
|
||||
msg << "... skipping " << it->sqldef;
|
||||
@ -203,7 +207,7 @@ void resultset::getTypes()
|
||||
}
|
||||
|
||||
msg.str("");
|
||||
switch(it->ctype)
|
||||
switch (it->ctype)
|
||||
{
|
||||
case sql::DataType::BIT:
|
||||
msg << "INSERT INTO test(id) VALUES (" << it->value << ")";
|
||||
@ -217,7 +221,7 @@ void resultset::getTypes()
|
||||
stmt->execute(msg.str());
|
||||
ASSERT_EQUALS(1, (int)stmt->getUpdateCount());
|
||||
}
|
||||
catch (sql::SQLException &e)
|
||||
catch (sql::SQLException & e)
|
||||
{
|
||||
logErr(e.what());
|
||||
logErr("SQLState: " + std::string(e.getSQLState()));
|
||||
@ -239,21 +243,23 @@ void resultset::getTypes()
|
||||
if (it->check_as_string)
|
||||
{
|
||||
logMsg("... checking string value");
|
||||
if (it->as_string != res->getString("id"))
|
||||
if (it->as_string != res->getString(id))
|
||||
{
|
||||
msg.str("");
|
||||
msg << "... expecting '" << it->as_string << "', got '" << res->getString("id") << "'";
|
||||
msg << "... expecting '" << it->as_string << "', got '" << res->getString(id) << "'";
|
||||
logMsg(msg.str());
|
||||
got_warning=true;
|
||||
got_warning = true;
|
||||
}
|
||||
}
|
||||
ASSERT_EQUALS(res->getString("id"), res->getString(1));
|
||||
|
||||
ASSERT(res->getString(id).compare(res->getString(1)) == 0);
|
||||
|
||||
try
|
||||
{
|
||||
res->getString(0);
|
||||
FAIL("Invalid argument not detected");
|
||||
}
|
||||
catch (sql::InvalidArgumentException &)
|
||||
catch (sql::InvalidArgumentException&)
|
||||
{
|
||||
}
|
||||
|
||||
@ -262,7 +268,7 @@ void resultset::getTypes()
|
||||
res->getString(3);
|
||||
FAIL("Invalid argument not detected");
|
||||
}
|
||||
catch (sql::InvalidArgumentException &)
|
||||
catch (sql::InvalidArgumentException&)
|
||||
{
|
||||
}
|
||||
|
||||
@ -272,7 +278,7 @@ void resultset::getTypes()
|
||||
res->getString(1);
|
||||
FAIL("Invalid argument not detected");
|
||||
}
|
||||
catch (sql::InvalidArgumentException &)
|
||||
catch (sql::SQLDataException&)
|
||||
{
|
||||
}
|
||||
res->afterLast();
|
||||
@ -281,19 +287,126 @@ void resultset::getTypes()
|
||||
res->getString(1);
|
||||
FAIL("Invalid argument not detected");
|
||||
}
|
||||
catch (sql::InvalidArgumentException &)
|
||||
catch (sql::SQLDataException&)
|
||||
{
|
||||
}
|
||||
res->first();
|
||||
ASSERT_EQUALS(res->getBoolean(id), res->getBoolean(1));
|
||||
try
|
||||
{
|
||||
res->getBoolean(0);
|
||||
FAIL("Invalid argument not detected");
|
||||
}
|
||||
catch (sql::InvalidArgumentException&)
|
||||
{
|
||||
}
|
||||
|
||||
ASSERT_EQUALS(res->getDouble("id"), res->getDouble(1));
|
||||
try
|
||||
{
|
||||
res->getBoolean(3);
|
||||
FAIL("Invalid argument not detected");
|
||||
}
|
||||
catch (sql::InvalidArgumentException&)
|
||||
{
|
||||
}
|
||||
|
||||
res->beforeFirst();
|
||||
try
|
||||
{
|
||||
res->getBoolean(1);
|
||||
FAIL("Invalid argument not detected");
|
||||
}
|
||||
catch (sql::SQLDataException&)
|
||||
{
|
||||
}
|
||||
res->afterLast();
|
||||
try
|
||||
{
|
||||
res->getBoolean(1);
|
||||
FAIL("Invalid argument not detected");
|
||||
}
|
||||
catch (sql::SQLDataException&)
|
||||
{
|
||||
}
|
||||
|
||||
res->first();
|
||||
// Comparing prepared statement resultset and statement resultset
|
||||
if (it->check_as_string && (pres->getString(id) != res->getString(id)))
|
||||
{
|
||||
if (it->sqldef.find("ZEROFILL", 0) == std::string::npos)
|
||||
{
|
||||
ps_value = pres->getString(id);
|
||||
len_st = res->getString(id).length();
|
||||
len_ps = ps_value.length();
|
||||
if (len_ps > len_st)
|
||||
{
|
||||
// Something like 1.01000 vs. 1.01 ?
|
||||
std::string::size_type i;
|
||||
for (i = len_st; i < len_ps; i++)
|
||||
{
|
||||
if (ps_value.at(i) != '0')
|
||||
break;
|
||||
}
|
||||
if (i < (len_ps - 1))
|
||||
{
|
||||
got_warning = true;
|
||||
msg.str("");
|
||||
msg << "... \t\tWARNING - getString(), PS: '" << pres->getString(id) << "'";
|
||||
msg << ", Statement: '" << res->getString(id) << "'";
|
||||
logMsg(msg.str());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
ASSERT_EQUALS(res->getDouble(id), res->getDouble(1));
|
||||
}
|
||||
catch (sql::SQLException & e)
|
||||
{
|
||||
if ((it->name.compare("DATE") != 0 && it->name.compare("DATETIME") != 0 && it->name.compare("TIMESTAMP") != 0 && it->name.compare("TIME") != 0 &&
|
||||
it->name.compare("CHAR") != 0 && it->name.compare("BINARY") != 0 && it->name.compare("VARCHAR") != 0 && it->name.compare("VARBINARY") != 0 &&
|
||||
it->name.compare("TINYBLOB") != 0 && it->name.compare("TINYTEXT") != 0 && it->name.compare("TEXT") != 0 && it->name.compare("BLOB") != 0 &&
|
||||
it->name.compare("MEDIUMTEXT") != 0 && it->name.compare("MEDIUMBLOB") != 0 && it->name.compare("LONGBLOB") != 0 &&
|
||||
it->name.compare("LONGTEXT") != 0 && it->name.compare("ENUM") && it->name.compare("SET"))
|
||||
|| !e.getMessage().startsWith("getDouble not available for data field type Types::") && !e.getMessage().startsWith("Incorrect format "))
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
try
|
||||
{
|
||||
res->getInt(id);
|
||||
FAIL("getInt shouldn't be available for this type");
|
||||
}
|
||||
catch (sql::SQLException&)
|
||||
{
|
||||
}
|
||||
try
|
||||
{
|
||||
pres->getDouble(id);
|
||||
FAIL("getInt shouldn't be available for this type");
|
||||
}
|
||||
catch (sql::SQLException&)
|
||||
{
|
||||
}
|
||||
try
|
||||
{
|
||||
pres->getInt(id);
|
||||
FAIL("getInt shouldn't be available for this type");
|
||||
}
|
||||
catch (sql::SQLException&)
|
||||
{
|
||||
}
|
||||
// There is not sense to continue for this type further
|
||||
continue;
|
||||
}
|
||||
try
|
||||
{
|
||||
res->getDouble(0);
|
||||
FAIL("Invalid argument not detected");
|
||||
}
|
||||
catch (sql::InvalidArgumentException &)
|
||||
catch (sql::InvalidArgumentException&)
|
||||
{
|
||||
}
|
||||
|
||||
@ -302,7 +415,7 @@ void resultset::getTypes()
|
||||
res->getDouble(3);
|
||||
FAIL("Invalid argument not detected");
|
||||
}
|
||||
catch (sql::InvalidArgumentException &)
|
||||
catch (sql::InvalidArgumentException&)
|
||||
{
|
||||
}
|
||||
|
||||
@ -312,7 +425,7 @@ void resultset::getTypes()
|
||||
res->getDouble(1);
|
||||
FAIL("Invalid argument not detected");
|
||||
}
|
||||
catch (sql::InvalidArgumentException &)
|
||||
catch (sql::SQLDataException&)
|
||||
{
|
||||
}
|
||||
res->afterLast();
|
||||
@ -321,18 +434,82 @@ void resultset::getTypes()
|
||||
res->getDouble(1);
|
||||
FAIL("Invalid argument not detected");
|
||||
}
|
||||
catch (sql::InvalidArgumentException &)
|
||||
catch (sql::SQLDataException&)
|
||||
{
|
||||
}
|
||||
res->first();
|
||||
|
||||
ASSERT_EQUALS(res->getInt(1), res->getInt("id"));
|
||||
int64_t intValue = 0;
|
||||
bool isNumber = true, inIntRange = true, inUintRange = !it->is_negative, inInt64Range = true;
|
||||
try
|
||||
{
|
||||
if (it->is_negative)
|
||||
{
|
||||
intValue = std::stoll(it->value.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
intValue = static_cast<int64_t>(std::stoull(it->value.c_str()));
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
isNumber = false;
|
||||
}
|
||||
|
||||
if (!it->is_negative && intValue < 0 || intValue < INT32_MIN || intValue > INT32_MAX)
|
||||
{
|
||||
inIntRange = false;
|
||||
try
|
||||
{
|
||||
res->getInt(1);
|
||||
FAIL("Overflow of int value is not detected");
|
||||
}
|
||||
catch (sql::SQLException & e)
|
||||
{
|
||||
//All is good
|
||||
ASSERT_EQUALS(1264, e.getErrorCode());
|
||||
ASSERT_EQUALS("22003", e.getSQLState());
|
||||
}
|
||||
|
||||
if (intValue >= 0 && intValue <= UINT32_MAX)
|
||||
{
|
||||
ASSERT_EQUALS(res->getUInt(1), res->getUInt(id));
|
||||
}
|
||||
else
|
||||
{
|
||||
inUintRange = false;
|
||||
if (!it->is_negative && intValue < 0)// i.e. value is in fact uint64_t
|
||||
{
|
||||
try
|
||||
{
|
||||
res->getLong(1); //getInt64 is the same
|
||||
FAIL("Overflow of int64 value is not detected");
|
||||
}
|
||||
catch (sql::SQLException & e)
|
||||
{
|
||||
//All is good
|
||||
ASSERT_EQUALS(1264, e.getErrorCode());
|
||||
ASSERT_EQUALS("22003", e.getSQLState());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT_EQUALS(res->getInt64(1), res->getInt64(id));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT_EQUALS(res->getInt(1), res->getInt(id));
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
res->getInt(0);
|
||||
FAIL("Invalid argument not detected");
|
||||
}
|
||||
catch (sql::InvalidArgumentException &)
|
||||
catch (sql::InvalidArgumentException&)
|
||||
{
|
||||
}
|
||||
|
||||
@ -341,7 +518,7 @@ void resultset::getTypes()
|
||||
res->getInt(3);
|
||||
FAIL("Invalid argument not detected");
|
||||
}
|
||||
catch (sql::InvalidArgumentException &)
|
||||
catch (sql::InvalidArgumentException&)
|
||||
{
|
||||
}
|
||||
|
||||
@ -351,7 +528,7 @@ void resultset::getTypes()
|
||||
res->getInt(1);
|
||||
FAIL("Invalid argument not detected");
|
||||
}
|
||||
catch (sql::InvalidArgumentException &)
|
||||
catch (sql::SQLDataException&)
|
||||
{
|
||||
}
|
||||
res->afterLast();
|
||||
@ -360,15 +537,33 @@ void resultset::getTypes()
|
||||
res->getInt(1);
|
||||
FAIL("Invalid argument not detected");
|
||||
}
|
||||
catch (sql::InvalidArgumentException &)
|
||||
catch (sql::SQLDataException&)
|
||||
{
|
||||
}
|
||||
res->first();
|
||||
|
||||
ASSERT_EQUALS(res->getUInt64(1), res->getUInt64("id"));
|
||||
if (it->is_negative || !inUintRange)
|
||||
{
|
||||
try
|
||||
{
|
||||
ASSERT_EQUALS(res->getUInt(1), res->getUInt(id));
|
||||
|
||||
FAIL("Range error(negative value) has not been detected");
|
||||
}
|
||||
catch (sql::SQLException & e)
|
||||
{
|
||||
ASSERT_EQUALS(1264, e.getErrorCode());
|
||||
ASSERT_EQUALS("22003", e.getSQLState());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT_EQUALS(res->getUInt(1), res->getUInt(id));
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
res->getUInt64(0);
|
||||
res->getUInt(0);
|
||||
FAIL("Invalid argument not detected");
|
||||
}
|
||||
catch (sql::InvalidArgumentException &)
|
||||
@ -377,7 +572,7 @@ void resultset::getTypes()
|
||||
|
||||
try
|
||||
{
|
||||
res->getUInt64(3);
|
||||
res->getUInt(3);
|
||||
FAIL("Invalid argument not detected");
|
||||
}
|
||||
catch (sql::InvalidArgumentException &)
|
||||
@ -387,24 +582,28 @@ void resultset::getTypes()
|
||||
res->beforeFirst();
|
||||
try
|
||||
{
|
||||
res->getUInt64(1);
|
||||
res->getUInt(1);
|
||||
FAIL("Invalid argument not detected");
|
||||
}
|
||||
catch (sql::InvalidArgumentException &)
|
||||
catch (sql::SQLDataException&)
|
||||
{
|
||||
}
|
||||
res->afterLast();
|
||||
try
|
||||
{
|
||||
res->getUInt64(1);
|
||||
res->getUInt(1);
|
||||
FAIL("Invalid argument not detected");
|
||||
}
|
||||
catch (sql::InvalidArgumentException &)
|
||||
catch (sql::SQLDataException&)
|
||||
{
|
||||
}
|
||||
res->first();
|
||||
|
||||
ASSERT_EQUALS(res->getInt64("id"), res->getInt64(1));
|
||||
// intValue >= 0 means it's in int64 range
|
||||
if (it->is_negative || intValue >= 0)
|
||||
{
|
||||
ASSERT_EQUALS(res->getInt64(id), res->getInt64(1));
|
||||
}
|
||||
try
|
||||
{
|
||||
res->getInt64(0);
|
||||
@ -429,7 +628,7 @@ void resultset::getTypes()
|
||||
res->getInt64(1);
|
||||
FAIL("Invalid argument not detected");
|
||||
}
|
||||
catch (sql::InvalidArgumentException &)
|
||||
catch (sql::SQLDataException&)
|
||||
{
|
||||
}
|
||||
res->afterLast();
|
||||
@ -438,12 +637,30 @@ void resultset::getTypes()
|
||||
res->getInt64(1);
|
||||
FAIL("Invalid argument not detected");
|
||||
}
|
||||
catch (sql::InvalidArgumentException &)
|
||||
catch (sql::SQLDataException&)
|
||||
{
|
||||
}
|
||||
res->first();
|
||||
|
||||
ASSERT_EQUALS(res->getUInt64("id"), res->getUInt64(1));
|
||||
if (it->is_negative)
|
||||
{
|
||||
try
|
||||
{
|
||||
ASSERT_EQUALS(res->getUInt64(1), res->getUInt64(id));
|
||||
|
||||
FAIL("Range error(negative value) has not been detected");
|
||||
}
|
||||
catch (sql::SQLException & e)
|
||||
{
|
||||
ASSERT_EQUALS(1264, e.getErrorCode());
|
||||
ASSERT_EQUALS("22003", e.getSQLState());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT_EQUALS(res->getUInt64(1), res->getUInt64(id));
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
res->getUInt64(0);
|
||||
@ -468,7 +685,7 @@ void resultset::getTypes()
|
||||
res->getUInt64(1);
|
||||
FAIL("Invalid argument not detected");
|
||||
}
|
||||
catch (sql::InvalidArgumentException &)
|
||||
catch (sql::SQLDataException&)
|
||||
{
|
||||
}
|
||||
res->afterLast();
|
||||
@ -477,134 +694,76 @@ void resultset::getTypes()
|
||||
res->getUInt64(1);
|
||||
FAIL("Invalid argument not detected");
|
||||
}
|
||||
catch (sql::InvalidArgumentException &)
|
||||
catch (sql::SQLDataException&)
|
||||
{
|
||||
}
|
||||
|
||||
res->first();
|
||||
|
||||
ASSERT_EQUALS(res->getBoolean("id"), res->getBoolean(1));
|
||||
try
|
||||
{
|
||||
res->getBoolean(0);
|
||||
FAIL("Invalid argument not detected");
|
||||
}
|
||||
catch (sql::InvalidArgumentException &)
|
||||
{
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
res->getBoolean(3);
|
||||
FAIL("Invalid argument not detected");
|
||||
}
|
||||
catch (sql::InvalidArgumentException &)
|
||||
{
|
||||
}
|
||||
|
||||
res->beforeFirst();
|
||||
try
|
||||
{
|
||||
res->getBoolean(1);
|
||||
FAIL("Invalid argument not detected");
|
||||
}
|
||||
catch (sql::InvalidArgumentException &)
|
||||
{
|
||||
}
|
||||
res->afterLast();
|
||||
try
|
||||
{
|
||||
res->getBoolean(1);
|
||||
FAIL("Invalid argument not detected");
|
||||
}
|
||||
catch (sql::InvalidArgumentException &)
|
||||
{
|
||||
}
|
||||
res->first();
|
||||
|
||||
// Comparing prepared statement resultset and statement resultset
|
||||
if (it->check_as_string && (pres->getString("id") != res->getString("id")))
|
||||
{
|
||||
if (it->sqldef.find("ZEROFILL", 0) == std::string::npos)
|
||||
if (!fuzzyEquals(pres->getDouble(id), res->getDouble(id), 0.001))
|
||||
{
|
||||
ps_value=pres->getString("id");
|
||||
len_st=res->getString("id").length();
|
||||
len_ps=ps_value.length();
|
||||
if (len_ps > len_st)
|
||||
{
|
||||
// Something like 1.01000 vs. 1.01 ?
|
||||
std::string::size_type i;
|
||||
for (i=len_st; i < len_ps; i++)
|
||||
{
|
||||
if (ps_value.at(i) != '0')
|
||||
break;
|
||||
}
|
||||
if (i < (len_ps - 1))
|
||||
{
|
||||
got_warning=true;
|
||||
msg.str("");
|
||||
msg << "... \t\tWARNING - getString(), PS: '" << pres->getString("id") << "'";
|
||||
msg << ", Statement: '" << res->getString("id") << "'";
|
||||
logMsg(msg.str());
|
||||
}
|
||||
}
|
||||
msg.str("");
|
||||
msg << "... \t\tWARNING - getDouble(), PS: '" << pres->getDouble(id) << "'";
|
||||
msg << ", Statement: '" << res->getDouble(id) << "'";
|
||||
msg << ", Difference: '" << (pres->getDouble(id) - res->getDouble(id)) << "'";
|
||||
logMsg(msg.str());
|
||||
got_warning = true;
|
||||
}
|
||||
}
|
||||
catch (sql::SQLException & e)
|
||||
{
|
||||
if (it->name.compare("DATE") != 0 || !e.getMessage().startsWith("getDouble not available for data field type Types::"))
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
|
||||
}
|
||||
// ASSERT_EQUALS(pres->getString("id"), res->getString("id"));
|
||||
|
||||
if (!fuzzyEquals(pres->getDouble("id"), res->getDouble("id"), 0.001))
|
||||
if (inIntRange && (pres->getInt(id) != res->getInt(id)))
|
||||
{
|
||||
msg.str("");
|
||||
msg << "... \t\tWARNING - getDouble(), PS: '" << pres->getDouble("id") << "'";
|
||||
msg << ", Statement: '" << res->getDouble("id") << "'";
|
||||
msg << ", Difference: '" << (pres->getDouble("id") - res->getDouble("id")) << "'";
|
||||
msg << "... \t\tWARNING - getInt(), PS: '" << pres->getInt(id) << "'";
|
||||
msg << ", Statement: '" << res->getInt(id) << "'";
|
||||
logMsg(msg.str());
|
||||
got_warning=true;
|
||||
}
|
||||
|
||||
//ASSERT_EQUALS(pres->getDouble("id"), res->getDouble("id"));
|
||||
|
||||
if (pres->getInt("id") != res->getInt("id"))
|
||||
if (!it->is_negative && (pres->getUInt64(id) != res->getUInt64(id)))
|
||||
{
|
||||
msg.str("");
|
||||
msg << "... \t\tWARNING - getInt(), PS: '" << pres->getInt("id") << "'";
|
||||
msg << ", Statement: '" << res->getInt("id") << "'";
|
||||
msg << "... \t\tWARNING - getUInt64(), PS: '" << pres->getUInt64(id) << "'";
|
||||
msg << ", Statement: '" << res->getUInt64(id) << "'";
|
||||
logMsg(msg.str());
|
||||
got_warning=true;
|
||||
}
|
||||
// ASSERT_EQUALS(pres->getInt("id"), res->getInt("id"));
|
||||
|
||||
if (!it->is_negative && (pres->getUInt64("id") != res->getUInt64("id")))
|
||||
if (inUintRange)
|
||||
{
|
||||
ASSERT_EQUALS(pres->getUInt(id), res->getUInt(id));
|
||||
}
|
||||
|
||||
if ((it->is_negative || intValue >= 0) && pres->getInt64(id) != res->getInt64(id))
|
||||
{
|
||||
msg.str("");
|
||||
msg << "... \t\tWARNING - getUInt(), PS: '" << pres->getUInt64("id") << "'";
|
||||
msg << ", Statement: '" << res->getUInt64("id") << "'";
|
||||
msg << "... \t\tWARNING - getInt64(), PS: '" << pres->getInt64(id) << "'";
|
||||
msg << ", Statement: '" << res->getInt64(id) << "'";
|
||||
logMsg(msg.str());
|
||||
got_warning=true;
|
||||
}
|
||||
// ASSERT_EQUALS(pres->getUInt("id"), res->getUInt("id"));
|
||||
// ASSERT_EQUALS(pres->getInt64(id), res->getInt64(id));
|
||||
|
||||
if (pres->getInt64("id") != res->getInt64("id"))
|
||||
if (!it->is_negative && (pres->getUInt64(id) != res->getUInt64(id)))
|
||||
{
|
||||
msg.str("");
|
||||
msg << "... \t\tWARNING - getInt64(), PS: '" << pres->getInt64("id") << "'";
|
||||
msg << ", Statement: '" << res->getInt64("id") << "'";
|
||||
msg << "... \t\tWARNING - getUInt64(), PS: '" << pres->getUInt64(id) << "'";
|
||||
msg << ", Statement: '" << res->getUInt64(id) << "'";
|
||||
logMsg(msg.str());
|
||||
got_warning=true;
|
||||
}
|
||||
// ASSERT_EQUALS(pres->getInt64("id"), res->getInt64("id"));
|
||||
// ASSERT_EQUALS(pres->getUInt64(id), res->getUInt64(id));
|
||||
|
||||
if (!it->is_negative && (pres->getUInt64("id") != res->getUInt64("id")))
|
||||
{
|
||||
msg.str("");
|
||||
msg << "... \t\tWARNING - getUInt64(), PS: '" << pres->getUInt64("id") << "'";
|
||||
msg << ", Statement: '" << res->getUInt64("id") << "'";
|
||||
logMsg(msg.str());
|
||||
got_warning=true;
|
||||
}
|
||||
// ASSERT_EQUALS(pres->getUInt64("id"), res->getUInt64("id"));
|
||||
|
||||
ASSERT_EQUALS(pres->getBoolean("id"), res->getBoolean(1));
|
||||
ASSERT_EQUALS(pres->getBoolean(id), res->getBoolean(1));
|
||||
|
||||
}
|
||||
if (got_warning)
|
||||
@ -691,23 +850,23 @@ void resultset::getTypesMinorIssues()
|
||||
checkResultSetScrolling(pres);
|
||||
ASSERT(pres->next());
|
||||
|
||||
if (it->check_as_string && (it->as_string != res->getString("id")))
|
||||
if (it->check_as_string && (it->as_string != res->getString(id)))
|
||||
{
|
||||
msg.str("");
|
||||
msg << "... expecting '" << it->as_string << "', got '" << res->getString("id") << "'";
|
||||
msg << "... expecting '" << it->as_string << "', got '" << res->getString(id) << "'";
|
||||
logMsg(msg.str());
|
||||
got_warning=true;
|
||||
|
||||
}
|
||||
|
||||
// Comparing prepared statement resultset and statement resultset
|
||||
if (pres->getString("id") != res->getString("id"))
|
||||
if (pres->getString(id) != res->getString(id))
|
||||
{
|
||||
if (it->sqldef.find("ZEROFILL", 0) == std::string::npos)
|
||||
{
|
||||
bool is_minor=false;
|
||||
ps_value=pres->getString("id");
|
||||
len_st=res->getString("id").length();
|
||||
ps_value=pres->getString(id);
|
||||
len_st=res->getString(id).length();
|
||||
len_ps=ps_value.length();
|
||||
if (len_ps > len_st)
|
||||
{
|
||||
@ -740,13 +899,13 @@ void resultset::getTypesMinorIssues()
|
||||
msg.str("");
|
||||
if (is_minor)
|
||||
{
|
||||
msg << "... \t\tMINOR WARNING - getString(), PS: '" << pres->getString("id") << "'";
|
||||
msg << "... \t\tMINOR WARNING - getString(), PS: '" << pres->getString(id) << "'";
|
||||
}
|
||||
else
|
||||
{
|
||||
msg << "... \t\tWARNING - getString(), PS: '" << pres->getString("id") << "'";
|
||||
msg << "... \t\tWARNING - getString(), PS: '" << pres->getString(id) << "'";
|
||||
}
|
||||
msg << ", Statement: '" << res->getString("id") << "'";
|
||||
msg << ", Statement: '" << res->getString(id) << "'";
|
||||
logMsg(msg.str());
|
||||
}
|
||||
|
||||
@ -944,8 +1103,8 @@ void resultset::fetchBitAsInt()
|
||||
res.reset(stmt->executeQuery("SELECT id, CAST(id AS SIGNED) AS bit_as_signed FROM test ORDER BY id"));
|
||||
while (res->next())
|
||||
{
|
||||
ASSERT_EQUALS(res->getInt("id"), res->getInt("bit_as_signed"));
|
||||
ASSERT_EQUALS(res->getInt("id"), res->getInt(1));
|
||||
ASSERT_EQUALS(res->getInt(id), res->getInt("bit_as_signed"));
|
||||
ASSERT_EQUALS(res->getInt(id), res->getInt(1));
|
||||
}
|
||||
|
||||
logMsg("... BIT(0) - PS");
|
||||
@ -953,8 +1112,8 @@ void resultset::fetchBitAsInt()
|
||||
res.reset(pstmt->executeQuery());
|
||||
while (res->next())
|
||||
{
|
||||
ASSERT_EQUALS(res->getInt("id"), res->getInt("bit_as_signed"));
|
||||
ASSERT_EQUALS(res->getInt("id"), res->getInt(1));
|
||||
ASSERT_EQUALS(res->getInt(id), res->getInt("bit_as_signed"));
|
||||
ASSERT_EQUALS(res->getInt(id), res->getInt(1));
|
||||
}
|
||||
|
||||
|
||||
@ -1005,16 +1164,15 @@ void resultset::getResultSetType()
|
||||
sql::ConnectOptionsMap connection_properties;
|
||||
|
||||
logMsg("resultset::getResultSetType - MySQL_ResultSet::*");
|
||||
|
||||
SKIP("defaultStatementResultType connection option is not supported")
|
||||
try
|
||||
{
|
||||
|
||||
/* url comes from the unit testing framework */
|
||||
connection_properties["hostName"]=url;
|
||||
|
||||
/* user comes from the unit testing framework */
|
||||
connection_properties["userName"]=user;
|
||||
connection_properties["user"]= user;
|
||||
|
||||
connection_properties["password"]=passwd;
|
||||
connection_properties["password"]= passwd;
|
||||
|
||||
connection_properties.erase("defaultStatementResultType");
|
||||
{
|
||||
@ -1023,7 +1181,7 @@ void resultset::getResultSetType()
|
||||
try
|
||||
{
|
||||
created_objects.clear();
|
||||
con.reset(driver->connect(connection_properties));
|
||||
con.reset(driver->connect(url, connection_properties));
|
||||
}
|
||||
catch (sql::SQLException &e)
|
||||
{
|
||||
@ -1035,14 +1193,14 @@ void resultset::getResultSetType()
|
||||
/* NOTE: no bug - PS supports TYPE_SCROLL_INSENSITIVE only and we
|
||||
are setting StatementResultType not PreparedStatementResultType */
|
||||
res.reset(pstmt->executeQuery());
|
||||
ASSERT_EQUALS(pstmt->getResultSetType(), sql::ResultSet::TYPE_SCROLL_INSENSITIVE);
|
||||
ASSERT_EQUALS(pstmt->getResultSetType(), sql::ResultSet::TYPE_FORWARD_ONLY);// sql::ResultSet::TYPE_SCROLL_INSENSITIVE);
|
||||
|
||||
connection_properties.erase("defaultStatementResultType");
|
||||
connection_properties["defaultStatementResultType"]= std::to_string(sql::ResultSet::TYPE_SCROLL_INSENSITIVE);
|
||||
try
|
||||
{
|
||||
created_objects.clear();
|
||||
con.reset(driver->connect(connection_properties));
|
||||
con.reset(driver->connect(url, connection_properties));
|
||||
}
|
||||
catch (sql::SQLException &e)
|
||||
{
|
||||
@ -1061,7 +1219,7 @@ void resultset::getResultSetType()
|
||||
created_objects.clear();
|
||||
try
|
||||
{
|
||||
con.reset(driver->connect(connection_properties));
|
||||
con.reset(driver->connect(url, connection_properties));
|
||||
FAIL("Bug or API change - TYPE_SCROLL_SENSITIVE is unsupported");
|
||||
stmt.reset(con->createStatement());
|
||||
ASSERT_EQUALS(stmt->getResultSetType(), sql::ResultSet::TYPE_SCROLL_SENSITIVE);
|
||||
|
@ -66,15 +66,15 @@ std::vector< columndefinition > unit_fixture::columns = {
|
||||
{"TINYINT", "BOOLEAN DEFAULT 0", sql::DataType::BIT, "3", true, 3, 0, true, "0", 0, "NO", false, "3"},
|
||||
{"SMALLINT", "SMALLINT", sql::DataType::SMALLINT, "-32768", true, 5, 0, true, "NULL", 0, "NO", true, "-32768"},
|
||||
{"SMALLINT", "SMALLINT NOT NULL", sql::DataType::SMALLINT, "32767", true, 5, 0, false, "", 0, "NO", false, "32767"},
|
||||
{"SMALLINT", "SMALLINT NOT NULL DEFAULT -1", sql::DataType::SMALLINT, "-32768", true, 5, 0, false, "-1", 0, "NO", false},
|
||||
{"SMALLINT", "SMALLINT(3)", sql::DataType::SMALLINT, "-32768", true, 5, 0, true, "NULL", 0, "NO", false},
|
||||
{"SMALLINT", "SMALLINT NOT NULL DEFAULT -1", sql::DataType::SMALLINT, "-32768", true, 5, 0, false, "-1", 0, "NO", true},
|
||||
{"SMALLINT", "SMALLINT(3)", sql::DataType::SMALLINT, "-32768", true, 5, 0, true, "NULL", 0, "NO", true},
|
||||
{"SMALLINT", "SMALLINT UNSIGNED", sql::DataType::SMALLINT, "65535", false, 5, 0, true, "NULL", 0, "NO", false, "65535"},
|
||||
{"SMALLINT", "SMALLINT ZEROFILL", sql::DataType::SMALLINT, "123", false, 5, 0, true, "NULL", 0, "NO", false},
|
||||
{"SMALLINT", "SMALLINT UNSIGNED ZEROFILL DEFAULT 101", sql::DataType::SMALLINT, "123", false, 5, 0, true, "00101", 0, "NO", false},
|
||||
{"MEDIUMINT", "MEDIUMINT", sql::DataType::INTEGER, "-8388608", true, 7, 0, true, "NULL", 0, "NO", true, "-8388608"},
|
||||
{"MEDIUMINT", "MEDIUMINT NOT NULL", sql::DataType::INTEGER, "-8388608", true, 7, 0, false, "", 0, "NO", true},
|
||||
{"MEDIUMINT", "MEDIUMINT(1)", sql::DataType::INTEGER, "2", true, 7, 0, true, "NULL", 0, "NO", false},
|
||||
{"MEDIUMINT", "MEDIUMINT(2) DEFAULT 12", sql::DataType::INTEGER, "2", true, 7, 0, true, "12", 0, "NO", true},
|
||||
{"MEDIUMINT", "MEDIUMINT(2) DEFAULT 12", sql::DataType::INTEGER, "2", true, 7, 0, true, "12", 0, "NO", false},
|
||||
{"MEDIUMINT", "MEDIUMINT UNSIGNED", sql::DataType::INTEGER, "16777215", false, 8, 0, true, "NULL", 0, "NO", false, "16777215"},
|
||||
{"MEDIUMINT", "MEDIUMINT UNSIGNED ZEROFILL", sql::DataType::INTEGER, "1677721", false, 8, 0, true, "NULL", 0, "NO", false},
|
||||
// Alias of INTEGER
|
||||
@ -100,11 +100,11 @@ std::vector< columndefinition > unit_fixture::columns = {
|
||||
{"DOUBLE", "DOUBLE", sql::DataType::DOUBLE, "-1.01", true, 22, 0, true, "NULL", 0, "NO", true},
|
||||
{"DOUBLE", "DOUBLE NOT NULL", sql::DataType::DOUBLE, "-1.01", true, 22, 0, false, "", 0, "NO", true},
|
||||
{"DOUBLE", "DOUBLE UNSIGNED", sql::DataType::DOUBLE, "1.01", false, 22, 0, true, "NULL", 0, "NO", false},
|
||||
{"DOUBLE", "DOUBLE UNSIGNED DEFAULT 1.123", sql::DataType::DOUBLE, "1.01", false, 22, 0, true, "1.123", 0, "NO", true},
|
||||
{"DOUBLE", "DOUBLE(5,3) UNSIGNED ZEROFILL", sql::DataType::DOUBLE, "1.01", false, 5, 3, true, "NULL", 0, "NO", true},
|
||||
{"DOUBLE", "DOUBLE UNSIGNED DEFAULT 1.123", sql::DataType::DOUBLE, "1.01", false, 22, 0, true, "1.123", 0, "NO", false},
|
||||
{"DOUBLE", "DOUBLE(5,3) UNSIGNED ZEROFILL", sql::DataType::DOUBLE, "1.01", false, 5, 3, true, "NULL", 0, "NO", false},
|
||||
{"DECIMAL", "DECIMAL", sql::DataType::DECIMAL, "-1.01", true, 10, 0, true, "NULL", 0, "NO", true},
|
||||
{"DECIMAL", "DECIMAL NOT NULL", sql::DataType::DECIMAL, "-1.01", true, 10, 0, false, "", 0, "NO", false},
|
||||
{"DECIMAL", "DECIMAL UNSIGNED", sql::DataType::DECIMAL, "1.01", false, 10, 0, true, "NULL", 0, "NO", true},
|
||||
{"DECIMAL", "DECIMAL NOT NULL", sql::DataType::DECIMAL, "-1.01", true, 10, 0, false, "", 0, "NO", true},
|
||||
{"DECIMAL", "DECIMAL UNSIGNED", sql::DataType::DECIMAL, "1.01", false, 10, 0, true, "NULL", 0, "NO", false},
|
||||
{"DECIMAL", "DECIMAL(5,3) UNSIGNED ZEROFILL", sql::DataType::DECIMAL, "1.01", false, 5, 3, true, "NULL", 0, "NO", false},
|
||||
{"DECIMAL", "DECIMAL(6,3) UNSIGNED ZEROFILL DEFAULT 34.56", sql::DataType::DECIMAL, "1.01", false, 6, 3, true, "034.560", 0, "NO", false},
|
||||
{"DATE", "DATE", sql::DataType::DATE, "2009-02-09", true, 10, 0, true, "NULL", 0, "NO", false, "2009-02-09"},
|
||||
|
Reference in New Issue
Block a user