Skip to content

Add support for async lambda in RegisterTableFunction #226

@mldisibio

Description

@mldisibio

(Discussed in Discord. Formalizing as an Issue so someone can work on it. Is a nice-to-have.)

The following code using an async lambda within RegisterTableFunction does not compile under v1.1.3:

void TestTableFn()
{
	using var duckDBConnection = new DuckDBConnection("Data Source=:memory:");
	duckDBConnection.Open();
	
#pragma warning disable
	duckDBConnection.RegisterTableFunction<string, int>("my_people",
	async (parameters) => 
	{
		string startingName = parameters[0].GetValue<string>();
		int startingAge = parameters[1].GetValue<int>();
		var result = await GetRandomPersons(startingName, startingAge).ConfigureAwait(false);

                // needs to be:
		//var result = GetRandomPersons(startingName, startingAge).ConfigureAwait(false).GetAwaiter().GetResult();

		return new TableFunction([new ColumnInfo("PersonName", typeof(string)), new ColumnInfo("PersonAge", typeof(int))], result);
	},
	(item, writers, rowIndex) =>
	{
		var person = item as Person;
		writers[0].WriteValue(person?.Name, rowIndex);
		writers[1].WriteValue(person?.Age, rowIndex);
	});
#pragma warning restore

	using var cmd = duckDBConnection.CreateCommand();
	cmd.CommandText = "SELECT * FROM my_people('Alice', 25);";
	var reader = cmd.ExecuteReader();
}

public record Person(string Name, int Age);

public static async Task<List<Person>> GetRandomPersons(string startingName, int startingAge)
{
	Random random = new Random();
	var data = new List<Person>();
	for (int i = 0; i < 10; i++)
	{
		data.Add(new Person($"{startingName}{i + 1:D2}", startingAge + random.Next(1, 50)));
		await Task.Delay(100); // Simulate asynchronous operation
	}
	return data;
}

The error is

CS4010 Cannot convert async lambda expression 
to delegate type 'Func<IReadOnlyList<IDuckDBValueReader>, TableFunction>'. 
An async lambda expression may return void, Task or Task<T>, 
none of which are convertible to 'Func<IReadOnlyList<IDuckDBValueReader>, TableFunction>'.

Giorgi mentioned it is a limitation of the C api within which the callback is executed and maybe that is a hard limit. But perhaps someone can find an implementation that allows for non-blocking awaits.

Metadata

Metadata

Assignees

No one assigned

    Labels

    help wantedExtra attention is needed

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions