Skip to content

Commit b3a7fdd

Browse files
F# Type Provider for LQL with Compile-Time Validation (#15)
# F# Type Provider for LQL with Compile-Time Validation # TLDR; Adds an F# type provider that validates LQL queries at compile time, converting them to SQL. Invalid LQL syntax causes compilation errors rather than runtime failures. # Brief Details - **LqlTypeProvider**: New F# type provider (`Lql.LqlCommand<"query">`) that parses LQL at compile time, validates syntax, and generates SQL - **Compile-time errors**: Invalid LQL queries fail the build with descriptive error messages including line/column positions - **Generated properties**: Each validated query type exposes `Query` (original LQL) and `Sql` (generated SQL) static properties - **E2E test suite**: 30+ tests covering selects, filters, joins, aggregations, ordering, limits, and arithmetic expressions - **Test data seeder**: C# helper using DataProvider-generated extensions to seed test databases (no raw SQL inserts) - **CI integration**: New GitHub Actions job `lql-fsharp-typeprovider-tests` runs F# type provider tests on LQL changes - **F# example project**: Demo app showing type provider usage with `.lql` query files # How Do The Tests Prove This Works? - `TypeProviderCompileTimeValidationTests`: Verify `Query` and `Sql` properties are generated correctly - `TypeProviderFilterTests`: Confirm filter expressions generate proper `WHERE` clauses with `AND`/`OR` - `TypeProviderJoinTests`: Validate `JOIN`, `LEFT JOIN`, and multi-table joins produce correct SQL - `TypeProviderAggregationTests`: Test `GROUP BY`, `SUM`, `AVG`, `COUNT`, and `HAVING` clauses - `TypeProviderE2EExecutionTests`: Execute generated SQL against real SQLite database, verify row counts and data - `TypeProviderRealWorldScenarioTests`: End-to-end scenarios querying customers, filtering users, joining orders
1 parent 7038bf4 commit b3a7fdd

File tree

81 files changed

+5429
-2993
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

81 files changed

+5429
-2993
lines changed

.github/workflows/ci.yml

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -118,11 +118,8 @@ jobs:
118118
restore-keys: |
119119
${{ runner.os }}-nuget-
120120
121-
- name: Restore dependencies
122-
run: dotnet restore
123-
124121
- name: Build
125-
run: dotnet build --no-restore -c Release
122+
run: dotnet build -c Release -m:1
126123

127124
# DataProvider tests
128125
dataprovider-tests:
@@ -206,6 +203,46 @@ jobs:
206203
name: test-results-lql-${{ strategy.job-index }}
207204
path: '**/TestResults/*.trx'
208205

206+
# LQL F# Type Provider tests
207+
lql-fsharp-typeprovider-tests:
208+
name: LQL F# Type Provider Tests
209+
runs-on: ubuntu-latest
210+
needs: [build, changes]
211+
if: needs.changes.outputs.lql == 'true'
212+
steps:
213+
- uses: actions/checkout@v4
214+
215+
- name: Setup .NET
216+
uses: actions/setup-dotnet@v4
217+
with:
218+
dotnet-version: ${{ env.DOTNET_VERSION }}
219+
220+
- name: Cache NuGet packages
221+
uses: actions/cache@v4
222+
with:
223+
path: ~/.nuget/packages
224+
key: ${{ runner.os }}-nuget-${{ hashFiles('**/*.csproj', '**/*.fsproj') }}
225+
restore-keys: |
226+
${{ runner.os }}-nuget-
227+
228+
- name: Restore
229+
run: dotnet restore Lql/Lql.TypeProvider.FSharp.Tests
230+
231+
- name: Build CLI tools (needed by MSBuild targets)
232+
run: |
233+
dotnet build Migration/Migration.Cli -c Debug
234+
dotnet build DataProvider/DataProvider.SQLite.Cli -c Debug
235+
236+
- name: Test
237+
run: dotnet test Lql/Lql.TypeProvider.FSharp.Tests --no-restore --verbosity normal --logger "trx;LogFileName=test-results.trx"
238+
239+
- name: Upload test results
240+
uses: actions/upload-artifact@v4
241+
if: always()
242+
with:
243+
name: test-results-lql-fsharp-typeprovider
244+
path: '**/TestResults/*.trx'
245+
209246
# Migration tests
210247
migration-tests:
211248
name: Migration Tests

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,9 @@ Generated_Code/
379379
# Generated C# code from DataProvider source generator
380380
*.g.cs
381381

382+
383+
!Lql/Lql.TypeProvider.FSharp.Tests.Data/Generated/*.g.cs
384+
382385
# Build timestamps
383386
.timestamp
384387

@@ -399,3 +402,5 @@ Website/src/apidocs/
399402
Website/src/docs/sync.md
400403
Website/src/docs/dataprovider.md
401404
Website/src/docs/lql.md
405+
406+
Lql/Lql.TypeProvider.FSharp.Tests.Data/Generated/

.vscode/launch.json

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,17 @@
3939
"console": "internalConsole",
4040
"stopAtEntry": false
4141
},
42+
{
43+
"name": "Run DataProvider.Example.FSharp",
44+
"type": "coreclr",
45+
"request": "launch",
46+
"preLaunchTask": "build",
47+
"program": "${workspaceFolder}/DataProvider/DataProvider.Example.FSharp/bin/Debug/net9.0/DataProvider.Example.FSharp.dll",
48+
"args": [],
49+
"cwd": "${workspaceFolder}/DataProvider/DataProvider.Example.FSharp",
50+
"console": "internalConsole",
51+
"stopAtEntry": false
52+
},
4253
{
4354
"name": "DB Browser",
4455
"type": "coreclr",

Agents.md

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
## Coding Rules
1010

11-
- **NEVER THROW** - Return `Result<T>`. Wrap failures in try/catch
11+
- **NEVER THROW** - Return `Result<T,E>`. Wrap failures in try/catch
1212
- **No casting/!** - Pattern match on type only
1313
- **NO GIT** - Source control is illegal
1414
- **No suppressing warnings** - Illegal
@@ -18,22 +18,32 @@
1818
- **Copious ILogger** - Especially sync projects
1919
- **NO INTERFACES** - Use `Action<T>`/`Func<T>`
2020
- **Expressions over assignments**
21+
- **Routinely format with csharpier** - `dotnet csharpier .` <- In root folder
2122
- **Named parameters** - No ordinal calls
2223
- **Close type hierarchies** - Private constructors:
2324
```csharp
2425
public abstract partial record Result<TSuccess, TFailure> { private Result() { } }
2526
```
26-
- **Extension methods on IDbConnection/IDbTransaction only**
27-
- **Pattern match, don't if** - Switch expressions on type
28-
- **No skipping tests** - Failing = OK, Skip = illegal
29-
- **E2E tests only** - No mocks, integration testing
30-
- **Type aliases for Results** - `using XResult = Result<X, XError>`
31-
- **Immutable** - Records, `ImmutableList`, `FrozenSet`, `ImmutableArray`
32-
- **NO REGEX** - ANTLR or SqlParserCS
33-
- **XMLDOC on public members** - Except tests
34-
- **< 450 LOC per file**
35-
- **No commented code** - Delete it
36-
- **No placeholders** - Leave compile errors with TODO
27+
- **Skipping tests = ⛔️ ILLEGAL** - Failing tests = OK. Aggressively unskip tests
28+
- **Test at the highest level** - Avoid mocks. Only full integration testing
29+
- **Keep files under 450 LOC and functions under 20 LOC**
30+
- **Always use type aliases (using) for result types** - Don't write like this: `new Result<string, SqlError>.Ok`
31+
- **All tables must have a SINGLE primary key**
32+
- **Primary keys MUST be UUIDs**
33+
- **No singletons** - Inject `Func` into static methods
34+
- **Immutable types!** - Use records. Don't use `List<T>`. Use `ImmutableList` `FrozenSet` or `ImmutableArray`
35+
- **No in-memory dbs** - Real dbs all the way
36+
- **NO REGEX** - Parse SQL with ANTLR .g4 grammars or SqlParserCS library
37+
- **All public members require XMLDOC** - Except in test projects
38+
- **One type per file** (except small records)
39+
- **No commented-out code** - Delete it
40+
- **No consecutive Console.WriteLine** - Use single string interpolation
41+
- **No placeholders** - If incomplete, leave LOUD compilation error with TODO
42+
- **Never use Fluent Assertions**
43+
44+
## CSS
45+
- **MINIMAL CSS** - Do not duplicate CSS clases
46+
- **Name classes after component, NOT section** - Sections should not have their own CSS classes
3747

3848
## Testing
3949
- E2E with zero mocking

CLAUDE.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
## Coding Rules
1010

11-
- **NEVER THROW** - Return `Result<T>`. Wrap failures in try/catch
11+
- **NEVER THROW** - Return `Result<T,E>``. Wrap failures in try/catch
1212
- **No casting/!** - Pattern match on type only
1313
- **NO GIT** - Source control is illegal
1414
- **No suppressing warnings** - Illegal
@@ -32,6 +32,7 @@ public abstract partial record Result<TSuccess, TFailure> { private Result() { }
3232
- **Primary keys MUST be UUIDs**
3333
- **No singletons** - Inject `Func` into static methods
3434
- **Immutable types!** - Use records. Don't use `List<T>`. Use `ImmutableList` `FrozenSet` or `ImmutableArray`
35+
- **No in-memory dbs** - Real dbs all the way
3536
- **NO REGEX** - Parse SQL with ANTLR .g4 grammars or SqlParserCS library
3637
- **All public members require XMLDOC** - Except in test projects
3738
- **One type per file** (except small records)

DataProvider.sln

Lines changed: 64 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,13 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DataProvider.Example.Tests"
3131
EndProject
3232
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DataProvider.Example", "DataProvider\DataProvider.Example\DataProvider.Example.csproj", "{EA9A0385-249F-4141-AD03-D67649110A84}"
3333
EndProject
34-
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lql.Browser", "Lql\Lql.Browser\Lql.Browser.csproj", "{1B5BAB33-4256-400B-A4F8-F318418A3548}"
34+
Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "Lql.TypeProvider.FSharp", "Lql\Lql.TypeProvider.FSharp\Lql.TypeProvider.FSharp.fsproj", "{B1234567-89AB-CDEF-0123-456789ABCDEF}"
35+
EndProject
36+
Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "DataProvider.SQLite.FSharp", "DataProvider\DataProvider.SQLite.FSharp\DataProvider.SQLite.FSharp.fsproj", "{D1234567-89AB-CDEF-0123-456789ABCDEF}"
37+
EndProject
38+
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "DataProvider.Example.FSharp", "DataProvider\DataProvider.Example.FSharp\DataProvider.Example.FSharp.fsproj", "{5C11B1F1-F6FF-45B9-B037-EDD054EED3F3}"
39+
EndProject
40+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lql.Browser", "Lql\Lql.Browser\Lql.Browser.csproj", "{0D96933C-DE5D-472B-9E9F-68DD15B85CF7}"
3541
EndProject
3642
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Sync", "Sync", "{5E63119C-E70B-5D45-ECC9-8CBACC584223}"
3743
EndProject
@@ -107,6 +113,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dashboard.Web", "Samples\Da
107113
EndProject
108114
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dashboard.Web.Tests", "Samples\Dashboard\Dashboard.Web.Tests\Dashboard.Web.Tests.csproj", "{25C125F3-B766-4DCD-8032-DB89818FFBC3}"
109115
EndProject
116+
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Lql.TypeProvider.FSharp.Tests", "Lql\Lql.TypeProvider.FSharp.Tests\Lql.TypeProvider.FSharp.Tests.fsproj", "{B0104C42-1B46-4CA5-9E91-A5F09D7E5B92}"
117+
EndProject
118+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lql.TypeProvider.FSharp.Tests.Data", "Lql\Lql.TypeProvider.FSharp.Tests.Data\Lql.TypeProvider.FSharp.Tests.Data.csproj", "{0D6A831B-4759-46F2-8527-51C8A9CB6F6F}"
119+
EndProject
110120
Global
111121
GlobalSection(SolutionConfigurationPlatforms) = preSolution
112122
Debug|Any CPU = Debug|Any CPU
@@ -261,18 +271,24 @@ Global
261271
{EA9A0385-249F-4141-AD03-D67649110A84}.Release|x64.Build.0 = Release|Any CPU
262272
{EA9A0385-249F-4141-AD03-D67649110A84}.Release|x86.ActiveCfg = Release|Any CPU
263273
{EA9A0385-249F-4141-AD03-D67649110A84}.Release|x86.Build.0 = Release|Any CPU
264-
{1B5BAB33-4256-400B-A4F8-F318418A3548}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
265-
{1B5BAB33-4256-400B-A4F8-F318418A3548}.Debug|Any CPU.Build.0 = Debug|Any CPU
266-
{1B5BAB33-4256-400B-A4F8-F318418A3548}.Debug|x64.ActiveCfg = Debug|Any CPU
267-
{1B5BAB33-4256-400B-A4F8-F318418A3548}.Debug|x64.Build.0 = Debug|Any CPU
268-
{1B5BAB33-4256-400B-A4F8-F318418A3548}.Debug|x86.ActiveCfg = Debug|Any CPU
269-
{1B5BAB33-4256-400B-A4F8-F318418A3548}.Debug|x86.Build.0 = Debug|Any CPU
270-
{1B5BAB33-4256-400B-A4F8-F318418A3548}.Release|Any CPU.ActiveCfg = Release|Any CPU
271-
{1B5BAB33-4256-400B-A4F8-F318418A3548}.Release|Any CPU.Build.0 = Release|Any CPU
272-
{1B5BAB33-4256-400B-A4F8-F318418A3548}.Release|x64.ActiveCfg = Release|Any CPU
273-
{1B5BAB33-4256-400B-A4F8-F318418A3548}.Release|x64.Build.0 = Release|Any CPU
274-
{1B5BAB33-4256-400B-A4F8-F318418A3548}.Release|x86.ActiveCfg = Release|Any CPU
275-
{1B5BAB33-4256-400B-A4F8-F318418A3548}.Release|x86.Build.0 = Release|Any CPU
274+
{B1234567-89AB-CDEF-0123-456789ABCDEF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
275+
{B1234567-89AB-CDEF-0123-456789ABCDEF}.Debug|Any CPU.Build.0 = Debug|Any CPU
276+
{D1234567-89AB-CDEF-0123-456789ABCDEF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
277+
{D1234567-89AB-CDEF-0123-456789ABCDEF}.Debug|Any CPU.Build.0 = Debug|Any CPU
278+
{5C11B1F1-F6FF-45B9-B037-EDD054EED3F3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
279+
{5C11B1F1-F6FF-45B9-B037-EDD054EED3F3}.Debug|Any CPU.Build.0 = Debug|Any CPU
280+
{0D96933C-DE5D-472B-9E9F-68DD15B85CF7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
281+
{0D96933C-DE5D-472B-9E9F-68DD15B85CF7}.Debug|Any CPU.Build.0 = Debug|Any CPU
282+
{0D96933C-DE5D-472B-9E9F-68DD15B85CF7}.Debug|x64.ActiveCfg = Debug|Any CPU
283+
{0D96933C-DE5D-472B-9E9F-68DD15B85CF7}.Debug|x64.Build.0 = Debug|Any CPU
284+
{0D96933C-DE5D-472B-9E9F-68DD15B85CF7}.Debug|x86.ActiveCfg = Debug|Any CPU
285+
{0D96933C-DE5D-472B-9E9F-68DD15B85CF7}.Debug|x86.Build.0 = Debug|Any CPU
286+
{0D96933C-DE5D-472B-9E9F-68DD15B85CF7}.Release|Any CPU.ActiveCfg = Release|Any CPU
287+
{0D96933C-DE5D-472B-9E9F-68DD15B85CF7}.Release|Any CPU.Build.0 = Release|Any CPU
288+
{0D96933C-DE5D-472B-9E9F-68DD15B85CF7}.Release|x64.ActiveCfg = Release|Any CPU
289+
{0D96933C-DE5D-472B-9E9F-68DD15B85CF7}.Release|x64.Build.0 = Release|Any CPU
290+
{0D96933C-DE5D-472B-9E9F-68DD15B85CF7}.Release|x86.ActiveCfg = Release|Any CPU
291+
{0D96933C-DE5D-472B-9E9F-68DD15B85CF7}.Release|x86.Build.0 = Release|Any CPU
276292
{C0B4116E-0635-4597-971D-6B70229FA30A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
277293
{C0B4116E-0635-4597-971D-6B70229FA30A}.Debug|Any CPU.Build.0 = Debug|Any CPU
278294
{C0B4116E-0635-4597-971D-6B70229FA30A}.Debug|x64.ActiveCfg = Debug|Any CPU
@@ -645,6 +661,30 @@ Global
645661
{25C125F3-B766-4DCD-8032-DB89818FFBC3}.Release|x64.Build.0 = Release|Any CPU
646662
{25C125F3-B766-4DCD-8032-DB89818FFBC3}.Release|x86.ActiveCfg = Release|Any CPU
647663
{25C125F3-B766-4DCD-8032-DB89818FFBC3}.Release|x86.Build.0 = Release|Any CPU
664+
{B0104C42-1B46-4CA5-9E91-A5F09D7E5B92}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
665+
{B0104C42-1B46-4CA5-9E91-A5F09D7E5B92}.Debug|Any CPU.Build.0 = Debug|Any CPU
666+
{B0104C42-1B46-4CA5-9E91-A5F09D7E5B92}.Debug|x64.ActiveCfg = Debug|Any CPU
667+
{B0104C42-1B46-4CA5-9E91-A5F09D7E5B92}.Debug|x64.Build.0 = Debug|Any CPU
668+
{B0104C42-1B46-4CA5-9E91-A5F09D7E5B92}.Debug|x86.ActiveCfg = Debug|Any CPU
669+
{B0104C42-1B46-4CA5-9E91-A5F09D7E5B92}.Debug|x86.Build.0 = Debug|Any CPU
670+
{B0104C42-1B46-4CA5-9E91-A5F09D7E5B92}.Release|Any CPU.ActiveCfg = Release|Any CPU
671+
{B0104C42-1B46-4CA5-9E91-A5F09D7E5B92}.Release|Any CPU.Build.0 = Release|Any CPU
672+
{B0104C42-1B46-4CA5-9E91-A5F09D7E5B92}.Release|x64.ActiveCfg = Release|Any CPU
673+
{B0104C42-1B46-4CA5-9E91-A5F09D7E5B92}.Release|x64.Build.0 = Release|Any CPU
674+
{B0104C42-1B46-4CA5-9E91-A5F09D7E5B92}.Release|x86.ActiveCfg = Release|Any CPU
675+
{B0104C42-1B46-4CA5-9E91-A5F09D7E5B92}.Release|x86.Build.0 = Release|Any CPU
676+
{0D6A831B-4759-46F2-8527-51C8A9CB6F6F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
677+
{0D6A831B-4759-46F2-8527-51C8A9CB6F6F}.Debug|Any CPU.Build.0 = Debug|Any CPU
678+
{0D6A831B-4759-46F2-8527-51C8A9CB6F6F}.Debug|x64.ActiveCfg = Debug|Any CPU
679+
{0D6A831B-4759-46F2-8527-51C8A9CB6F6F}.Debug|x64.Build.0 = Debug|Any CPU
680+
{0D6A831B-4759-46F2-8527-51C8A9CB6F6F}.Debug|x86.ActiveCfg = Debug|Any CPU
681+
{0D6A831B-4759-46F2-8527-51C8A9CB6F6F}.Debug|x86.Build.0 = Debug|Any CPU
682+
{0D6A831B-4759-46F2-8527-51C8A9CB6F6F}.Release|Any CPU.ActiveCfg = Release|Any CPU
683+
{0D6A831B-4759-46F2-8527-51C8A9CB6F6F}.Release|Any CPU.Build.0 = Release|Any CPU
684+
{0D6A831B-4759-46F2-8527-51C8A9CB6F6F}.Release|x64.ActiveCfg = Release|Any CPU
685+
{0D6A831B-4759-46F2-8527-51C8A9CB6F6F}.Release|x64.Build.0 = Release|Any CPU
686+
{0D6A831B-4759-46F2-8527-51C8A9CB6F6F}.Release|x86.ActiveCfg = Release|Any CPU
687+
{0D6A831B-4759-46F2-8527-51C8A9CB6F6F}.Release|x86.Build.0 = Release|Any CPU
648688
EndGlobalSection
649689
GlobalSection(SolutionProperties) = preSolution
650690
HideSolutionNode = FALSE
@@ -662,7 +702,10 @@ Global
662702
{A7EC2050-FE5E-4BBD-AF5F-7F07D3688118} = {43BAF0A3-C050-BE83-B489-7FC6F9FDE235}
663703
{16FA9B36-CB2A-4B79-A3BE-937C94BF03F8} = {43BAF0A3-C050-BE83-B489-7FC6F9FDE235}
664704
{EA9A0385-249F-4141-AD03-D67649110A84} = {43BAF0A3-C050-BE83-B489-7FC6F9FDE235}
665-
{1B5BAB33-4256-400B-A4F8-F318418A3548} = {54B846BA-A27D-B76F-8730-402A5742FF43}
705+
{B1234567-89AB-CDEF-0123-456789ABCDEF} = {54B846BA-A27D-B76F-8730-402A5742FF43}
706+
{D1234567-89AB-CDEF-0123-456789ABCDEF} = {43BAF0A3-C050-BE83-B489-7FC6F9FDE235}
707+
{5C11B1F1-F6FF-45B9-B037-EDD054EED3F3} = {43BAF0A3-C050-BE83-B489-7FC6F9FDE235}
708+
{0D96933C-DE5D-472B-9E9F-68DD15B85CF7} = {54B846BA-A27D-B76F-8730-402A5742FF43}
666709
{C0B4116E-0635-4597-971D-6B70229FA30A} = {5E63119C-E70B-5D45-ECC9-8CBACC584223}
667710
{9B303409-0052-45B9-8616-CC1ED80A5595} = {5E63119C-E70B-5D45-ECC9-8CBACC584223}
668711
{50CFDEC4-66C8-4330-8D5F-9D96A764378B} = {5E63119C-E70B-5D45-ECC9-8CBACC584223}
@@ -688,8 +731,15 @@ Global
688731
{4EB6CC28-7D1B-4E39-80F2-84CA4494AF23} = {048F5F03-6DDC-C04F-70D5-B8139DC8E373}
689732
{2FD305AC-927E-4D24-9FA6-923C30E4E4A8} = {048F5F03-6DDC-C04F-70D5-B8139DC8E373}
690733
{57572A45-33CD-4928-9C30-13480AEDB313} = {C7F49633-8D5E-7E19-1580-A6459B2EAE66}
734+
{A8A70E6D-1D43-437F-9971-44A4FA1BDD74} = {43BAF0A3-C050-BE83-B489-7FC6F9FDE235}
735+
{0858FE19-C59B-4A77-B76E-7053E8AFCC8D} = {C7F49633-8D5E-7E19-1580-A6459B2EAE66}
736+
{CA395494-F072-4A5B-9DD4-950530A69E0E} = {5D20AA90-6969-D8BD-9DCD-8634F4692FDA}
737+
{1AE87774-E914-40BC-95BA-56FB45D78C0D} = {54B846BA-A27D-B76F-8730-402A5742FF43}
738+
{6AB2EA96-4A75-49DB-AC65-B247BBFAE9A3} = {54B846BA-A27D-B76F-8730-402A5742FF43}
691739
{A82453CD-8E3C-44B7-A78F-97F392016385} = {B03CA193-C175-FB88-B41C-CBBC0E037C7E}
692740
{25C125F3-B766-4DCD-8032-DB89818FFBC3} = {B03CA193-C175-FB88-B41C-CBBC0E037C7E}
741+
{B0104C42-1B46-4CA5-9E91-A5F09D7E5B92} = {54B846BA-A27D-B76F-8730-402A5742FF43}
742+
{0D6A831B-4759-46F2-8527-51C8A9CB6F6F} = {54B846BA-A27D-B76F-8730-402A5742FF43}
693743
EndGlobalSection
694744
GlobalSection(ExtensibilityGlobals) = postSolution
695745
SolutionGuid = {53128A75-E7B6-4B83-B079-A309FCC2AD9C}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<OutputType>Exe</OutputType>
5+
<TargetFramework>net9.0</TargetFramework>
6+
<GenerateDocumentationFile>true</GenerateDocumentationFile>
7+
<LangVersion>preview</LangVersion>
8+
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
9+
<WarningLevel>3</WarningLevel>
10+
</PropertyGroup>
11+
12+
<ItemGroup>
13+
<Compile Include="LqlValidator.fs" />
14+
<Compile Include="Program.fs" />
15+
</ItemGroup>
16+
17+
<ItemGroup>
18+
<Content Include="GetCustomers.lql">
19+
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
20+
</Content>
21+
<Content Include="GetInvoices.lql">
22+
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
23+
</Content>
24+
</ItemGroup>
25+
26+
<ItemGroup>
27+
<PackageReference Include="Microsoft.Data.Sqlite" Version="9.0.0" />
28+
<PackageReference Include="FSharp.TypeProviders.SDK" Version="6.0.0" />
29+
</ItemGroup>
30+
31+
<ItemGroup>
32+
<ProjectReference Include="../../Lql/Lql.SQLite/Lql.SQLite.csproj" />
33+
<ProjectReference Include="../../Lql/Lql/Lql.csproj" />
34+
<ProjectReference Include="../../Lql/Lql.TypeProvider.FSharp/Lql.TypeProvider.FSharp.fsproj" />
35+
<ProjectReference Include="../../Other/Selecta/Selecta.csproj" />
36+
</ItemGroup>
37+
38+
</Project>
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Customer
2+
|> join(Address, on = Customer.Id = Address.CustomerId)
3+
|> select(Customer.Id, Customer.CustomerName, Customer.Email, Customer.Phone, Customer.CreatedDate, Address.Id AS AddressId, Address.CustomerId, Address.Street, Address.City, Address.State, Address.ZipCode, Address.Country)
4+
|> order_by(Customer.CustomerName)
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Invoice
2+
|> join(InvoiceLine, on = Invoice.Id = InvoiceLine.InvoiceId)
3+
|> select(Invoice.Id, Invoice.InvoiceNumber, Invoice.InvoiceDate, Invoice.CustomerName, Invoice.CustomerEmail, Invoice.TotalAmount, InvoiceLine.Description, InvoiceLine.Quantity, InvoiceLine.UnitPrice, InvoiceLine.Amount)
4+
|> order_by(Invoice.InvoiceDate)

0 commit comments

Comments
 (0)