libsql 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (98) hide show
  1. checksums.yaml +7 -0
  2. data/CONTRIBUTING.md +60 -0
  3. data/HISTORY.md +6 -0
  4. data/LICENSE +31 -0
  5. data/Manifest.txt +96 -0
  6. data/README.md +59 -0
  7. data/Rakefile +28 -0
  8. data/TODO.md +57 -0
  9. data/examples/a.rb +9 -0
  10. data/examples/blob.rb +106 -0
  11. data/examples/define_aggregate.rb +75 -0
  12. data/examples/define_function.rb +104 -0
  13. data/examples/fts5.rb +152 -0
  14. data/examples/gem-db.rb +94 -0
  15. data/examples/schema-info.rb +34 -0
  16. data/ext/libsql/c/extconf.rb +86 -0
  17. data/ext/libsql/c/gen_constants.rb +353 -0
  18. data/ext/libsql/c/libsql_blob.c +240 -0
  19. data/ext/libsql/c/libsql_constants.c +1518 -0
  20. data/ext/libsql/c/libsql_database.c +1188 -0
  21. data/ext/libsql/c/libsql_ext.c +383 -0
  22. data/ext/libsql/c/libsql_ext.h +149 -0
  23. data/ext/libsql/c/libsql_statement.c +649 -0
  24. data/ext/libsql/c/notes.txt +134 -0
  25. data/ext/libsql/c/sqlite3.c +247030 -0
  26. data/ext/libsql/c/sqlite3.h +13436 -0
  27. data/lib/libsql/aggregate.rb +73 -0
  28. data/lib/libsql/blob.rb +186 -0
  29. data/lib/libsql/boolean.rb +42 -0
  30. data/lib/libsql/busy_timeout.rb +47 -0
  31. data/lib/libsql/column.rb +99 -0
  32. data/lib/libsql/csv_table_importer.rb +75 -0
  33. data/lib/libsql/database.rb +933 -0
  34. data/lib/libsql/function.rb +61 -0
  35. data/lib/libsql/index.rb +43 -0
  36. data/lib/libsql/memory_database.rb +15 -0
  37. data/lib/libsql/paths.rb +80 -0
  38. data/lib/libsql/profile_tap.rb +131 -0
  39. data/lib/libsql/progress_handler.rb +21 -0
  40. data/lib/libsql/schema.rb +225 -0
  41. data/lib/libsql/sqlite3/constants.rb +95 -0
  42. data/lib/libsql/sqlite3/database/function.rb +48 -0
  43. data/lib/libsql/sqlite3/database/status.rb +68 -0
  44. data/lib/libsql/sqlite3/libsql_version.rb +32 -0
  45. data/lib/libsql/sqlite3/status.rb +60 -0
  46. data/lib/libsql/sqlite3/version.rb +55 -0
  47. data/lib/libsql/sqlite3.rb +7 -0
  48. data/lib/libsql/statement.rb +421 -0
  49. data/lib/libsql/table.rb +91 -0
  50. data/lib/libsql/taps/console.rb +27 -0
  51. data/lib/libsql/taps/io.rb +74 -0
  52. data/lib/libsql/taps.rb +2 -0
  53. data/lib/libsql/trace_tap.rb +35 -0
  54. data/lib/libsql/type_map.rb +63 -0
  55. data/lib/libsql/type_maps/default_map.rb +166 -0
  56. data/lib/libsql/type_maps/storage_map.rb +38 -0
  57. data/lib/libsql/type_maps/text_map.rb +21 -0
  58. data/lib/libsql/version.rb +8 -0
  59. data/lib/libsql/view.rb +26 -0
  60. data/lib/libsql-ruby.rb +1 -0
  61. data/lib/libsql.rb +51 -0
  62. data/spec/aggregate_spec.rb +158 -0
  63. data/spec/blob_spec.rb +78 -0
  64. data/spec/boolean_spec.rb +24 -0
  65. data/spec/busy_handler.rb +157 -0
  66. data/spec/data/iso-3166-country.txt +242 -0
  67. data/spec/data/iso-3166-schema.sql +22 -0
  68. data/spec/data/iso-3166-subcountry.txt +3995 -0
  69. data/spec/data/make-iso-db.sh +12 -0
  70. data/spec/database_spec.rb +505 -0
  71. data/spec/default_map_spec.rb +92 -0
  72. data/spec/function_spec.rb +78 -0
  73. data/spec/integeration_spec.rb +97 -0
  74. data/spec/iso_3166_database.rb +58 -0
  75. data/spec/json_spec.rb +24 -0
  76. data/spec/libsql_spec.rb +4 -0
  77. data/spec/paths_spec.rb +28 -0
  78. data/spec/progress_handler_spec.rb +91 -0
  79. data/spec/rtree_spec.rb +66 -0
  80. data/spec/schema_spec.rb +131 -0
  81. data/spec/spec_helper.rb +48 -0
  82. data/spec/sqlite3/constants_spec.rb +108 -0
  83. data/spec/sqlite3/database_status_spec.rb +36 -0
  84. data/spec/sqlite3/libsql_version_spec.rb +16 -0
  85. data/spec/sqlite3/status_spec.rb +22 -0
  86. data/spec/sqlite3/version_spec.rb +28 -0
  87. data/spec/sqlite3_spec.rb +53 -0
  88. data/spec/statement_spec.rb +168 -0
  89. data/spec/storage_map_spec.rb +38 -0
  90. data/spec/tap_spec.rb +57 -0
  91. data/spec/text_map_spec.rb +20 -0
  92. data/spec/type_map_spec.rb +14 -0
  93. data/spec/version_spec.rb +8 -0
  94. data/tasks/custom.rake +134 -0
  95. data/tasks/default.rake +257 -0
  96. data/tasks/extension.rake +29 -0
  97. data/tasks/this.rb +208 -0
  98. metadata +325 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 4a4257a3382ce29836c8946b14640967d51dc53c58cc6a61374d5c3522d75249
4
+ data.tar.gz: ed5aa55d6e3a20d93c946fc3cef64943bbdc30c734eed6862e7b2c220b309445
5
+ SHA512:
6
+ metadata.gz: 559bc6235c96ba9e27eac6ad22c235c697dd6212ea70767fae3071c78b6279bb9b5b7a27cd9744309394b62a933e21238df706e7a6a3a7754de5aa8c53cc9446
7
+ data.tar.gz: 9abf46e3166aa0ee653dd87be63b2fdcbd29f4c54c64cbdf24526e08ae6babb9499f8d73d7736d9517e9b4e13465be06aaaafd153f7a4b1e1056b8b43d73ef5e
data/CONTRIBUTING.md ADDED
@@ -0,0 +1,60 @@
1
+ # Hi there!
2
+
3
+ I see you are interested in contributing. That is wonderful. I love
4
+ contributions.
5
+
6
+ I guarantee that there are bugs in this software. And I guarantee that there is
7
+ a feature you want that is not in here yet. As such, any and all bugs reports
8
+ are gratefully accepted, bugfixes even more so. Helping out with bugs is the
9
+ easiest way to contribute.
10
+
11
+
12
+ ## The Quick Version
13
+
14
+ * Have a [GitHub Account][].
15
+ * Search the [GitHub Issues][] and see if your issue already present. If so
16
+ add your comments, :thumbsup:, etc.
17
+ * Issue not there? Not a problem, open up a [new issue][].
18
+ * **Bug reports** please be as detailed as possible. Include:
19
+ * full ruby engine and version: `ruby -e 'puts RUBY_DESCRIPTION'`
20
+ * operating system and version
21
+ * version of libsql `ruby -rubygems -e "require 'libsql'; puts Libsql::VERSION"`
22
+ * as much detail about the bug as possible so I can replicate it. Feel free
23
+ to link in a [gist][]
24
+ * **New Feature**
25
+ * What the new feature should do.
26
+ * What benefit the new feature brings to the project.
27
+ * Fork the [repo][].
28
+ * Create a new branch for your issue: `git checkout -b issue/my-issue`
29
+ * Lovingly craft your contribution:
30
+ * `rake develop` to get started, or if you prefer bundler `rake develop:using_bundler && bundle`.
31
+ * `rake test` to run tests
32
+ * Make sure that `rake test` passes. It's important, I said it twice.
33
+ * Add yourself to the contributors section below.
34
+ * Submit your [pull request][].
35
+
36
+ ## Building Windows Binaries
37
+
38
+ This is done using https://github.com/rake-compiler/rake-compiler-dock
39
+
40
+ 1. have VirtualBox installed
41
+ 2. have Docker Machine installed (https://docs.docker.com/engine/installation/)
42
+ 3. `gem install rake-compiler-dock`
43
+ 4. `rake-compiler-dock` (this could take a while)
44
+ 5. `bundle`
45
+ 6. `rake cross native gem`
46
+
47
+ # Contributors
48
+
49
+ * [Jeremy Hinegardner](https://github.com/copiousfreetime)
50
+ * [Jos Backus](https://github.com/josb)
51
+ * [Alex Young](https://github.com/regularfry)
52
+ * [Michael Granger](https://github.com/ged)
53
+ * [Alex Young](https://github.com/bmalex)
54
+
55
+ [GitHub Account]: https://github.com/signup/free "GitHub Signup"
56
+ [GitHub Issues]: https://github.com/copiousfreetime/libsql-ruby/issues "libsql-ruby Issues"
57
+ [new issue]: https://github.com/copiousfreetime/libsql-ruby/issues/new "New libsql-ruby Issue"
58
+ [gist]: https://gist.github.com/ "New Gist"
59
+ [repo]: https://github.com/copiousfreetime/libsql-ruby "libsql-ruby Repo"
60
+ [pull request]: https://help.github.com/articles/using-pull-requests "Using Pull Requests"
data/HISTORY.md ADDED
@@ -0,0 +1,6 @@
1
+ # Libsql Changelog
2
+
3
+ ## Version 0.1.0 - 2023-05-03
4
+ * Use the the [amalgalite](https://github.com/copiousfreetime/amalgalite) codebase to bootstrap libsql.
5
+ * Initial public release
6
+ * embedds [libSQL-v0.2.1](https://github.com/libsql/libsql/releases/tag/libsql-0.2.1)
data/LICENSE ADDED
@@ -0,0 +1,31 @@
1
+ BSD License - https://opensource.org/licenses/BSD-3-Clause
2
+
3
+ Copyright (c) 2023 Jeremy Hinegardner
4
+
5
+ All rights reserved.
6
+
7
+ Redistribution and use in source and binary forms, with or without
8
+ modification, are permitted provided that the following conditions are met:
9
+
10
+ * Redistributions of source code must retain the above copyright notice,
11
+ this list of conditions and the following disclaimer.
12
+
13
+ * Redistributions in binary form must reproduce the above copyright notice,
14
+ this list of conditions and the following disclaimer in the documentation
15
+ and/or other materials provided with the distribution.
16
+
17
+ * Neither the name of Jeremy Hinegardner nor the names of its contributors
18
+ may be used to endorse or promote products derived from this software without
19
+ specific prior written permission.
20
+
21
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
22
+ IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23
+ TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
24
+ PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
25
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
data/Manifest.txt ADDED
@@ -0,0 +1,96 @@
1
+ CONTRIBUTING.md
2
+ HISTORY.md
3
+ LICENSE
4
+ Manifest.txt
5
+ README.md
6
+ Rakefile
7
+ TODO.md
8
+ examples/a.rb
9
+ examples/blob.rb
10
+ examples/define_aggregate.rb
11
+ examples/define_function.rb
12
+ examples/fts5.rb
13
+ examples/gem-db.rb
14
+ examples/schema-info.rb
15
+ ext/libsql/c/extconf.rb
16
+ ext/libsql/c/gen_constants.rb
17
+ ext/libsql/c/libsql_blob.c
18
+ ext/libsql/c/libsql_constants.c
19
+ ext/libsql/c/libsql_database.c
20
+ ext/libsql/c/libsql_ext.c
21
+ ext/libsql/c/libsql_ext.h
22
+ ext/libsql/c/libsql_statement.c
23
+ ext/libsql/c/notes.txt
24
+ ext/libsql/c/sqlite3.c
25
+ ext/libsql/c/sqlite3.h
26
+ lib/libsql-ruby.rb
27
+ lib/libsql.rb
28
+ lib/libsql/aggregate.rb
29
+ lib/libsql/blob.rb
30
+ lib/libsql/boolean.rb
31
+ lib/libsql/busy_timeout.rb
32
+ lib/libsql/column.rb
33
+ lib/libsql/csv_table_importer.rb
34
+ lib/libsql/database.rb
35
+ lib/libsql/function.rb
36
+ lib/libsql/index.rb
37
+ lib/libsql/memory_database.rb
38
+ lib/libsql/paths.rb
39
+ lib/libsql/profile_tap.rb
40
+ lib/libsql/progress_handler.rb
41
+ lib/libsql/schema.rb
42
+ lib/libsql/sqlite3.rb
43
+ lib/libsql/sqlite3/constants.rb
44
+ lib/libsql/sqlite3/database/function.rb
45
+ lib/libsql/sqlite3/database/status.rb
46
+ lib/libsql/sqlite3/libsql_version.rb
47
+ lib/libsql/sqlite3/status.rb
48
+ lib/libsql/sqlite3/version.rb
49
+ lib/libsql/statement.rb
50
+ lib/libsql/table.rb
51
+ lib/libsql/taps.rb
52
+ lib/libsql/taps/console.rb
53
+ lib/libsql/taps/io.rb
54
+ lib/libsql/trace_tap.rb
55
+ lib/libsql/type_map.rb
56
+ lib/libsql/type_maps/default_map.rb
57
+ lib/libsql/type_maps/storage_map.rb
58
+ lib/libsql/type_maps/text_map.rb
59
+ lib/libsql/version.rb
60
+ lib/libsql/view.rb
61
+ spec/aggregate_spec.rb
62
+ spec/blob_spec.rb
63
+ spec/boolean_spec.rb
64
+ spec/busy_handler.rb
65
+ spec/data/iso-3166-country.txt
66
+ spec/data/iso-3166-schema.sql
67
+ spec/data/iso-3166-subcountry.txt
68
+ spec/data/make-iso-db.sh
69
+ spec/database_spec.rb
70
+ spec/default_map_spec.rb
71
+ spec/function_spec.rb
72
+ spec/integeration_spec.rb
73
+ spec/iso_3166_database.rb
74
+ spec/json_spec.rb
75
+ spec/libsql_spec.rb
76
+ spec/paths_spec.rb
77
+ spec/progress_handler_spec.rb
78
+ spec/rtree_spec.rb
79
+ spec/schema_spec.rb
80
+ spec/spec_helper.rb
81
+ spec/sqlite3/constants_spec.rb
82
+ spec/sqlite3/database_status_spec.rb
83
+ spec/sqlite3/libsql_version_spec.rb
84
+ spec/sqlite3/status_spec.rb
85
+ spec/sqlite3/version_spec.rb
86
+ spec/sqlite3_spec.rb
87
+ spec/statement_spec.rb
88
+ spec/storage_map_spec.rb
89
+ spec/tap_spec.rb
90
+ spec/text_map_spec.rb
91
+ spec/type_map_spec.rb
92
+ spec/version_spec.rb
93
+ tasks/custom.rake
94
+ tasks/default.rake
95
+ tasks/extension.rake
96
+ tasks/this.rb
data/README.md ADDED
@@ -0,0 +1,59 @@
1
+ ## libsql
2
+
3
+ [![Build Status](https://copiousfreetime.semaphoreci.com/badges/libsql-ruby/branches/main.svg)](https://copiousfreetime.semaphoreci.com/projects/libsql-ruby)
4
+
5
+ * [Homepage](http://github.com/copiousfreetime/libsql-ruby)
6
+ * `git clone git://github.com/copiousfreetime/libsql-ruby.git`
7
+ * [Github](http://github.com/copiousfreetime/libsql-ruby/)
8
+ * [Bug Tracking](http://github.com/copiousfreetime/libsql-ruby/issues)
9
+
10
+ ## INSTALL
11
+
12
+ * `gem install libsql`
13
+ * `bundle add libsql`
14
+
15
+ ## DESCRIPTION
16
+
17
+ libsql embeds the libsql fork of the SQLite database engine as a ruby extension.
18
+ There is no need to install libsql separately.
19
+
20
+ Look in the examples/ directory to see
21
+
22
+ * general usage
23
+ * blob io
24
+ * schema information
25
+ * custom functions
26
+ * custom aggregates
27
+ * requiring ruby code from a database
28
+ * full text search
29
+
30
+ Also scroll through Libsql::Database for a quick example, and a general
31
+ overview of the API.
32
+
33
+ libsql adds in the following additional non-default SQLite extensions:
34
+
35
+ * [R*Tree index extension](http://sqlite.org/rtree.html)
36
+ * [Full Text Search](http://sqlite.org/fts5.html) - both fts3 and fts5
37
+ * [Geopoly Interface to R*Tree](https://www.sqlite.org/geopoly.html)
38
+ * [JSON Extension](https://www.sqlite.org/json1.html)
39
+
40
+ Other extensions are add that might not be usable/visible by users of the gem.
41
+ The full list of extensions added is in
42
+ [extconf.rb](ext/libsql/c/extconf.rb). And those may be cross referenced
43
+ against the [compile options from SQLite](https://www.sqlite.org/compile.html)
44
+
45
+ ## CREDITS
46
+
47
+ * This is a straight port of the [amalgalite](https://github.com/copiousfreetime/amalgalite) gem, also written by me.
48
+
49
+ ## CHANGES
50
+
51
+ Read the [HISTORY.md](HISTORY.md) file.
52
+
53
+ ## LICENSE
54
+
55
+ Copyright (c) 2023 Jeremy Hinegardner
56
+
57
+ All rights reserved.
58
+
59
+ See LICENSE and/or COPYING for details.
data/Rakefile ADDED
@@ -0,0 +1,28 @@
1
+ # vim: syntax=ruby
2
+ load 'tasks/this.rb'
3
+
4
+ This.name = "libsql"
5
+ This.author = "Jeremy Hinegardner"
6
+ This.email = "jeremy@copiousfreetime.org"
7
+ This.homepage = "http://github.com/copiousfreetime/#{ This.name }-ruby"
8
+
9
+ This.ruby_gemspec do |spec|
10
+ spec.add_dependency( 'arrayfields', '~> 4.9' )
11
+
12
+ spec.add_development_dependency( 'debug', '~> 1.0' )
13
+ spec.add_development_dependency( 'rspec', '~> 3.12' )
14
+ spec.add_development_dependency( 'rspec_junit_formatter','~> 0.6' )
15
+ spec.add_development_dependency( 'rake', '~> 13.0' )
16
+ spec.add_development_dependency( 'rake-compiler', '~> 1.2' )
17
+ spec.add_development_dependency( 'rake-compiler-dock', '~> 1.3' )
18
+ spec.add_development_dependency( 'rdoc', '~> 6.5' )
19
+ spec.add_development_dependency( 'simplecov', '~> 0.21' )
20
+ spec.add_development_dependency( 'archive-zip', '~> 0.12' )
21
+
22
+ spec.extensions.concat This.extension_conf_files
23
+ spec.license = "BSD-3-Clause"
24
+ end
25
+
26
+ load 'tasks/default.rake'
27
+ load 'tasks/extension.rake'
28
+ load 'tasks/custom.rake'
data/TODO.md ADDED
@@ -0,0 +1,57 @@
1
+ # Future Release possibilties:
2
+ - rebuild statement constants
3
+ - look at all pragma statements
4
+
5
+ ## SQLite API:
6
+ - authorizers
7
+ - loading of extensions -- readfile / writefile
8
+ - utf-16 integration
9
+ - create_collation
10
+ - encryption key support
11
+ - expose sqlite3_strnicmp
12
+ - table name and column name in a type map?
13
+ - type conversion for manifest typing? how to allow it through?
14
+ - explicit pragma handler
15
+ - application_id pragma setter
16
+
17
+ ## Non backwards compatible changes:
18
+ - change the schema objects to be more consistent
19
+ - change taps to use to_proc protocol
20
+ - convert type dependency to just use 'call'
21
+ - integrate transaction and savepoint under the same api
22
+
23
+ ## SQLite Features:
24
+ - activate SQLITE_ENABLE_ICU extension
25
+ - activate SQLITE_ENABLE_LOCKING_STYLE
26
+ - activate SQLITE_ENABLE_UNLOCK_NOTIFY
27
+ - expose PRAGMA foreign_keys
28
+ - virtual file system
29
+ - full text search (FTS3)
30
+ - expose the sqlite mutex lib
31
+ - statement status ( sqlite3_stmt_status )
32
+ - db status ( sqlite3_db_status )
33
+ - library status ( sqlite3_status )
34
+ - sqlite3_index_info
35
+ - sqlite3_create_function has 4th parameter SQLITE_DETERMINISTIC
36
+ - sqlite3_rtree_query_callback()
37
+
38
+ ## Drivers:
39
+ - data mapper driver
40
+ - sequel driver optimization
41
+
42
+ ## Features:
43
+ - Think about moving from arrayfields to ordered hash?
44
+ - add to command line which directory to pack into a rubylibs table
45
+ - command line tool
46
+ - use ruby's ALLOC_N and hook into sqlite3_mem_methods
47
+
48
+ ## Functions to possibly expose:
49
+ - sqlite3_backup_remaining, sqlite3_backup_pagecount
50
+ - sqlite3_compileoption_used, sqlite3_compileoption_get
51
+ - sqlite3_config
52
+ - sqlite3_data_count - returns number of colums in the result set of a
53
+ prepared statement
54
+ - sqlite_sourceid, sqlite_source_id
55
+ - sqlite3_strnicmp
56
+ -
57
+
data/examples/a.rb ADDED
@@ -0,0 +1,9 @@
1
+ class A
2
+ def initialize
3
+ puts "Initialized A"
4
+ end
5
+
6
+ def a
7
+ puts "called a"
8
+ end
9
+ end
data/examples/blob.rb ADDED
@@ -0,0 +1,106 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ #
4
+ # A Libsql example showing how Blob's can be utilized
5
+ #
6
+ # We'll make a database with one table, that we store files in. We'll use the
7
+ # Blob incremental IO to store the files and retrieve them from the database
8
+ #
9
+ # This little program will store 1 or more files in the sqlite3 database when
10
+ # the 'store' action is given, and cat a file to stdout on 'retrieve'
11
+ #
12
+ # e.g.
13
+ #
14
+ # ruby blob.rb store a.rb b.rb c.rb # => stores a.rb b.rb and c.rb in the db
15
+ #
16
+ # ruby blob.rb retrieve a.rb # => dumps a.rb to stdout
17
+ #
18
+
19
+ require 'rubygems'
20
+ $: << "../lib"
21
+ $: << "../ext"
22
+ require 'libsql'
23
+ VALID_ACTIONS = %w[ list retrieve store ]
24
+ def usage
25
+ STDERR.puts "Usage: #{File.basename($0)} ( #{VALID_ACTIONS.join(' | ')} ) file(s)"
26
+ exit 1
27
+ end
28
+
29
+ #
30
+ # This does the basic command line parsing
31
+ #
32
+ usage if ARGV.size < 1
33
+ action = ARGV.shift
34
+ usage unless VALID_ACTIONS.include? action
35
+ file_list = ARGV
36
+
37
+ #
38
+ # create the database if it doesn't exist
39
+ #
40
+ db = ::Libsql::Database.new( "filestore.db" )
41
+ schema = db.schema
42
+ unless schema.tables['files']
43
+
44
+ schema = <<~SQL
45
+ CREATE TABLE files (
46
+ id integer primary key autoincrement,
47
+ filename text unique,
48
+ contents blob
49
+ )
50
+ SQL
51
+
52
+ db.execute(schema)
53
+ db.reload_schema!
54
+ end
55
+
56
+
57
+ case action
58
+ #
59
+ # list all the files that are stored in the database
60
+ #
61
+ when 'list'
62
+ db.execute("SELECT filename FROM files") do |row|
63
+ puts row['filename']
64
+ end
65
+
66
+ #
67
+ # if we are doing the store action, then loop over the files and store them in
68
+ # the database. This will use incremental IO to store the files directly from
69
+ # the file names.
70
+ #
71
+ # It is slightly strange in that you have to tell the Blob object what column
72
+ # it is going to, but that is necessary at this point to be able to hook
73
+ # automatically into the lower level incremental blob IO api.
74
+ #
75
+ # This also shows using the $var syntax for binding name sql values in a
76
+ # prepared statement.
77
+ #
78
+ when 'store'
79
+ usage if file_list.empty?
80
+
81
+ contents_column = db.schema.tables['files'].columns['contents']
82
+ db.transaction do |trans|
83
+ trans.prepare("INSERT INTO files (filename, contents) VALUES ($filename, $contents)") do |stmt|
84
+ file_list.each do |file_path|
85
+ contents = IO.read(file_path)
86
+ content_io = StringIO.new(contents)
87
+ stmt.execute("$filename" => file_path,
88
+ "$contents" => ::Libsql::Blob.new(io: content_io,
89
+ column: contents_column)
90
+ )
91
+ end
92
+ end
93
+ end
94
+
95
+ #
96
+ # dump the file that matches the right path to stdout. This also shows
97
+ # positional sql varible binding using the '?' syntax.
98
+ #
99
+ when 'retrieve'
100
+ usage if file_list.empty?
101
+ db.execute("SELECT id, filename, contents FROM files WHERE filename = ?", file_list.first) do |row|
102
+ STDERR.puts "Dumping #{row['filename']} to stdout"
103
+ row['contents'].write_to_io( STDOUT )
104
+ end
105
+ end
106
+ db.close
@@ -0,0 +1,75 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ $: << "../lib"
5
+ $: << "../ext"
6
+ require 'libsql'
7
+
8
+ #--
9
+ # Create a database and a table to put some results from the functions in
10
+ #--
11
+ db = ::Libsql::Database.new( ":memory:" )
12
+ db.execute( "CREATE TABLE atest( words )" )
13
+
14
+ #------------------------------------------------------------------------------
15
+ # Create unique word count aggregate
16
+ #------------------------------------------------------------------------------
17
+ class UniqueWordCount < ::Libsql::Aggregate
18
+ attr_accessor :words
19
+
20
+ def initialize
21
+ @name = 'unique_word_count'
22
+ @arity = 1
23
+ @words = Hash.new { |h,k| h[k] = 0 }
24
+ end
25
+
26
+ def step( str )
27
+ str.split(/\W+/).each do |word|
28
+ words[ word.downcase ] += 1
29
+ end
30
+ return nil
31
+ end
32
+
33
+ def finalize
34
+ return words.size
35
+ end
36
+ end
37
+
38
+ db.define_aggregate( 'unique_word_count', UniqueWordCount )
39
+
40
+ #------------------------------------------------------------------------------
41
+ # Now we have a new aggregate function, lets insert some rows into the database
42
+ # and see what we can find.
43
+ #------------------------------------------------------------------------------
44
+ sql = "INSERT INTO atest( words ) VALUES( ? )"
45
+ verify = {}
46
+ db.prepare( sql ) do |stmt|
47
+ DATA.each do |words|
48
+ words.strip!
49
+ puts "Inserting #{words}"
50
+ stmt.execute( words )
51
+ words.split(/\W+/).each { |w| verify[w] = true }
52
+ end
53
+ end
54
+
55
+ #------------------------------------------------------------------------------
56
+ # And show the results
57
+ #------------------------------------------------------------------------------
58
+ puts
59
+ puts "Getting results..."
60
+ puts
61
+ all_rows = db.execute("SELECT unique_word_count( words ) AS uwc FROM atest")
62
+ puts "#{all_rows.first['uwc']} unique words found"
63
+ puts "#{verify.size} unique words to verify"
64
+
65
+ __END__
66
+ some random
67
+ words with
68
+ which
69
+ to play
70
+ and there should
71
+ be a couple of different
72
+ words that appear
73
+ more than once and
74
+ some that appear only
75
+ once
@@ -0,0 +1,104 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ $: << "../lib"
5
+ $: << "../ext"
6
+ require 'libsql'
7
+
8
+ #--
9
+ # Create a database and a table to put some results from the functions in
10
+ #--
11
+ db = ::Libsql::Database.new( ":memory:" )
12
+ db.execute( "CREATE TABLE ftest( data, md5, sha1, sha2_bits, sha2)" )
13
+
14
+ #------------------------------------------------------------------------------
15
+ # Create an MD5 method using the block format of defining an sql fuction
16
+ #------------------------------------------------------------------------------
17
+ require 'digest/md5'
18
+ db.define_function( 'md5' ) do |x|
19
+ Digest::MD5.hexdigest( x.to_s )
20
+ end
21
+
22
+ #------------------------------------------------------------------------------
23
+ # Create a SHA1 method using the lambda format of defining an sql function
24
+ #------------------------------------------------------------------------------
25
+ require 'digest/sha1'
26
+ sha1 = lambda do |y|
27
+ Digest::SHA1.hexdigest( y.to_s )
28
+ end
29
+ db.define_function( "sha1", sha1 )
30
+
31
+ #------------------------------------------------------------------------------
32
+ # Create a SHA2 method using the class format for defining an sql function
33
+ # In this one we will allow any number of parameters, but we will only use the
34
+ # first two.
35
+ #------------------------------------------------------------------------------
36
+ require 'digest/sha2'
37
+ class SQLSha2
38
+ # track the number of invocations
39
+ attr_reader :call_count
40
+
41
+ def initialize
42
+ @call_count = 0
43
+ end
44
+
45
+ # the protocol that is used for sql function definition
46
+ def to_proc() self ; end
47
+
48
+ # say we take any number of parameters
49
+ def arity
50
+ -1
51
+ end
52
+
53
+ # The method that is called by SQLite, must be named 'call'
54
+ def call( *args )
55
+ text = args.shift.to_s
56
+ bitlength = (args.shift || 256).to_i
57
+ Digest::SHA2.new( bitlength ).hexdigest( text )
58
+ end
59
+ end
60
+ db.define_function('sha2', SQLSha2.new)
61
+
62
+
63
+ #------------------------------------------------------------------------------
64
+ # Now we have 3 new sql functions, each defined in one of the available methods
65
+ # to define sql functions in libsql. Lets insert some rows and look at the
66
+ # results
67
+ #------------------------------------------------------------------------------
68
+ possible_bits = [ 256, 384, 512 ]
69
+ sql = "INSERT INTO ftest( data, md5, sha1, sha2_bits, sha2 ) VALUES( @word , md5( @word ), sha1( @word ), @bits, sha2(@word,@bits) )"
70
+ db.prepare( sql ) do |stmt|
71
+ DATA.each do |word|
72
+ word.strip!
73
+ bits = possible_bits[ rand(3) ]
74
+ puts "Inserting #{word}, #{bits}"
75
+ stmt.execute( { '@word' => word, '@bits' => bits } )
76
+ end
77
+ end
78
+
79
+ #------------------------------------------------------------------------------
80
+ # And show the results
81
+ #------------------------------------------------------------------------------
82
+ puts
83
+ puts "Getting results..."
84
+ puts
85
+ columns = db.schema.tables['ftest'].columns.keys.sort
86
+ i = 0
87
+ db.execute("SELECT #{columns.join(',')} FROM ftest") do |row|
88
+ i += 1
89
+ puts "-----[ row #{i} ]-" + "-" * 42
90
+ columns.each do |col|
91
+ puts "#{col.ljust(10)} : #{row[col]}"
92
+ end
93
+ puts
94
+ end
95
+
96
+
97
+ __END__
98
+ some
99
+ random
100
+ words
101
+ with
102
+ which
103
+ to
104
+ play