Pure.RelationalSchema.Storage.PostgreSQL.Querying
0.1.0-preview.0.2.0
dotnet add package Pure.RelationalSchema.Storage.PostgreSQL.Querying --version 0.1.0-preview.0.2.0
NuGet\Install-Package Pure.RelationalSchema.Storage.PostgreSQL.Querying -Version 0.1.0-preview.0.2.0
<PackageReference Include="Pure.RelationalSchema.Storage.PostgreSQL.Querying" Version="0.1.0-preview.0.2.0" />
<PackageVersion Include="Pure.RelationalSchema.Storage.PostgreSQL.Querying" Version="0.1.0-preview.0.2.0" />
<PackageReference Include="Pure.RelationalSchema.Storage.PostgreSQL.Querying" />
paket add Pure.RelationalSchema.Storage.PostgreSQL.Querying --version 0.1.0-preview.0.2.0
#r "nuget: Pure.RelationalSchema.Storage.PostgreSQL.Querying, 0.1.0-preview.0.2.0"
#:package Pure.RelationalSchema.Storage.PostgreSQL.Querying@0.1.0-preview.0.2.0
#addin nuget:?package=Pure.RelationalSchema.Storage.PostgreSQL.Querying&version=0.1.0-preview.0.2.0&prerelease
#tool nuget:?package=Pure.RelationalSchema.Storage.PostgreSQL.Querying&version=0.1.0-preview.0.2.0&prerelease
Pure.RelationalSchema.Storage.PostgreSQL.Querying
PostgreSQL row querying for the Pure relational schema ecosystem — IQueryable / IAsyncEnumerable stored datasets over hash-named tables, read through IDbConnection.
Overview
Pure.RelationalSchema.Storage.PostgreSQL.Querying reads rows from a live PostgreSQL database through the storage abstractions defined in Pure.RelationalSchema.Storage:
- Row access —
PostgreSqlStoredTableDataSetexposes the rows of a table as bothIQueryable<IRow>andIAsyncEnumerable<IRow>, backed by aSELECTof all columns. - Query translation — LINQ composed over the stored tables of one schema runs as one PostgreSQL
SELECT, translated byLinq.Expressions.Translation.PostgreSql. A query across schemas is split: each part that reads one schema runs in SQL, and the parts are combined in memory. - Schema-wide access —
PostgreSqlStoredSchemaDataSetmaps everyITableof anISchemato itsPostgreSqlStoredTableDataSet. It implementsIPostgreSqlStoredSchemaDataSet, which is defined in the separatePure.RelationalSchema.Storage.PostgreSQL.Abstractionspackage.
This package covers reads only. Creating the tables and inserting rows is handled by the related packages listed below.
The tables must already exist with the hash-based names produced by Pure.RelationalSchema.Storage.PostgreSQL.Creation (any other creator that produces the same names works too). Schema, table and column identifiers are the first 63 hexadecimal characters of the hashes from Pure.RelationalSchema.HashCodes, not the model names. The caller owns the IDbConnection: it must be opened before use, and this package never disposes it.
Public API
| Type | Kind | Description |
|---|---|---|
PostgreSqlStoredSchemaDataSet |
record | Maps each ITable in an ISchema to a PostgreSqlStoredTableDataSet; implements IPostgreSqlStoredSchemaDataSet (from Pure.RelationalSchema.Storage.PostgreSQL.Abstractions) |
PostgreSqlStoredTableDataSet |
record | IStoredTableDataSet backed by a PostgreSQL table; supports sync and async enumeration. Public members: SchemaName, Connection, TableSchema |
IPostgreSqlStoredSchemaDataSet (an IStoredSchemaDataSet with an IDbConnection Connection property) lives in Pure.RelationalSchema.Storage.PostgreSQL.Abstractions, so other packages can depend on it without depending on this one. All SQL statement builders, the row enumerables and the query provider are internal.
Query translation
The Provider of a PostgreSqlStoredTableDataSet translates the LINQ composed over it. When a query is enumerated (or a terminal operator such as Count or First runs), the provider walks its expression tree from the top:
- The largest operator whose sources are all stored tables of one schema — the same
IDbConnectioninstance and the same schema name — is translated into oneSELECTand executed; its result replaces the operator in the tree. - An operator that reads several schemas or connections, or that cannot be translated, stays in the tree, and the provider tries its operands instead. What is left runs in memory with LINQ to Objects over those results, and a table no translated part reads is read with a
SELECTof all its columns.
So a join of two tables of one schema is one SELECT ... JOIN ..., while a join of tables of two schemas is two filtered SELECTs joined in memory. A subquery that depends on a row of another schema (a correlated subquery) runs in memory per row.
Rows are read as cells of text, so the provider translates cell reads of the form row.Cells[column].Value.TextValue, where column is a constant or captured IColumn of a queried table, into the SQL text of the column, matching what enumeration returns:
| Column type | Text in SQL |
|---|---|
string |
the value |
int, ushort, long, uint, ulong, uuid |
CAST(... AS text) |
bool |
True / False |
Cells of the other column types (date, time, datetime, double, float, determined_hash) are read in memory, as is any other use of a row (row.Cells.Count, a cell's IString itself, ...).
A translated query returns rows of one table (through Where, OrderBy, Skip, Take, Distinct, set operations of the same table and the element operators), scalars, anonymous types and value tuples of scalars; any other result shape runs in memory over translated operands. Results keep the semantics of enumeration, except that SQL compares and orders text by the database collation.
IQueryable<IRow> customers = shop[customersTable];
IQueryable<IRow> orders = shop[ordersTable];
// One statement: SELECT ... FROM ... AS t0 INNER JOIN ... AS t1 ON ... WHERE ...
var totals = customers
.Where(c => c.Cells[activeColumn].Value.TextValue == "True")
.Join(
orders,
c => c.Cells[idColumn].Value.TextValue,
o => o.Cells[customerIdColumn].Value.TextValue,
(c, o) => new
{
Name = c.Cells[nameColumn].Value.TextValue,
Total = o.Cells[totalColumn].Value.TextValue,
}
)
.ToArray();
IStoredTableDataSet is both IQueryable<IRow> and IAsyncEnumerable<IRow>, so with System.Linq.Async (or .NET 10's System.Linq.AsyncEnumerable) in scope, compose over it as IQueryable<IRow> to pick the translated operators.
Dependencies
Pure.RelationalSchema.Storage— storage abstractions (IStoredSchemaDataSet,IStoredTableDataSet,IRow) that this package implementsPure.RelationalSchema.Storage.PostgreSQL.Abstractions—IPostgreSqlStoredSchemaDataSet, the interface implemented byPostgreSqlStoredSchemaDataSetLinq.Expressions.Translation.PostgreSql— translates LINQ expression trees into PostgreSQLSELECTstatementsPure.RelationalSchema.HashCodes— hash codes used to derive PostgreSQL object namesPure.Primitives.Abstractions— base interfaces for primitive types (IString, etc.)Pure.Primitives— concrete primitive type implementationsPure.Primitives.String.Operations— string composition utilities used to build SQL statementsPure.Primitives.Choices— choice typesPure.Collections.Generic— generic collection implementations (e.g.Dictionary<TKey1, TKey2, TValue>with dual-key lookup)
Target Frameworks
- .NET 8
- .NET 9
- .NET 10
Installation
dotnet add package Pure.RelationalSchema.Storage.PostgreSQL.Querying
The example below also uses Pure.RelationalSchema.Storage.PostgreSQL.Creation to create the tables. Any creator that produces the same hash-based names works; Creation is not a dependency of this package.
Usage
using System.Data;
using Npgsql;
using Pure.RelationalSchema.Abstractions.Column;
using Pure.RelationalSchema.Abstractions.Schema;
using Pure.RelationalSchema.Abstractions.Table;
using Pure.RelationalSchema.ColumnType;
using Pure.RelationalSchema.Storage.Abstractions;
using Pure.RelationalSchema.Storage.PostgreSQL.Abstractions;
using Pure.RelationalSchema.Storage.PostgreSQL.Creation;
using Pure.RelationalSchema.Storage.PostgreSQL.Querying;
using Column = Pure.RelationalSchema.Column.Column;
using Schema = Pure.RelationalSchema.Schema.Schema;
using String = Pure.Primitives.String.String;
using Table = Pure.RelationalSchema.Table.Table;
// The caller owns the connection and opens it.
IDbConnection connection = new NpgsqlConnection(connectionString);
connection.Open();
// Describe a schema with one table.
IColumn idColumn = new Column(new String("Id"), new IntColumnType());
IColumn nameColumn = new Column(new String("Name"), new StringColumnType());
ITable usersTable = new Table(new String("Users"), [idColumn, nameColumn], []);
ISchema schema = new Schema(new String("Shop"), [usersTable], []);
// Create the tables with hash-based names (DDL runs lazily, on first access).
ISchema createdSchema = new PostgreSqlCreatedSchema(schema, connection);
_ = createdSchema.Tables.ToArray();
// Query them.
IPostgreSqlStoredSchemaDataSet dataSet =
new PostgreSqlStoredSchemaDataSet(createdSchema, connection);
IStoredTableDataSet users = dataSet[usersTable];
// Synchronous: IQueryable<IRow>
foreach (IRow row in users)
{
string name = row.Cells[nameColumn].Value.TextValue;
Console.WriteLine(name);
}
// Asynchronous: IAsyncEnumerable<IRow>
await foreach (IRow row in users)
{
string id = row.Cells[idColumn].Value.TextValue;
Console.WriteLine(id);
}
Every cell value is an IString; read its text through TextValue.
Related packages
Pure.RelationalSchema.Storage.PostgreSQL.Abstractions— the sharedIPostgreSqlStoredSchemaDataSetinterfacePure.RelationalSchema.Storage.PostgreSQL.Creation— creates the schema and tables this package reads fromPure.RelationalSchema.Storage.PostgreSQL.Insertion— inserts rows into those tables
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Linq.Expressions.Translation.PostgreSql (>= 0.1.0-preview.0.2.0)
- Pure.Collections.Generic (>= 0.1.0-preview.3.0.0)
- Pure.Primitives (>= 3.6.5)
- Pure.Primitives.Abstractions (>= 4.3.0)
- Pure.Primitives.Choices (>= 1.2.2)
- Pure.Primitives.String.Operations (>= 1.5.1)
- Pure.RelationalSchema.HashCodes (>= 3.3.0)
- Pure.RelationalSchema.Storage (>= 0.1.0-preview.8.0.0)
- Pure.RelationalSchema.Storage.PostgreSQL.Abstractions (>= 0.1.0-preview.0.1.0)
-
net8.0
- Linq.Expressions.Translation.PostgreSql (>= 0.1.0-preview.0.2.0)
- Pure.Collections.Generic (>= 0.1.0-preview.3.0.0)
- Pure.Primitives (>= 3.6.5)
- Pure.Primitives.Abstractions (>= 4.3.0)
- Pure.Primitives.Choices (>= 1.2.2)
- Pure.Primitives.String.Operations (>= 1.5.1)
- Pure.RelationalSchema.HashCodes (>= 3.3.0)
- Pure.RelationalSchema.Storage (>= 0.1.0-preview.8.0.0)
- Pure.RelationalSchema.Storage.PostgreSQL.Abstractions (>= 0.1.0-preview.0.1.0)
-
net9.0
- Linq.Expressions.Translation.PostgreSql (>= 0.1.0-preview.0.2.0)
- Pure.Collections.Generic (>= 0.1.0-preview.3.0.0)
- Pure.Primitives (>= 3.6.5)
- Pure.Primitives.Abstractions (>= 4.3.0)
- Pure.Primitives.Choices (>= 1.2.2)
- Pure.Primitives.String.Operations (>= 1.5.1)
- Pure.RelationalSchema.HashCodes (>= 3.3.0)
- Pure.RelationalSchema.Storage (>= 0.1.0-preview.8.0.0)
- Pure.RelationalSchema.Storage.PostgreSQL.Abstractions (>= 0.1.0-preview.0.1.0)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on Pure.RelationalSchema.Storage.PostgreSQL.Querying:
| Package | Downloads |
|---|---|
|
Pure.RelationalSchema.Storage.PostgreSQL
Meta-package that references the Abstractions, Creation, Querying and Insertion packages of the Pure relational schema PostgreSQL storage. It contains no code. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 0.1.0-preview.0.2.0 | 46 | 10/16/2026 |
| 0.1.0-preview.0.1.0 | 38 | 10/15/2026 |