cs/ScalarFunctionWrapper.cs
|
#pragma warning disable DuckDBNET001
#pragma warning disable CS1701 using System; using System.Collections.Generic; using System.Management.Automation; using System.Reflection; using DuckDB.NET.Data.DataChunk.Reader; using DuckDB.NET.Data.DataChunk.Writer; namespace PaperinikDB { /// <summary> /// Wraps a PowerShell ScriptBlock to be used as a DuckDB scalar function delegate. /// </summary> public class ScalarFunctionWrapper { private readonly ScriptBlock _scriptBlock; private readonly Type _resultType; public ScalarFunctionWrapper(ScriptBlock scriptBlock, Type resultType) { _scriptBlock = scriptBlock ?? throw new ArgumentNullException(nameof(scriptBlock)); _resultType = resultType ?? throw new ArgumentNullException(nameof(resultType)); } public void Invoke(IReadOnlyList<IDuckDBDataReader> readers, IDuckDBDataWriter writer, ulong rowCount) { // Get the WriteValue method with proper generic parameter (cached reflection) var writeValueMethod = writer.GetType().GetMethod("WriteValue"); MethodInfo genericWriteValue = null; if (writeValueMethod != null && writeValueMethod.IsGenericMethodDefinition) { genericWriteValue = writeValueMethod.MakeGenericMethod(_resultType); } for (ulong index = 0; index < rowCount; index++) { try { // Collect input values var inputValues = new object[readers.Count]; for (int p = 0; p < readers.Count; p++) { inputValues[p] = readers[p].GetValue(index); } // Invoke the ScriptBlock var results = _scriptBlock.Invoke(inputValues); if (results != null && results.Count > 0 && results[0] != null) { var result = results[0].BaseObject; // Convert result to the expected type and write var convertedResult = Convert.ChangeType(result, _resultType); if (genericWriteValue != null) { genericWriteValue.Invoke(writer, new object[] { convertedResult, index }); } else if (writeValueMethod != null) { writeValueMethod.Invoke(writer, new object[] { convertedResult, index }); } else { writer.WriteNull(index); } } else { writer.WriteNull(index); } } catch { // On any error, write NULL for this row writer.WriteNull(index); } } } } } |