Copilot commented on code in PR #4885:
URL: https://github.com/apache/arrow-adbc/pull/4885#discussion_r4261059157


##########
csharp/src/Apache.Arrow.Adbc/C/CAdbcDriverImporter.cs:
##########
@@ -606,21 +778,193 @@ public override IsolationLevel IsolationLevel
 
             public override bool ReadOnly
             {
-                get => _readOnly ?? throw AdbcException.NotImplemented("no 
value has been set for ReadOnly");
+                get => _readOnly ??
+                    (TryGetNativeOption(AdbcOptions.Connection.ReadOnly, 
AdbcOptions.GetEnabled, out bool value)
+                        ? value
+                        : throw AdbcException.NotImplemented("no value has 
been set for ReadOnly"));
                 set
                 {
                     SetOption(AdbcOptions.Connection.ReadOnly, 
AdbcOptions.GetEnabled(value));
                     _readOnly = value;
                 }
             }
 
+            public override string? CurrentCatalog
+            {
+                get => GetOptionOrNull(AdbcOptions.Connection.CurrentCatalog);
+            }
+
+            public override string? CurrentDbSchema
+            {
+                get => GetOptionOrNull(AdbcOptions.Connection.CurrentDbSchema);
+            }
+
+            /// <summary>
+            /// Asks an ADBC 1.1 driver for a value that hasn't been set 
through this object.
+            /// Any failure yields null so that callers keep their ADBC 1.0 
behavior.
+            /// </summary>
+            private bool TryGetNativeOption<T>(string key, Func<string, T> 
parse, out T value)
+            {
+                if (IsVersion1_1)
+                {
+                    try
+                    {
+                        value = parse(GetOption(key));
+                        return true;
+                    }
+                    catch (AdbcException)
+                    {
+                    }
+                    catch (NotSupportedException)
+                    {
+                        // The driver reported a value that isn't one of the 
standard ones
+                    }
+                }
+
+                value = default!;
+                return false;
+            }
+
+            private string? GetOptionOrNull(string key)
+            {
+                // A 1.0 driver can't report the value. Don't call GetOption, 
whose 1.0
+                // fallback reads these properties.
+                if (!IsVersion1_1)
+                {
+                    return null;
+                }
+
+                try
+                {
+                    return GetOption(key);
+                }
+                catch (AdbcException e) when (e.Status == 
AdbcStatusCode.NotFound || e.Status == AdbcStatusCode.NotImplemented)
+                {
+                    return null;
+                }
+            }
+
+            private OptionFunctions Options
+            {
+                get
+                {
+                    if (_disposed) { throw new 
ObjectDisposedException(nameof(ImportedAdbcConnection)); }
+                    return _driver.ConnectionOptions;
+                }
+            }
+
+            public unsafe override void SetOptionInt64(string key, long value)
+            {
+                if (!IsVersion1_1) { base.SetOptionInt64(key, value); return; }
+                fixed (CAdbcConnection* connection = &_nativeConnection)
+                {
+                    CAdbcDriverImporter.SetOptionInt64(_driver, 
Options.SetOptionInt, connection, key, value);
+                }
+            }
+
+            public unsafe override void SetOptionDouble(string key, double 
value)
+            {
+                if (!IsVersion1_1) { base.SetOptionDouble(key, value); return; 
}
+                fixed (CAdbcConnection* connection = &_nativeConnection)
+                {
+                    CAdbcDriverImporter.SetOptionDouble(_driver, 
Options.SetOptionDouble, connection, key, value);
+                }
+            }
+
+            public unsafe override void SetOptionBytes(string key, 
ReadOnlySpan<byte> value)
+            {
+                fixed (CAdbcConnection* connection = &_nativeConnection)
+                {
+                    CAdbcDriverImporter.SetOptionBytes(_driver, 
Options.SetOptionBytes, connection, key, value);
+                }
+            }
+
+            public unsafe override string GetOption(string key)
+            {
+                if (_driver.DriverVersion < AdbcVersion.Version_1_1_0) { 
return base.GetOption(key); }
+
+                fixed (CAdbcConnection* connection = &_nativeConnection)
+                {
+                    return GetOptionString(_driver, Options.GetOption, 
connection, key);
+                }
+            }
+
+            public unsafe override long GetOptionInt64(string key)
+            {
+                if (_driver.DriverVersion < AdbcVersion.Version_1_1_0) { 
return base.GetOptionInt64(key); }
+
+                fixed (CAdbcConnection* connection = &_nativeConnection)
+                {
+                    return CAdbcDriverImporter.GetOptionInt64(_driver, 
Options.GetOptionInt, connection, key);
+                }
+            }
+
+            public unsafe override double GetOptionDouble(string key)
+            {
+                if (_driver.DriverVersion < AdbcVersion.Version_1_1_0) { 
return base.GetOptionDouble(key); }
+
+                fixed (CAdbcConnection* connection = &_nativeConnection)
+                {
+                    return CAdbcDriverImporter.GetOptionDouble(_driver, 
Options.GetOptionDouble, connection, key);
+                }
+            }
+
+            public unsafe override byte[] GetOptionBytes(string key)
+            {
+                if (_driver.DriverVersion < AdbcVersion.Version_1_1_0) { 
return base.GetOptionBytes(key); }
+
+                fixed (CAdbcConnection* connection = &_nativeConnection)
+                {
+                    return GetOptionBuffer(_driver, Options.GetOptionBytes, 
connection, key);
+                }
+            }
+
+            public unsafe override IArrowArrayStream GetStatistics(string? 
catalogPattern, string? schemaPattern, string tableNamePattern, bool 
approximate)
+            {
+                using (Utf8Helper utf8Catalog = new Utf8Helper(catalogPattern))
+                using (Utf8Helper utf8Schema = new Utf8Helper(schemaPattern))
+                using (Utf8Helper utf8Table = new Utf8Helper(tableNamePattern))
+                using (CallHelper caller = new CallHelper(_driver))

Review Comment:
   This new override calls the 1.1 `ConnectionGetStatistics` callback 
unconditionally. For a negotiated 1.0 driver, `ValidateDriver` returns before 
those callbacks are populated (`CAdbcDriverImporter.cs:183-216`), so this 
dispatches through a zero function pointer instead of the base class's 
`NotImplemented` implementation. Add an `IsVersion1_1` guard and return 
`base.GetStatistics(...)` for 1.0 drivers.
   
   This issue also appears on line 943 of the same file.



##########
csharp/src/Apache.Arrow.Adbc/C/CAdbcDriverImporter.cs:
##########
@@ -502,12 +591,87 @@ public unsafe override AdbcConnection 
Connect(IReadOnlyDictionary<string, string
 
             public unsafe override void SetOption(string key, string value)
             {
-                using (CallHelper caller = new CallHelper())
+                using (CallHelper caller = new CallHelper(_driver))
                 {
                     caller.Call(Driver.DatabaseSetOption, ref _nativeDatabase, 
key, value);
                 }
             }
 
+            public unsafe override void SetOptionInt64(string key, long value)
+            {
+                if (_driver.DriverVersion < AdbcVersion.Version_1_1_0) { 
base.SetOptionInt64(key, value); return; }
+                fixed (CAdbcDatabase* database = &_nativeDatabase)
+                {
+                    CAdbcDriverImporter.SetOptionInt64(_driver, 
Options.SetOptionInt, database, key, value);
+                }
+            }
+
+            public unsafe override void SetOptionDouble(string key, double 
value)
+            {
+                if (_driver.DriverVersion < AdbcVersion.Version_1_1_0) { 
base.SetOptionDouble(key, value); return; }
+                fixed (CAdbcDatabase* database = &_nativeDatabase)
+                {
+                    CAdbcDriverImporter.SetOptionDouble(_driver, 
Options.SetOptionDouble, database, key, value);
+                }
+            }
+
+            public unsafe override void SetOptionBytes(string key, 
ReadOnlySpan<byte> value)
+            {
+                fixed (CAdbcDatabase* database = &_nativeDatabase)
+                {
+                    CAdbcDriverImporter.SetOptionBytes(_driver, 
Options.SetOptionBytes, database, key, value);
+                }
+            }

Review Comment:
   This setter is callable on a driver negotiated as ADBC 1.0, but 
`ValidateDriver` returns before populating the 1.1 function pointers 
(`CAdbcDriverImporter.cs:183-216`). Unlike the integer and double setters 
below, this path does not fall back to the base implementation, so it invokes a 
zero `DatabaseSetOptionBytes` pointer instead of returning the documented 
`NotImplemented` status (and can crash on native-call targets). Guard the call 
by driver version and delegate to `base.SetOptionBytes` for 1.0 drivers.
   
   This issue also appears in the following locations of the same file:
   - line 874
   - line 1526



##########
csharp/src/Apache.Arrow.Adbc/C/CAdbcDriverImporter.cs:
##########
@@ -1022,7 +1366,7 @@ public unsafe override QueryResult ExecuteQuery()
 
             public override unsafe Schema ExecuteSchema()
             {
-                using (CallHelper caller = new CallHelper())
+                using (CallHelper caller = new CallHelper(_driver))
                 {
                     fixed (CAdbcStatement* statement = &_nativeStatement)

Review Comment:
   A 1.0 imported driver has no `StatementExecuteSchema` pointer because 
`ValidateDriver` skips the 1.1 fields. Guard on `DriverVersion` and call 
`base.ExecuteSchema()` before this native call; otherwise invoking the newly 
added override on a 1.0 driver jumps through null.



-- 
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: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to