This is an automated email from the ASF dual-hosted git repository.
curth pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow-adbc.git
The following commit(s) were added to refs/heads/main by this push:
new 43ee3aa02 feat(csharp/src/Drivers/Apache): improve type name handling
for CHAR/VARCHAR/DECIMAL (#1896)
43ee3aa02 is described below
commit 43ee3aa02cc4a77b1551311396e3a88a32fb7b96
Author: Bruce Irschick <[email protected]>
AuthorDate: Tue Jun 4 10:30:10 2024 -0700
feat(csharp/src/Drivers/Apache): improve type name handling for
CHAR/VARCHAR/DECIMAL (#1896)
The native response from Spark/Databricks for the type name in the
column metadata (which is used to populate the `XdbcTypeName` column in
the `GetObjects` call) includes both the base type and the precision and
scale clause for DECIMAL/CHAR/VARCHAR. For example, `DECIMAL(38,2)`,
`CHAR(255)`, `VARCHAR(255)`, etc.
This change removes the trailing precision and scale clause `( precision
[ , scale ] )` from returned value for `XdbcTypeName`. As well, the
`XdbcColumnSize` is now being populated with the maximum precision of
`VARCHAR` and the fixed length of `CHAR` types.
Examples:
| Native Type Name| XdbcTypeName | XdbcColumnSize | XdbcDecimalDigits |
| ------------- | ------------- | ------------- | ------------- |
| VARCHAR(255) | VARCHAR | 255 | `null` |
| CHAR(255) | CHAR | 255 | `null` |
| DECIMAL(38,2) | DECIMAL | 38 | 2 |
| DECIMAL(38) | DECIMAL | 38 | 0 |
| DECIMAL | DECIMAL | 10 | 0 |
| STRING | STRING | 2147483647 | `null` |
---
csharp/src/Drivers/Apache/Spark/SparkConnection.cs | 107 ++++------
.../src/Drivers/Apache/Spark/SqlTypeNameParser.cs | 227 +++++++++++++++++++++
csharp/test/Drivers/Apache/Spark/DriverTests.cs | 30 ++-
csharp/test/Drivers/Apache/Spark/StatementTests.cs | 2 +-
4 files changed, 290 insertions(+), 76 deletions(-)
diff --git a/csharp/src/Drivers/Apache/Spark/SparkConnection.cs
b/csharp/src/Drivers/Apache/Spark/SparkConnection.cs
index 33a65f0a8..798fdeec2 100644
--- a/csharp/src/Drivers/Apache/Spark/SparkConnection.cs
+++ b/csharp/src/Drivers/Apache/Spark/SparkConnection.cs
@@ -54,8 +54,6 @@ namespace Apache.Arrow.Adbc.Drivers.Apache.Spark
const string InfoDriverName = "ADBC Spark Driver";
const string InfoDriverArrowVersion = "1.0.0";
const bool InfoVendorSql = true;
- const int DecimalPrecisionDefault = 10;
- const int DecimalScaleDefault = 0;
const string ColumnDef = "COLUMN_DEF";
const string ColumnName = "COLUMN_NAME";
const string DataType = "DATA_TYPE";
@@ -154,7 +152,7 @@ namespace Apache.Arrow.Adbc.Drivers.Apache.Spark
/// </summary>
NCHAR = -15,
/// <summary>
- /// identifies the generic SQL value NULL
+ /// identifies the generic SQL type NULL
/// </summary>
NULL = 0,
/// <summary>
@@ -660,12 +658,11 @@ namespace Apache.Arrow.Adbc.Drivers.Apache.Spark
tableInfo?.ColumnName.Add(columnName);
tableInfo?.ColType.Add(colType);
tableInfo?.Nullable.Add(nullable);
- tableInfo?.TypeName.Add(typeName);
tableInfo?.IsAutoIncrement.Add(isAutoIncrement);
tableInfo?.IsNullable.Add(isNullable);
tableInfo?.ColumnDefault.Add(columnDefault);
tableInfo?.OrdinalPosition.Add(ordinalPos);
- SetPrecisionAndScale(colType, typeName, tableInfo);
+ SetPrecisionScaleAndTypeName(colType, typeName, tableInfo);
}
}
@@ -702,22 +699,47 @@ namespace Apache.Arrow.Adbc.Drivers.Apache.Spark
.Select(t => new { Index = t.Position - 1, t.ColumnName })
.ToDictionary(t => t.ColumnName, t => t.Index);
- private static void SetPrecisionAndScale(short colType, string
typeName, TableInfo? tableInfo)
+ private static void SetPrecisionScaleAndTypeName(short colType, string
typeName, TableInfo? tableInfo)
{
+ // Keep the original type name
+ tableInfo?.TypeName.Add(typeName);
switch (colType)
{
case (short)ColumnTypeId.DECIMAL:
case (short)ColumnTypeId.NUMERIC:
{
- Decimal128Type decimalType =
SqlDecimalTypeParser.ParseOrDefault(typeName, new
Decimal128Type(DecimalPrecisionDefault, DecimalScaleDefault));
- tableInfo?.Precision.Add(decimalType.Precision);
- tableInfo?.Scale.Add((short)decimalType.Scale);
+ SqlDecimalParserResult result = new
SqlDecimalTypeParser().ParseOrDefault(typeName, new
SqlDecimalParserResult(typeName));
+ tableInfo?.Precision.Add(result.Precision);
+ tableInfo?.Scale.Add((short)result.Scale);
+ tableInfo?.BaseTypeName.Add(result.BaseTypeName);
+ break;
+ }
+
+ case (short)ColumnTypeId.CHAR:
+ case (short)ColumnTypeId.NCHAR:
+ {
+ bool success = new
SqlCharTypeParser().TryParse(typeName, out SqlCharVarcharParserResult? result);
+ tableInfo?.Precision.Add(success ? result!.ColumnSize
: SqlVarcharTypeParser.VarcharColumnSizeDefault);
+ tableInfo?.Scale.Add(null);
+ tableInfo?.BaseTypeName.Add(success ?
result!.BaseTypeName : "CHAR");
+ break;
+ }
+ case (short)ColumnTypeId.VARCHAR:
+ case (short)ColumnTypeId.LONGVARCHAR:
+ case (short)ColumnTypeId.LONGNVARCHAR:
+ case (short)ColumnTypeId.NVARCHAR:
+ {
+ bool success = new
SqlVarcharTypeParser().TryParse(typeName, out SqlCharVarcharParserResult?
result);
+ tableInfo?.Precision.Add(success ? result!.ColumnSize
: SqlVarcharTypeParser.VarcharColumnSizeDefault);
+ tableInfo?.Scale.Add(null);
+ tableInfo?.BaseTypeName.Add(success ?
result!.BaseTypeName : "STRING");
break;
}
default:
tableInfo?.Precision.Add(null);
tableInfo?.Scale.Add(null);
+ tableInfo?.BaseTypeName.Add(typeName);
break;
}
}
@@ -761,7 +783,9 @@ namespace Apache.Arrow.Adbc.Drivers.Apache.Spark
case (int)ColumnTypeId.NUMERIC:
// Note: parsing the type name for SQL DECIMAL types as
the precision and scale values
// are not returned in the Thrift call to GetColumns
- return SqlDecimalTypeParser.ParseOrDefault(typeName, new
Decimal128Type(DecimalPrecisionDefault, DecimalScaleDefault));
+ return new SqlDecimalTypeParser()
+ .ParseOrDefault(typeName, new
SqlDecimalParserResult(typeName))
+ .Decimal128Type;
case (int)ColumnTypeId.NULL:
return NullType.Default;
case (int)ColumnTypeId.ARRAY:
@@ -897,11 +921,13 @@ namespace Apache.Arrow.Adbc.Drivers.Apache.Spark
{
columnNameBuilder.Append(tableInfo.ColumnName[i]);
ordinalPositionBuilder.Append(tableInfo.OrdinalPosition[i]);
- remarksBuilder.Append("");
+ // Use the "remarks" field to store the original type name
value
+ remarksBuilder.Append(tableInfo.TypeName[i]);
xdbcColumnSizeBuilder.Append(tableInfo.Precision[i]);
xdbcDecimalDigitsBuilder.Append(tableInfo.Scale[i]);
xdbcDataTypeBuilder.Append(tableInfo.ColType[i]);
- xdbcTypeNameBuilder.Append(tableInfo.TypeName[i]);
+ // Just the base type name without precision or scale clause
+ xdbcTypeNameBuilder.Append(tableInfo.BaseTypeName[i]);
xdbcNumPrecRadixBuilder.AppendNull();
xdbcNullableBuilder.Append(tableInfo.Nullable[i]);
xdbcColumnDefBuilder.Append(tableInfo.ColumnDefault[i]);
@@ -963,61 +989,6 @@ namespace Apache.Arrow.Adbc.Drivers.Apache.Spark
return builder.ToString();
}
- /// <summary>
- /// Provides a parser for SQL DECIMAL type definitions.
- /// </summary>
- private static class SqlDecimalTypeParser
- {
- // Pattern is based on this definition
- //
https://docs.databricks.com/en/sql/language-manual/data-types/decimal-type.html#syntax
- // { DECIMAL | DEC | NUMERIC } [ ( p [ , s ] ) ]
- // p: Optional maximum precision (total number of digits) of the
number between 1 and 38. The default is 10.
- // s: Optional scale of the number between 0 and p. The number of
digits to the right of the decimal point. The default is 0.
- private static readonly Regex s_expression = new(
-
@"^\s*(?<typeName>((DECIMAL)|(DEC)|(NUMERIC)))(\s*\(\s*((?<precision>\d{1,2})(\s*\,\s*(?<scale>\d{1,2}))?)\s*\))?\s*$",
- RegexOptions.IgnoreCase | RegexOptions.Compiled |
RegexOptions.CultureInvariant);
-
- /// <summary>
- /// Parses the input string for a valid SQL DECIMAL type
definition and returns a new <see cref="Decimal128Type"/> or returns the
<c>defaultValue</c>, if invalid.
- /// </summary>
- /// <param name="input">The SQL type defintion string to
parse.</param>
- /// <param name="defaultValue">If input string is an invalid SQL
DECIMAL type definition, this value is returned instead.</param>
- /// <returns>If input string is a valid SQL DECIMAL type
definition, it returns a new <see cref="Decimal128Type"/>; otherwise
<c>defaultValue</c>.</returns>
- public static Decimal128Type ParseOrDefault(string input,
Decimal128Type defaultValue)
- {
- return TryParse(input, out Decimal128Type? candidate) ?
candidate! : defaultValue;
- }
-
- /// <summary>
- /// Tries to parse the input string for a valid SQL DECIMAL type
definition.
- /// </summary>
- /// <param name="input">The SQL type defintion string to
parse.</param>
- /// <param name="value">If successful, an new <see
cref="Decimal128Type"/> with the precision and scale set; otherwise
<c>null</c>.</param>
- /// <returns>True if it can successfully parse the type definition
input string; otherwise false.</returns>
- private static bool TryParse(string input, out Decimal128Type?
value)
- {
- // Ensure defaults are set, in case not provided in
precision/scale clause.
- int precision = DecimalPrecisionDefault;
- int scale = DecimalScaleDefault;
-
- Match match = s_expression.Match(input);
- if (!match.Success)
- {
- value = null;
- return false;
- }
-
- GroupCollection groups = match.Groups;
- Group precisionGroup = groups["precision"];
- Group scaleGroup = groups["scale"];
-
- precision = precisionGroup.Success &&
int.TryParse(precisionGroup.Value, out int candidatePrecision) ?
candidatePrecision : precision;
- scale = scaleGroup.Success && int.TryParse(scaleGroup.Value,
out int candidateScale) ? candidateScale : scale;
-
- value = new Decimal128Type(precision, scale);
- return true;
- }
- }
private string GetProductVersion()
{
@@ -1034,6 +1005,8 @@ namespace Apache.Arrow.Adbc.Drivers.Apache.Spark
public List<short> ColType { get; } = new();
+ public List<string> BaseTypeName { get; } = new();
+
public List<string> TypeName { get; } = new();
public List<short> Nullable { get; } = new();
diff --git a/csharp/src/Drivers/Apache/Spark/SqlTypeNameParser.cs
b/csharp/src/Drivers/Apache/Spark/SqlTypeNameParser.cs
new file mode 100644
index 000000000..915fb1a19
--- /dev/null
+++ b/csharp/src/Drivers/Apache/Spark/SqlTypeNameParser.cs
@@ -0,0 +1,227 @@
+/*
+* 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.Text.RegularExpressions;
+using Apache.Arrow.Types;
+
+namespace Apache.Arrow.Adbc.Drivers.Apache.Spark
+{
+ /// <summary>
+ /// Abstract and generic SQL data type name parser.
+ /// </summary>
+ /// <typeparam name="T">The <see cref="ParserResult"/> type when returning
a successful parse</typeparam>
+ internal abstract class SqlTypeNameParser<T> where T : ParserResult
+ {
+ /// <summary>
+ /// Gets the <see cref="Regex"/> expression to parse the SQL type name
+ /// </summary>
+ public abstract Regex Expression { get; }
+
+ /// <summary>
+ /// Generates the successful result of a matching parse
+ /// </summary>
+ /// <param name="input">The original SQL type name</param>
+ /// <param name="match">The successful <see cref="Match"/>
result</param>
+ /// <returns></returns>
+ public abstract T GenerateResult(string input, Match match);
+
+ /// <summary>
+ /// Tries to parse the input string for a valid SQL type definition.
+ /// </summary>
+ /// <param name="input">The SQL type defintion string to parse.</param>
+ /// <param name="result">If successful, the result; otherwise
<c>null</c>.</param>
+ /// <returns>True if it can successfully parse the type definition
input string; otherwise false.</returns>
+ public bool TryParse(string input, out T? result)
+ {
+ Match match = Expression.Match(input);
+ if (!match.Success)
+ {
+ result = default;
+ return false;
+ }
+
+ result = GenerateResult(input, match);
+ return match.Success;
+ }
+
+ /// <summary>
+ /// Parses the input string for a valid SQL type definition and
returns the result or returns the <c>defaultValue</c>, if invalid.
+ /// </summary>
+ /// <param name="input">The SQL type defintion string to parse.</param>
+ /// <param name="defaultValue">If input string is an invalid type
definition, this result is returned instead.</param>
+ /// <returns>If input string is a valid SQL type definition, it
returns the result; otherwise <c>defaultValue</c>.</returns>
+ public T ParseOrDefault(string input, T defaultValue)
+ {
+ return TryParse(input, out T? result) ? result! : defaultValue;
+ }
+ }
+
+ /// <summary>
+ /// An result for parsing a SQL data type.
+ /// </summary>
+ /// <param name="typeName">The original SQL type name to parse</param>
+ /// <param name="baseTypeName">The 'base' type name to use which is
typically more simple without sub-clauses</param>
+ internal class ParserResult(string typeName, string baseTypeName)
+ {
+ /// <summary>
+ /// The original SQL type name
+ /// </summary>
+ public string TypeName { get; } = typeName;
+
+ /// <summary>
+ /// The 'base' type name to use which is typically more simple without
sub-clauses
+ /// </summary>
+ public string BaseTypeName { get; } = baseTypeName;
+ }
+
+ /// <summary>
+ /// An result for parsing the SQL
CHAR/NCHAR/STRING/VARCHAR/NVARCHAR/LONGVARCHAR/LONGNVARCHAR data types.
+ /// </summary>
+ /// <param name="typeName">The original SQL type name to parse</param>
+ /// <param name="baseTypeName">The 'base' type name without the length
clause</param>
+ /// <param name="columnSize">The length of the column for this type
name</param>
+ internal class SqlCharVarcharParserResult(string typeName, string
baseTypeName, int columnSize) : ParserResult(typeName, baseTypeName)
+ {
+ /// <summary>
+ /// The length of the column for this type name
+ /// </summary>
+ public int ColumnSize { get; } = columnSize;
+ }
+
+ /// <summary>
+ /// An result for parsing the SQL DECIMAL/DEC/NUMERIC data types.
+ /// </summary>
+ /// <param name="typeName">The original SQL type name to parse</param>
+ /// <param name="baseTypeName">The 'base' type name without the precision
or scale clause</param>
+ /// <param name="precision">The precision of the decimal type</param>
+ /// <param name="scale">The scale (decimal digits) of the decimal
type</param>
+ internal class SqlDecimalParserResult(string typeName, string
baseTypeName, int precision, int scale) : ParserResult(typeName, baseTypeName)
+ {
+ /// <summary>
+ /// Constructs a new default result given the original type name.
+ /// </summary>
+ /// <param name="typeName">The original SQL type name to parse</param>
+ public SqlDecimalParserResult(string typeName) : this(typeName,
"DECIMAL", SqlDecimalTypeParser.DecimalPrecisionDefault,
SqlDecimalTypeParser.DecimalScaleDefault) { }
+
+ /// <summary>
+ /// The precision of the decimal type
+ /// </summary>
+ public int Precision { get; } = precision;
+
+ /// <summary>
+ /// The scale (decimal digits) of the decimal type
+ /// </summary>
+ public int Scale { get; } = scale;
+
+ /// <summary>
+ /// The <see cref='Types.Decimal128Type'/> representing the parsed
type name
+ /// </summary>
+ public Decimal128Type Decimal128Type { get; } = new
Decimal128Type(precision, scale);
+ }
+
+ /// <summary>
+ /// Provides a parser for CHAR type definitions.
+ /// </summary>
+ internal class SqlCharTypeParser :
SqlTypeNameParser<SqlCharVarcharParserResult>
+ {
+ private const string BaseTypeName = "CHAR";
+
+ private static readonly Regex s_expression = new(
+
@"^\s*(?<typeName>((CHAR)|(NCHAR)))(\s*\(\s*(?<precision>\d{1,10})\s*\))\s*$",
+ RegexOptions.IgnoreCase | RegexOptions.Compiled |
RegexOptions.CultureInvariant);
+
+ public override Regex Expression => s_expression;
+
+ public override SqlCharVarcharParserResult GenerateResult(string
input, Match match)
+ {
+ GroupCollection groups = match.Groups;
+ Group precisionGroup = groups["precision"];
+
+ int precision = int.TryParse(precisionGroup.Value, out int
candidatePrecision)
+ ? candidatePrecision
+ : throw new ArgumentException($"Unable to parse length:
'{precisionGroup.Value}'", nameof(input));
+ return new SqlCharVarcharParserResult(input, BaseTypeName,
precision);
+ }
+ }
+
+ /// <summary>
+ /// Provides a parser for SQL VARCHAR/STRING type definitions.
+ /// </summary>
+ internal class SqlVarcharTypeParser :
SqlTypeNameParser<SqlCharVarcharParserResult>
+ {
+ internal const int VarcharColumnSizeDefault = int.MaxValue;
+
+ private const string VarcharBaseTypeName = "VARCHAR";
+ private const string StringBaseTypeName = "STRING";
+
+ private static readonly Regex s_expression = new(
+
@"^\s*(?<typeName>((STRING)|(VARCHAR)|(LONGVARCHAR)|(LONGNVARCHAR)|(NVARCHAR)))(\s*\(\s*(?<precision>\d{1,10})\s*\))?\s*$",
+ RegexOptions.IgnoreCase | RegexOptions.Compiled |
RegexOptions.CultureInvariant);
+
+ public override Regex Expression => s_expression;
+
+ public override SqlCharVarcharParserResult GenerateResult(string
input, Match match)
+ {
+ GroupCollection groups = match.Groups;
+ Group precisionGroup = groups["precision"];
+ Group typeNameGroup = groups["typeName"];
+
+ string baseTypeName =
typeNameGroup.Value.Equals(StringBaseTypeName,
StringComparison.InvariantCultureIgnoreCase)
+ ? StringBaseTypeName
+ : VarcharBaseTypeName;
+ int precision = precisionGroup.Success &&
int.TryParse(precisionGroup.Value, out int candidatePrecision)
+ ? candidatePrecision
+ : VarcharColumnSizeDefault;
+ return new SqlCharVarcharParserResult(input, baseTypeName,
precision);
+ }
+ }
+
+ /// <summary>
+ /// Provides a parser for SQL DECIMAL type definitions.
+ /// </summary>
+ internal class SqlDecimalTypeParser :
SqlTypeNameParser<SqlDecimalParserResult>
+ {
+ internal const int DecimalPrecisionDefault = 10;
+ internal const int DecimalScaleDefault = 0;
+
+ private const string BaseTypeName = "DECIMAL";
+
+ // Pattern is based on this definition
+ //
https://docs.databricks.com/en/sql/language-manual/data-types/decimal-type.html#syntax
+ // { DECIMAL | DEC | NUMERIC } [ ( p [ , s ] ) ]
+ // p: Optional maximum result (total number of digits) of the number
between 1 and 38. The default is 10.
+ // s: Optional scale of the number between 0 and p. The number of
digits to the right of the decimal point. The default is 0.
+ private static readonly Regex s_expression = new(
+
@"^\s*(?<typeName>((DECIMAL)|(DEC)|(NUMERIC)))(\s*\(\s*((?<precision>\d{1,2})(\s*\,\s*(?<scale>\d{1,2}))?)\s*\))?\s*$",
+ RegexOptions.IgnoreCase | RegexOptions.Compiled |
RegexOptions.CultureInvariant);
+
+ public override Regex Expression => s_expression;
+
+ public override SqlDecimalParserResult GenerateResult(string input,
Match match)
+ {
+ GroupCollection groups = match.Groups;
+ Group precisionGroup = groups["precision"];
+ Group scaleGroup = groups["scale"];
+
+ int precision = precisionGroup.Success &&
int.TryParse(precisionGroup.Value, out int candidatePrecision) ?
candidatePrecision : DecimalPrecisionDefault;
+ int scale = scaleGroup.Success && int.TryParse(scaleGroup.Value,
out int candidateScale) ? candidateScale : DecimalScaleDefault;
+
+ return new SqlDecimalParserResult(input, BaseTypeName, precision,
scale);
+ }
+ }
+}
diff --git a/csharp/test/Drivers/Apache/Spark/DriverTests.cs
b/csharp/test/Drivers/Apache/Spark/DriverTests.cs
index 822dae2e0..8fb341f87 100644
--- a/csharp/test/Drivers/Apache/Spark/DriverTests.cs
+++ b/csharp/test/Drivers/Apache/Spark/DriverTests.cs
@@ -351,19 +351,33 @@ namespace Apache.Arrow.Adbc.Tests.Drivers.Apache.Spark
Assert.False(string.IsNullOrEmpty(column.Name));
Assert.False(string.IsNullOrEmpty(column.XdbcTypeName));
- var types =
Enum.GetValues(typeof(SupportedSparkDataType)).Cast<SupportedSparkDataType>();
-
Assert.Contains((SupportedSparkDataType)column.XdbcSqlDataType!, types);
+ var supportedTypes =
Enum.GetValues(typeof(SupportedSparkDataType)).Cast<SupportedSparkDataType>();
+
Assert.Contains((SupportedSparkDataType)column.XdbcSqlDataType!,
supportedTypes);
Assert.Equal(column.XdbcDataType, column.XdbcSqlDataType);
Assert.NotNull(column.XdbcDataType);
- Assert.Contains((SupportedSparkDataType)column.XdbcDataType!,
types);
+ Assert.Contains((SupportedSparkDataType)column.XdbcDataType!,
supportedTypes);
- bool isDecimalType = column.XdbcDataType ==
(short)SupportedSparkDataType.DECIMAL || column.XdbcDataType ==
(short)SupportedSparkDataType.NUMERIC;
- Assert.Equal(column.XdbcColumnSize.HasValue, isDecimalType);
- Assert.Equal(column.XdbcDecimalDigits.HasValue, isDecimalType);
+ HashSet<short> typesHaveColumnSize = new()
+ {
+ (short)SupportedSparkDataType.DECIMAL,
+ (short)SupportedSparkDataType.NUMERIC,
+ (short)SupportedSparkDataType.CHAR,
+ (short)SupportedSparkDataType.VARCHAR,
+ };
+ HashSet<short> typesHaveDecimalDigits = new()
+ {
+ (short)SupportedSparkDataType.DECIMAL,
+ (short)SupportedSparkDataType.NUMERIC,
+ };
+
+ bool typeHasColumnSize =
typesHaveColumnSize.Contains(column.XdbcDataType.Value);
+ Assert.Equal(column.XdbcColumnSize.HasValue,
typeHasColumnSize);
+
+ bool typeHasDecimalDigits =
typesHaveDecimalDigits.Contains(column.XdbcDataType.Value);
+ Assert.Equal(column.XdbcDecimalDigits.HasValue,
typeHasDecimalDigits);
- Assert.NotNull(column.Remarks);
- Assert.True(string.IsNullOrEmpty(column.Remarks));
+ Assert.False(string.IsNullOrEmpty(column.Remarks));
Assert.NotNull(column.XdbcColumnDef);
diff --git a/csharp/test/Drivers/Apache/Spark/StatementTests.cs
b/csharp/test/Drivers/Apache/Spark/StatementTests.cs
index 6a1e4c00a..e1e44e59f 100644
--- a/csharp/test/Drivers/Apache/Spark/StatementTests.cs
+++ b/csharp/test/Drivers/Apache/Spark/StatementTests.cs
@@ -35,7 +35,7 @@ namespace Apache.Arrow.Adbc.Tests.Drivers.Apache.Spark
[TestCaseOrderer("Apache.Arrow.Adbc.Tests.Xunit.TestOrderer",
"Apache.Arrow.Adbc.Tests")]
public class StatementTests : SparkTestBase
{
- private static List<string> DefaultTableTypes => new() { "BASE TABLE",
"VIEW" };
+ private static List<string> DefaultTableTypes => new() { "TABLE",
"VIEW" };
public StatementTests(ITestOutputHelper? outputHelper) :
base(outputHelper)
{