From f65ab90b682337b3fc1d75ecf1f92003f23de293 Mon Sep 17 00:00:00 2001 From: nikitapaliwal Date: Wed, 5 Apr 2023 10:25:22 +0530 Subject: [PATCH 1/6] Changed the logic to handle datetime datatype --- .../src/main/java/io/cdap/plugin/db/DBRecord.java | 3 +++ .../main/java/io/cdap/plugin/mssql/SqlFieldsValidator.java | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/database-commons/src/main/java/io/cdap/plugin/db/DBRecord.java b/database-commons/src/main/java/io/cdap/plugin/db/DBRecord.java index 1d1743177..7998611d4 100644 --- a/database-commons/src/main/java/io/cdap/plugin/db/DBRecord.java +++ b/database-commons/src/main/java/io/cdap/plugin/db/DBRecord.java @@ -311,6 +311,9 @@ protected void writeToDB(PreparedStatement stmt, @Nullable Schema.Field field, i case DECIMAL: stmt.setBigDecimal(sqlIndex, record.getDecimal(fieldName)); break; + case DATETIME: + stmt.setTimestamp(sqlIndex, Timestamp.valueOf(record.getDateTime(fieldName))); + break; } return; } diff --git a/mssql-plugin/src/main/java/io/cdap/plugin/mssql/SqlFieldsValidator.java b/mssql-plugin/src/main/java/io/cdap/plugin/mssql/SqlFieldsValidator.java index b9c95edd9..56c345993 100644 --- a/mssql-plugin/src/main/java/io/cdap/plugin/mssql/SqlFieldsValidator.java +++ b/mssql-plugin/src/main/java/io/cdap/plugin/mssql/SqlFieldsValidator.java @@ -38,6 +38,10 @@ public boolean isFieldCompatible(Schema.Field field, ResultSetMetaData metadata, boolean isSigned = metadata.isSigned(index); int precision = metadata.getPrecision(index); + if ((sqlType == Types.TIMESTAMP || sqlType == SqlServerSourceSchemaReader.DATETIME_OFFSET_TYPE) + && fieldLogicalType.equals(Schema.LogicalType.DATETIME)) { + return true; + } // Handle logical types first if (fieldLogicalType != null) { return super.isFieldCompatible(fieldType, fieldLogicalType, sqlType, precision, isSigned); From 6c64afc34ba10f4c18dcbf13a2079f42fc6dc702 Mon Sep 17 00:00:00 2001 From: nikitapaliwal Date: Wed, 5 Apr 2023 19:29:23 +0530 Subject: [PATCH 2/6] Changed the logic to handle datetime datatype --- .../src/main/java/io/cdap/plugin/mssql/SqlFieldsValidator.java | 1 + 1 file changed, 1 insertion(+) diff --git a/mssql-plugin/src/main/java/io/cdap/plugin/mssql/SqlFieldsValidator.java b/mssql-plugin/src/main/java/io/cdap/plugin/mssql/SqlFieldsValidator.java index 56c345993..aca1ae9ac 100644 --- a/mssql-plugin/src/main/java/io/cdap/plugin/mssql/SqlFieldsValidator.java +++ b/mssql-plugin/src/main/java/io/cdap/plugin/mssql/SqlFieldsValidator.java @@ -38,6 +38,7 @@ public boolean isFieldCompatible(Schema.Field field, ResultSetMetaData metadata, boolean isSigned = metadata.isSigned(index); int precision = metadata.getPrecision(index); + // Handles datetime datatypes if ((sqlType == Types.TIMESTAMP || sqlType == SqlServerSourceSchemaReader.DATETIME_OFFSET_TYPE) && fieldLogicalType.equals(Schema.LogicalType.DATETIME)) { return true; From f2a14138d0e498908cea1df2e07ccff76eb2304d Mon Sep 17 00:00:00 2001 From: nikitapaliwal Date: Thu, 6 Apr 2023 13:03:37 +0530 Subject: [PATCH 3/6] Changed the logic to handle datetime datatype --- .../src/main/java/io/cdap/plugin/mssql/SqlFieldsValidator.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mssql-plugin/src/main/java/io/cdap/plugin/mssql/SqlFieldsValidator.java b/mssql-plugin/src/main/java/io/cdap/plugin/mssql/SqlFieldsValidator.java index aca1ae9ac..d5d7ae9b1 100644 --- a/mssql-plugin/src/main/java/io/cdap/plugin/mssql/SqlFieldsValidator.java +++ b/mssql-plugin/src/main/java/io/cdap/plugin/mssql/SqlFieldsValidator.java @@ -39,6 +39,9 @@ public boolean isFieldCompatible(Schema.Field field, ResultSetMetaData metadata, int precision = metadata.getPrecision(index); // Handles datetime datatypes + // Case when Timestamp maps to datetime + // Case when Datetime2 maps to datetime + // Case when DatetimeOffset maps to datetime if ((sqlType == Types.TIMESTAMP || sqlType == SqlServerSourceSchemaReader.DATETIME_OFFSET_TYPE) && fieldLogicalType.equals(Schema.LogicalType.DATETIME)) { return true; From 4707286263513f51c72d181507143a2b4da53c8d Mon Sep 17 00:00:00 2001 From: nikitapaliwal Date: Wed, 12 Apr 2023 10:40:14 +0530 Subject: [PATCH 4/6] Added datetime datatypes --- .../e2e-test/resources/pluginParameters.properties | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/mssql-plugin/src/e2e-test/resources/pluginParameters.properties b/mssql-plugin/src/e2e-test/resources/pluginParameters.properties index c22b6b6c6..b7979a4e3 100644 --- a/mssql-plugin/src/e2e-test/resources/pluginParameters.properties +++ b/mssql-plugin/src/e2e-test/resources/pluginParameters.properties @@ -1,4 +1,4 @@ -driverName=sqlserver +driverName=sqlserver42 databaseName=temp1 sourceRef=source targetRef=target @@ -13,13 +13,13 @@ datatypeColumns=(ID VARCHAR(100) PRIMARY KEY, COL1 TINYINT, COL2 SMALLINT, COL3 COL5 BIT, COL6 DECIMAL(38, 0), COL7 DECIMAL(10, 4), COL8 DECIMAL(5, 0), COL9 SMALLMONEY, COL10 MONEY, \ COL11 NUMERIC(38, 0), COL12 NUMERIC(10, 4), COL13 FLOAT, COL14 REAL, COL15 DATE, COL20 TIME(0), COL21 CHAR(100), \ COL22 VARCHAR(100) , COL23 TEXT, COL24 NCHAR(100), COL25 NVARCHAR(100), COL26 NTEXT, COL27 BINARY(100), COL28 VARBINARY(100), \ - COL30 HIERARCHYID, COL32 XML, COL33 GEOGRAPHY, COL34 GEOMETRY) + COL30 HIERARCHYID, COL32 XML, COL33 GEOGRAPHY, COL34 GEOMETRY, COL35 DATETIME, COL36 DATETIME2(0), COL37 DATETIMEOFFSET(0)) datatypeColumnsList=(ID, COL1, COL2, COL3, COL4, COL5, COL6, COL7, COL8, COL9, COL10, COL11, COL12, \ - COL13, COL14, COL15, COL20, COL21, COL22, COL23, COL24, COL25, COL26, COL27, COL28, COL30, COL32, COL33, COL34) + COL13, COL14, COL15, COL20, COL21, COL22, COL23, COL24, COL25, COL26, COL27, COL28, COL30, COL32, COL33, COL34, COL35) datatypeValues=VALUES ('USER1',1, 111, 1213232312, 1242343541515455, 1, 10, 1.1235, 1, 99999.0000, 10.5000, 1, 1.2346, 1.23, \ 88888885248, '2023-01-01', '12:00:00', 'ABCDEF', 'ABC', 'Sample text', '$#', \ '$#', '$#', 1, 0x12345, '/1/1/', 'abc', \ - 'POINT(10 10)', 'POINT(10 10)') + 'POINT(10 10)', 'POINT(10 10)', '2023-01-01 01:00:00.000', '2023-01-01 01:00:00.000', '2025-12-10 12:32:10 +01:00') outputDatatypesSchema=[{"key":"ID","value":"string"}, {"key":"COL1","value":"int"}, {"key":"COL2","value":"int"},{"key":"COL3","value":"int"},\ {"key":"COL4","value":"long"},{"key":"COL5","value":"boolean"},{"key":"COL6","value":"decimal"},{"key":"COL7","value":"decimal"}, \ {"key":"COL8","value":"decimal"},{"key":"COL9","value":"decimal"},{"key":"COL10","value":"decimal"},{"key":"COL11","value":"decimal"},\ @@ -28,14 +28,14 @@ outputDatatypesSchema=[{"key":"ID","value":"string"}, {"key":"COL1","value":"int {"key":"COL22","value":"string"},{"key":"COL23","value":"string"},\ {"key":"COL24","value":"string"},{"key":"COL25","value":"string"},{"key":"COL26","value":"string"},{"key":"COL27","value":"bytes"},\ {"key":"COL28","value":"bytes"},{"key":"COL30","value":"bytes"},\ - {"key":"COL32","value":"string"},{"key":"COL33","value":"bytes"},{"key":"COL34","value":"bytes"}] + {"key":"COL32","value":"string"},{"key":"COL33","value":"bytes"},{"key":"COL34","value":"bytes"},{"key":"COL35","value":"datetime"},\ + {"key":"COL36","value":"datetime"},{"key":"COL37","value":"datetime"}] imageColumns=(ID VARCHAR(100) PRIMARY KEY, COL1 IMAGE) imageColumnsList=(ID,COL1) imageValues=VALUES ('User1', '0x48692054686572652120486F772061726520796F75206665656C696E6720746F646179203F') outputDatatypesSchema2=[{"key":"ID","value":"string"},{"key":"COL1","value":"bytes"}] - uniqueIdentifierColumns=(ID VARCHAR(100) PRIMARY KEY, COL1 UNIQUEIDENTIFIER) uniqueIdentifierColumnsList=(ID, COL1) uniqueIdentifierValues=VALUES ('User1', '6F9619FF-8B86-D011-B42D-00C04FC964FF') From 938611d6d7c756ddf28b23747637165730429ff8 Mon Sep 17 00:00:00 2001 From: nikitapaliwal Date: Tue, 18 Apr 2023 10:49:05 +0530 Subject: [PATCH 5/6] Added datetime datatypes --- .../features/mssql/DatatypeDateTime.feature | 65 +++++++++++++++++++ .../java/io.cdap.plugin/MssqlClient.java | 24 +++++++ .../common.stepsdesign/TestSetupHooks.java | 8 +++ .../resources/pluginParameters.properties | 15 +++-- 4 files changed, 107 insertions(+), 5 deletions(-) create mode 100644 mssql-plugin/src/e2e-test/features/mssql/DatatypeDateTime.feature diff --git a/mssql-plugin/src/e2e-test/features/mssql/DatatypeDateTime.feature b/mssql-plugin/src/e2e-test/features/mssql/DatatypeDateTime.feature new file mode 100644 index 000000000..0e82b034e --- /dev/null +++ b/mssql-plugin/src/e2e-test/features/mssql/DatatypeDateTime.feature @@ -0,0 +1,65 @@ +# +# Copyright © 2023 Cask Data, Inc. +# +# Licensed 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. +# + +@Mssql +Feature: Mssql - Verify Mssql source data transfer + @MSSQL_SOURCE_DATATYPES_DATETIME_TEST @MSSQL_SINK_TEST @Mssql_Required + Scenario: To verify data is getting transferred from Mssql to Mssql successfully + Given Open Datafusion Project to configure pipeline + When Expand Plugin group in the LHS plugins list: "Source" + When Select plugin: "SQL Server" from the plugins list as: "Source" + When Expand Plugin group in the LHS plugins list: "Sink" + When Select plugin: "SQL Server" from the plugins list as: "Sink" + Then Connect plugins: "SQL Server" and "SQL Server2" to establish connection + Then Navigate to the properties page of plugin: "SQL Server" + Then Select dropdown plugin property: "select-jdbcPluginName" with option value: "driverName" + Then Replace input plugin property: "host" with value: "host" for Credentials and Authorization related fields + Then Replace input plugin property: "port" with value: "port" for Credentials and Authorization related fields + Then Replace input plugin property: "user" with value: "username" for Credentials and Authorization related fields + Then Replace input plugin property: "password" with value: "password" for Credentials and Authorization related fields + Then Enter input plugin property: "referenceName" with value: "sourceRef" + Then Replace input plugin property: "database" with value: "databaseName" + Then Enter textarea plugin property: "importQuery" with value: "selectQuery" + Then Click on the Get Schema button + Then Verify the Output Schema matches the Expected Schema: "outputDatatypesSchema4" + Then Validate "SQL Server" plugin properties + Then Close the Plugin Properties page + Then Navigate to the properties page of plugin: "SQL Server2" + Then Select dropdown plugin property: "select-jdbcPluginName" with option value: "driverName" + Then Replace input plugin property: "host" with value: "host" for Credentials and Authorization related fields + Then Replace input plugin property: "port" with value: "port" for Credentials and Authorization related fields + Then Replace input plugin property: "database" with value: "databaseName" + Then Replace input plugin property: "tableName" with value: "targetTable" + Then Replace input plugin property: "dbSchemaName" with value: "schema" + Then Replace input plugin property: "user" with value: "username" for Credentials and Authorization related fields + Then Replace input plugin property: "password" with value: "password" for Credentials and Authorization related fields + Then Enter input plugin property: "referenceName" with value: "targetRef" + Then Validate "SQL Server2" plugin properties + Then Close the Plugin Properties page + Then Save the pipeline + Then Preview and run the pipeline + Then Verify the preview of pipeline is "success" + Then Click on preview data for Mssql sink + Then Verify preview output schema matches the outputSchema captured in properties + Then Close the preview data + Then Deploy the pipeline + Then Run the Pipeline in Runtime + Then Wait till pipeline is in running state + Then Open and capture logs + Then Verify the pipeline status is "Succeeded" + Then Validate records transferred to target table are equal to number of records from the source table + + diff --git a/mssql-plugin/src/e2e-test/java/io.cdap.plugin/MssqlClient.java b/mssql-plugin/src/e2e-test/java/io.cdap.plugin/MssqlClient.java index 941149549..14cd3d2d3 100644 --- a/mssql-plugin/src/e2e-test/java/io.cdap.plugin/MssqlClient.java +++ b/mssql-plugin/src/e2e-test/java/io.cdap.plugin/MssqlClient.java @@ -155,6 +155,30 @@ public static void createTargetUniqueIdentifierTable(String targetTable, String } } + public static void createSourceDateTimeTable(String sourceTable, String schema) throws SQLException, + ClassNotFoundException { + try (Connection connect = getMssqlConnection(); Statement statement = connect.createStatement()) { + String dateTimeColumns = PluginPropertyUtils.pluginProp("dateTimeColumns"); + String createSourceTableQuery3 = createTableQuery(sourceTable, schema, dateTimeColumns); + statement.executeUpdate(createSourceTableQuery3); + + // Insert dummy data. + String dateTimeValues = PluginPropertyUtils.pluginProp("dateTimeValues"); + String dateTimeColumnsList = PluginPropertyUtils.pluginProp("dateTimeColumnsList"); + statement.executeUpdate(insertQuery(sourceTable, schema, dateTimeColumnsList, + dateTimeValues)); + } + } + + public static void createTargetDateTimeTable(String targetTable, String schema) throws SQLException, + ClassNotFoundException { + try (Connection connect = getMssqlConnection(); Statement statement = connect.createStatement()) { + String dateTimeColumns = PluginPropertyUtils.pluginProp("dateTimeColumns"); + String createTargetTableQuery3 = createTableQuery(targetTable, schema, dateTimeColumns); + statement.executeUpdate(createTargetTableQuery3); + } + } + public static void deleteTables(String schema, String[] tables) throws SQLException, ClassNotFoundException { try (Connection connect = getMssqlConnection(); Statement statement = connect.createStatement()) { diff --git a/mssql-plugin/src/e2e-test/java/io.cdap.plugin/common.stepsdesign/TestSetupHooks.java b/mssql-plugin/src/e2e-test/java/io.cdap.plugin/common.stepsdesign/TestSetupHooks.java index 95e625f82..02737fe1f 100644 --- a/mssql-plugin/src/e2e-test/java/io.cdap.plugin/common.stepsdesign/TestSetupHooks.java +++ b/mssql-plugin/src/e2e-test/java/io.cdap.plugin/common.stepsdesign/TestSetupHooks.java @@ -73,6 +73,14 @@ public static void createDatatypesTablesUniqueIdentifier() throws SQLException, PluginPropertyUtils.pluginProp("schema")); } + @Before(order = 2, value = "@MSSQL_SOURCE_DATATYPES_DATETIME_TEST") + public static void createDatatypesTablesDateTime() throws SQLException, ClassNotFoundException { + MssqlClient.createSourceDateTimeTable(PluginPropertyUtils.pluginProp("sourceTable"), + PluginPropertyUtils.pluginProp("schema")); + MssqlClient.createTargetDateTimeTable(PluginPropertyUtils.pluginProp("targetTable"), + PluginPropertyUtils.pluginProp("schema")); + } + @After(order = 1, value = "@MSSQL_SINK_TEST") public static void dropTables() throws SQLException, ClassNotFoundException { MssqlClient.deleteTables(PluginPropertyUtils.pluginProp("schema"), diff --git a/mssql-plugin/src/e2e-test/resources/pluginParameters.properties b/mssql-plugin/src/e2e-test/resources/pluginParameters.properties index b7979a4e3..1d439bd83 100644 --- a/mssql-plugin/src/e2e-test/resources/pluginParameters.properties +++ b/mssql-plugin/src/e2e-test/resources/pluginParameters.properties @@ -13,13 +13,13 @@ datatypeColumns=(ID VARCHAR(100) PRIMARY KEY, COL1 TINYINT, COL2 SMALLINT, COL3 COL5 BIT, COL6 DECIMAL(38, 0), COL7 DECIMAL(10, 4), COL8 DECIMAL(5, 0), COL9 SMALLMONEY, COL10 MONEY, \ COL11 NUMERIC(38, 0), COL12 NUMERIC(10, 4), COL13 FLOAT, COL14 REAL, COL15 DATE, COL20 TIME(0), COL21 CHAR(100), \ COL22 VARCHAR(100) , COL23 TEXT, COL24 NCHAR(100), COL25 NVARCHAR(100), COL26 NTEXT, COL27 BINARY(100), COL28 VARBINARY(100), \ - COL30 HIERARCHYID, COL32 XML, COL33 GEOGRAPHY, COL34 GEOMETRY, COL35 DATETIME, COL36 DATETIME2(0), COL37 DATETIMEOFFSET(0)) + COL30 HIERARCHYID, COL32 XML, COL33 GEOGRAPHY, COL34 GEOMETRY) datatypeColumnsList=(ID, COL1, COL2, COL3, COL4, COL5, COL6, COL7, COL8, COL9, COL10, COL11, COL12, \ - COL13, COL14, COL15, COL20, COL21, COL22, COL23, COL24, COL25, COL26, COL27, COL28, COL30, COL32, COL33, COL34, COL35) + COL13, COL14, COL15, COL20, COL21, COL22, COL23, COL24, COL25, COL26, COL27, COL28, COL30, COL32, COL33, COL34) datatypeValues=VALUES ('USER1',1, 111, 1213232312, 1242343541515455, 1, 10, 1.1235, 1, 99999.0000, 10.5000, 1, 1.2346, 1.23, \ 88888885248, '2023-01-01', '12:00:00', 'ABCDEF', 'ABC', 'Sample text', '$#', \ '$#', '$#', 1, 0x12345, '/1/1/', 'abc', \ - 'POINT(10 10)', 'POINT(10 10)', '2023-01-01 01:00:00.000', '2023-01-01 01:00:00.000', '2025-12-10 12:32:10 +01:00') + 'POINT(10 10)', 'POINT(10 10)') outputDatatypesSchema=[{"key":"ID","value":"string"}, {"key":"COL1","value":"int"}, {"key":"COL2","value":"int"},{"key":"COL3","value":"int"},\ {"key":"COL4","value":"long"},{"key":"COL5","value":"boolean"},{"key":"COL6","value":"decimal"},{"key":"COL7","value":"decimal"}, \ {"key":"COL8","value":"decimal"},{"key":"COL9","value":"decimal"},{"key":"COL10","value":"decimal"},{"key":"COL11","value":"decimal"},\ @@ -28,8 +28,7 @@ outputDatatypesSchema=[{"key":"ID","value":"string"}, {"key":"COL1","value":"int {"key":"COL22","value":"string"},{"key":"COL23","value":"string"},\ {"key":"COL24","value":"string"},{"key":"COL25","value":"string"},{"key":"COL26","value":"string"},{"key":"COL27","value":"bytes"},\ {"key":"COL28","value":"bytes"},{"key":"COL30","value":"bytes"},\ - {"key":"COL32","value":"string"},{"key":"COL33","value":"bytes"},{"key":"COL34","value":"bytes"},{"key":"COL35","value":"datetime"},\ - {"key":"COL36","value":"datetime"},{"key":"COL37","value":"datetime"}] + {"key":"COL32","value":"string"},{"key":"COL33","value":"bytes"},{"key":"COL34","value":"bytes"}] imageColumns=(ID VARCHAR(100) PRIMARY KEY, COL1 IMAGE) imageColumnsList=(ID,COL1) @@ -40,3 +39,9 @@ uniqueIdentifierColumns=(ID VARCHAR(100) PRIMARY KEY, COL1 UNIQUEIDENTIFIER) uniqueIdentifierColumnsList=(ID, COL1) uniqueIdentifierValues=VALUES ('User1', '6F9619FF-8B86-D011-B42D-00C04FC964FF') outputDatatypesSchema3=[{"key":"ID","value":"string"},{"key":"COL1","value":"string"}] + +dateTimeColumns=(ID VARCHAR(100) PRIMARY KEY, COL1 DATETIME, COL2 DATETIME2(0), COL3 DATETIMEOFFSET(0)) +dateTimeColumnsList=(ID, COL1, COL2, COL3) +dateTimeValues=VALUES ('User1', '2023-01-01 01:00:00.000', '2023-01-01 01:00:00.000', '2025-12-10 12:32:10 +01:00') +outputDatatypesSchema4=[{"key":"ID","value":"string"},{"key":"COL35","value":"datetime"},\ + {"key":"COL36","value":"datetime"},{"key":"COL37","value":"datetime"}] From 1d871b3603c6e88dcfafeb9a71ab2254018eb480 Mon Sep 17 00:00:00 2001 From: nikitapaliwal Date: Tue, 18 Apr 2023 11:40:37 +0530 Subject: [PATCH 6/6] Added datetime datatypes --- .../src/e2e-test/resources/pluginParameters.properties | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mssql-plugin/src/e2e-test/resources/pluginParameters.properties b/mssql-plugin/src/e2e-test/resources/pluginParameters.properties index 1d439bd83..e75cefa47 100644 --- a/mssql-plugin/src/e2e-test/resources/pluginParameters.properties +++ b/mssql-plugin/src/e2e-test/resources/pluginParameters.properties @@ -1,4 +1,4 @@ -driverName=sqlserver42 +driverName=sqlserver databaseName=temp1 sourceRef=source targetRef=target @@ -43,5 +43,5 @@ outputDatatypesSchema3=[{"key":"ID","value":"string"},{"key":"COL1","value":"str dateTimeColumns=(ID VARCHAR(100) PRIMARY KEY, COL1 DATETIME, COL2 DATETIME2(0), COL3 DATETIMEOFFSET(0)) dateTimeColumnsList=(ID, COL1, COL2, COL3) dateTimeValues=VALUES ('User1', '2023-01-01 01:00:00.000', '2023-01-01 01:00:00.000', '2025-12-10 12:32:10 +01:00') -outputDatatypesSchema4=[{"key":"ID","value":"string"},{"key":"COL35","value":"datetime"},\ - {"key":"COL36","value":"datetime"},{"key":"COL37","value":"datetime"}] +outputDatatypesSchema4=[{"key":"ID","value":"string"},{"key":"COL1","value":"datetime"},\ + {"key":"COL2","value":"datetime"},{"key":"COL3","value":"datetime"}]