diff --git a/README.md b/README.md index ae924ec00..0378b5416 100644 --- a/README.md +++ b/README.md @@ -108,6 +108,10 @@ How execute a query, use query bindings, run queries synchronously and asynchron Using structured types: [Structured types](doc/StructuredTypes.md) +## Vector type + +Using vector type: [Vector type](doc/VectorType.md) + ## Stage Files Using stage files within PUT/GET commands: diff --git a/Snowflake.Data.Tests/IntegrationTests/StructuredArraysIT.cs b/Snowflake.Data.Tests/IntegrationTests/StructuredArraysIT.cs index 142f1eae3..aee5e666e 100644 --- a/Snowflake.Data.Tests/IntegrationTests/StructuredArraysIT.cs +++ b/Snowflake.Data.Tests/IntegrationTests/StructuredArraysIT.cs @@ -28,7 +28,7 @@ public void TestSelectArray() Assert.IsTrue(reader.Read()); // act - var array = reader.GetStucturedArray(0); + var array = reader.GetArray(0); // assert Assert.AreEqual(3, array.Length); @@ -54,7 +54,7 @@ public void TestSelectArrayOfObjects() Assert.IsTrue(reader.Read()); // act - var array = reader.GetStucturedArray(0); + var array = reader.GetArray(0); // assert Assert.AreEqual(2, array.Length); @@ -79,7 +79,7 @@ public void TestSelectArrayOfArrays() Assert.IsTrue(reader.Read()); // act - var array = reader.GetStucturedArray(0); + var array = reader.GetArray(0); // assert Assert.AreEqual(2, array.Length); @@ -104,7 +104,7 @@ public void TestSelectArrayOfMap() Assert.IsTrue(reader.Read()); // act - var array = reader.GetStucturedArray>(0); + var array = reader.GetArray>(0); // assert Assert.AreEqual(1, array.Length); @@ -134,7 +134,7 @@ public void TestSelectSemiStructuredTypesInArray(string valueSfString, string ex Assert.IsTrue(reader.Read()); // act - var array = reader.GetStucturedArray(0); + var array = reader.GetArray(0); // assert Assert.NotNull(array); @@ -159,7 +159,7 @@ public void TestSelectArrayOfIntegers() Assert.IsTrue(reader.Read()); // act - var array = reader.GetStucturedArray(0); + var array = reader.GetArray(0); // assert Assert.AreEqual(3, array.Length); @@ -184,7 +184,7 @@ public void TestSelectArrayOfLong() Assert.IsTrue(reader.Read()); // act - var array = reader.GetStucturedArray(0); + var array = reader.GetArray(0); // assert Assert.AreEqual(3, array.Length); @@ -209,7 +209,7 @@ public void TestSelectArrayOfFloats() Assert.IsTrue(reader.Read()); // act - var array = reader.GetStucturedArray(0); + var array = reader.GetArray(0); // assert Assert.AreEqual(3, array.Length); @@ -234,7 +234,7 @@ public void TestSelectArrayOfDoubles() Assert.IsTrue(reader.Read()); // act - var array = reader.GetStucturedArray(0); + var array = reader.GetArray(0); // assert Assert.AreEqual(3, array.Length); @@ -259,7 +259,7 @@ public void TestSelectArrayOfDoublesWithExponentNotation() Assert.IsTrue(reader.Read()); // act - var array = reader.GetStucturedArray(0); + var array = reader.GetArray(0); // assert Assert.AreEqual(2, array.Length); @@ -284,7 +284,7 @@ public void TestSelectStringArrayWithNulls() Assert.IsTrue(reader.Read()); // act - var array = reader.GetStucturedArray(0); + var array = reader.GetArray(0); // assert Assert.AreEqual(3, array.Length); @@ -309,7 +309,7 @@ public void TestSelectIntArrayWithNulls() Assert.IsTrue(reader.Read()); // act - var array = reader.GetStucturedArray(0); + var array = reader.GetArray(0); // assert Assert.AreEqual(3, array.Length); @@ -334,7 +334,7 @@ public void TestSelectNullArray() Assert.IsTrue(reader.Read()); // act - var nullArray = reader.GetStucturedArray(0); + var nullArray = reader.GetArray(0); // assert Assert.IsNull(nullArray); @@ -358,7 +358,7 @@ public void TestThrowExceptionForInvalidArray() Assert.IsTrue(reader.Read()); // act - var thrown = Assert.Throws(() => reader.GetStucturedArray(0)); + var thrown = Assert.Throws(() => reader.GetArray(0)); // assert SnowflakeDbExceptionAssert.HasErrorCode(thrown, SFError.STRUCTURED_TYPE_READ_DETAILED_ERROR); @@ -384,7 +384,7 @@ public void TestThrowExceptionForInvalidArrayElement() Assert.IsTrue(reader.Read()); // act - var thrown = Assert.Throws(() => reader.GetStucturedArray(0)); + var thrown = Assert.Throws(() => reader.GetArray(0)); // assert SnowflakeDbExceptionAssert.HasErrorCode(thrown, SFError.STRUCTURED_TYPE_READ_ERROR); @@ -411,7 +411,7 @@ public void TestThrowExceptionForNextedInvalidElement() Assert.IsTrue(reader.Read()); // act - var thrown = Assert.Throws(() => reader.GetStucturedArray(0)); + var thrown = Assert.Throws(() => reader.GetArray(0)); // assert SnowflakeDbExceptionAssert.HasErrorCode(thrown, SFError.STRUCTURED_TYPE_READ_DETAILED_ERROR); diff --git a/Snowflake.Data/Client/SnowflakeDbDataReader.cs b/Snowflake.Data/Client/SnowflakeDbDataReader.cs index 7d624bd80..170c50819 100755 --- a/Snowflake.Data/Client/SnowflakeDbDataReader.cs +++ b/Snowflake.Data/Client/SnowflakeDbDataReader.cs @@ -253,7 +253,7 @@ public override int GetValues(object[] values) return count; } - internal T GetObject(int ordinal) + public T GetObject(int ordinal) where T : class, new() { try @@ -282,9 +282,11 @@ public T[] GetArray(int ordinal) { var rowType = resultSet.sfResultSetMetaData.rowTypes[ordinal]; var fields = rowType.fields; - if (fields == null || fields.Count == 0 || !JsonToStructuredTypeConverter.IsVectorType(rowType.type)) + var isArrayOrVector = JsonToStructuredTypeConverter.IsArrayType(rowType.type) || + JsonToStructuredTypeConverter.IsVectorType(rowType.type); + if (fields == null || fields.Count == 0 || !isArrayOrVector) { - throw new StructuredTypesReadingException($"Method GetArray<{typeof(T)}> can be used only for vector types"); + throw new StructuredTypesReadingException($"Method GetArray<{typeof(T)}> can be used only for for structured array or vector types"); } var stringValue = GetString(ordinal); @@ -299,30 +301,7 @@ public T[] GetArray(int ordinal) } } - internal T[] GetStucturedArray(int ordinal) - { - try - { - var rowType = resultSet.sfResultSetMetaData.rowTypes[ordinal]; - var fields = rowType.fields; - if (fields == null || fields.Count == 0 || !JsonToStructuredTypeConverter.IsArrayType(rowType.type)) - { - throw new StructuredTypesReadingException($"Method GetArray<{typeof(T)}> can be used only for structured array"); - } - - var stringValue = GetString(ordinal); - var json = stringValue == null ? null : JArray.Parse(stringValue); - return JsonToStructuredTypeConverter.ConvertArray(fields, json); - } - catch (Exception e) - { - if (e is SnowflakeDbException) - throw; - throw StructuredTypesReadingHandler.ToSnowflakeDbException(e, "when getting an array"); - } - } - - internal Dictionary GetMap(int ordinal) + public Dictionary GetMap(int ordinal) { try { diff --git a/doc/StructuredTypes.md b/doc/StructuredTypes.md index 2b78b21e0..bc45d98c9 100644 --- a/doc/StructuredTypes.md +++ b/doc/StructuredTypes.md @@ -18,11 +18,7 @@ Currently, reading structured types is available only for JSON result format, so ALTER SESSION SET DOTNET_QUERY_RESULT_FORMAT = JSON; ``` -You can enable the feature by setting parameters: -```sql -ALTER SESSION SET ENABLE_STRUCTURED_TYPES_IN_CLIENT_RESPONSE = true; -ALTER SESSION SET IGNORE_CLIENT_VERSION_IN_STRUCTURED_TYPES_RESPONSE = true; -``` +The structured types feature is enabled starting from v4.2.0 driver version. ## Structured types vs semi-structured types diff --git a/doc/VectorType.md b/doc/VectorType.md new file mode 100644 index 000000000..fcf3cdaa4 --- /dev/null +++ b/doc/VectorType.md @@ -0,0 +1,18 @@ +# Vector type + +Vector type represents an array of either integer or float type and a fixed size. +Examples: +- `[4, 5, 6]::VECTOR(INT, 3)` is a 3 elements vector of integers +- `[1.1, 2.2]::VECTOR(FLOAT, 2)` is a 2 elements vector of floats + +More about vectors you can read here: [Vector data types](https://docs.snowflake.com/en/sql-reference/data-types-vector). + +The driver allows to read a vector column into `int[]` or `float[]` arrays by calling `T[] SnowflakeDbReader.GetArray(int ordinal)` +method for either int or float types. + +```csharp +var reader = (SnowflakeDbDataReader) command.ExecuteReader(); +Assert.IsTrue(reader.Read()); +int[] intVector = reader.GetArray(0); +float[] floatVector = reader.GetArray(1); +```