blob: b48f3bc062c1663965264a54fddda42ed19ac03c [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "drill/common.hpp"
#include "drill/fieldmeta.hpp"
#include "../protobuf/UserBitShared.pb.h"
#include "../protobuf/User.pb.h"
namespace {
// List of SQL types as string constants
static std::string SQLAny("ANY");
static std::string SQLArray("ARRAY");
static std::string SQLBigint("BIGINT");
static std::string SQLBinary("BINARY");
static std::string SQLBoolean("BOOLEAN");
static std::string SQLChar("CHARACTER");
static std::string SQLDate("DATE");
static std::string SQLDecimal("DECIMAL");
static std::string SQLDouble("DOUBLE");
static std::string SQLFloat("FLOAT");
static std::string SQLInteger("INTEGER");
static std::string SQLInterval("INTERVAL");
static std::string SQLIntervalYearMonth("INTERVAL YEAR TO MONTH");
static std::string SQLIntervalDaySecond("INTERVAL DAY TO SECOND");
static std::string SQLNChar("NATIONAL CHARACTER");
static std::string SQLNull("NULL");
static std::string SQLMap("MAP");
static std::string SQLSmallint("SMALLINT");
static std::string SQLTime("TIME");
static std::string SQLTimestamp("TIMESTAMP");
static std::string SQLTimestampTZ("TIMESTAMP WITH TIME ZONE");
static std::string SQLTimeTZ("TIME WITH TIME ZONE");
static std::string SQLTinyint("TINYINT");
static std::string SQLUnion("UNION");
static std::string SQLVarbinary("BINARY VARYING");
static std::string SQLVarchar("CHARACTER VARYING");
static std::string SQLVarnchar("NATIONAL CHARACTER VARYING");
static std::string SQLUnknown("__unknown__");
static const std::string& getSQLType(common::MinorType type, common::DataMode mode) {
if (mode == common::DM_REPEATED || type == common::LIST) {
return SQLArray;
}
switch(type) {
case common::BIT: return SQLBoolean;
case common::TINYINT: return SQLTinyint;
case common::SMALLINT: return SQLSmallint;
case common::INT: return SQLInteger;
case common::BIGINT: return SQLBigint;
case common::FLOAT4: return SQLFloat;
case common::FLOAT8: return SQLDouble;
case common::DECIMAL9:
case common::DECIMAL18:
case common::DECIMAL28DENSE:
case common::DECIMAL28SPARSE:
case common::DECIMAL38DENSE:
case common::VARDECIMAL:
case common::DECIMAL38SPARSE: return SQLDecimal;
case common::VARCHAR: return SQLVarchar;
case common::FIXEDCHAR: return SQLChar;
case common::VAR16CHAR: return SQLVarnchar;
case common::FIXED16CHAR: return SQLNChar;
case common::VARBINARY: return SQLVarbinary;
case common::FIXEDBINARY: return SQLBinary;
case common::DATE: return SQLDate;
case common::TIME: return SQLTime;
case common::TIMETZ: return SQLTimeTZ;
case common::TIMESTAMP: return SQLTimestamp;
case common::TIMESTAMPTZ: return SQLTimestampTZ;
case common::INTERVALYEAR: return SQLIntervalYearMonth;
case common::INTERVALDAY: return SQLIntervalDaySecond;
case common::INTERVAL: return SQLInterval;
case common::MONEY: return SQLDecimal;
case common::MAP: return SQLMap;
case common::LATE: return SQLAny;
case common::DM_UNKNOWN: return SQLNull;
case common::UNION: return SQLUnion;
case common::UINT1: return SQLTinyint;
case common::UINT2: return SQLSmallint;
case common::UINT4: return SQLInteger;
case common::UINT8: return SQLBigint;
default:
return SQLUnknown;
}
}
static bool isSortable(common::MinorType type) {
return type != common::MAP && type != common::LIST;
}
static bool isNullable(common::DataMode mode) {
return mode == common::DM_OPTIONAL; // Same behaviour as JDBC
}
static bool isSigned(common::MinorType type, common::DataMode mode) {
if (mode == common::DM_REPEATED) {
return false;// SQL ARRAY
}
switch(type) {
case common::SMALLINT:
case common::INT:
case common::BIGINT:
case common::FLOAT4:
case common::FLOAT8:
case common::DECIMAL9:
case common::DECIMAL18:
case common::DECIMAL28DENSE:
case common::DECIMAL38DENSE:
case common::DECIMAL38SPARSE:
case common::VARDECIMAL:
case common::INTERVALYEAR:
case common::INTERVALDAY:
case common::INTERVAL:
case common::MONEY:
case common::TINYINT:
return true;
case common::BIT:
case common::VARCHAR:
case common::FIXEDCHAR:
case common::VAR16CHAR:
case common::FIXED16CHAR:
case common::VARBINARY:
case common::FIXEDBINARY:
case common::DATE:
case common::TIME:
case common::TIMETZ:
case common::TIMESTAMP:
case common::TIMESTAMPTZ:
case common::MAP:
case common::LATE:
case common::DM_UNKNOWN:
case common::UNION:
case common::UINT1:
case common::UINT2:
case common::UINT4:
case common::UINT8:
return false;
default:
return false;
}
}
static Drill::FieldMetadata::ColumnSearchability getSearchability(exec::user::ColumnSearchability s) {
switch(s) {
case exec::user::UNKNOWN_SEARCHABILITY: return Drill::FieldMetadata::UNKNOWN_SEARCHABILITY;
case exec::user::NONE: return Drill::FieldMetadata::NONE;
case exec::user::CHAR: return Drill::FieldMetadata::CHAR;
case exec::user::NUMBER: return Drill::FieldMetadata::NUMBER;
case exec::user::ALL: return Drill::FieldMetadata::ALL;
default:
return Drill::FieldMetadata::UNKNOWN_SEARCHABILITY;
}
}
static Drill::FieldMetadata::ColumnUpdatability getUpdatability(exec::user::ColumnUpdatability u) {
switch(u) {
case exec::user::UNKNOWN_UPDATABILITY: return Drill::FieldMetadata::UNKNOWN_UPDATABILITY;
case exec::user::READ_ONLY: return Drill::FieldMetadata::READ_ONLY;
case exec::user::WRITABLE: return Drill::FieldMetadata::WRITABLE;
default:
return Drill::FieldMetadata::UNKNOWN_UPDATABILITY;
}
}
// Based on ODBC spec
// https://msdn.microsoft.com/en-us/library/ms711786(v=vs.85).aspx
static uint32_t getColumnSize(const std::string& type, uint32_t precision) {
if (type == SQLBoolean) {
return 1;
}
else if (type == SQLTinyint) {
return 3;
}
else if (type == SQLSmallint) {
return 5;
}
else if (type == SQLInteger) {
return 10;
}
else if (type == SQLBigint) {
return 19;
}
else if (type == SQLFloat) {
return 7;
}
else if (type == SQLDouble) {
return 15;
}
else if (type == SQLDecimal) {
return precision;
}
else if (type == SQLBinary || type == SQLVarbinary
|| type == SQLChar || type == SQLVarchar
|| type == SQLNChar || type == SQLVarnchar) {
return precision;
}
else if (type == SQLDate) {
return 10; // 'yyyy-MM-dd' format
}
else if (type == SQLTime) {
if (precision > 0) {
return 9 + precision;
}
else return 8; // 'hh-mm-ss' format
}
else if (type == SQLTimestamp) {
return (precision > 0)
? 20 + precision
: 19; // 'yyyy-MM-ddThh-mm-ss' format
}
else if (type == SQLIntervalYearMonth) {
return (precision > 0)
? 5 + precision // P..M31
: 9; // we assume max is P9999Y12M
}
else if (type == SQLIntervalDaySecond) {
return (precision > 0)
? 12 + precision // P..DT12H60M60....S
: 22; // the first 4 bytes give the number of days, so we assume max is P2147483648DT12H60M60S
}
else {
return 0;
}
}
static uint32_t getPrecision(const ::common::MajorType& type) {
const ::common::MinorType& minor_type = type.minor_type();
if (type.has_precision()) {
return type.precision();
}
if (minor_type == ::common::VARBINARY || minor_type == ::common::VARCHAR) {
return 65535;
}
return 0;
}
// From Types.java
// Based on ODBC spec:
// https://msdn.microsoft.com/en-us/library/ms713974(v=vs.85).aspx
static uint32_t getDisplaySize(const ::common::MajorType& type) {
if (type.mode() == ::common::DM_REPEATED || type.minor_type() == ::common::LIST) {
return 0;
}
uint32_t precision = getPrecision(type);
switch(type.minor_type()) {
case ::common::BIT: return 1; // 1 digit
case ::common::TINYINT: return 4; // sign + 3 digit
case ::common::SMALLINT: return 6; // sign + 5 digits
case ::common::INT: return 11; // sign + 10 digits
case ::common::BIGINT: return 20; // sign + 19 digits
case ::common::UINT1: return 3; // 3 digits
case ::common::UINT2: return 5; // 5 digits
case ::common::UINT4: return 10; // 10 digits
case ::common::UINT8: return 19; // 19 digits
case ::common::FLOAT4: return 14; // sign + 7 digits + decimal point + E + 2 digits
case ::common::FLOAT8: return 24; // sign + 15 digits + decimal point + E + 3 digits
case ::common::DECIMAL9:
case ::common::DECIMAL18:
case ::common::DECIMAL28DENSE:
case ::common::DECIMAL28SPARSE:
case ::common::DECIMAL38DENSE:
case ::common::DECIMAL38SPARSE:
case ::common::VARDECIMAL:
case ::common::MONEY: return 2 + precision; // precision of the column plus a sign and a decimal point
case ::common::VARCHAR:
case ::common::FIXEDCHAR:
case ::common::VAR16CHAR:
case ::common::FIXED16CHAR: return precision; // number of characters
case ::common::VARBINARY:
case ::common::FIXEDBINARY: return 2 * precision; // each binary byte is represented as a 2digit hex number
case ::common::DATE: return 10; // yyyy-mm-dd
case ::common::TIME:
return precision > 0
? 9 + precision // hh-mm-ss.SSS
: 8; // hh-mm-ss
case ::common::TIMETZ:
return precision > 0
? 15 + precision // hh-mm-ss.SSS-zz:zz
: 14; // hh-mm-ss-zz:zz
case ::common::TIMESTAMP:
return precision > 0
? 20 + precision // yyyy-mm-ddThh:mm:ss.SSS
: 19; // yyyy-mm-ddThh:mm:ss
case ::common::TIMESTAMPTZ:
return precision > 0
? 26 + precision // yyyy-mm-ddThh:mm:ss.SSS:ZZ-ZZ
: 25; // yyyy-mm-ddThh:mm:ss-ZZ:ZZ
case ::common::INTERVALYEAR:
return precision > 0
? 5 + precision // P..Y12M
: 9; // we assume max is P9999Y12M
case ::common::INTERVALDAY:
return precision > 0
? 12 + precision // P..DT12H60M60S assuming fractional seconds precision is not supported
: 22; // the first 4 bytes give the number of days, so we assume max is P2147483648DT12H60M60S
default:
// We don't know how to compute a display size, let's return 0 (unknown)
return 0;
}
}
} // namespace
namespace Drill{
void FieldMetadata::set(const exec::shared::SerializedField& f){
m_name=f.name_part().name();
m_minorType=f.major_type().minor_type();
m_dataMode=f.major_type().mode();
m_valueCount=f.value_count();
m_scale=f.major_type().scale();
m_precision=f.major_type().precision();
m_bufferLength=f.buffer_length();
m_catalogName="DRILL";
m_schemaName=""; // unknown
m_tableName=""; // unknown;
m_label=m_name;
m_sqlType=::getSQLType(m_minorType, m_dataMode);
m_nullable=::isNullable(m_dataMode);
m_signed=::isSigned(m_minorType, m_dataMode);
m_displaySize=::getDisplaySize(f.major_type());
m_searchability=ALL;
m_updatability=READ_ONLY;
m_autoIncremented=false;
m_caseSensitive=false;
m_sortable=::isSortable(m_minorType);
m_currency=false;
m_columnSize = ::getColumnSize(m_sqlType, m_precision);
}
void FieldMetadata::set(const exec::user::ResultColumnMetadata& m){
m_name=m.column_name();
m_minorType=static_cast<common::MinorType>(-1);
m_dataMode=static_cast<common::DataMode>(-1);
m_valueCount=0;
m_scale=m.scale();
m_precision=m.precision();
m_bufferLength=0;
m_catalogName=m.catalog_name();
m_schemaName=m.schema_name();
m_tableName=m.table_name();
m_label=m.label();
m_sqlType=m.data_type();
m_nullable=m.is_nullable();
m_displaySize=m.display_size();
m_signed=m.signed_();
m_searchability=::getSearchability(m.searchability());
m_updatability=::getUpdatability(m.updatability());
m_autoIncremented=m.auto_increment();
m_caseSensitive=m.case_sensitivity();
m_sortable=m.sortable();
m_currency=m.is_currency();
m_columnSize =::getColumnSize(m_sqlType, m_precision);
}
}// namespace Drill