From b466fdcda2d8aed93e4e6e458156fa684095c97d Mon Sep 17 00:00:00 2001 From: Maxim Rylov Date: Mon, 15 Apr 2024 17:18:04 +0200 Subject: [PATCH] HANA: Add support for REAL_VECTOR type --- autotest/ogr/ogr_hana.py | 52 +++- ogr/ogrsf_frmts/hana/ogr_hana.h | 70 ++++- ogr/ogrsf_frmts/hana/ogrhanadatasource.cpp | 155 +++++----- ogr/ogrsf_frmts/hana/ogrhanalayer.cpp | 151 +++++----- ogr/ogrsf_frmts/hana/ogrhanatablelayer.cpp | 325 +++++++++++---------- 5 files changed, 449 insertions(+), 304 deletions(-) diff --git a/autotest/ogr/ogr_hana.py b/autotest/ogr/ogr_hana.py index e7345c3961ab..6910ff874baa 100644 --- a/autotest/ogr/ogr_hana.py +++ b/autotest/ogr/ogr_hana.py @@ -1167,6 +1167,56 @@ def create_feature(fid, geom_wkt=None): layer.CommitTransaction() +############################################################################### +# Test REAL_VECTOR type + + +def test_ogr_hana_38(): + conn = create_connection() + layer_name = get_test_name() + table_name = f'"{gdaltest.hana_schema_name}"."{layer_name}"' + execute_sql( + conn, + f"CREATE COLUMN TABLE {table_name} (ID INT PRIMARY KEY, EMB1 REAL_VECTOR(3), EMB2 REAL_VECTOR)", + ) + execute_sql( + conn, + f"INSERT INTO {table_name} VALUES (1, TO_REAL_VECTOR('[0.1,0.2,0.3]'), TO_REAL_VECTOR('[0.1,0.2,0.3]'))", + ) + + def check_value(expected): + ds = open_datasource(0) + layer = ds.GetLayerByName(layer_name) + layer_defn = layer.GetLayerDefn() + assert layer.GetLayerDefn().GetFieldCount() == 2 + field_emb1 = layer_defn.GetFieldDefn(layer_defn.GetFieldIndex("EMB1")) + assert field_emb1.GetType() == ogr.OFTBinary + assert field_emb1.GetWidth() == 16 + field_emb2 = layer_defn.GetFieldDefn(layer_defn.GetFieldIndex("EMB2")) + assert field_emb2.GetType() == ogr.OFTBinary + assert field_emb2.GetWidth() == 65000 + check_feature_count(layer, 1) + feat = layer.GetNextFeature() + assert feat.GetFieldAsBinary("EMB1") == expected + assert feat.GetFieldAsBinary("EMB2") == expected + + # '[0.1,0.2,0.3]' + vec0 = b"\x03\x00\x00\x00\xCD\xCC\xCC\x3D\xCD\xCC\x4C\x3E\x9A\x99\x99\x3E" + # '[0.1,0.2,0.1]' + vec1 = b"\x03\x00\x00\x00\xCD\xCC\xCC\x3D\xCD\xCC\x4C\x3E\xCD\xCC\xCC\x3D" + + check_value(vec0) + + ds = open_datasource(1) + layer = ds.GetLayerByName(layer_name) + feat = layer.GetNextFeature() + feat.SetField("EMB1", vec1) + feat.SetField("EMB2", vec1) + layer.SetFeature(feat) + + check_value(vec1) + + ############################################################################### # Create a table from data/poly.shp @@ -1245,7 +1295,7 @@ def create_tpoly_table(ds, layer_name="TPOLY"): def get_connection_str(): uri = gdal.GetConfigOption("OGR_HANA_CONNECTION_STRING", None) if uri is not None: - conn_str = uri + ";ENCRYPT=YES;SSL_VALIDATE_CERTIFICATE=false;CHAR_AS_UTF8=1" + conn_str = uri + ";ENCRYPT=FALSE;SSL_VALIDATE_CERTIFICATE=false;CHAR_AS_UTF8=1" else: conn_str = "HANA:autotest" diff --git a/ogr/ogrsf_frmts/hana/ogr_hana.h b/ogr/ogrsf_frmts/hana/ogr_hana.h index dc2c5e54cdc1..2d391c7bd5ba 100644 --- a/ogr/ogrsf_frmts/hana/ogr_hana.h +++ b/ogr/ogrsf_frmts/hana/ogr_hana.h @@ -38,6 +38,7 @@ #include #include "odbc/Forwards.h" +#include "odbc/Types.h" class OGRHanaDataSource; @@ -50,9 +51,76 @@ constexpr static int DEFAULT_STRING_SIZE = 256; constexpr static int UNDETERMINED_SRID = -1; /************************************************************************/ -/* Internal struct definitions */ +/* Internal enum and struct definitions */ /************************************************************************/ +class QGRHanaDataTypes +{ + QGRHanaDataTypes() = delete; + + public: + /// Unknown data type. + static constexpr int Unknown = odbc::SQLDataTypes::Unknown; + /// 64-bit integer value. + static constexpr int BigInt = odbc::SQLDataTypes::BigInt; + /// Binary data of fixed length. + static constexpr int Binary = odbc::SQLDataTypes::Binary; + /// Single bit binary data. + static constexpr int Bit = odbc::SQLDataTypes::Bit; + /// Boolean value. + static constexpr int Boolean = odbc::SQLDataTypes::Boolean; + /// Character string of fixed string length. + static constexpr int Char = odbc::SQLDataTypes::Char; + /// Year, month, and day fields. + static constexpr int Date = odbc::SQLDataTypes::Date; + /// Year, month, and day fields. + static constexpr int DateTime = odbc::SQLDataTypes::DateTime; + /// Signed, exact, numeric value. + static constexpr int Decimal = odbc::SQLDataTypes::Decimal; + /// Double-precision floating point number. + static constexpr int Double = odbc::SQLDataTypes::Double; + /// Floating point number with driver-specific precision. + static constexpr int Float = odbc::SQLDataTypes::Float; + /// 32-bit integer value. + static constexpr int Integer = odbc::SQLDataTypes::Integer; + /// Variable length binary data. + static constexpr int LongVarBinary = odbc::SQLDataTypes::LongVarBinary; + /// Variable length character data. + static constexpr int LongVarChar = odbc::SQLDataTypes::LongVarChar; + /// Signed, exact, numeric value. + static constexpr int Numeric = odbc::SQLDataTypes::Numeric; + /// Single-precision floating point number. + static constexpr int Real = odbc::SQLDataTypes::Real; + /// 16-bit integer value. + static constexpr int SmallInt = odbc::SQLDataTypes::SmallInt; + /// Hour, minute, and second fields. + static constexpr int Time = odbc::SQLDataTypes::Time; + /// Year, month, day, hour, minute, and second fields. + static constexpr int Timestamp = odbc::SQLDataTypes::Timestamp; + /// 8-bit integer value. + static constexpr int TinyInt = odbc::SQLDataTypes::TinyInt; + /// Year, month, and day fields. + static constexpr int TypeDate = odbc::SQLDataTypes::TypeDate; + /// Hour, minute, and second fields. + static constexpr int TypeTime = odbc::SQLDataTypes::TypeTime; + /// Year, month, day, hour, minute, and second fields. + static constexpr int TypeTimestamp = odbc::SQLDataTypes::TypeTimestamp; + /// Variable length binary data. + static constexpr int VarBinary = odbc::SQLDataTypes::VarBinary; + /// Variable-length character string. + static constexpr int VarChar = odbc::SQLDataTypes::VarChar; + /// Unicode character string of fixed string length. + static constexpr int WChar = odbc::SQLDataTypes::WChar; + /// Unicode variable-length character data. + static constexpr int WLongVarChar = odbc::SQLDataTypes::WLongVarChar; + /// Unicode variable-length character string. + static constexpr int WVarChar = odbc::SQLDataTypes::WVarChar; + /// ST_GEOMETRY/ST_POINT value. + static constexpr int Geometry = 29812; + /// REAL_VECTOR value. + static constexpr int RealVector = 29814; +}; + struct ColumnDefinition { CPLString name; diff --git a/ogr/ogrsf_frmts/hana/ogrhanadatasource.cpp b/ogr/ogrsf_frmts/hana/ogrhanadatasource.cpp index 8527bbebfc34..401385db8bb4 100644 --- a/ogr/ogrsf_frmts/hana/ogrhanadatasource.cpp +++ b/ogr/ogrsf_frmts/hana/ogrhanadatasource.cpp @@ -411,42 +411,43 @@ CPLString FormatDefaultValue(const char *value, short dataType) switch (dataType) { - case odbc::SQLDataTypes::Bit: - case odbc::SQLDataTypes::Boolean: + case QGRHanaDataTypes::Bit: + case QGRHanaDataTypes::Boolean: return value; - case odbc::SQLDataTypes::TinyInt: - case odbc::SQLDataTypes::SmallInt: - case odbc::SQLDataTypes::Integer: - case odbc::SQLDataTypes::BigInt: - case odbc::SQLDataTypes::Real: - case odbc::SQLDataTypes::Float: - case odbc::SQLDataTypes::Double: - case odbc::SQLDataTypes::Decimal: - case odbc::SQLDataTypes::Numeric: + case QGRHanaDataTypes::TinyInt: + case QGRHanaDataTypes::SmallInt: + case QGRHanaDataTypes::Integer: + case QGRHanaDataTypes::BigInt: + case QGRHanaDataTypes::Real: + case QGRHanaDataTypes::Float: + case QGRHanaDataTypes::Double: + case QGRHanaDataTypes::Decimal: + case QGRHanaDataTypes::Numeric: return value; - case odbc::SQLDataTypes::Char: - case odbc::SQLDataTypes::VarChar: - case odbc::SQLDataTypes::LongVarChar: - case odbc::SQLDataTypes::WChar: - case odbc::SQLDataTypes::WVarChar: - case odbc::SQLDataTypes::WLongVarChar: + case QGRHanaDataTypes::Char: + case QGRHanaDataTypes::VarChar: + case QGRHanaDataTypes::LongVarChar: + case QGRHanaDataTypes::WChar: + case QGRHanaDataTypes::WVarChar: + case QGRHanaDataTypes::WLongVarChar: return Literal(value); - case odbc::SQLDataTypes::Binary: - case odbc::SQLDataTypes::VarBinary: - case odbc::SQLDataTypes::LongVarBinary: + case QGRHanaDataTypes::Binary: + case QGRHanaDataTypes::VarBinary: + case QGRHanaDataTypes::LongVarBinary: + case QGRHanaDataTypes::RealVector: return value; - case odbc::SQLDataTypes::Date: - case odbc::SQLDataTypes::TypeDate: + case QGRHanaDataTypes::Date: + case QGRHanaDataTypes::TypeDate: if (EQUAL(value, "CURRENT_DATE")) return value; return Literal(value); - case odbc::SQLDataTypes::Time: - case odbc::SQLDataTypes::TypeTime: + case QGRHanaDataTypes::Time: + case QGRHanaDataTypes::TypeTime: if (EQUAL(value, "CURRENT_TIME")) return value; return Literal(value); - case odbc::SQLDataTypes::Timestamp: - case odbc::SQLDataTypes::TypeTimestamp: + case QGRHanaDataTypes::Timestamp: + case QGRHanaDataTypes::TypeTimestamp: if (EQUAL(value, "CURRENT_TIMESTAMP")) return value; return Literal(value); @@ -458,37 +459,37 @@ CPLString FormatDefaultValue(const char *value, short dataType) short GetArrayDataType(const CPLString &typeName) { if (typeName == "BOOLEAN ARRAY") - return odbc::SQLDataTypes::Boolean; + return QGRHanaDataTypes::Boolean; else if (typeName == "TINYINT ARRAY") - return odbc::SQLDataTypes::TinyInt; + return QGRHanaDataTypes::TinyInt; else if (typeName == "SMALLINT ARRAY") - return odbc::SQLDataTypes::SmallInt; + return QGRHanaDataTypes::SmallInt; else if (typeName == "INTEGER ARRAY") - return odbc::SQLDataTypes::Integer; + return QGRHanaDataTypes::Integer; else if (typeName == "BIGINT ARRAY") - return odbc::SQLDataTypes::BigInt; + return QGRHanaDataTypes::BigInt; else if (typeName == "DOUBLE ARRAY") - return odbc::SQLDataTypes::Double; + return QGRHanaDataTypes::Double; else if (typeName == "REAL ARRAY") - return odbc::SQLDataTypes::Float; + return QGRHanaDataTypes::Float; else if (typeName == "DECIMAL ARRAY" || typeName == "SMALLDECIMAL ARRAY") - return odbc::SQLDataTypes::Decimal; + return QGRHanaDataTypes::Decimal; else if (typeName == "CHAR ARRAY") - return odbc::SQLDataTypes::Char; + return QGRHanaDataTypes::Char; else if (typeName == "VARCHAR ARRAY") - return odbc::SQLDataTypes::VarChar; + return QGRHanaDataTypes::VarChar; else if (typeName == "NCHAR ARRAY") - return odbc::SQLDataTypes::WChar; + return QGRHanaDataTypes::WChar; else if (typeName == "NVARCHAR ARRAY") - return odbc::SQLDataTypes::WVarChar; + return QGRHanaDataTypes::WVarChar; else if (typeName == "DATE ARRAY") - return odbc::SQLDataTypes::Date; + return QGRHanaDataTypes::Date; else if (typeName == "TIME ARRAY") - return odbc::SQLDataTypes::Time; + return QGRHanaDataTypes::Time; else if (typeName == "TIMESTAMP ARRAY" || typeName == "SECONDDATE ARRAY") - return odbc::SQLDataTypes::Timestamp; + return QGRHanaDataTypes::Timestamp; - return odbc::SQLDataTypes::Unknown; + return QGRHanaDataTypes::Unknown; } std::vector GetSupportedArrayTypes() @@ -498,32 +499,34 @@ std::vector GetSupportedArrayTypes() bool IsKnownDataType(short dataType) { - return dataType == odbc::SQLDataTypes::Bit || - dataType == odbc::SQLDataTypes::Boolean || - dataType == odbc::SQLDataTypes::TinyInt || - dataType == odbc::SQLDataTypes::SmallInt || - dataType == odbc::SQLDataTypes::Integer || - dataType == odbc::SQLDataTypes::BigInt || - dataType == odbc::SQLDataTypes::Double || - dataType == odbc::SQLDataTypes::Real || - dataType == odbc::SQLDataTypes::Float || - dataType == odbc::SQLDataTypes::Decimal || - dataType == odbc::SQLDataTypes::Numeric || - dataType == odbc::SQLDataTypes::Char || - dataType == odbc::SQLDataTypes::VarChar || - dataType == odbc::SQLDataTypes::LongVarChar || - dataType == odbc::SQLDataTypes::WChar || - dataType == odbc::SQLDataTypes::WVarChar || - dataType == odbc::SQLDataTypes::WLongVarChar || - dataType == odbc::SQLDataTypes::Date || - dataType == odbc::SQLDataTypes::TypeDate || - dataType == odbc::SQLDataTypes::Time || - dataType == odbc::SQLDataTypes::TypeTime || - dataType == odbc::SQLDataTypes::Timestamp || - dataType == odbc::SQLDataTypes::TypeTimestamp || - dataType == odbc::SQLDataTypes::Binary || - dataType == odbc::SQLDataTypes::VarBinary || - dataType == odbc::SQLDataTypes::LongVarBinary; + return dataType == QGRHanaDataTypes::Bit || + dataType == QGRHanaDataTypes::Boolean || + dataType == QGRHanaDataTypes::TinyInt || + dataType == QGRHanaDataTypes::SmallInt || + dataType == QGRHanaDataTypes::Integer || + dataType == QGRHanaDataTypes::BigInt || + dataType == QGRHanaDataTypes::Double || + dataType == QGRHanaDataTypes::Real || + dataType == QGRHanaDataTypes::Float || + dataType == QGRHanaDataTypes::Decimal || + dataType == QGRHanaDataTypes::Numeric || + dataType == QGRHanaDataTypes::Char || + dataType == QGRHanaDataTypes::VarChar || + dataType == QGRHanaDataTypes::LongVarChar || + dataType == QGRHanaDataTypes::WChar || + dataType == QGRHanaDataTypes::WVarChar || + dataType == QGRHanaDataTypes::WLongVarChar || + dataType == QGRHanaDataTypes::Date || + dataType == QGRHanaDataTypes::TypeDate || + dataType == QGRHanaDataTypes::Time || + dataType == QGRHanaDataTypes::TypeTime || + dataType == QGRHanaDataTypes::Timestamp || + dataType == QGRHanaDataTypes::TypeTimestamp || + dataType == QGRHanaDataTypes::Binary || + dataType == QGRHanaDataTypes::VarBinary || + dataType == QGRHanaDataTypes::LongVarBinary || + dataType == QGRHanaDataTypes::Geometry || + dataType == QGRHanaDataTypes::RealVector; } } // anonymous namespace @@ -1048,11 +1051,14 @@ OGRErr OGRHanaDataSource::GetQueryColumns( continue; bool isArray = false; - bool isGeometry = false; CPLString tableName = rsmd->getTableName(clmIndex); CPLString columnName = rsmd->getColumnName(clmIndex); CPLString defaultValue; short dataType = rsmd->getColumnType(clmIndex); + // TODO: remove when HANA Client is fixed. + if (dataType == QGRHanaDataTypes::VarBinary && + typeName == "REAL_VECTOR") + dataType = QGRHanaDataTypes::RealVector; if (!schemaName.empty() && !tableName.empty()) { @@ -1080,7 +1086,7 @@ OGRErr OGRHanaDataSource::GetQueryColumns( typeName = *rsArrayTypes->getString(1); dataType = GetArrayDataType(typeName); - if (dataType == odbc::SQLDataTypes::Unknown) + if (dataType == QGRHanaDataTypes::Unknown) { CPLError( CE_Failure, CPLE_AppDefined, @@ -1105,18 +1111,13 @@ OGRErr OGRHanaDataSource::GetQueryColumns( if (name->compare("SHORTTEXT") == 0 || name->compare("ALPHANUM") == 0) { - dataType = odbc::SQLDataTypes::WVarChar; - } - else if (name->compare("ST_GEOMETRY") == 0 || - name->compare("ST_POINT") == 0) - { - isGeometry = true; + dataType = QGRHanaDataTypes::WVarChar; } } rsTypeInfo->close(); } - if (isGeometry) + if (dataType == QGRHanaDataTypes::Geometry) { GeometryColumnDescription geometryColumnDesc; if (schemaName.empty() || tableName.empty()) diff --git a/ogr/ogrsf_frmts/hana/ogrhanalayer.cpp b/ogr/ogrsf_frmts/hana/ogrhanalayer.cpp index 04d2422f6356..fa4c267abf5c 100644 --- a/ogr/ogrsf_frmts/hana/ogrhanalayer.cpp +++ b/ogr/ogrsf_frmts/hana/ogrhanalayer.cpp @@ -114,65 +114,75 @@ CreateFieldDefn(const AttributeColumnDescription &columnDesc) OGRFieldType ogrFieldType = OFTString; OGRFieldSubType ogrFieldSubType = OGRFieldSubType::OFSTNone; + int width = columnDesc.length; switch (columnDesc.type) { - case odbc::SQLDataTypes::Bit: - case odbc::SQLDataTypes::Boolean: + case QGRHanaDataTypes::Bit: + case QGRHanaDataTypes::Boolean: ogrFieldType = columnDesc.isArray ? OFTIntegerList : OFTInteger; ogrFieldSubType = OGRFieldSubType::OFSTBoolean; break; - case odbc::SQLDataTypes::TinyInt: - case odbc::SQLDataTypes::SmallInt: + case QGRHanaDataTypes::TinyInt: + case QGRHanaDataTypes::SmallInt: ogrFieldType = columnDesc.isArray ? OFTIntegerList : OFTInteger; ogrFieldSubType = OGRFieldSubType::OFSTInt16; break; - case odbc::SQLDataTypes::Integer: + case QGRHanaDataTypes::Integer: ogrFieldType = columnDesc.isArray ? OFTIntegerList : OFTInteger; break; - case odbc::SQLDataTypes::BigInt: + case QGRHanaDataTypes::BigInt: ogrFieldType = columnDesc.isArray ? OFTInteger64List : OFTInteger64; break; - case odbc::SQLDataTypes::Double: - case odbc::SQLDataTypes::Real: - case odbc::SQLDataTypes::Float: + case QGRHanaDataTypes::Double: + case QGRHanaDataTypes::Real: + case QGRHanaDataTypes::Float: ogrFieldType = columnDesc.isArray ? OFTRealList : OFTReal; - if (columnDesc.type != odbc::SQLDataTypes::Double) + if (columnDesc.type != QGRHanaDataTypes::Double) ogrFieldSubType = OGRFieldSubType::OFSTFloat32; break; - case odbc::SQLDataTypes::Decimal: - case odbc::SQLDataTypes::Numeric: + case QGRHanaDataTypes::Decimal: + case QGRHanaDataTypes::Numeric: ogrFieldType = columnDesc.isArray ? OFTRealList : OFTReal; setFieldPrecision = true; break; - case odbc::SQLDataTypes::Char: - case odbc::SQLDataTypes::VarChar: - case odbc::SQLDataTypes::LongVarChar: - case odbc::SQLDataTypes::WChar: - case odbc::SQLDataTypes::WVarChar: - case odbc::SQLDataTypes::WLongVarChar: + case QGRHanaDataTypes::Char: + case QGRHanaDataTypes::VarChar: + case QGRHanaDataTypes::LongVarChar: + case QGRHanaDataTypes::WChar: + case QGRHanaDataTypes::WVarChar: + case QGRHanaDataTypes::WLongVarChar: // Note: OFTWideString is deprecated ogrFieldType = columnDesc.isArray ? OFTStringList : OFTString; setFieldSize = true; break; - case odbc::SQLDataTypes::Date: - case odbc::SQLDataTypes::TypeDate: + case QGRHanaDataTypes::Date: + case QGRHanaDataTypes::TypeDate: ogrFieldType = OFTDate; break; - case odbc::SQLDataTypes::Time: - case odbc::SQLDataTypes::TypeTime: + case QGRHanaDataTypes::Time: + case QGRHanaDataTypes::TypeTime: ogrFieldType = OFTTime; break; - case odbc::SQLDataTypes::Timestamp: - case odbc::SQLDataTypes::TypeTimestamp: + case QGRHanaDataTypes::Timestamp: + case QGRHanaDataTypes::TypeTimestamp: ogrFieldType = OFTDateTime; break; - case odbc::SQLDataTypes::Binary: - case odbc::SQLDataTypes::VarBinary: - case odbc::SQLDataTypes::LongVarBinary: + case QGRHanaDataTypes::Binary: + case QGRHanaDataTypes::VarBinary: + case QGRHanaDataTypes::LongVarBinary: ogrFieldType = OFTBinary; setFieldSize = true; break; + case QGRHanaDataTypes::RealVector: + ogrFieldType = OFTBinary; + // The .fvecs format is used for REAL_VECTOR with the dimension + // lying in the range [1,65000]. + width = (columnDesc.precision == 0) + ? 65000 + : 4 * (columnDesc.precision + 1); + setFieldSize = true; + break; default: break; } @@ -189,7 +199,7 @@ CreateFieldDefn(const AttributeColumnDescription &columnDesc) if (!columnDesc.isArray) { if (setFieldSize) - field->SetWidth(columnDesc.length); + field->SetWidth(width); if (setFieldPrecision) { field->SetWidth(columnDesc.precision); @@ -472,13 +482,13 @@ OGRFeature *OGRHanaLayer::ReadFeature() if (clmDesc.isFeatureID) { - if (clmDesc.type == odbc::SQLDataTypes::Integer) + if (clmDesc.type == QGRHanaDataTypes::Integer) { odbc::Int val = resultSet_->getInt(paramIndex); if (!val.isNull()) feature->SetFID(static_cast(*val)); } - else if (clmDesc.type == odbc::SQLDataTypes::BigInt) + else if (clmDesc.type == QGRHanaDataTypes::BigInt) { odbc::Long val = resultSet_->getLong(paramIndex); if (!val.isNull()) @@ -504,41 +514,41 @@ OGRFeature *OGRHanaLayer::ReadFeature() switch (clmDesc.type) { - case odbc::SQLDataTypes::Boolean: + case QGRHanaDataTypes::Boolean: featWriter.SetFieldValueAsArray( fieldIndex, val); break; - case odbc::SQLDataTypes::TinyInt: + case QGRHanaDataTypes::TinyInt: featWriter.SetFieldValueAsArray( fieldIndex, val); break; - case odbc::SQLDataTypes::SmallInt: + case QGRHanaDataTypes::SmallInt: featWriter.SetFieldValueAsArray( fieldIndex, val); break; - case odbc::SQLDataTypes::Integer: + case QGRHanaDataTypes::Integer: featWriter.SetFieldValueAsArray( fieldIndex, val); break; - case odbc::SQLDataTypes::BigInt: + case QGRHanaDataTypes::BigInt: featWriter.SetFieldValueAsArray( fieldIndex, val); break; - case odbc::SQLDataTypes::Float: - case odbc::SQLDataTypes::Real: + case QGRHanaDataTypes::Float: + case QGRHanaDataTypes::Real: featWriter.SetFieldValueAsArray(fieldIndex, val); break; - case odbc::SQLDataTypes::Double: + case QGRHanaDataTypes::Double: featWriter.SetFieldValueAsArray(fieldIndex, val); break; - case odbc::SQLDataTypes::Char: - case odbc::SQLDataTypes::VarChar: - case odbc::SQLDataTypes::LongVarChar: - case odbc::SQLDataTypes::WChar: - case odbc::SQLDataTypes::WVarChar: - case odbc::SQLDataTypes::WLongVarChar: + case QGRHanaDataTypes::Char: + case QGRHanaDataTypes::VarChar: + case QGRHanaDataTypes::LongVarChar: + case QGRHanaDataTypes::WChar: + case QGRHanaDataTypes::WVarChar: + case QGRHanaDataTypes::WLongVarChar: featWriter.SetFieldValueAsStringArray(fieldIndex, val); break; } @@ -548,65 +558,65 @@ OGRFeature *OGRHanaLayer::ReadFeature() switch (clmDesc.type) { - case odbc::SQLDataTypes::Bit: - case odbc::SQLDataTypes::Boolean: + case QGRHanaDataTypes::Bit: + case QGRHanaDataTypes::Boolean: { odbc::Boolean val = resultSet_->getBoolean(paramIndex); featWriter.SetFieldValue(fieldIndex, val); } break; - case odbc::SQLDataTypes::TinyInt: + case QGRHanaDataTypes::TinyInt: { odbc::Byte val = resultSet_->getByte(paramIndex); featWriter.SetFieldValue(fieldIndex, val); } break; - case odbc::SQLDataTypes::SmallInt: + case QGRHanaDataTypes::SmallInt: { odbc::Short val = resultSet_->getShort(paramIndex); featWriter.SetFieldValue(fieldIndex, val); } break; - case odbc::SQLDataTypes::Integer: + case QGRHanaDataTypes::Integer: { odbc::Int val = resultSet_->getInt(paramIndex); featWriter.SetFieldValue(fieldIndex, val); } break; - case odbc::SQLDataTypes::BigInt: + case QGRHanaDataTypes::BigInt: { odbc::Long val = resultSet_->getLong(paramIndex); featWriter.SetFieldValue(fieldIndex, val); } break; - case odbc::SQLDataTypes::Real: - case odbc::SQLDataTypes::Float: + case QGRHanaDataTypes::Real: + case QGRHanaDataTypes::Float: { odbc::Float val = resultSet_->getFloat(paramIndex); featWriter.SetFieldValue(fieldIndex, val); } break; - case odbc::SQLDataTypes::Double: + case QGRHanaDataTypes::Double: { odbc::Double val = resultSet_->getDouble(paramIndex); featWriter.SetFieldValue(fieldIndex, val); } break; - case odbc::SQLDataTypes::Decimal: - case odbc::SQLDataTypes::Numeric: + case QGRHanaDataTypes::Decimal: + case QGRHanaDataTypes::Numeric: { odbc::Decimal val = resultSet_->getDecimal(paramIndex); featWriter.SetFieldValue(fieldIndex, val); } break; - case odbc::SQLDataTypes::Char: - case odbc::SQLDataTypes::VarChar: - case odbc::SQLDataTypes::LongVarChar: + case QGRHanaDataTypes::Char: + case QGRHanaDataTypes::VarChar: + case QGRHanaDataTypes::LongVarChar: // Note: NVARCHAR data type is converted to UTF-8 on the HANA side // when using a connection setting CHAR_AS_UTF8=1. - case odbc::SQLDataTypes::WChar: - case odbc::SQLDataTypes::WVarChar: - case odbc::SQLDataTypes::WLongVarChar: + case QGRHanaDataTypes::WChar: + case QGRHanaDataTypes::WVarChar: + case QGRHanaDataTypes::WLongVarChar: { std::size_t len = resultSet_->getStringLength(paramIndex); if (len == odbc::ResultSet::NULL_DATA) @@ -627,9 +637,10 @@ OGRFeature *OGRHanaLayer::ReadFeature() } } break; - case odbc::SQLDataTypes::Binary: - case odbc::SQLDataTypes::VarBinary: - case odbc::SQLDataTypes::LongVarBinary: + case QGRHanaDataTypes::Binary: + case QGRHanaDataTypes::VarBinary: + case QGRHanaDataTypes::LongVarBinary: + case QGRHanaDataTypes::RealVector: { std::size_t len = resultSet_->getBinaryLength(paramIndex); if (len == 0) @@ -652,22 +663,22 @@ OGRFeature *OGRHanaLayer::ReadFeature() } } break; - case odbc::SQLDataTypes::Date: - case odbc::SQLDataTypes::TypeDate: + case QGRHanaDataTypes::Date: + case QGRHanaDataTypes::TypeDate: { odbc::Date date = resultSet_->getDate(paramIndex); featWriter.SetFieldValue(fieldIndex, date); } break; - case odbc::SQLDataTypes::Time: - case odbc::SQLDataTypes::TypeTime: + case QGRHanaDataTypes::Time: + case QGRHanaDataTypes::TypeTime: { odbc::Time time = resultSet_->getTime(paramIndex); featWriter.SetFieldValue(fieldIndex, time); } break; - case odbc::SQLDataTypes::Timestamp: - case odbc::SQLDataTypes::TypeTimestamp: + case QGRHanaDataTypes::Timestamp: + case QGRHanaDataTypes::TypeTimestamp: { odbc::Timestamp timestamp = resultSet_->getTimestamp(paramIndex); diff --git a/ogr/ogrsf_frmts/hana/ogrhanatablelayer.cpp b/ogr/ogrsf_frmts/hana/ogrhanatablelayer.cpp index e87270dfdf0d..c9744d039477 100644 --- a/ogr/ogrsf_frmts/hana/ogrhanatablelayer.cpp +++ b/ogr/ogrsf_frmts/hana/ogrhanatablelayer.cpp @@ -84,26 +84,26 @@ CPLString GetParameterValue(short type, const CPLString &typeName, bool isArray) CPLString arrayType = "STRING"; switch (type) { - case odbc::SQLDataTypes::TinyInt: + case QGRHanaDataTypes::TinyInt: arrayType = "TINYINT"; break; - case odbc::SQLDataTypes::SmallInt: + case QGRHanaDataTypes::SmallInt: arrayType = "SMALLINT"; break; - case odbc::SQLDataTypes::Integer: + case QGRHanaDataTypes::Integer: arrayType = "INT"; break; - case odbc::SQLDataTypes::BigInt: + case QGRHanaDataTypes::BigInt: arrayType = "BIGINT"; break; - case odbc::SQLDataTypes::Float: - case odbc::SQLDataTypes::Real: + case QGRHanaDataTypes::Float: + case QGRHanaDataTypes::Real: arrayType = "REAL"; break; - case odbc::SQLDataTypes::Double: + case QGRHanaDataTypes::Double: arrayType = "DOUBLE"; break; - case odbc::SQLDataTypes::WVarChar: + case QGRHanaDataTypes::WVarChar: arrayType = "STRING"; break; } @@ -174,30 +174,30 @@ ColumnTypeInfo ParseColumnTypeInfo(const CPLString &typeDef) if (typeSize.empty() || typeSize.size() > 2) { incorrectFormatErr(); - return {"", odbc::SQLDataTypes::Unknown, 0, 0}; + return {"", QGRHanaDataTypes::Unknown, 0, 0}; } } typeName.Trim(); if (EQUAL(typeName.c_str(), "BOOLEAN")) - return {typeName, odbc::SQLDataTypes::Boolean, 0, 0}; + return {typeName, QGRHanaDataTypes::Boolean, 0, 0}; else if (EQUAL(typeName.c_str(), "TINYINT")) - return {typeName, odbc::SQLDataTypes::TinyInt, 0, 0}; + return {typeName, QGRHanaDataTypes::TinyInt, 0, 0}; else if (EQUAL(typeName.c_str(), "SMALLINT")) - return {typeName, odbc::SQLDataTypes::SmallInt, 0, 0}; + return {typeName, QGRHanaDataTypes::SmallInt, 0, 0}; else if (EQUAL(typeName.c_str(), "INTEGER")) - return {typeName, odbc::SQLDataTypes::Integer, 0, 0}; + return {typeName, QGRHanaDataTypes::Integer, 0, 0}; else if (EQUAL(typeName.c_str(), "DECIMAL")) { switch (typeSize.size()) { case 0: - return {typeName, odbc::SQLDataTypes::Decimal, 0, 0}; + return {typeName, QGRHanaDataTypes::Decimal, 0, 0}; case 1: - return {typeName, odbc::SQLDataTypes::Decimal, typeSize[0], 0}; + return {typeName, QGRHanaDataTypes::Decimal, typeSize[0], 0}; case 2: - return {typeName, odbc::SQLDataTypes::Decimal, typeSize[0], + return {typeName, QGRHanaDataTypes::Decimal, typeSize[0], typeSize[1]}; } } @@ -206,29 +206,29 @@ ColumnTypeInfo ParseColumnTypeInfo(const CPLString &typeDef) switch (typeSize.size()) { case 0: - return {typeName, odbc::SQLDataTypes::Float, 10, 0}; + return {typeName, QGRHanaDataTypes::Float, 10, 0}; case 1: - return {typeName, odbc::SQLDataTypes::Float, typeSize[0], 0}; + return {typeName, QGRHanaDataTypes::Float, typeSize[0], 0}; default: incorrectFormatErr(); - return {"", odbc::SQLDataTypes::Unknown, 0, 0}; + return {"", QGRHanaDataTypes::Unknown, 0, 0}; } } else if (EQUAL(typeName.c_str(), "REAL")) - return {typeName, odbc::SQLDataTypes::Real, 0, 0}; + return {typeName, QGRHanaDataTypes::Real, 0, 0}; else if (EQUAL(typeName.c_str(), "DOUBLE")) - return {typeName, odbc::SQLDataTypes::Double, 0, 0}; + return {typeName, QGRHanaDataTypes::Double, 0, 0}; else if (EQUAL(typeName.c_str(), "VARCHAR")) { switch (typeSize.size()) { case 0: - return {typeName, odbc::SQLDataTypes::VarChar, 1, 0}; + return {typeName, QGRHanaDataTypes::VarChar, 1, 0}; case 1: - return {typeName, odbc::SQLDataTypes::VarChar, typeSize[0], 0}; + return {typeName, QGRHanaDataTypes::VarChar, typeSize[0], 0}; default: incorrectFormatErr(); - return {"", odbc::SQLDataTypes::Unknown, 0, 0}; + return {"", QGRHanaDataTypes::Unknown, 0, 0}; } } else if (EQUAL(typeName.c_str(), "NVARCHAR")) @@ -236,42 +236,54 @@ ColumnTypeInfo ParseColumnTypeInfo(const CPLString &typeDef) switch (typeSize.size()) { case 0: - return {typeName, odbc::SQLDataTypes::WVarChar, 1, 0}; + return {typeName, QGRHanaDataTypes::WVarChar, 1, 0}; case 1: - return {typeName, odbc::SQLDataTypes::WVarChar, typeSize[0], 0}; + return {typeName, QGRHanaDataTypes::WVarChar, typeSize[0], 0}; case 2: incorrectFormatErr(); - return {"", odbc::SQLDataTypes::Unknown, 0, 0}; + return {"", QGRHanaDataTypes::Unknown, 0, 0}; } } else if (EQUAL(typeName.c_str(), "NCLOB")) - return {typeName, odbc::SQLDataTypes::WLongVarChar, 0, 0}; + return {typeName, QGRHanaDataTypes::WLongVarChar, 0, 0}; else if (EQUAL(typeName.c_str(), "DATE")) - return {typeName, odbc::SQLDataTypes::Date, 0, 0}; + return {typeName, QGRHanaDataTypes::Date, 0, 0}; else if (EQUAL(typeName.c_str(), "TIME")) - return {typeName, odbc::SQLDataTypes::Time, 0, 0}; + return {typeName, QGRHanaDataTypes::Time, 0, 0}; else if (EQUAL(typeName.c_str(), "TIMESTAMP")) - return {typeName, odbc::SQLDataTypes::Timestamp, 0, 0}; + return {typeName, QGRHanaDataTypes::Timestamp, 0, 0}; else if (EQUAL(typeName.c_str(), "VARBINARY")) { switch (typeSize.size()) { case 0: - return {typeName, odbc::SQLDataTypes::VarBinary, 1, 0}; + return {typeName, QGRHanaDataTypes::VarBinary, 1, 0}; case 1: - return {typeName, odbc::SQLDataTypes::VarBinary, typeSize[0], - 0}; + return {typeName, QGRHanaDataTypes::VarBinary, typeSize[0], 0}; case 2: incorrectFormatErr(); - return {"", odbc::SQLDataTypes::Unknown, 0, 0}; + return {"", QGRHanaDataTypes::Unknown, 0, 0}; } } else if (EQUAL(typeName.c_str(), "BLOB")) - return {typeName, odbc::SQLDataTypes::LongVarBinary, 0, 0}; + return {typeName, QGRHanaDataTypes::LongVarBinary, 0, 0}; + else if (EQUAL(typeName.c_str(), "REAL_VECTOR")) + { + switch (typeSize.size()) + { + case 0: + return {typeName, QGRHanaDataTypes::RealVector, 1, 0}; + case 1: + return {typeName, QGRHanaDataTypes::RealVector, typeSize[0], 0}; + case 2: + incorrectFormatErr(); + return {"", QGRHanaDataTypes::Unknown, 0, 0}; + } + } CPLError(CE_Failure, CPLE_NotSupported, "Unknown column type '%s'.", typeName.c_str()); - return {std::move(typeName), odbc::SQLDataTypes::Unknown, 0, 0}; + return {std::move(typeName), QGRHanaDataTypes::Unknown, 0, 0}; } CPLString GetColumnDefinition(const ColumnTypeInfo &typeInfo) @@ -282,17 +294,17 @@ CPLString GetColumnDefinition(const ColumnTypeInfo &typeInfo) { switch (typeInfo.type) { - case odbc::SQLDataTypes::SmallInt: + case QGRHanaDataTypes::SmallInt: return "SMALLINT ARRAY"; - case odbc::SQLDataTypes::Integer: + case QGRHanaDataTypes::Integer: return "INTEGER ARRAY"; - case odbc::SQLDataTypes::BigInt: + case QGRHanaDataTypes::BigInt: return "BIGINT ARRAY"; - case odbc::SQLDataTypes::Real: + case QGRHanaDataTypes::Real: return "REAL ARRAY"; - case odbc::SQLDataTypes::Double: + case QGRHanaDataTypes::Double: return "DOUBLE ARRAY"; - case odbc::SQLDataTypes::WVarChar: + case QGRHanaDataTypes::WVarChar: return "NVARCHAR(512) ARRAY"; default: return "UNKNOWN"; @@ -301,34 +313,35 @@ CPLString GetColumnDefinition(const ColumnTypeInfo &typeInfo) switch (typeInfo.type) { - case odbc::SQLDataTypes::Boolean: - case odbc::SQLDataTypes::TinyInt: - case odbc::SQLDataTypes::SmallInt: - case odbc::SQLDataTypes::Integer: - case odbc::SQLDataTypes::BigInt: - case odbc::SQLDataTypes::Float: - case odbc::SQLDataTypes::Real: - case odbc::SQLDataTypes::Double: - case odbc::SQLDataTypes::Date: - case odbc::SQLDataTypes::TypeDate: - case odbc::SQLDataTypes::Time: - case odbc::SQLDataTypes::TypeTime: - case odbc::SQLDataTypes::Timestamp: - case odbc::SQLDataTypes::TypeTimestamp: - case odbc::SQLDataTypes::Char: - case odbc::SQLDataTypes::WChar: - case odbc::SQLDataTypes::LongVarChar: - case odbc::SQLDataTypes::LongVarBinary: + case QGRHanaDataTypes::Boolean: + case QGRHanaDataTypes::TinyInt: + case QGRHanaDataTypes::SmallInt: + case QGRHanaDataTypes::Integer: + case QGRHanaDataTypes::BigInt: + case QGRHanaDataTypes::Float: + case QGRHanaDataTypes::Real: + case QGRHanaDataTypes::Double: + case QGRHanaDataTypes::Date: + case QGRHanaDataTypes::TypeDate: + case QGRHanaDataTypes::Time: + case QGRHanaDataTypes::TypeTime: + case QGRHanaDataTypes::Timestamp: + case QGRHanaDataTypes::TypeTimestamp: + case QGRHanaDataTypes::Char: + case QGRHanaDataTypes::WChar: + case QGRHanaDataTypes::LongVarChar: + case QGRHanaDataTypes::LongVarBinary: return typeInfo.name; - case odbc::SQLDataTypes::Decimal: - case odbc::SQLDataTypes::Numeric: + case QGRHanaDataTypes::Decimal: + case QGRHanaDataTypes::Numeric: return CPLString().Printf("DECIMAL(%d,%d)", typeInfo.width, typeInfo.precision); - case odbc::SQLDataTypes::VarChar: - case odbc::SQLDataTypes::WVarChar: - case odbc::SQLDataTypes::Binary: - case odbc::SQLDataTypes::VarBinary: - case odbc::SQLDataTypes::WLongVarChar: + case QGRHanaDataTypes::VarChar: + case QGRHanaDataTypes::WVarChar: + case QGRHanaDataTypes::Binary: + case QGRHanaDataTypes::VarBinary: + case QGRHanaDataTypes::WLongVarChar: + case QGRHanaDataTypes::RealVector: return (typeInfo.width == 0) ? typeInfo.name : CPLString().Printf("%s(%d)", typeInfo.name.c_str(), @@ -345,58 +358,59 @@ void SetFieldDefn(OGRFieldDefn &field, const ColumnTypeInfo &typeInfo) switch (typeInfo.type) { - case odbc::SQLDataTypes::Bit: - case odbc::SQLDataTypes::Boolean: + case QGRHanaDataTypes::Bit: + case QGRHanaDataTypes::Boolean: field.SetType(OFTInteger); field.SetSubType(OFSTBoolean); break; - case odbc::SQLDataTypes::TinyInt: - case odbc::SQLDataTypes::SmallInt: + case QGRHanaDataTypes::TinyInt: + case QGRHanaDataTypes::SmallInt: field.SetType(isArray() ? OFTIntegerList : OFTInteger); field.SetSubType(OFSTInt16); break; - case odbc::SQLDataTypes::Integer: + case QGRHanaDataTypes::Integer: field.SetType(isArray() ? OFTIntegerList : OFTInteger); break; - case odbc::SQLDataTypes::BigInt: + case QGRHanaDataTypes::BigInt: field.SetType(isArray() ? OFTInteger64List : OFTInteger64); break; - case odbc::SQLDataTypes::Double: - case odbc::SQLDataTypes::Real: - case odbc::SQLDataTypes::Float: + case QGRHanaDataTypes::Double: + case QGRHanaDataTypes::Real: + case QGRHanaDataTypes::Float: field.SetType(isArray() ? OFTRealList : OFTReal); - if (typeInfo.type != odbc::SQLDataTypes::Double) + if (typeInfo.type != QGRHanaDataTypes::Double) field.SetSubType(OFSTFloat32); break; - case odbc::SQLDataTypes::Decimal: - case odbc::SQLDataTypes::Numeric: + case QGRHanaDataTypes::Decimal: + case QGRHanaDataTypes::Numeric: field.SetType(isArray() ? OFTRealList : OFTReal); break; - case odbc::SQLDataTypes::Char: - case odbc::SQLDataTypes::VarChar: - case odbc::SQLDataTypes::LongVarChar: + case QGRHanaDataTypes::Char: + case QGRHanaDataTypes::VarChar: + case QGRHanaDataTypes::LongVarChar: field.SetType(isArray() ? OFTStringList : OFTString); break; - case odbc::SQLDataTypes::WChar: - case odbc::SQLDataTypes::WVarChar: - case odbc::SQLDataTypes::WLongVarChar: + case QGRHanaDataTypes::WChar: + case QGRHanaDataTypes::WVarChar: + case QGRHanaDataTypes::WLongVarChar: field.SetType(isArray() ? OFTStringList : OFTString); break; - case odbc::SQLDataTypes::Date: - case odbc::SQLDataTypes::TypeDate: + case QGRHanaDataTypes::Date: + case QGRHanaDataTypes::TypeDate: field.SetType(OFTDate); break; - case odbc::SQLDataTypes::Time: - case odbc::SQLDataTypes::TypeTime: + case QGRHanaDataTypes::Time: + case QGRHanaDataTypes::TypeTime: field.SetType(OFTTime); break; - case odbc::SQLDataTypes::Timestamp: - case odbc::SQLDataTypes::TypeTimestamp: + case QGRHanaDataTypes::Timestamp: + case QGRHanaDataTypes::TypeTimestamp: field.SetType(OFTDateTime); break; - case odbc::SQLDataTypes::Binary: - case odbc::SQLDataTypes::VarBinary: - case odbc::SQLDataTypes::LongVarBinary: + case QGRHanaDataTypes::Binary: + case QGRHanaDataTypes::VarBinary: + case QGRHanaDataTypes::LongVarBinary: + case QGRHanaDataTypes::RealVector: field.SetType(OFTBinary); break; default: @@ -659,7 +673,7 @@ OGRErr OGRHanaTableLayer::SetStatementParameters( switch (clmDesc.type) { - case odbc::SQLDataTypes::Integer: + case QGRHanaDataTypes::Integer: if (feature->GetFID() == OGRNullFID) statement.setInt(paramIndex, odbc::Int()); else @@ -682,7 +696,7 @@ OGRErr OGRHanaTableLayer::SetStatementParameters( feature->GetFID()))); } break; - case odbc::SQLDataTypes::BigInt: + case QGRHanaDataTypes::BigInt: if (feature->GetFID() == OGRNullFID) statement.setLong(paramIndex, odbc::Long()); else @@ -707,12 +721,12 @@ OGRErr OGRHanaTableLayer::SetStatementParameters( switch (clmDesc.type) { - case odbc::SQLDataTypes::Bit: - case odbc::SQLDataTypes::Boolean: + case QGRHanaDataTypes::Bit: + case QGRHanaDataTypes::Boolean: statement.setBoolean(paramIndex, featReader.GetFieldAsBoolean(fieldIndex)); break; - case odbc::SQLDataTypes::TinyInt: + case QGRHanaDataTypes::TinyInt: if (clmDesc.isArray) statement.setString( paramIndex, featReader.GetFieldAsIntArray(fieldIndex)); @@ -720,7 +734,7 @@ OGRErr OGRHanaTableLayer::SetStatementParameters( statement.setByte(paramIndex, featReader.GetFieldAsByte(fieldIndex)); break; - case odbc::SQLDataTypes::SmallInt: + case QGRHanaDataTypes::SmallInt: if (clmDesc.isArray) statement.setString( paramIndex, featReader.GetFieldAsIntArray(fieldIndex)); @@ -728,7 +742,7 @@ OGRErr OGRHanaTableLayer::SetStatementParameters( statement.setShort(paramIndex, featReader.GetFieldAsShort(fieldIndex)); break; - case odbc::SQLDataTypes::Integer: + case QGRHanaDataTypes::Integer: if (clmDesc.isArray) statement.setString( paramIndex, featReader.GetFieldAsIntArray(fieldIndex)); @@ -736,7 +750,7 @@ OGRErr OGRHanaTableLayer::SetStatementParameters( statement.setInt(paramIndex, featReader.GetFieldAsInt(fieldIndex)); break; - case odbc::SQLDataTypes::BigInt: + case QGRHanaDataTypes::BigInt: if (clmDesc.isArray) statement.setString( paramIndex, @@ -745,8 +759,8 @@ OGRErr OGRHanaTableLayer::SetStatementParameters( statement.setLong(paramIndex, featReader.GetFieldAsLong(fieldIndex)); break; - case odbc::SQLDataTypes::Float: - case odbc::SQLDataTypes::Real: + case QGRHanaDataTypes::Float: + case QGRHanaDataTypes::Real: if (clmDesc.isArray) statement.setString( paramIndex, featReader.GetFieldAsRealArray(fieldIndex)); @@ -754,7 +768,7 @@ OGRErr OGRHanaTableLayer::SetStatementParameters( statement.setFloat(paramIndex, featReader.GetFieldAsFloat(fieldIndex)); break; - case odbc::SQLDataTypes::Double: + case QGRHanaDataTypes::Double: if (clmDesc.isArray) statement.setString( paramIndex, @@ -763,8 +777,8 @@ OGRErr OGRHanaTableLayer::SetStatementParameters( statement.setDouble( paramIndex, featReader.GetFieldAsDouble(fieldIndex)); break; - case odbc::SQLDataTypes::Decimal: - case odbc::SQLDataTypes::Numeric: + case QGRHanaDataTypes::Decimal: + case QGRHanaDataTypes::Numeric: if ((!feature->IsFieldSet(fieldIndex) || feature->IsFieldNull(fieldIndex)) && feature->GetFieldDefnRef(fieldIndex)->GetDefault() == @@ -774,9 +788,9 @@ OGRErr OGRHanaTableLayer::SetStatementParameters( statement.setDouble( paramIndex, featReader.GetFieldAsDouble(fieldIndex)); break; - case odbc::SQLDataTypes::Char: - case odbc::SQLDataTypes::VarChar: - case odbc::SQLDataTypes::LongVarChar: + case QGRHanaDataTypes::Char: + case QGRHanaDataTypes::VarChar: + case QGRHanaDataTypes::LongVarChar: if (clmDesc.isArray) statement.setString( paramIndex, @@ -786,9 +800,9 @@ OGRErr OGRHanaTableLayer::SetStatementParameters( featReader.GetFieldAsString( fieldIndex, clmDesc.length)); break; - case odbc::SQLDataTypes::WChar: - case odbc::SQLDataTypes::WVarChar: - case odbc::SQLDataTypes::WLongVarChar: + case QGRHanaDataTypes::WChar: + case QGRHanaDataTypes::WVarChar: + case QGRHanaDataTypes::WLongVarChar: if (clmDesc.isArray) statement.setString( paramIndex, @@ -798,26 +812,27 @@ OGRErr OGRHanaTableLayer::SetStatementParameters( featReader.GetFieldAsNString( fieldIndex, clmDesc.length)); break; - case odbc::SQLDataTypes::Binary: - case odbc::SQLDataTypes::VarBinary: - case odbc::SQLDataTypes::LongVarBinary: + case QGRHanaDataTypes::Binary: + case QGRHanaDataTypes::VarBinary: + case QGRHanaDataTypes::LongVarBinary: + case QGRHanaDataTypes::RealVector: { Binary bin = featReader.GetFieldAsBinary(fieldIndex); statement.setBytes(paramIndex, bin.data, bin.size); } break; - case odbc::SQLDataTypes::DateTime: - case odbc::SQLDataTypes::TypeDate: + case QGRHanaDataTypes::DateTime: + case QGRHanaDataTypes::TypeDate: statement.setDate(paramIndex, featReader.GetFieldAsDate(fieldIndex)); break; - case odbc::SQLDataTypes::Time: - case odbc::SQLDataTypes::TypeTime: + case QGRHanaDataTypes::Time: + case QGRHanaDataTypes::TypeTime: statement.setTime(paramIndex, featReader.GetFieldAsTime(fieldIndex)); break; - case odbc::SQLDataTypes::Timestamp: - case odbc::SQLDataTypes::TypeTimestamp: + case QGRHanaDataTypes::Timestamp: + case QGRHanaDataTypes::TypeTimestamp: statement.setTimestamp( paramIndex, featReader.GetFieldAsTimestamp(fieldIndex)); break; @@ -955,98 +970,97 @@ OGRHanaTableLayer::GetColumnTypeInfo(const OGRFieldDefn &field) const case OFTInteger: if (preservePrecision_ && field.GetWidth() > 10) { - return {"DECIMAL", odbc::SQLDataTypes::Decimal, - field.GetWidth(), 0}; + return {"DECIMAL", QGRHanaDataTypes::Decimal, field.GetWidth(), + 0}; } else { if (field.GetSubType() == OFSTBoolean) - return {"BOOLEAN", odbc::SQLDataTypes::Boolean, + return {"BOOLEAN", QGRHanaDataTypes::Boolean, field.GetWidth(), 0}; else if (field.GetSubType() == OFSTInt16) - return {"SMALLINT", odbc::SQLDataTypes::SmallInt, + return {"SMALLINT", QGRHanaDataTypes::SmallInt, field.GetWidth(), 0}; else - return {"INTEGER", odbc::SQLDataTypes::Integer, + return {"INTEGER", QGRHanaDataTypes::Integer, field.GetWidth(), 0}; } break; case OFTInteger64: if (preservePrecision_ && field.GetWidth() > 20) { - return {"DECIMAL", odbc::SQLDataTypes::Decimal, - field.GetWidth(), 0}; + return {"DECIMAL", QGRHanaDataTypes::Decimal, field.GetWidth(), + 0}; } else - return {"BIGINT", odbc::SQLDataTypes::BigInt, field.GetWidth(), + return {"BIGINT", QGRHanaDataTypes::BigInt, field.GetWidth(), 0}; break; case OFTReal: if (preservePrecision_ && field.GetWidth() != 0) { - return {"DECIMAL", odbc::SQLDataTypes::Decimal, - field.GetWidth(), field.GetPrecision()}; + return {"DECIMAL", QGRHanaDataTypes::Decimal, field.GetWidth(), + field.GetPrecision()}; } else { if (field.GetSubType() == OFSTFloat32) - return {"REAL", odbc::SQLDataTypes::Real, field.GetWidth(), + return {"REAL", QGRHanaDataTypes::Real, field.GetWidth(), field.GetPrecision()}; else - return {"DOUBLE", odbc::SQLDataTypes::Double, + return {"DOUBLE", QGRHanaDataTypes::Double, field.GetWidth(), field.GetPrecision()}; } case OFTString: if (field.GetWidth() == 0 || !preservePrecision_) { int width = static_cast(defaultStringSize_); - return {"NVARCHAR", odbc::SQLDataTypes::WLongVarChar, width, 0}; + return {"NVARCHAR", QGRHanaDataTypes::WLongVarChar, width, 0}; } else { - if (field.GetWidth() <= 5000) - return {"NVARCHAR", odbc::SQLDataTypes::WLongVarChar, + if (field.GetWidth() >= 1 && field.GetWidth() <= 5000) + return {"NVARCHAR", QGRHanaDataTypes::WLongVarChar, field.GetWidth(), 0}; else - return {"NCLOB", odbc::SQLDataTypes::WLongVarChar, 0, 0}; + return {"NCLOB", QGRHanaDataTypes::WLongVarChar, 0, 0}; } case OFTBinary: - if (field.GetWidth() <= 5000) - return {"VARBINARY", odbc::SQLDataTypes::VarBinary, + if (field.GetWidth() >= 1 && field.GetWidth() <= 5000) + return {"VARBINARY", QGRHanaDataTypes::VarBinary, field.GetWidth(), 0}; else - return {"BLOB", odbc::SQLDataTypes::LongVarBinary, + return {"BLOB", QGRHanaDataTypes::LongVarBinary, field.GetWidth(), 0}; case OFTDate: - return {"DATE", odbc::SQLDataTypes::TypeDate, field.GetWidth(), 0}; + return {"DATE", QGRHanaDataTypes::TypeDate, field.GetWidth(), 0}; case OFTTime: - return {"TIME", odbc::SQLDataTypes::TypeTime, field.GetWidth(), 0}; + return {"TIME", QGRHanaDataTypes::TypeTime, field.GetWidth(), 0}; case OFTDateTime: - return {"TIMESTAMP", odbc::SQLDataTypes::TypeTimestamp, + return {"TIMESTAMP", QGRHanaDataTypes::TypeTimestamp, field.GetWidth(), 0}; case OFTIntegerList: if (field.GetSubType() == OGRFieldSubType::OFSTInt16) - return {"ARRAY", odbc::SQLDataTypes::SmallInt, field.GetWidth(), + return {"ARRAY", QGRHanaDataTypes::SmallInt, field.GetWidth(), 0}; else - return {"ARRAY", odbc::SQLDataTypes::Integer, field.GetWidth(), + return {"ARRAY", QGRHanaDataTypes::Integer, field.GetWidth(), 0}; case OFTInteger64List: - return {"ARRAY", odbc::SQLDataTypes::BigInt, field.GetWidth(), 0}; + return {"ARRAY", QGRHanaDataTypes::BigInt, field.GetWidth(), 0}; case OFTRealList: if (field.GetSubType() == OGRFieldSubType::OFSTFloat32) - return {"ARRAY", odbc::SQLDataTypes::Real, field.GetWidth(), 0}; + return {"ARRAY", QGRHanaDataTypes::Real, field.GetWidth(), 0}; else - return {"ARRAY", odbc::SQLDataTypes::Double, field.GetWidth(), - 0}; + return {"ARRAY", QGRHanaDataTypes::Double, field.GetWidth(), 0}; break; case OFTStringList: - return {"ARRAY", odbc::SQLDataTypes::WVarChar, 512, 0}; + return {"ARRAY", QGRHanaDataTypes::WVarChar, 512, 0}; default: break; } - return {"", odbc::SQLDataTypes::Unknown, 0, 0}; + return {"", QGRHanaDataTypes::Unknown, 0, 0}; } /* -------------------------------------------------------------------- */ @@ -1446,7 +1460,7 @@ OGRErr OGRHanaTableLayer::CreateField(const OGRFieldDefn *srsField, ColumnTypeInfo columnTypeInfo = GetColumnTypeInfo(dstField); CPLString columnDef = GetColumnDefinition(columnTypeInfo); - if (columnTypeInfo.type == odbc::SQLDataTypes::Unknown) + if (columnTypeInfo.type == QGRHanaDataTypes::Unknown) { if (columnTypeInfo.name.empty()) return OGRERR_FAILURE; @@ -1481,7 +1495,8 @@ OGRErr OGRHanaTableLayer::CreateField(const OGRFieldDefn *srsField, if (dstField.GetDefault() != nullptr && !dstField.IsDefaultDriverSpecific()) { if (IsArrayField(dstField.GetType()) || - columnTypeInfo.type == odbc::SQLDataTypes::LongVarBinary) + columnTypeInfo.type == QGRHanaDataTypes::LongVarBinary || + columnTypeInfo.type == QGRHanaDataTypes::RealVector) { CPLError( CE_Failure, CPLE_NotSupported,