You are viewing a plain text version of this content. The canonical link for it is here.
Posted to github@arrow.apache.org by "birschick-bq (via GitHub)" <gi...@apache.org> on 2024/01/16 18:38:22 UTC
[PR] test:(csharp/test/Drivers/Interop/Snowflake): Add testing for CAST functions. [arrow-adbc]
birschick-bq opened a new pull request, #1467:
URL: https://github.com/apache/arrow-adbc/pull/1467
Adds test for C# interop layer 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
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] test(csharp/test/Drivers/Interop/Snowflake): Add testing for CAST functions. [arrow-adbc]
Posted by "birschick-bq (via GitHub)" <gi...@apache.org>.
birschick-bq commented on code in PR #1467:
URL: https://github.com/apache/arrow-adbc/pull/1467#discussion_r1454055149
##########
csharp/test/Drivers/Interop/Snowflake/CastTests.cs:
##########
@@ -0,0 +1,397 @@
+/*
+* 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;
+
+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 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 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()
+ {
+ 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);
+ // 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 insertNumberStatement = string.Format("INSERT INTO {0} ({1}) VALUES ({2});", table, columnName, value);
+ Console.WriteLine(insertNumberStatement);
+ _statement.SqlQuery = insertNumberStatement;
+ UpdateResult updateResult = _statement.ExecuteUpdate();
+ Assert.Equal(1, updateResult.AffectedRows);
+ }
+
+ private void InsertIntoFromSelect(string table, string columnName, string selectQuery, long expectedAffectedRows = 1)
+ {
+ string insertNumberStatement = string.Format("INSERT INTO {0} ({1}) {2};", table, columnName, selectQuery);
+ Console.WriteLine(insertNumberStatement);
+ _statement.SqlQuery = insertNumberStatement;
+ 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);
+ Console.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));
Review Comment:
Hmm. The only problem the Xunit framework don't have any overloads for adding a custom message (known issue: https://github.com/xunit/xunit/issues/350). What I can say is 1. We only every have one value to test; 2. the exception messages thrown are pretty specific with full stack trace and runtime values.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] test(csharp/test/Drivers/Interop/Snowflake): Add testing for CAST functions. [arrow-adbc]
Posted by "jduo (via GitHub)" <gi...@apache.org>.
jduo commented on code in PR #1467:
URL: https://github.com/apache/arrow-adbc/pull/1467#discussion_r1453930055
##########
csharp/test/Drivers/Interop/Snowflake/CastTests.cs:
##########
@@ -0,0 +1,397 @@
+/*
+* 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;
+
+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 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 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()
+ {
+ 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);
+ // 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 insertNumberStatement = string.Format("INSERT INTO {0} ({1}) VALUES ({2});", table, columnName, value);
+ Console.WriteLine(insertNumberStatement);
Review Comment:
Do we want to retain these console writes? Is there a logger in the framework that can be used instead?
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] test(csharp/test/Drivers/Interop/Snowflake): Add testing for CAST functions. [arrow-adbc]
Posted by "ryan-syed (via GitHub)" <gi...@apache.org>.
ryan-syed commented on code in PR #1467:
URL: https://github.com/apache/arrow-adbc/pull/1467#discussion_r1454025738
##########
csharp/test/Drivers/Interop/Snowflake/CastTests.cs:
##########
@@ -0,0 +1,397 @@
+/*
+* 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;
+
+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 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 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()
+ {
+ 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);
+ // 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")]
Review Comment:
nit: we could use constant strings for the cast functions
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] test(csharp/test/Drivers/Interop/Snowflake): Add testing for CAST functions. [arrow-adbc]
Posted by "birschick-bq (via GitHub)" <gi...@apache.org>.
birschick-bq commented on code in PR #1467:
URL: https://github.com/apache/arrow-adbc/pull/1467#discussion_r1459449708
##########
csharp/test/Drivers/Interop/Snowflake/CastTests.cs:
##########
@@ -0,0 +1,397 @@
+/*
+* 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;
+
+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 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 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()
+ {
+ 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);
+ // 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 insertNumberStatement = string.Format("INSERT INTO {0} ({1}) VALUES ({2});", table, columnName, value);
+ Console.WriteLine(insertNumberStatement);
Review Comment:
Opened #1468 to remove Console.WriteLine.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] test:(csharp/test/Drivers/Interop/Snowflake): Add testing for CAST functions. [arrow-adbc]
Posted by "github-actions[bot] (via GitHub)" <gi...@apache.org>.
github-actions[bot] commented on PR #1467:
URL: https://github.com/apache/arrow-adbc/pull/1467#issuecomment-1894311199
:warning: Please follow the [Conventional Commits format in CONTRIBUTING.md](https://github.com/apache/arrow-adbc/blob/main/CONTRIBUTING.md) for PR titles.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] test(csharp/test/Drivers/Interop/Snowflake): Add testing for CAST functions. [arrow-adbc]
Posted by "birschick-bq (via GitHub)" <gi...@apache.org>.
birschick-bq commented on code in PR #1467:
URL: https://github.com/apache/arrow-adbc/pull/1467#discussion_r1454056863
##########
csharp/test/Drivers/Interop/Snowflake/CastTests.cs:
##########
@@ -0,0 +1,397 @@
+/*
+* 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;
+
+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 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 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()
+ {
+ 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);
+ // 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 insertNumberStatement = string.Format("INSERT INTO {0} ({1}) VALUES ({2});", table, columnName, value);
+ Console.WriteLine(insertNumberStatement);
Review Comment:
@jduo - Do you want me to replace the `Console` usage in all tests?
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] test(csharp/test/Drivers/Interop/Snowflake): Add testing for CAST functions. [arrow-adbc]
Posted by "jduo (via GitHub)" <gi...@apache.org>.
jduo commented on code in PR #1467:
URL: https://github.com/apache/arrow-adbc/pull/1467#discussion_r1453928533
##########
csharp/test/Drivers/Interop/Snowflake/CastTests.cs:
##########
@@ -0,0 +1,397 @@
+/*
+* 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;
+
+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 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 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()
+ {
+ 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);
+ // 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 insertNumberStatement = string.Format("INSERT INTO {0} ({1}) VALUES ({2});", table, columnName, value);
+ Console.WriteLine(insertNumberStatement);
+ _statement.SqlQuery = insertNumberStatement;
+ UpdateResult updateResult = _statement.ExecuteUpdate();
+ Assert.Equal(1, updateResult.AffectedRows);
+ }
+
+ private void InsertIntoFromSelect(string table, string columnName, string selectQuery, long expectedAffectedRows = 1)
+ {
+ string insertNumberStatement = string.Format("INSERT INTO {0} ({1}) {2};", table, columnName, selectQuery);
+ Console.WriteLine(insertNumberStatement);
+ _statement.SqlQuery = insertNumberStatement;
+ 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);
+ Console.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));
Review Comment:
Suggestion, add a custom error message to these generic assertions to provide traceability if there's a failure (which test value is failing, which index).
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] test(csharp/test/Drivers/Interop/Snowflake): Add testing for CAST functions. [arrow-adbc]
Posted by "CurtHagenlocher (via GitHub)" <gi...@apache.org>.
CurtHagenlocher commented on code in PR #1467:
URL: https://github.com/apache/arrow-adbc/pull/1467#discussion_r1459552707
##########
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)]
Review Comment:
Until Arrow itself has better support for VARIANT types, I don't know that we can realistically do much better than this.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] test(csharp/test/Drivers/Interop/Snowflake): Add testing for CAST functions. [arrow-adbc]
Posted by "birschick-bq (via GitHub)" <gi...@apache.org>.
birschick-bq commented on code in PR #1467:
URL: https://github.com/apache/arrow-adbc/pull/1467#discussion_r1457888480
##########
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)]
Review Comment:
Note: Is it acceptable to expect that ARRAY/OBJECT/VARIANT all return String data representation? Or should it deserialize in a native data type?
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] test(csharp/test/Drivers/Interop/Snowflake): Add testing for CAST functions. [arrow-adbc]
Posted by "birschick-bq (via GitHub)" <gi...@apache.org>.
birschick-bq commented on code in PR #1467:
URL: https://github.com/apache/arrow-adbc/pull/1467#discussion_r1456501537
##########
csharp/test/Drivers/Interop/Snowflake/CastTests.cs:
##########
@@ -0,0 +1,397 @@
+/*
+* 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;
+
+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 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 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()
+ {
+ 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);
+ // 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")]
Review Comment:
Now using constants.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] test(csharp/test/Drivers/Interop/Snowflake): Add testing for CAST functions [arrow-adbc]
Posted by "CurtHagenlocher (via GitHub)" <gi...@apache.org>.
CurtHagenlocher merged PR #1467:
URL: https://github.com/apache/arrow-adbc/pull/1467
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] test(csharp/test/Drivers/Interop/Snowflake): Add testing for CAST functions. [arrow-adbc]
Posted by "birschick-bq (via GitHub)" <gi...@apache.org>.
birschick-bq commented on code in PR #1467:
URL: https://github.com/apache/arrow-adbc/pull/1467#discussion_r1454177991
##########
csharp/test/Drivers/Interop/Snowflake/CastTests.cs:
##########
@@ -0,0 +1,397 @@
+/*
+* 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;
+
+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 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 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()
+ {
+ 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);
+ // 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 insertNumberStatement = string.Format("INSERT INTO {0} ({1}) VALUES ({2});", table, columnName, value);
+ Console.WriteLine(insertNumberStatement);
Review Comment:
Done.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org