This is an automated email from the ASF dual-hosted git repository.

curth pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow-adbc.git


The following commit(s) were added to refs/heads/main by this push:
     new ccc989aa test(csharp/test/Drivers/Interop/Snowflake): Add testing for 
CAST functions (#1467)
ccc989aa is described below

commit ccc989aac620da394e439a6dddd2770e1173bd07
Author: Bruce Irschick <[email protected]>
AuthorDate: Tue Jan 23 07:18:54 2024 -0800

    test(csharp/test/Drivers/Interop/Snowflake): Add testing for CAST functions 
(#1467)
    
    Adds test for C# interop layer for the Snowflake driver on the CAST and
    TO_* functions.
    * Used the explicit TO_* functions instead of the generic CAST function.
    * Ignored many TO_* variants which were aliases for the same function.
    
    Includes tests for the following cast functions.
    
    - [X] TO_DOUBLE
    - [X] TO_BOOLEAN
    - [X] TO_NUMERIC
    - [X] TO_VARCHAR
    - [X] TO_OBJECT
    - [X] TO_ARRAY
    - [X] TO_VARIANT
    - [X] TRY_TO_NUMERIC
    - [X] TRY_TO_TIMESTAMP
    - [X] TRY_TO_BOOLEAN
---
 csharp/test/Drivers/Interop/Snowflake/CastTests.cs | 440 +++++++++++++++++++++
 1 file changed, 440 insertions(+)

diff --git a/csharp/test/Drivers/Interop/Snowflake/CastTests.cs 
b/csharp/test/Drivers/Interop/Snowflake/CastTests.cs
new file mode 100644
index 00000000..aa4d3bad
--- /dev/null
+++ b/csharp/test/Drivers/Interop/Snowflake/CastTests.cs
@@ -0,0 +1,440 @@
+/*
+* 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.
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using Apache.Arrow.Ipc;
+using Apache.Arrow.Types;
+using Xunit;
+using Xunit.Abstractions;
+
+namespace Apache.Arrow.Adbc.Tests.Drivers.Interop.Snowflake
+{
+    // TODO: When supported, use prepared statements instead of SQL string 
literals
+    //      Which will better test how the driver handles values sent/received
+
+    public class CastTests : IDisposable
+    {
+        private const string ARRAY = "ARRAY";
+        private const string BOOLEAN = "BOOLEAN";
+        private const string NUMERIC = "NUMERIC";
+        private const string OBJECT = "OBJECT";
+        private const string VARCHAR = "VARCHAR";
+        private const string VARIANT = "VARIANT";
+        private const string TIMESTAMP_TZ = "TIMESTAMP_TZ";
+        private const string DOUBLE = "DOUBLE";
+        private const string BIGINT = "BIGINT";
+        private const string INTEGER = "INTEGER";
+        private const string TO_VARCHAR = "TO_VARCHAR";
+        private const string TO_DOUBLE = "TO_DOUBLE";
+        private const string TO_BOOLEAN = "TO_BOOLEAN";
+        private const string TO_NUMERIC = "TO_NUMERIC";
+        private const string TO_TIMESTAMP_TZ = "TO_TIMESTAMP_TZ";
+        private const string TO_DATE = "TO_DATE";
+        private const string TO_TIME = "TO_TIME";
+        private const string TO_ARRAY = "TO_ARRAY";
+        private const string TO_VARIANT = "TO_VARIANT";
+        private const string TO_OBJECT = "TO_OBJECT";
+        private const string TRY_TO_NUMERIC = "TRY_TO_NUMERIC";
+        private const string TRY_TO_BOOLEAN = "TRY_TO_BOOLEAN";
+        private const string TRY_TO_TIMESTAMP_TZ = "TRY_TO_TIMESTAMP_TZ";
+        private const string COLUMN_NAME = "SOURCE_COLUMN";
+        static readonly string s_testTablePrefix = "ADBCCASTTEST_"; // Make 
configurable? Also; must be all caps if not double quoted
+        readonly SnowflakeTestConfiguration _snowflakeTestConfiguration;
+        readonly AdbcConnection _connection;
+        readonly AdbcStatement _statement;
+        readonly string _catalogSchema;
+        readonly Dictionary<string, string> _columnSpecifications;
+        private readonly ITestOutputHelper _output;
+        private bool _disposed = false;
+
+        /// <summary>
+        /// Validates that specific conversion and casting functions perform 
correctly.
+        /// Note: Does not test the generic CAST and TRY_CAST, but instead 
uses the
+        /// direct conversion functions.
+        /// </summary>
+        public CastTests(ITestOutputHelper output)
+        {
+            
Skip.IfNot(Utils.CanExecuteTestConfig(SnowflakeTestingUtils.SNOWFLAKE_TEST_CONFIG_VARIABLE));
+            _snowflakeTestConfiguration = 
SnowflakeTestingUtils.TestConfiguration;
+            Dictionary<string, string> parameters = new Dictionary<string, 
string>();
+            Dictionary<string, string> options = new Dictionary<string, 
string>();
+            AdbcDriver snowflakeDriver = 
SnowflakeTestingUtils.GetSnowflakeAdbcDriver(_snowflakeTestConfiguration, out 
parameters);
+            AdbcDatabase adbcDatabase = snowflakeDriver.Open(parameters);
+            _connection = adbcDatabase.Connect(options);
+            _statement = _connection.CreateStatement();
+            _catalogSchema = string.Format("{0}.{1}", 
_snowflakeTestConfiguration.Metadata.Catalog, 
_snowflakeTestConfiguration.Metadata.Schema);
+            _output = output;
+            // Simplify TIMEZONE tests so we don't have to deal with time zone 
offsets.
+            SetSessionTimezone(_statement, "UTC");
+        }
+
+        [SkippableTheory]
+        // From NUMERIC
+        [InlineData(BIGINT, "2345", "2345", ArrowTypeId.String, TO_VARCHAR)]
+        [InlineData(INTEGER, "2345", "2345", ArrowTypeId.String, TO_VARCHAR)]
+        [InlineData(NUMERIC + "(1,0)", "-9", "-09.00", ArrowTypeId.String, 
TO_VARCHAR, COLUMN_NAME + ", '00.00'")]
+        [InlineData(NUMERIC + "(1,0)", "9", "09.00 ", ArrowTypeId.String, 
TO_VARCHAR, COLUMN_NAME + ", '00.00MI'")]
+        [InlineData(NUMERIC + "(38,2)", "9.50", 9.5, ArrowTypeId.Double, 
TO_DOUBLE)]
+        [InlineData(NUMERIC + "(1,0)", "1", true, ArrowTypeId.Boolean, 
TO_BOOLEAN)]
+        [InlineData(NUMERIC + "(1,0)", "0", false, ArrowTypeId.Boolean, 
TO_BOOLEAN)]
+        // From DOUBLE
+        [InlineData(DOUBLE, "2345.67", "2345.67", ArrowTypeId.String, 
TO_VARCHAR)]
+        [InlineData(DOUBLE, "2345.67", 2345.67, ArrowTypeId.Double, TO_DOUBLE)]
+        [InlineData(DOUBLE, "2345.5", 2346, ArrowTypeId.Decimal128, 
TO_NUMERIC)] // Rounded up
+        [InlineData(DOUBLE, "2345.4", 2345, ArrowTypeId.Decimal128, 
TO_NUMERIC)] // Rounded down
+        [InlineData(DOUBLE, "2345.67", 2345.67, ArrowTypeId.Decimal128, 
TO_NUMERIC, COLUMN_NAME + ", 6, 2")]
+        // From BOOLEAN
+        [InlineData(BOOLEAN, "'true'", "true", ArrowTypeId.String, TO_VARCHAR)]
+        [InlineData(BOOLEAN, "'false'", "false", ArrowTypeId.String, 
TO_VARCHAR)]
+        // From VARCHAR
+        [InlineData(VARCHAR, "'欢迎'", "欢迎", ArrowTypeId.String, TO_VARCHAR)]
+        [InlineData(VARCHAR, "'123'", 123, ArrowTypeId.Decimal128, TO_NUMERIC)]
+        [InlineData(VARCHAR, "'123.45'", 123.45, ArrowTypeId.Decimal128, 
TO_NUMERIC, COLUMN_NAME + ", 5, 2")]
+        [InlineData(VARCHAR, "'123.45'", 123, ArrowTypeId.Decimal128, 
TO_NUMERIC, COLUMN_NAME + ", 5, 0")]
+        [InlineData(VARCHAR, "'123.45'", 123.45, ArrowTypeId.Double, 
TO_DOUBLE)]
+        [InlineData(VARCHAR, "'123,456'", 123456, ArrowTypeId.Double, 
TO_DOUBLE, COLUMN_NAME + ", '000,000'")]
+        [InlineData(VARCHAR, "'NaN'", double.NaN, ArrowTypeId.Double, 
TO_DOUBLE)]
+        [InlineData(VARCHAR, "'inf'", double.PositiveInfinity, 
ArrowTypeId.Double, TO_DOUBLE)]
+        [InlineData(VARCHAR, "'-inf'", double.NegativeInfinity, 
ArrowTypeId.Double, TO_DOUBLE)]
+        [InlineData(VARCHAR, "'true'", true, ArrowTypeId.Boolean, TO_BOOLEAN)]
+        [InlineData(VARCHAR, "'fALSE'", false, ArrowTypeId.Boolean, 
TO_BOOLEAN)]
+        [InlineData(VARCHAR, "'1970-01-01 00:00:00+0000'", "1970-01-01 
00:00:00+0000", ArrowTypeId.Timestamp, TO_TIMESTAMP_TZ)]
+        [InlineData(VARCHAR, "'31/12/1970 00:00:00'", "1970-12-31 
00:00:00+0000", ArrowTypeId.Timestamp, TO_TIMESTAMP_TZ, COLUMN_NAME + ", 
'dd/mm/yyyy hh24:mi:ss'")]
+        // From TIMESTAMP/DATE/TIME
+        [InlineData(TIMESTAMP_TZ, "'1970-01-01 00:00:00+0000'", "1970-01-01 
00:00:00+0000", ArrowTypeId.Timestamp, TO_TIMESTAMP_TZ)]
+        [InlineData(TIMESTAMP_TZ, "'1970-01-01 12:34:56+0000'", "1970-01-01 
00:00:00+0000", ArrowTypeId.Date32, TO_DATE)] // Date portion, only
+        [InlineData(TIMESTAMP_TZ, "'2970-01-01 12:00:00+0000'", "2970-01-01 
12:00:00.000 Z", ArrowTypeId.String, TO_VARCHAR)]
+        [InlineData(TIMESTAMP_TZ, "'2970-01-01 12:00:00+0000'", "Jan 01, 
2970", ArrowTypeId.String, TO_VARCHAR, COLUMN_NAME + ", 'mon dd, yyyy'")]
+#if NET6_0_OR_GREATER
+        [InlineData(TIMESTAMP_TZ, "'2970-01-01 12:00:00+0000'", "1970-01-01 
12:00:00+0000", ArrowTypeId.Time64, TO_TIME)] // Time portion, only
+#else
+        [InlineData(TIMESTAMP_TZ, "'2970-01-01 12:00:00+0000'", 43200000000, 
ArrowTypeId.Time64, TO_TIME)] // Microseconds
+#endif
+        public void TestCastPositive(
+            string columnSpecification,
+            string sourceValue,
+            object expectedValue,
+            ArrowTypeId expectedType,
+            string castFunction,
+            string castExpression = null)
+        {
+            InitializeTest(columnSpecification, sourceValue, out string 
columnName, out string table);
+            SelectWithCastAndValidateValue(
+                table,
+                castFunction,
+                castExpression ?? columnName,
+                expectedValue,
+                expectedType);
+        }
+
+        [SkippableTheory]
+        [InlineData(NUMERIC, "2345", typeof(AdbcException), TO_VARCHAR, 
COLUMN_NAME + ", 123", new[] { "42601", "SQL compilation error" })] // Invalid 
format type.
+        [InlineData(NUMERIC, "2345", typeof(AdbcException), TO_VARCHAR, 
COLUMN_NAME + ", '123'", new[] { "22007", "Bad output format" })] // Invalid 
format type.
+        [InlineData(VARCHAR, "'ABC'", typeof(AdbcException), TO_NUMERIC, null, 
new[] { "22018", "Numeric value" })] // Non numeric value
+        [InlineData(VARCHAR, "'3'", typeof(AdbcException), TO_BOOLEAN, null, 
new[] { "22018", "Boolean value" })] // Non boolean value
+        [InlineData(VARCHAR, "'31/12/1970'", typeof(AdbcException), 
TO_TIMESTAMP_TZ, null, new[] { "22007", "Timestamp" })] // Non date value
+        public void TestCastNegative(
+            string columnSpecification,
+            string sourceValue,
+            Type expectedExceptionType,
+            string castFunction,
+            string castExpression = null,
+            string[] expectedExceptionTextContains = null)
+        {
+            InitializeTest(columnSpecification, sourceValue, out string 
columnName, out string table);
+            SelectWithCastAndValidateException(
+                table,
+                castFunction,
+                castExpression ?? columnName,
+                expectedExceptionType,
+                expectedExceptionTextContains);
+        }
+
+        [SkippableTheory]
+        [InlineData(ARRAY, "SELECT ARRAY_CONSTRUCT('TRUE', 'FALSE')", "[\n  
\"TRUE\",\n  \"FALSE\"\n]", ArrowTypeId.String, TO_ARRAY)]
+        [InlineData(ARRAY, "SELECT ARRAY_CONSTRUCT('TRUE', 'FALSE')", "[\n  
\"TRUE\",\n  \"FALSE\"\n]", ArrowTypeId.String, TO_VARIANT)]
+        [InlineData(BOOLEAN, "SELECT 'TRUE'", "true", ArrowTypeId.String, 
TO_VARIANT)]
+        [InlineData(NUMERIC, "SELECT 42", "42", ArrowTypeId.String, 
TO_VARIANT)]
+        [InlineData(OBJECT, "SELECT OBJECT_CONSTRUCT('fortyTwo', 
42::VARIANT)", "{\n  \"fortyTwo\": 42\n}", ArrowTypeId.String, TO_OBJECT)]
+        [InlineData(OBJECT, "SELECT OBJECT_CONSTRUCT('fortyTwo', 
42::VARIANT)", "{\n  \"fortyTwo\": 42\n}", ArrowTypeId.String, TO_VARIANT)]
+        [InlineData(OBJECT, "SELECT OBJECT_CONSTRUCT('fortyTwo', 
42::NUMERIC)", "{\n  \"fortyTwo\": 42\n}", ArrowTypeId.String, TO_VARIANT)]
+        [InlineData(VARCHAR, "SELECT 42", "\"42\"", ArrowTypeId.String, 
TO_VARIANT)]
+        [InlineData(VARIANT, "SELECT 42::VARIANT", "42", ArrowTypeId.String, 
TO_VARIANT)]
+        [InlineData(VARIANT, "SELECT 'JONES'::VARIANT", "\"JONES\"", 
ArrowTypeId.String, TO_VARIANT)]
+        public void TestCastPositiveStructured(
+            string columnSpecification,
+            string sourceValue,
+            object expectedValue,
+            ArrowTypeId expectedType,
+            string castFunction,
+            string castExpression = null)
+        {
+            InitializeTest(columnSpecification, sourceValue, out string 
columnName, out string table, useSelectSyntax: true);
+            SelectWithCastAndValidateValue(
+                table,
+                castFunction,
+                castExpression ?? columnName,
+                expectedValue,
+                expectedType);
+        }
+
+        [SkippableTheory]
+        [InlineData(VARCHAR, "'ABC'", ArrowTypeId.Decimal128, TRY_TO_NUMERIC, 
null)] // Non numeric value
+        [InlineData(VARCHAR, "'3'", ArrowTypeId.Boolean, TRY_TO_BOOLEAN, 
null)] // Non boolean value
+        [InlineData(VARCHAR, "'31/12/1970'", ArrowTypeId.Timestamp, 
TRY_TO_TIMESTAMP_TZ, null)] // Non date value
+        public void TestTryCastNegative(
+            string columnSpecification,
+            string sourceValue,
+            ArrowTypeId expectedType,
+            string castFunction,
+            string castExpression = null)
+        {
+            {
+                InitializeTest(columnSpecification, sourceValue, out string 
columnName, out string table);
+                SelectWithCastAndValidateValue(
+                    table,
+                    castFunction,
+                    castExpression ?? columnName,
+                    null, // Returns null if value cannot be converted.
+                    expectedType);
+            }
+        }
+
+        private void InitializeTest(
+            string columnSpecification,
+            string sourceValue,
+            out string columnName,
+            out string table,
+            bool useSelectSyntax = false)
+        {
+            columnName = COLUMN_NAME;
+            table = CreateTemporaryTable(
+                _statement,
+                s_testTablePrefix,
+                _catalogSchema,
+                string.Format("{0} {1}", columnName, columnSpecification));
+            if (useSelectSyntax)
+            {
+                InsertIntoFromSelect(table, columnName, sourceValue);
+            }
+            else
+            {
+                InsertSingleValue(table, columnName, sourceValue);
+            }
+        }
+
+        private void InsertSingleValue(string table, string columnName, string 
value)
+        {
+            string insertStatement = string.Format("INSERT INTO {0} ({1}) 
VALUES ({2});", table, columnName, value);
+            _output.WriteLine(insertStatement);
+            _statement.SqlQuery = insertStatement;
+            UpdateResult updateResult = _statement.ExecuteUpdate();
+            Assert.Equal(1, updateResult.AffectedRows);
+        }
+
+        private void InsertIntoFromSelect(string table, string columnName, 
string selectQuery, long expectedAffectedRows = 1)
+        {
+            string insertStatement = string.Format("INSERT INTO {0} ({1}) 
{2};", table, columnName, selectQuery);
+            _output.WriteLine(insertStatement);
+            _statement.SqlQuery = insertStatement;
+            UpdateResult updateResult = _statement.ExecuteUpdate();
+            Assert.Equal(expectedAffectedRows, updateResult.AffectedRows);
+        }
+
+        private async void SelectWithCastAndValidateValue(
+            string table,
+            string castFunction,
+            string castExpression,
+            object value,
+            ArrowTypeId expectedType)
+        {
+            QueryResult queryResult = PerformQuery(table, castFunction, 
castExpression);
+            await ValidateCast(value, expectedType, queryResult);
+        }
+
+        private void SelectWithCastAndValidateException(
+            string table,
+            string castFunction,
+            string castExpression,
+            Type expectedExceptionType,
+            string[] expectedExceptionTextContains = null)
+        {
+            Exception actualException = Assert.Throws(expectedExceptionType, 
() => PerformQuery(table, castFunction, castExpression));
+            AssertContainsAll(expectedExceptionTextContains, 
actualException.Message);
+        }
+
+        private static void AssertContainsAll(string[] expectedTexts, string 
actualText)
+        {
+            if (expectedTexts == null) { return; };
+            foreach (string text in expectedTexts)
+            {
+                Assert.Contains(text, actualText);
+            }
+        }
+
+        private QueryResult PerformQuery(string table, string castFunction, 
string castExpression)
+        {
+            string selectStatement = string.Format(
+                "SELECT {0}({1}) AS CASTRESULT FROM {2};",
+                castFunction,
+                castExpression,
+                table);
+            _output.WriteLine(selectStatement);
+            _statement.SqlQuery = selectStatement;
+            return _statement.ExecuteQuery();
+        }
+
+        private static async Task ValidateCast(object value, ArrowTypeId 
expectedType, QueryResult queryResult)
+        {
+            Assert.Equal(1, queryResult.RowCount);
+            using IArrowArrayStream stream = queryResult.Stream;
+            Field field = stream.Schema.GetFieldByName("CASTRESULT");
+            Assert.NotNull(field);
+            while (true)
+            {
+                using RecordBatch nextBatch = await 
stream.ReadNextRecordBatchAsync();
+                if (nextBatch == null) { break; }
+                Assert.Equal(expectedType, field.DataType.TypeId);
+                IArrowArray valueArray = nextBatch.Column(0);
+
+                switch (field.DataType.TypeId)
+                {
+                    case ArrowTypeId.Double:
+                        var doubleArray = valueArray as DoubleArray;
+                        for (int i = 0; i < doubleArray.Length; i++)
+                        {
+                            Assert.Equal(Convert.ToDouble(value), 
doubleArray.GetValue(i));
+                        };
+                        break;
+                    case ArrowTypeId.Int32:
+                        var int32Array = valueArray as Int32Array;
+                        for (int i = 0; i < int32Array.Length; i++)
+                        {
+                            Assert.Equal(value, int32Array.GetValue(i));
+                        };
+                        break;
+                    case ArrowTypeId.Int64:
+                        var int64Array = valueArray as Int64Array;
+                        for (int i = 0; i < int64Array.Length; i++)
+                        {
+                            Assert.Equal(value, int64Array.GetValue(i));
+                        };
+                        break;
+                    case ArrowTypeId.String:
+                        var stringArray = valueArray as StringArray;
+                        for (int i = 0; i < stringArray.Length; i++)
+                        {
+                            Assert.Equal(value, stringArray.GetString(i));
+                        };
+                        break;
+                    case ArrowTypeId.Boolean:
+                        var booleanArray = valueArray as BooleanArray;
+                        for (int i = 0; i < booleanArray.Length; i++)
+                        {
+                            Assert.Equal(value, booleanArray.GetValue(i));
+                        };
+                        break;
+                    case ArrowTypeId.Date64:
+                        var date64Array = valueArray as Date64Array;
+                        for (int i = 0; i < date64Array.Length; i++)
+                        {
+                            Assert.Equal(value, date64Array.GetValue(i));
+                        };
+                        break;
+                    case ArrowTypeId.Decimal128:
+                        var decimal128Array = valueArray as Decimal128Array;
+                        for (int i = 0; i < decimal128Array.Length; i++)
+                        {
+
+                            Assert.Equal(value == null ? null : 
Convert.ToDecimal(value), decimal128Array.GetValue(i));
+                        };
+                        break;
+                    case ArrowTypeId.Decimal256:
+                        var decimal256Array = valueArray as Decimal256Array;
+                        for (int i = 0; i < decimal256Array.Length; i++)
+                        {
+                            Assert.Equal(value, decimal256Array.GetValue(i));
+                        };
+                        break;
+                    case ArrowTypeId.Timestamp:
+                        var timestampArray = valueArray as TimestampArray;
+                        for (int i = 0; i < timestampArray.Length; i++)
+                        {
+                            Assert.Equal(value == null ? null : new 
DateTimeOffset(Convert.ToDateTime(value).ToUniversalTime()), 
timestampArray.GetTimestamp(i));
+                        };
+                        break;
+                    case ArrowTypeId.Time64:
+                        var time64Array = valueArray as Time64Array;
+                        for (int i = 0; i < time64Array.Length; i++)
+                        {
+#if NET6_0_OR_GREATER
+                            
Assert.Equal(TimeOnly.FromDateTime(Convert.ToDateTime(value).ToUniversalTime()),
 time64Array.GetTime(i));
+#else
+                            Assert.Equal(Convert.ToInt64(value), 
time64Array.GetMicroSeconds(i));
+#endif
+                        };
+                        break;
+                    case ArrowTypeId.Date32:
+                        var date32Array = valueArray as Date32Array;
+                        for (int i = 0; i < date32Array.Length; i++)
+                        {
+                            Assert.Equal(Convert.ToDateTime(value), 
date32Array.GetDateTimeOffset(i));
+                        };
+                        break;
+
+                    default:
+                        throw new ArgumentException(string.Format("Unexpected 
ArrowTypeId: {0}({1})", field.DataType.TypeId.ToString(), 
field.DataType.TypeId));
+
+                }
+            }
+        }
+
+        private static string CreateTemporaryTable(AdbcStatement statement, 
string testTablePrefix, string catalogSchema, string columns)
+        {
+            string tableName = string.Format("{0}.{1}{2}", catalogSchema, 
testTablePrefix, Guid.NewGuid().ToString().Replace("-", ""));
+            string createTableStatement = string.Format("CREATE TEMPORARY 
TABLE {0} ({1})", tableName, columns);
+            statement.SqlQuery = createTableStatement;
+            statement.ExecuteUpdate();
+            return tableName;
+        }
+
+        private static void SetSessionTimezone(AdbcStatement statement, string 
timezone)
+        {
+            statement.SqlQuery = string.Format("ALTER SESSION SET TIMEZONE = 
'{0}'", timezone);
+            UpdateResult result = statement.ExecuteUpdate();
+            Assert.Equal(-1, result.AffectedRows);
+        }
+
+        public void Dispose()
+        {
+            Dispose(true);
+            GC.SuppressFinalize(this);
+        }
+
+        protected virtual void Dispose(bool disposing)
+        {
+            if (disposing && !_disposed)
+            {
+                _connection?.Dispose();
+                _statement?.Dispose();
+                _disposed = true;
+            }
+        }
+    }
+}

Reply via email to