├── .github
└── workflows
│ ├── deploy.yml
│ └── dotnet.yml
├── .gitignore
├── Directory.Build.props
├── LICENSE
├── README.md
├── chdb-dotnet.png
├── chdb.png
├── chdb.sln
├── src
├── chdb-meta
│ └── chdb-meta.csproj
├── chdb-tool
│ ├── Program.cs
│ └── chdb-tool.csproj
└── chdb
│ ├── ChDb.cs
│ ├── LocalResult.cs
│ ├── Session.cs
│ └── chdb.csproj
├── test
└── ChDbTest
│ ├── ChDbTest.cs
│ ├── GlobalUsings.cs
│ └── test.csproj
└── update_libchdb.sh
/.github/workflows/deploy.yml:
--------------------------------------------------------------------------------
1 | name: publish dotnet packages
2 |
3 | on:
4 | release:
5 | types: [ created ]
6 |
7 | jobs:
8 | deploy:
9 | runs-on: ubuntu-latest
10 | permissions:
11 | packages: write
12 | contents: read
13 | steps:
14 | - name: Checkout the repository
15 | uses: actions/checkout@v4
16 | - name: Setup .NET Core 8.x
17 | uses: actions/setup-dotnet@v3
18 | with:
19 | dotnet-version: |
20 | 6.x
21 | 8.x
22 | cache: true
23 | - name: Download chdb library
24 | run: ./update_libchdb.sh
25 | - run: dotnet build --configuration Release
26 | - name: Create the packages
27 | run: dotnet pack --configuration Release --include-symbols
28 | - name: Publish the package to nuget.org
29 | run: dotnet nuget push nupkg/*.nupkg -k $NUGET_AUTH_TOKEN -s https://api.nuget.org/v3/index.json
30 | env:
31 | NUGET_AUTH_TOKEN: ${{secrets.NUGET_TOKEN}}
32 |
--------------------------------------------------------------------------------
/.github/workflows/dotnet.yml:
--------------------------------------------------------------------------------
1 | # This workflow will build a .NET project
2 | # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-net
3 |
4 | name: build
5 |
6 | env:
7 | DOTNET_NOLOGO: 1
8 | DOTNET_CLI_TELEMETRY_OPTOUT: 1
9 |
10 | on:
11 | push:
12 | branches: [ "main" ]
13 | pull_request:
14 | branches: [ "main" ]
15 | workflow_dispatch:
16 | inputs:
17 | reason:
18 | description: 'The reason for running the workflow'
19 | required: true
20 | default: 'Manual run'
21 |
22 | jobs:
23 | build_chdb:
24 | name: Build chdb-${{ matrix.rid }}
25 | runs-on: ${{ matrix.os }}
26 | strategy:
27 | matrix:
28 | include:
29 | - os: ubuntu-latest
30 | rid: linux-x64
31 | - os: macos-latest
32 | rid: osx-x64
33 | - os: macos-14
34 | rid: osx-arm64
35 |
36 | steps:
37 | - name: 'Print manual run reason'
38 | if: ${{ github.event_name == 'workflow_dispatch' }}
39 | run: |
40 | echo 'Reason: ${{ github.event.inputs.reason }}'
41 |
42 | - uses: actions/checkout@v4
43 |
44 | - name: Setup .NET Core
45 | uses: actions/setup-dotnet@v3
46 | with:
47 | dotnet-version: |
48 | 6.0.x
49 | 8.0.x
50 | source-url: https://nuget.pkg.github.com/vilinski/index.json
51 | env:
52 | NUGET_AUTH_TOKEN: ${{secrets.GITHUB_TOKEN}}
53 | - name: Display dotnet version
54 | run: |
55 | dotnet --version
56 | echo "GITHUB_WORKSPACE $GITHUB_WORKSPACE"
57 | echo "GITHUB_ACTION $GITHUB_ACTION"
58 | echo "GITHUB_RUN_ID $GITHUB_RUN_ID"
59 | echo "GITHUB_RUN_NUMBER $GITHUB_RUN_NUMBER"
60 |
61 | - name: Restore
62 | run: dotnet restore
63 |
64 | - name: Download chdb library
65 | run: ./update_libchdb.sh
66 |
67 | - name: Build
68 | run: |
69 | # copy to the correct location
70 | cp libchdb.so src/chdb/libchdb.so
71 | ls -lahS src/chdb/libchdb*
72 | dotnet build --no-restore --configuration Release
73 |
74 | - name: Test
75 | run: dotnet test -c Release /p:TestTfmsInParallel=false --logger "console;verbosity=detailed" --no-build --logger trx --results-directory "TestResults-${{ matrix.rid }}"
76 |
77 | # - name: Upload dotnet test results
78 | # uses: actions/upload-artifact@v4
79 | # with:
80 | # name: dotnet-results-${{ matrix.rid }}
81 | # path: TestResults-${{ matrix.rid }}
82 | # # Use always() to always run this step to publish test results when there are test failures
83 | # if: ${{ always() }}
84 |
85 | # - name: Pack chdb-${{ matrix.rid }}
86 | # run: |
87 | # dotnet pack src/chdb/chdb.csproj -c Release
88 | # ls -lahS nupkg
89 |
90 | # - name: Publish the package to nuget.org
91 | # run: dotnet nuget push nupkg/*.nupkg --skip-duplicate --source https://api.nuget.org/v3/index.json --api-key ${{ secrets.NUGET_AUTH_TOKEN_CHDB }}
92 | # env:
93 | # NUGET_AUTH_TOKEN: ${{ secrets.NUGET_AUTH_TOKEN_CHDB }}
94 |
95 | # - name: Publish chdb-${{ matrix.rid }} package to GPR
96 | # run: dotnet nuget push nupkg/chdb-${{ matrix.rid }}.*.nupkg --skip-duplicate --api-key ${{ secrets.PACKAGES_TOKEN }} --source https://nuget.pkg.github.com/chdb-io/index.json
97 | # env:
98 | # NUGET_AUTH_TOKEN: ${{ secrets.PACKAGES_TOKEN }}
99 |
100 | # - name: Upload nupkg
101 | # #run: ls -l nupkg/*.nupkg
102 | # uses: actions/upload-artifact@v4
103 | # with:
104 | # name: dotnet-nupkg-${{ matrix.rid }}
105 | # path: nupkg
106 |
107 | push_chdb:
108 | if: github.event.pull_request.merged
109 | name: Push chdb
110 | needs: build_chdb
111 | runs-on: ubuntu-latest
112 | steps:
113 |
114 | - uses: actions/checkout@v4
115 |
116 | - name: Download chdb library
117 | run: ./update_libchdb.sh
118 |
119 | # - name: Upload libchdb Artifact
120 | # uses: actions/upload-artifact@v4
121 | # with:
122 | # name: libchdb
123 | # path: libchdb.so
124 |
125 | - name: Pack
126 | run: |
127 | cp libchdb.so src/chdb/libchdb.so
128 | ls -lahS src/chdb/libchdb*
129 | dotnet pack src/chdb/chdb.csproj -c Release --include-symbols
130 | ls -lahS nupkg
131 |
132 | - name: Publish the package to nuget.org
133 | run: dotnet nuget push nupkg/chdb.*.nupkg --skip-duplicate --source https://api.nuget.org/v3/index.json --api-key ${{ secrets.NUGET_AUTH_TOKEN_CHDB }}
134 |
135 |
136 | push_tool:
137 | if: github.event.pull_request.merged
138 | name: Push chdb-tool
139 | needs: push_chdb
140 | runs-on: ubuntu-latest
141 | env:
142 | PUSH_TOOL: true
143 | steps:
144 | - uses: actions/checkout@v4
145 |
146 | - name: Download chdb library
147 | run: ./update_libchdb.sh
148 |
149 | - name: Pack
150 | run: |
151 | ls -lahS .
152 | ls -lahS src/chdb/*
153 | cp libchdb.so src/chdb/
154 | ls -lahS src/chdb/libchdb*
155 | dotnet nuget sources add -n chdb ./nupkg
156 | dotnet pack src/chdb-tool/chdb-tool.csproj -c Release --include-symbols
157 | ls -lahS nupkg
158 |
159 | - name: Publish
160 | run: dotnet nuget push nupkg/chdb-tool.*.nupkg --skip-duplicate --source https://api.nuget.org/v3/index.json --api-key ${{ secrets.NUGET_AUTH_TOKEN_CHDB }}
161 |
162 | - name: Test chdb-tool
163 | run: |
164 | ./update_libchdb.sh
165 | dotnet tool install --add-source ./nupkg --global chdb-tool
166 | which chdb
167 | cp libchdb.so /home/runner/.dotnet/tools/
168 | chdb --help
169 | chdb "select version()" PrettyCompact
170 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 | ##
4 | ## Get latest from `dotnet new gitignore`
5 |
6 | libchdb.tar.gz
7 | chdb.h
8 | src/chdb/libchdb.so
9 |
10 | # dotenv files
11 | .env
12 |
13 | # User-specific files
14 | *.rsuser
15 | *.suo
16 | *.user
17 | *.userosscache
18 | *.sln.docstates
19 |
20 | # User-specific files (MonoDevelop/Xamarin Studio)
21 | *.userprefs
22 |
23 | # Mono auto generated files
24 | mono_crash.*
25 |
26 | # Build results
27 | [Dd]ebug/
28 | [Dd]ebugPublic/
29 | [Rr]elease/
30 | [Rr]eleases/
31 | x64/
32 | x86/
33 | [Ww][Ii][Nn]32/
34 | [Aa][Rr][Mm]/
35 | [Aa][Rr][Mm]64/
36 | bld/
37 | [Bb]in/
38 | [Oo]bj/
39 | [Ll]og/
40 | [Ll]ogs/
41 |
42 | # Visual Studio 2015/2017 cache/options directory
43 | .vs/
44 | # Uncomment if you have tasks that create the project's static files in wwwroot
45 | #wwwroot/
46 |
47 | # Visual Studio 2017 auto generated files
48 | Generated\ Files/
49 |
50 | # MSTest test Results
51 | [Tt]est[Rr]esult*/
52 | [Bb]uild[Ll]og.*
53 |
54 | # NUnit
55 | *.VisualState.xml
56 | TestResult.xml
57 | nunit-*.xml
58 |
59 | # Build Results of an ATL Project
60 | [Dd]ebugPS/
61 | [Rr]eleasePS/
62 | dlldata.c
63 |
64 | # Benchmark Results
65 | BenchmarkDotNet.Artifacts/
66 |
67 | # .NET
68 | project.lock.json
69 | project.fragment.lock.json
70 | artifacts/
71 |
72 | # Tye
73 | .tye/
74 |
75 | # ASP.NET Scaffolding
76 | ScaffoldingReadMe.txt
77 |
78 | # StyleCop
79 | StyleCopReport.xml
80 |
81 | # Files built by Visual Studio
82 | *_i.c
83 | *_p.c
84 | *_h.h
85 | *.ilk
86 | *.meta
87 | *.obj
88 | *.iobj
89 | *.pch
90 | *.pdb
91 | *.ipdb
92 | *.pgc
93 | *.pgd
94 | *.rsp
95 | *.sbr
96 | *.tlb
97 | *.tli
98 | *.tlh
99 | *.tmp
100 | *.tmp_proj
101 | *_wpftmp.csproj
102 | *.log
103 | *.tlog
104 | *.vspscc
105 | *.vssscc
106 | .builds
107 | *.pidb
108 | *.svclog
109 | *.scc
110 |
111 | # Chutzpah Test files
112 | _Chutzpah*
113 |
114 | # Visual C++ cache files
115 | ipch/
116 | *.aps
117 | *.ncb
118 | *.opendb
119 | *.opensdf
120 | *.sdf
121 | *.cachefile
122 | *.VC.db
123 | *.VC.VC.opendb
124 |
125 | # Visual Studio profiler
126 | *.psess
127 | *.vsp
128 | *.vspx
129 | *.sap
130 |
131 | # Visual Studio Trace Files
132 | *.e2e
133 |
134 | # TFS 2012 Local Workspace
135 | $tf/
136 |
137 | # Guidance Automation Toolkit
138 | *.gpState
139 |
140 | # ReSharper is a .NET coding add-in
141 | _ReSharper*/
142 | *.[Rr]e[Ss]harper
143 | *.DotSettings.user
144 |
145 | # TeamCity is a build add-in
146 | _TeamCity*
147 |
148 | # DotCover is a Code Coverage Tool
149 | *.dotCover
150 |
151 | # AxoCover is a Code Coverage Tool
152 | .axoCover/*
153 | !.axoCover/settings.json
154 |
155 | # Coverlet is a free, cross platform Code Coverage Tool
156 | coverage*.json
157 | coverage*.xml
158 | coverage*.info
159 |
160 | # Visual Studio code coverage results
161 | *.coverage
162 | *.coveragexml
163 |
164 | # NCrunch
165 | _NCrunch_*
166 | .*crunch*.local.xml
167 | nCrunchTemp_*
168 |
169 | # MightyMoose
170 | *.mm.*
171 | AutoTest.Net/
172 |
173 | # Web workbench (sass)
174 | .sass-cache/
175 |
176 | # Installshield output folder
177 | [Ee]xpress/
178 |
179 | # DocProject is a documentation generator add-in
180 | DocProject/buildhelp/
181 | DocProject/Help/*.HxT
182 | DocProject/Help/*.HxC
183 | DocProject/Help/*.hhc
184 | DocProject/Help/*.hhk
185 | DocProject/Help/*.hhp
186 | DocProject/Help/Html2
187 | DocProject/Help/html
188 |
189 | # Click-Once directory
190 | publish/
191 |
192 | # Publish Web Output
193 | *.[Pp]ublish.xml
194 | *.azurePubxml
195 | # Note: Comment the next line if you want to checkin your web deploy settings,
196 | # but database connection strings (with potential passwords) will be unencrypted
197 | *.pubxml
198 | *.publishproj
199 |
200 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
201 | # checkin your Azure Web App publish settings, but sensitive information contained
202 | # in these scripts will be unencrypted
203 | PublishScripts/
204 |
205 | # NuGet Packages
206 | *.nupkg
207 | # NuGet Symbol Packages
208 | *.snupkg
209 | # The packages folder can be ignored because of Package Restore
210 | **/[Pp]ackages/*
211 | # except build/, which is used as an MSBuild target.
212 | !**/[Pp]ackages/build/
213 | # Uncomment if necessary however generally it will be regenerated when needed
214 | #!**/[Pp]ackages/repositories.config
215 | # NuGet v3's project.json files produces more ignorable files
216 | *.nuget.props
217 | *.nuget.targets
218 |
219 | # Microsoft Azure Build Output
220 | csx/
221 | *.build.csdef
222 |
223 | # Microsoft Azure Emulator
224 | ecf/
225 | rcf/
226 |
227 | # Windows Store app package directories and files
228 | AppPackages/
229 | BundleArtifacts/
230 | Package.StoreAssociation.xml
231 | _pkginfo.txt
232 | *.appx
233 | *.appxbundle
234 | *.appxupload
235 |
236 | # Visual Studio cache files
237 | # files ending in .cache can be ignored
238 | *.[Cc]ache
239 | # but keep track of directories ending in .cache
240 | !?*.[Cc]ache/
241 |
242 | # Others
243 | ClientBin/
244 | ~$*
245 | *~
246 | *.dbmdl
247 | *.dbproj.schemaview
248 | *.jfm
249 | *.pfx
250 | *.publishsettings
251 | orleans.codegen.cs
252 |
253 | # Including strong name files can present a security risk
254 | # (https://github.com/github/gitignore/pull/2483#issue-259490424)
255 | #*.snk
256 |
257 | # Since there are multiple workflows, uncomment next line to ignore bower_components
258 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
259 | #bower_components/
260 |
261 | # RIA/Silverlight projects
262 | Generated_Code/
263 |
264 | # Backup & report files from converting an old project file
265 | # to a newer Visual Studio version. Backup files are not needed,
266 | # because we have git ;-)
267 | _UpgradeReport_Files/
268 | Backup*/
269 | UpgradeLog*.XML
270 | UpgradeLog*.htm
271 | ServiceFabricBackup/
272 | *.rptproj.bak
273 |
274 | # SQL Server files
275 | *.mdf
276 | *.ldf
277 | *.ndf
278 |
279 | # Business Intelligence projects
280 | *.rdl.data
281 | *.bim.layout
282 | *.bim_*.settings
283 | *.rptproj.rsuser
284 | *- [Bb]ackup.rdl
285 | *- [Bb]ackup ([0-9]).rdl
286 | *- [Bb]ackup ([0-9][0-9]).rdl
287 |
288 | # Microsoft Fakes
289 | FakesAssemblies/
290 |
291 | # GhostDoc plugin setting file
292 | *.GhostDoc.xml
293 |
294 | # Node.js Tools for Visual Studio
295 | .ntvs_analysis.dat
296 | node_modules/
297 |
298 | # Visual Studio 6 build log
299 | *.plg
300 |
301 | # Visual Studio 6 workspace options file
302 | *.opt
303 |
304 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
305 | *.vbw
306 |
307 | # Visual Studio 6 auto-generated project file (contains which files were open etc.)
308 | *.vbp
309 |
310 | # Visual Studio 6 workspace and project file (working project files containing files to include in project)
311 | *.dsw
312 | *.dsp
313 |
314 | # Visual Studio 6 technical files
315 | *.ncb
316 | *.aps
317 |
318 | # Visual Studio LightSwitch build output
319 | **/*.HTMLClient/GeneratedArtifacts
320 | **/*.DesktopClient/GeneratedArtifacts
321 | **/*.DesktopClient/ModelManifest.xml
322 | **/*.Server/GeneratedArtifacts
323 | **/*.Server/ModelManifest.xml
324 | _Pvt_Extensions
325 |
326 | # Paket dependency manager
327 | .paket/paket.exe
328 | paket-files/
329 |
330 | # FAKE - F# Make
331 | .fake/
332 |
333 | # CodeRush personal settings
334 | .cr/personal
335 |
336 | # Python Tools for Visual Studio (PTVS)
337 | __pycache__/
338 | *.pyc
339 |
340 | # Cake - Uncomment if you are using it
341 | # tools/**
342 | # !tools/packages.config
343 |
344 | # Tabs Studio
345 | *.tss
346 |
347 | # Telerik's JustMock configuration file
348 | *.jmconfig
349 |
350 | # BizTalk build output
351 | *.btp.cs
352 | *.btm.cs
353 | *.odx.cs
354 | *.xsd.cs
355 |
356 | # OpenCover UI analysis results
357 | OpenCover/
358 |
359 | # Azure Stream Analytics local run output
360 | ASALocalRun/
361 |
362 | # MSBuild Binary and Structured Log
363 | *.binlog
364 |
365 | # NVidia Nsight GPU debugger configuration file
366 | *.nvuser
367 |
368 | # MFractors (Xamarin productivity tool) working folder
369 | .mfractor/
370 |
371 | # Local History for Visual Studio
372 | .localhistory/
373 |
374 | # Visual Studio History (VSHistory) files
375 | .vshistory/
376 |
377 | # BeatPulse healthcheck temp database
378 | healthchecksdb
379 |
380 | # Backup folder for Package Reference Convert tool in Visual Studio 2017
381 | MigrationBackup/
382 |
383 | # Ionide (cross platform F# VS Code tools) working folder
384 | .ionide/
385 |
386 | # Fody - auto-generated XML schema
387 | FodyWeavers.xsd
388 |
389 | # VS Code files for those working on multiple tools
390 | .vscode/*
391 | !.vscode/settings.json
392 | !.vscode/tasks.json
393 | !.vscode/launch.json
394 | !.vscode/extensions.json
395 | *.code-workspace
396 |
397 | # Local History for Visual Studio Code
398 | .history/
399 |
400 | # Windows Installer files from build outputs
401 | *.cab
402 | *.msi
403 | *.msix
404 | *.msm
405 | *.msp
406 |
407 | # JetBrains Rider
408 | *.sln.iml
409 | .idea
410 |
411 | ##
412 | ## Visual studio for Mac
413 | ##
414 |
415 |
416 | # globs
417 | Makefile.in
418 | *.userprefs
419 | *.usertasks
420 | config.make
421 | config.status
422 | aclocal.m4
423 | install-sh
424 | autom4te.cache/
425 | *.tar.gz
426 | tarballs/
427 | test-results/
428 |
429 | # Mac bundle stuff
430 | *.dmg
431 | *.app
432 |
433 | # content below from: https://github.com/github/gitignore/blob/master/Global/macOS.gitignore
434 | # General
435 | .DS_Store
436 | .AppleDouble
437 | .LSOverride
438 |
439 | # Icon must end with two \r
440 | Icon
441 |
442 |
443 | # Thumbnails
444 | ._*
445 |
446 | # Files that might appear in the root of a volume
447 | .DocumentRevisions-V100
448 | .fseventsd
449 | .Spotlight-V100
450 | .TemporaryItems
451 | .Trashes
452 | .VolumeIcon.icns
453 | .com.apple.timemachine.donotpresent
454 |
455 | # Directories potentially created on remote AFP share
456 | .AppleDB
457 | .AppleDesktop
458 | Network Trash Folder
459 | Temporary Items
460 | .apdisk
461 |
462 | # content below from: https://github.com/github/gitignore/blob/master/Global/Windows.gitignore
463 | # Windows thumbnail cache files
464 | Thumbs.db
465 | ehthumbs.db
466 | ehthumbs_vista.db
467 |
468 | # Dump file
469 | *.stackdump
470 |
471 | # Folder config file
472 | [Dd]esktop.ini
473 |
474 | # Recycle Bin used on file shares
475 | $RECYCLE.BIN/
476 |
477 | # Windows Installer files
478 | *.cab
479 | *.msi
480 | *.msix
481 | *.msm
482 | *.msp
483 |
484 | # Windows shortcuts
485 | *.lnk
486 |
487 | # Vim temporary swap files
488 | *.swp
489 |
--------------------------------------------------------------------------------
/Directory.Build.props:
--------------------------------------------------------------------------------
1 |
2 |
3 | linux-x64;osx-x64
4 | enable
5 | enable
6 | latest
7 | ChDb
8 | $(NoWarn);CS1591
9 |
10 |
11 |
12 | True
13 | true
14 | ../../nupkg
15 | 0.0.3.0$(GITHUB_RUN_NUMBER)
16 | true
17 | $(Version).$(BuildNumber)
18 | vilinski
19 | Apache-2.0
20 | chdb.png
21 | clickhouse;chdb
22 | README.md
23 | https://github.com/vilinski/chdb
24 | https://github.com/chdb-io/chdb-dotnet
25 | git
26 | Create
27 |
28 |
29 |
30 | true
31 | true
32 | true
33 | true
34 | true
35 | true
36 | true
37 |
38 |
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # chdb
2 |
3 | A .NET Core binding for [chdb](https://doc.chdb.io) library.
4 |
5 | 
6 | 
7 | 
8 | 
9 |
10 | ### Architecture
11 |
12 |
13 |

14 |
15 |
16 | ### Usage
17 |
18 | Running on platforms: linux, osx, windows, and architectures: x64, arm64.
19 |
20 | >Note for windows users - there is no windows bild in sight, but you can still use it in WSL.
21 |
22 | Currently the librairy is too large to be packed into a nuget package, so you need to install it manually. Use the [update_libchdb.sh](update_libchdb.sh) script to download the library for your platform and architecture.
23 |
24 | ```bash
25 | # download the latest version of the library - it takes a version as an optional argument
26 | ./update_libchdb.sh
27 | # install the package to your project
28 | dotnet add package chdb
29 | ```
30 |
31 | Also place the library in appropriate folder, and add following to your csproj file:
32 |
33 | ```xml
34 |
35 |
36 | PreserveNewest
37 |
38 |
39 | ```
40 |
41 | Then you can use it in your code like this:
42 |
43 | ```csharp
44 | using ChDb;
45 |
46 | var result = ChDb.Query("select version()");
47 | Console.WriteLine(result.Text);
48 | // 23.10.1.1
49 | var s = new Session();
50 | var result = s.Query("select * from system.formats where is_output = 1", "PrettyCompact");
51 | // ┌─name───────────────────────────────────────┬─is_input─┬─is_output─┬─supports_parallel_parsing─┬─supports_parallel_formatting─┐
52 | // │ Prometheus │ 0 │ 1 │ 0 │ 0 │
53 | // │ PostgreSQLWire │ 0 │ 1 │ 0 │ 0 │
54 | // │ MySQLWire │ 0 │ 1 │ 0 │ 0 │
55 | // │ JSONEachRowWithProgress │ 0 │ 1 │ 0 │ 0 │
56 | // │ ODBCDriver2 │ 0 │ 1 │ 0 │ 0 │
57 | // ...
58 | var result = s.Query("DESCRIBE s3('https://datasets-documentation.s3.eu-west-3.amazonaws.com/house_parquet/house_0.parquet')");
59 | Console.WriteLine(result.Text);
60 | ```
61 |
62 | or use it right in F# interactive with `dotnet fsi`:
63 |
64 | ```fsharp
65 | #r "nuget: chdb"
66 |
67 | open ChDb
68 |
69 | // print out result in the PrettyCompact format by default
70 | let result = ChDb.Query "select version()"
71 | printfn "%s" result.Text
72 | // or save result to a text or binary file in any supported format
73 | let result = ChDb.Query("select * from system.formats where is_output = 1", "CSVWithNames")
74 | System.IO.File.WriteAllBytes("supported_formats.csv", result.Buf)
75 | ```
76 |
77 | ## chdb-tool
78 |
79 | 
80 | 
81 |
82 | This is a dotnet tool, running [chdb](https://doc.chdb.io) library.
83 | Probably you better served using the clickhouse client and run `clickhouse local`, but maybe it is more useful in some cases.
84 |
85 | ### Installation
86 |
87 | Requires .NET SDK 6.0 or later.
88 |
89 | ```bash
90 | dotnet tool install --global chdb-tool
91 | ```
92 |
93 | OS supported: linux, osx
94 | ARCH supported: x64, arm64
95 |
96 | ### Usage
97 |
98 | Try any of this commands lines to see which output you get.
99 |
100 | ```bash
101 | chdb
102 | chdb --version
103 | chdb --help
104 | chdb "select version()"
105 | chdb "select * from system.formats where is_output = 1" PrettyCompact
106 | ```
107 |
108 | # Build
109 |
110 | ```bash
111 | ./update_libchdb.sh [v2.0.4]
112 | cp libchdb.so src/chdb/
113 | dotnet build -c Release
114 | dotnet test -c Release
115 | dotnet pack -c Release
116 | dotnet nuget add source ./nupkg --name chdb
117 | dotnet tool update -g chdb-tool
118 | chdb --version
119 | ```
120 |
121 | ## Authors
122 |
123 | * [Andreas Vilinski](https://github.com/vilinski)
124 | * [Auxten](https://github.com/auxten)
125 |
--------------------------------------------------------------------------------
/chdb-dotnet.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chdb-io/chdb-dotnet/db6a04919a737a6f00d5cfa8154c23272897edc9/chdb-dotnet.png
--------------------------------------------------------------------------------
/chdb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chdb-io/chdb-dotnet/db6a04919a737a6f00d5cfa8154c23272897edc9/chdb.png
--------------------------------------------------------------------------------
/chdb.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 17
4 | VisualStudioVersion = 17.0.31903.59
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{53AE4A72-327B-44A3-BFAF-DF227D4D848A}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "chdb", "src\chdb\chdb.csproj", "{3B3A43FC-6DD0-4285-857C-271D19099613}"
9 | EndProject
10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "chdb-tool", "src\chdb-tool\chdb-tool.csproj", "{78D934D4-0467-410A-83A7-AC9FF23C1E79}"
11 | EndProject
12 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{F34DFA50-9A9B-406A-8535-D705F29730F3}"
13 | EndProject
14 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "test", "test\ChDbTest\test.csproj", "{458995B1-8DB5-40AC-9703-1049CA8A534B}"
15 | EndProject
16 | Global
17 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
18 | Debug|Any CPU = Debug|Any CPU
19 | Release|Any CPU = Release|Any CPU
20 | EndGlobalSection
21 | GlobalSection(SolutionProperties) = preSolution
22 | HideSolutionNode = FALSE
23 | EndGlobalSection
24 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
25 | {3B3A43FC-6DD0-4285-857C-271D19099613}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
26 | {3B3A43FC-6DD0-4285-857C-271D19099613}.Debug|Any CPU.Build.0 = Debug|Any CPU
27 | {3B3A43FC-6DD0-4285-857C-271D19099613}.Release|Any CPU.ActiveCfg = Release|Any CPU
28 | {3B3A43FC-6DD0-4285-857C-271D19099613}.Release|Any CPU.Build.0 = Release|Any CPU
29 | {78D934D4-0467-410A-83A7-AC9FF23C1E79}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
30 | {78D934D4-0467-410A-83A7-AC9FF23C1E79}.Debug|Any CPU.Build.0 = Debug|Any CPU
31 | {78D934D4-0467-410A-83A7-AC9FF23C1E79}.Release|Any CPU.ActiveCfg = Release|Any CPU
32 | {78D934D4-0467-410A-83A7-AC9FF23C1E79}.Release|Any CPU.Build.0 = Release|Any CPU
33 | {458995B1-8DB5-40AC-9703-1049CA8A534B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
34 | {458995B1-8DB5-40AC-9703-1049CA8A534B}.Debug|Any CPU.Build.0 = Debug|Any CPU
35 | {458995B1-8DB5-40AC-9703-1049CA8A534B}.Release|Any CPU.ActiveCfg = Release|Any CPU
36 | {458995B1-8DB5-40AC-9703-1049CA8A534B}.Release|Any CPU.Build.0 = Release|Any CPU
37 | EndGlobalSection
38 | GlobalSection(NestedProjects) = preSolution
39 | {3B3A43FC-6DD0-4285-857C-271D19099613} = {53AE4A72-327B-44A3-BFAF-DF227D4D848A}
40 | {78D934D4-0467-410A-83A7-AC9FF23C1E79} = {53AE4A72-327B-44A3-BFAF-DF227D4D848A}
41 | {458995B1-8DB5-40AC-9703-1049CA8A534B} = {F34DFA50-9A9B-406A-8535-D705F29730F3}
42 | EndGlobalSection
43 | EndGlobal
44 |
--------------------------------------------------------------------------------
/src/chdb-meta/chdb-meta.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | chdb
5 | chdb
6 | chdb native bindings for dotnet core
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/src/chdb-tool/Program.cs:
--------------------------------------------------------------------------------
1 | // See https://aka.ms/new-console-template for more information
2 |
3 | using System.Reflection;
4 |
5 | void PrintVersion()
6 | {
7 | var versionString = Assembly.GetEntryAssembly()?
8 | .GetCustomAttribute()?
9 | .InformationalVersion ?? "unknown";
10 | Console.WriteLine($"chdb-tool v{versionString}");
11 | }
12 |
13 | void PrintHelp()
14 | {
15 | PrintVersion();
16 | Console.WriteLine("-------------");
17 | Console.WriteLine("\nUsage:");
18 | Console.WriteLine(" chdb-tool ");
19 | }
20 |
21 | if (args.Length == 0 || args[0] == "--help" || args[0] == "-h")
22 | {
23 | PrintHelp();
24 | }
25 | else if (args[0] == "--version" || args[0] == "-v")
26 | {
27 | PrintVersion();
28 | }
29 | else
30 | try
31 | {
32 | var result = ChDb.ChDb.Query(args[0], args.Length > 1 && !args[1].StartsWith('-') ? args[1] : "PrettyCompact");
33 | if (result == null)
34 | return; // TODO behavior changed in 1.2.1
35 | Console.WriteLine(result.Text);
36 | if (!args.Contains("--quiet") && !args.Contains("-q"))
37 | {
38 | Console.WriteLine($"Elapsed: {result.Elapsed} s, read {result.RowsRead} rows, {result.BytesRead} bytes" +
39 | $", {result.RowsRead / result.Elapsed.TotalSeconds:F0} rows/s, {result.BytesRead / result.Elapsed.TotalSeconds:F0} bytes/s");
40 | if (!string.IsNullOrWhiteSpace(result.ErrorMessage))
41 | Console.Error.WriteLine("Error message: " + result.ErrorMessage);
42 | }
43 | }
44 | catch (ArgumentException e)
45 | {
46 | Console.Error.WriteLine(e.Message);
47 | Environment.Exit(1);
48 | }
49 |
--------------------------------------------------------------------------------
/src/chdb-tool/chdb-tool.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
11 |
12 |
13 |
14 | net6.0;net8.0
15 | Exe
16 | true
17 | chdb
18 | chdb-tool
19 |
23 | chdb tool
24 | clickhouse local cli as a dotnet tool
25 |
26 |
27 |
--------------------------------------------------------------------------------
/src/chdb/ChDb.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.CompilerServices;
2 | using System.Runtime.InteropServices;
3 | using System.Security;
4 |
5 | namespace ChDb;
6 |
7 | internal static class NativeMethods
8 | {
9 | private const string __DllName = "libchdb.so";
10 |
11 | [DllImport(__DllName, EntryPoint = "query_stable_v2", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
12 | internal static extern IntPtr query_stable_v2(int argc, string[] argv);
13 |
14 | [DllImport(__DllName, EntryPoint = "free_result_v2", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
15 | internal static extern void free_result_v2(IntPtr result);
16 | }
17 |
18 | ///
19 | /// Entry point for stateless chdb queries.
20 | ///
21 | public static class ChDb
22 | {
23 | ///
24 | /// Execute a stateless query and return the result.
25 | ///
26 | /// SQL query
27 | /// Optional output format from supported by clickhouse. Default is TabSeparated.
28 | /// Query result
29 | ///
30 | /// Stateless queries are useful for simple queries that do not require a session.
31 | /// Use if you need to create databases or tables.
32 | /// Set to a non-temporary directory to keep the data between sessions.
33 | ///
34 | public static LocalResult? Query(string query, string? format = null)
35 | {
36 | if (query is null)
37 | throw new ArgumentNullException(nameof(query));
38 | var argv = new[] {
39 | "clickhouse",
40 | "--multiquery",
41 | $"--query={query}",
42 | $"--output-format={format ?? "TabSeparated"}"
43 | };
44 | return Execute(argv);
45 | }
46 |
47 | private static string? LookUpArg(string[] argv, string key)
48 | {
49 | foreach (var arg in argv)
50 | {
51 | var prefix = $"--{key}=";
52 | if (arg.StartsWith(prefix))
53 | return arg.Substring(prefix.Length);
54 | }
55 | return null;
56 | }
57 |
58 | [SuppressUnmanagedCodeSecurity]
59 | [SecurityCritical]
60 | internal static LocalResult? Execute(string[] argv)
61 | {
62 | try
63 | {
64 | var ptr = NativeMethods.query_stable_v2(argv.Length, argv);
65 | var res = LocalResult.FromPtr(ptr);
66 | NativeMethods.free_result_v2(ptr);
67 | // Marshal.FreeHGlobal(ptr);
68 | return res;
69 | }
70 | catch (RuntimeWrappedException e)
71 | {
72 | if (e.WrappedException is string s)
73 | throw new ArgumentException($"Unmanaged string error {s}");
74 | else
75 | throw new ArgumentException($"Unmanaged unknown error {e.WrappedException}");
76 | }
77 | catch (Exception e)
78 | {
79 | throw new Exception("Managed error", e);
80 | }
81 | }
82 | }
--------------------------------------------------------------------------------
/src/chdb/LocalResult.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.InteropServices;
2 |
3 | namespace ChDb;
4 |
5 | ///
6 | /// The query result.
7 | ///
8 | public record LocalResult
9 | {
10 | public byte[]? Buf { get; }
11 | public string? ErrorMessage { get; }
12 | ///
13 | /// By text formats contains a result text.
14 | ///
15 | public string? Text => Buf == null ? null : System.Text.Encoding.UTF8.GetString(Buf);
16 | public ulong RowsRead { get; }
17 | public ulong BytesRead { get; }
18 | public TimeSpan Elapsed { get; }
19 |
20 | /// Result buffer.
21 | /// Error message if occured.
22 | /// Number of rows read
23 | /// Number of bytes read
24 | /// Query time elapsed, in seconds.
25 | public LocalResult(byte[]? Buf, string? ErrorMessage, ulong RowsRead, ulong BytesRead, TimeSpan Elapsed)
26 | {
27 | this.Buf = Buf;
28 | this.ErrorMessage = ErrorMessage;
29 | this.RowsRead = RowsRead;
30 | this.BytesRead = BytesRead;
31 | this.Elapsed = Elapsed;
32 | }
33 |
34 | internal static LocalResult? FromPtr(nint ptr)
35 | {
36 | if (ptr == IntPtr.Zero)
37 | return null;
38 | var h = Marshal.PtrToStructure(ptr);
39 | if (h == null)
40 | return null;
41 |
42 | var errorMessage = h.error_message == IntPtr.Zero ? null : MarshalPtrToStringUTF8(h.error_message);
43 | if (errorMessage != null)
44 | return new LocalResult(null, errorMessage, 0, 0, TimeSpan.Zero);
45 |
46 | var elapsed = TimeSpan.FromSeconds(h.elapsed);
47 |
48 | var buf = h.buf == IntPtr.Zero ? null : new byte[h.len];
49 | if (buf != null)
50 | Marshal.Copy(h.buf, buf, 0, h.len);
51 | return new LocalResult(buf, errorMessage, h.rows_read, h.bytes_read, elapsed);
52 | }
53 |
54 | private static string MarshalPtrToStringUTF8(nint ptr)
55 | {
56 | unsafe
57 | {
58 | var str = (byte*)ptr;
59 | var length = 0;
60 | for (var i = str; *i != 0; i++, length++) ;
61 | var clrString = System.Text.Encoding.UTF8.GetString(str, length);
62 | return clrString;
63 | }
64 | }
65 |
66 | [StructLayout(LayoutKind.Sequential)]
67 | internal class Handle
68 | {
69 | internal nint buf;
70 | internal int len;
71 | internal nint _vec; // std::vector *, for freeing
72 | internal double elapsed;
73 | internal ulong rows_read;
74 | internal ulong bytes_read;
75 | internal nint error_message;
76 |
77 | public override string ToString() => $"Handle{{\n\tbuf={buf},\n\tlen={len},\n\t_vec={_vec},\n\telapsed={elapsed},\n\trows_read={rows_read},\n\tbytes_read={bytes_read},\n\terror_message={error_message}}}";
78 | }
79 | }
--------------------------------------------------------------------------------
/src/chdb/Session.cs:
--------------------------------------------------------------------------------
1 | namespace ChDb;
2 |
3 | public record Session : IDisposable
4 | {
5 | ///
6 | /// Output format for queries if not explicitely specified. Default is TabSeparated
7 | ///
8 | public string? Format { get; set; }
9 | ///
10 | /// Path to the ClickHouse data directory. If not set, a temporary directory will be used.
11 | ///
12 | public string? DataPath { get; set; } = Path.Combine(Path.GetTempPath(), "chdb_");
13 | ///
14 | /// Query Log Level.
15 | ///
16 | public string? LogLevel { get; set; }
17 | ///
18 | /// Whether to delete the data directory on dispose. Default is true.
19 | ///
20 | public bool IsTemp { get; set; } = true;
21 |
22 | public void Dispose()
23 | {
24 | if (IsTemp && DataPath?.EndsWith("chdb_") == true && Directory.Exists(DataPath))
25 | Directory.Delete(DataPath, true);
26 | }
27 |
28 | ///
29 | /// Execute a query and return the result.
30 | ///
31 | /// SQL query
32 | /// Output format, optional.
33 | /// Query result
34 | public LocalResult? Query(string query, string? format = null)
35 | {
36 | if (IsTemp && DataPath is null)
37 | {
38 | DataPath = Path.Combine(Path.GetTempPath(), "chdb_");
39 | }
40 |
41 | var argv = new[] {
42 | "clickhouse",
43 | "--multiquery",
44 | $"--query={query}",
45 | $"--output-format={format ?? Format ?? "TabSeparated"}", //$"--path={DataPath}",
46 | $"--path={DataPath}",
47 | // $"--user_scripts_path={UdfPath}", $"--user_defined_executable_functions_config={UdfPath}/*.xml",
48 | $"--log-level={LogLevel ?? "trace"}",
49 | };
50 | return ChDb.Execute(argv);
51 | }
52 | }
--------------------------------------------------------------------------------
/src/chdb/chdb.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | tests
5 | netstandard2.1
6 |
10 | chdb
11 | chdb
12 | chdb native bindings for dotnet core
13 | true
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/test/ChDbTest/ChDbTest.cs:
--------------------------------------------------------------------------------
1 | namespace ChDb;
2 |
3 | [TestClass]
4 | public class ChDbTest
5 | {
6 | [TestMethod]
7 | public void QueryVersionTest()
8 | {
9 | var result = ChDb.Query("select version()");
10 | Assert.IsNotNull(result);
11 | Assert.AreEqual(1UL, result.RowsRead);
12 | Assert.AreEqual(50UL, result.BytesRead);
13 | Assert.AreEqual("24.5.1.1\n", result.Text);
14 | Assert.IsNull(result.ErrorMessage);
15 | Assert.AreNotEqual(TimeSpan.Zero, result.Elapsed);
16 | }
17 |
18 | [TestMethod]
19 | public void QueryErrorTest()
20 | {
21 | Assert.ThrowsException(() => ChDb.Query(null!));
22 | // TODO behavior changed in 1.2.1
23 | var r1 = ChDb.Query("wrong_query");
24 | Assert.IsNotNull(r1);
25 | Assert.IsNull(r1.Text);
26 | Assert.IsNotNull(r1.ErrorMessage);
27 |
28 | var r2 = ChDb.Query("wrong_query", "PrettyCompact");
29 | Assert.IsNotNull(r2);
30 | Assert.IsNull(r2.Text);
31 | Assert.IsNotNull(r2.ErrorMessage);
32 |
33 | var r3 = ChDb.Query("select version()", "wrong_format");
34 | Assert.IsNotNull(r3);
35 | Assert.IsNull(r3.Text);
36 | StringAssert.Contains(r3.ErrorMessage, "Unknown output format");
37 | }
38 |
39 | [TestMethod]
40 | public void NoDataTest()
41 | {
42 | var result = ChDb.Query("create table x(a UInt8, b UInt8, c UInt8) Engine=Memory");
43 | Assert.IsNotNull(result);
44 | Assert.AreEqual(0UL, result.RowsRead);
45 | Assert.AreEqual(0UL, result.BytesRead);
46 | Assert.IsNull(result.Text);
47 | Assert.IsNull(result.ErrorMessage);
48 | Assert.AreNotEqual(TimeSpan.Zero, result.Elapsed);
49 | Assert.IsTrue(0.1 > result.Elapsed.TotalSeconds);
50 | }
51 |
52 | [TestMethod]
53 | public void EmptyResultTest()
54 | {
55 | var result = ChDb.Query("show tables");
56 | Assert.IsNotNull(result);
57 | Assert.AreEqual(0UL, result.RowsRead);
58 | Assert.AreEqual(0UL, result.BytesRead);
59 | Assert.AreEqual("", result.Text);
60 | Assert.IsNull(result.ErrorMessage);
61 | Assert.AreNotEqual(TimeSpan.Zero, result.Elapsed);
62 | Assert.IsTrue(0.1 > result.Elapsed.TotalSeconds);
63 | }
64 |
65 | [TestMethod]
66 | public void RowNumberTest()
67 | {
68 | var result = ChDb.Query("SELECT * FROM numbers(10)");
69 | Assert.IsNotNull(result);
70 | Assert.AreEqual(10UL, result.RowsRead);
71 | }
72 |
73 | [TestMethod]
74 | public void FormatTest()
75 | {
76 | Assert.AreEqual("1\t2\t3\n", ChDb.Query("SELECT 1 as a, 2 b, 3 c")!.Text);
77 | Assert.AreEqual("1,2,3\n", ChDb.Query("SELECT 1 as a, 2 b, 3 c", "CSV")!.Text);
78 | Assert.AreEqual("\"a\",\"b\",\"c\"\n1,2,3\n", ChDb.Query("SELECT 1 as a, 2 b, 3 c", "CSVWithNames")!.Text);
79 | StringAssert.Contains(ChDb.Query("SELECT 1 as a, 2 b, 3 c", "CSVWithNamesAndTypes")!.Text, "UInt8");
80 | }
81 |
82 | [TestMethod]
83 | public void InMemoryTest()
84 | {
85 | var sql =
86 | """
87 | create table test (a UInt8, b UInt8, c UInt8) Engine=Memory;
88 | insert into test values (1, 2, 3);
89 | select * from test; show tables;
90 | drop table test;show tables
91 | """;
92 | var result = ChDb.Query(sql);
93 | Assert.IsNotNull(result);
94 | Assert.AreEqual("", result.Text);
95 | Assert.AreEqual(null, result.ErrorMessage);
96 | }
97 |
98 | [TestMethod]
99 | public void S3ParquetTest()
100 | {
101 | var result = ChDb.Query("DESCRIBE s3('https://datasets-documentation.s3.eu-west-3.amazonaws.com/house_parquet/house_0.parquet')");
102 | Assert.IsNotNull(result);
103 | Assert.IsNull(result.ErrorMessage);
104 | StringAssert.StartsWith(result.Text, "price\tNullable(Int64)");
105 | }
106 |
107 | [TestMethod]
108 | public void S3CountTest()
109 | {
110 | var result = ChDb.Query(
111 | """
112 | SELECT count()
113 | FROM s3('https://datasets-documentation.s3.eu-west-3.amazonaws.com/house_parquet/house_0.parquet')
114 | """);
115 | Assert.IsNotNull(result);
116 | Assert.IsNull(result.ErrorMessage);
117 | Assert.IsTrue(int.TryParse(result.Text, out var count));
118 | Assert.AreEqual(2772030, count);
119 | }
120 |
121 | [TestMethod]
122 | public void CsvTest()
123 | {
124 | var csv = """
125 | Name, Age, City
126 | John, 25, New York
127 | Alice, 30, London
128 | Bob, 22, Tokyo
129 | Eva, 28, Paris
130 | """;
131 | var dataPath = "/tmp/chdb/data";
132 | if (Directory.Exists(dataPath))
133 | Directory.Delete(dataPath, true);
134 | Directory.CreateDirectory(dataPath);
135 | File.WriteAllText(Path.Combine(".", "test.csv"), csv);
136 | using var session = new Session
137 | {
138 | IsTemp = false,
139 | Format = "PrettyCompact",
140 | DataPath = dataPath,
141 | LogLevel = "trace",
142 | };
143 | var result = session.Query("SELECT * FROM 'test.csv'", "CSVWithNamesAndTypes");
144 | // Console.WriteLine($"Error message:\n{result?.ErrorMessage}");
145 | // Console.WriteLine($"Query result:\n{result?.Text}");
146 | Assert.IsNotNull(result);
147 | Assert.AreEqual(4UL, result.RowsRead);
148 | Assert.AreEqual(155UL, result.BytesRead);
149 | StringAssert.StartsWith(result.Text,
150 | """
151 | "Name","Age","City"
152 | """);
153 | }
154 |
155 | [TestMethod]
156 | public void SessionTest()
157 | {
158 | using var s = new Session
159 | {
160 | Format = "PrettyCompact",
161 | LogLevel = "trace",
162 | };
163 | var nr = "xyz";
164 |
165 | var result = s.Query($"select version()");
166 | // Console.WriteLine($"Error message:\n{result?.ErrorMessage}");
167 | // Console.WriteLine($"Query result:\n{result?.Text}");
168 | Assert.IsNull(s.Query($"select version()")?.ErrorMessage);
169 |
170 | StringAssert.Contains(s.Query($"SHOW DATABASES")?.Text, "default");
171 | StringAssert.Contains(s.Query($"SELECT currentDatabase()")?.Text, "default");
172 | Assert.AreEqual("", s.Query($"SHOW TABLES")?.Text);
173 |
174 | var r1 = s.Query($"DROP DATABASE IF EXISTS db_{nr}");
175 | Assert.IsNotNull(r1);
176 | Assert.IsNull(r1.Text);
177 | Assert.IsNull(r1.ErrorMessage);
178 |
179 | var r2 = s.Query($"CREATE DATABASE IF NOT EXISTS db_{nr} ENGINE = Atomic");
180 | Assert.IsNotNull(r2);
181 | Assert.IsNull(r2.Text);
182 | Assert.IsNull(r2.ErrorMessage);
183 |
184 | var r3 = s.Query($"CREATE TABLE IF NOT EXISTS db_{nr}.log_table_{nr} (x String, y Int) ENGINE = Log;");
185 | Assert.IsNotNull(r3);
186 | Assert.IsNull(r3.Text);
187 | Assert.IsNull(r3.ErrorMessage);
188 |
189 | var r4 = s.Query($"INSERT INTO db_{nr}.log_table_{nr} VALUES ('a', 1), ('b', 3), ('c', 2), ('d', 5);");
190 | Assert.IsNotNull(r4);
191 | Assert.IsNull(r4.Text);
192 | Assert.IsNull(r4.ErrorMessage);
193 |
194 | var r5 = s.Query($"SELECT * FROM db_{nr}.log_table_{nr}", "TabSeparatedWithNames");
195 | Assert.IsNotNull(r5);
196 | Assert.AreEqual("x\ty\na\t1\nb\t3\nc\t2\nd\t5\n", r5.Text);
197 | Assert.IsNull(r5.ErrorMessage);
198 |
199 | var r6 = s.Query($"CREATE VIEW db_{nr}.view_{nr} AS SELECT * FROM db_{nr}.log_table_{nr} LIMIT 4;");
200 | Assert.IsNotNull(r6);
201 | Assert.IsNull(r6.Text);
202 | Assert.IsNull(r6.ErrorMessage);
203 |
204 | var r7 = s.Query($"SELECT * FROM db_{nr}.view_{nr}", "TabSeparatedWithNames");
205 | Assert.IsNotNull(r7);
206 | Assert.AreEqual("x\ty\na\t1\nb\t3\nc\t2\nd\t5\n", r7.Text);
207 | Assert.IsNull(r7.ErrorMessage);
208 |
209 | s.Query($"DROP DATABASE IF EXISTS db_{nr}");
210 | }
211 | }
212 |
--------------------------------------------------------------------------------
/test/ChDbTest/GlobalUsings.cs:
--------------------------------------------------------------------------------
1 | global using Microsoft.VisualStudio.TestTools.UnitTesting;
--------------------------------------------------------------------------------
/test/ChDbTest/test.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net6.0;net8.0
5 | false
6 | true
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/update_libchdb.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Download the correct version based on the platform
4 | case "$(uname -s)" in
5 | Linux)
6 | if [[ $(uname -m) == "aarch64" ]]; then
7 | PLATFORM="linux-aarch64"
8 | else
9 | PLATFORM="linux-x86_64"
10 | fi
11 | ;;
12 | Darwin)
13 | if [[ $(uname -m) == "arm64" ]]; then
14 | PLATFORM="macos-arm64"
15 | else
16 | PLATFORM="macos-x86_64"
17 | fi
18 | ;;
19 | *)
20 | echo "Unsupported platform"
21 | exit 1
22 | ;;
23 | esac
24 |
25 | # Get the newest release version
26 | # LATEST_RELEASE=$(curl --silent "https://api.github.com/repos/chdb-io/chdb/releases/latest" | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/')
27 | LATEST_RELEASE=v2.0.4
28 | RELEASE=${1:-$LATEST_RELEASE}
29 |
30 | DOWNLOAD_URL="https://github.com/chdb-io/chdb/releases/download/$RELEASE/$PLATFORM-libchdb.tar.gz"
31 |
32 | echo "Downloading $PLATFORM-libchdb.tar.gz from $DOWNLOAD_URL (latest is $LATEST_RELEASE)"
33 |
34 | # Download the file
35 | curl -L -o libchdb.tar.gz "$DOWNLOAD_URL"
36 |
37 | # Untar the file
38 | tar -xzf libchdb.tar.gz
39 |
40 | # Set execute permission for libchdb.so
41 | chmod +x libchdb.so
42 |
43 | # Clean up
44 | rm -f libchdb.tar.gz
45 |
--------------------------------------------------------------------------------