libsql 0.1.0-x86-mingw32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) 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/3.0/libsql_ext.so +0 -0
  28. data/lib/libsql/3.1/libsql_ext.so +0 -0
  29. data/lib/libsql/3.2/libsql_ext.so +0 -0
  30. data/lib/libsql/aggregate.rb +73 -0
  31. data/lib/libsql/blob.rb +186 -0
  32. data/lib/libsql/boolean.rb +42 -0
  33. data/lib/libsql/busy_timeout.rb +47 -0
  34. data/lib/libsql/column.rb +99 -0
  35. data/lib/libsql/csv_table_importer.rb +75 -0
  36. data/lib/libsql/database.rb +933 -0
  37. data/lib/libsql/function.rb +61 -0
  38. data/lib/libsql/index.rb +43 -0
  39. data/lib/libsql/memory_database.rb +15 -0
  40. data/lib/libsql/paths.rb +80 -0
  41. data/lib/libsql/profile_tap.rb +131 -0
  42. data/lib/libsql/progress_handler.rb +21 -0
  43. data/lib/libsql/schema.rb +225 -0
  44. data/lib/libsql/sqlite3/constants.rb +95 -0
  45. data/lib/libsql/sqlite3/database/function.rb +48 -0
  46. data/lib/libsql/sqlite3/database/status.rb +68 -0
  47. data/lib/libsql/sqlite3/libsql_version.rb +32 -0
  48. data/lib/libsql/sqlite3/status.rb +60 -0
  49. data/lib/libsql/sqlite3/version.rb +55 -0
  50. data/lib/libsql/sqlite3.rb +7 -0
  51. data/lib/libsql/statement.rb +421 -0
  52. data/lib/libsql/table.rb +91 -0
  53. data/lib/libsql/taps/console.rb +27 -0
  54. data/lib/libsql/taps/io.rb +74 -0
  55. data/lib/libsql/taps.rb +2 -0
  56. data/lib/libsql/trace_tap.rb +35 -0
  57. data/lib/libsql/type_map.rb +63 -0
  58. data/lib/libsql/type_maps/default_map.rb +166 -0
  59. data/lib/libsql/type_maps/storage_map.rb +38 -0
  60. data/lib/libsql/type_maps/text_map.rb +21 -0
  61. data/lib/libsql/version.rb +8 -0
  62. data/lib/libsql/view.rb +26 -0
  63. data/lib/libsql-ruby.rb +1 -0
  64. data/lib/libsql.rb +51 -0
  65. data/spec/aggregate_spec.rb +158 -0
  66. data/spec/blob_spec.rb +78 -0
  67. data/spec/boolean_spec.rb +24 -0
  68. data/spec/busy_handler.rb +157 -0
  69. data/spec/data/iso-3166-country.txt +242 -0
  70. data/spec/data/iso-3166-schema.sql +22 -0
  71. data/spec/data/iso-3166-subcountry.txt +3995 -0
  72. data/spec/data/make-iso-db.sh +12 -0
  73. data/spec/database_spec.rb +505 -0
  74. data/spec/default_map_spec.rb +92 -0
  75. data/spec/function_spec.rb +78 -0
  76. data/spec/integeration_spec.rb +97 -0
  77. data/spec/iso_3166_database.rb +58 -0
  78. data/spec/json_spec.rb +24 -0
  79. data/spec/libsql_spec.rb +4 -0
  80. data/spec/paths_spec.rb +28 -0
  81. data/spec/progress_handler_spec.rb +91 -0
  82. data/spec/rtree_spec.rb +66 -0
  83. data/spec/schema_spec.rb +131 -0
  84. data/spec/spec_helper.rb +48 -0
  85. data/spec/sqlite3/constants_spec.rb +108 -0
  86. data/spec/sqlite3/database_status_spec.rb +36 -0
  87. data/spec/sqlite3/libsql_version_spec.rb +16 -0
  88. data/spec/sqlite3/status_spec.rb +22 -0
  89. data/spec/sqlite3/version_spec.rb +28 -0
  90. data/spec/sqlite3_spec.rb +53 -0
  91. data/spec/statement_spec.rb +168 -0
  92. data/spec/storage_map_spec.rb +38 -0
  93. data/spec/tap_spec.rb +57 -0
  94. data/spec/text_map_spec.rb +20 -0
  95. data/spec/type_map_spec.rb +14 -0
  96. data/spec/version_spec.rb +8 -0
  97. data/tasks/custom.rake +134 -0
  98. data/tasks/default.rake +257 -0
  99. data/tasks/extension.rake +29 -0
  100. data/tasks/this.rb +208 -0
  101. metadata +330 -0
@@ -0,0 +1,61 @@
1
+ require 'libsql/sqlite3/database/function'
2
+ module ::Libsql
3
+ #
4
+ # A Base class to inherit from for creating your own SQL scalar functions
5
+ # in ruby.
6
+ #
7
+ # These are SQL functions similar to _abs(X)_, _length(X)_, _random()_. Items
8
+ # that take parameters and return value. They have no state between
9
+ # calls. Built in SQLite scalar functions are :
10
+ #
11
+ # * http://www.sqlite.org/lang_corefunc.html
12
+ # * http://www.sqlite.org/lang_datefunc.html
13
+ #
14
+ # Functions defined in ::Libsql databases conform to the Proc interface.
15
+ # Everything that is defined in an ::Libsql database using +define_function+
16
+ # has its +to_proc+ method called. As a result, any Function must also
17
+ # conform to the +to_proc+ protocol.
18
+ #
19
+ # If you choose to use Function as a parent class of your SQL scalar function
20
+ # implementation you should only have implement +call+ with the appropriate
21
+ # _arity_.
22
+ #
23
+ # For instance to implement a _sha1(X)_ SQL function you could implement it as
24
+ #
25
+ # class SQLSha1 < ::Libsql::Function
26
+ # def initialize
27
+ # super( 'md5', 1 )
28
+ # end
29
+ # def call( s )
30
+ # ::Digest::MD5.hexdigest( s.to_s )
31
+ # end
32
+ # end
33
+ #
34
+ class Function
35
+ # The name of the SQL function
36
+ attr_accessor :name
37
+
38
+ # The arity of the SQL function
39
+ attr_accessor :arity
40
+
41
+ # Initialize the function with a name and arity
42
+ def initialize( name, arity )
43
+ @name = name
44
+ @arity = arity
45
+ end
46
+
47
+ # All SQL functions defined foloow the +to_proc+ protocol
48
+ def to_proc
49
+ self
50
+ end
51
+
52
+ # <b>Do Not Override</b>
53
+ #
54
+ # The function signature for use by the Amaglaite datase in tracking
55
+ # function definition and removal.
56
+ #
57
+ def signature
58
+ @signature ||= ::Libsql::SQLite3::Database::Function.signature( self.name, self.arity )
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,43 @@
1
+ #--
2
+ # Copyright (c) 2023 Jeremy Hinegardner
3
+ # All rights reserved. See LICENSE and/or COPYING for details.
4
+ #++
5
+
6
+ module ::Libsql
7
+ #
8
+ # a class representing the meta information about an SQLite index
9
+ #
10
+ class Index
11
+ # the name of the index
12
+ attr_reader :name
13
+
14
+ # the sql statement that created the index
15
+ attr_reader :sql
16
+
17
+ # the table the index is for
18
+ attr_accessor :table
19
+
20
+ # the columns that make up this index, in index order
21
+ attr_accessor :columns
22
+
23
+ # sqlite sequence number of the index
24
+ attr_accessor :sequence_number
25
+
26
+ # is the index unique
27
+ attr_writer :unique
28
+
29
+ def initialize( name, sql, table )
30
+ @name = name
31
+ @sql = sql
32
+ @table = table
33
+ @columns = []
34
+ @sequence_number = nil
35
+ @unique = nil
36
+ end
37
+
38
+ def unique?
39
+ return @unique
40
+ end
41
+ end
42
+ end
43
+
@@ -0,0 +1,15 @@
1
+ require 'libsql/database'
2
+ module ::Libsql
3
+ #
4
+ # The encapsulation of a connection to an SQLite3 in-memory database.
5
+ #
6
+ # Open an in-memory database:
7
+ #
8
+ # db = ::Libsql::MemoryDatabase.new
9
+ #
10
+ class MemoryDatabase < Database
11
+ def initialize
12
+ super( ":memory:" )
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,80 @@
1
+ #--
2
+ # Copyright (c) 2023 Jeremy Hinegardner
3
+ # All rights reserved. See LICENSE and/or COPYING for details.
4
+ #++
5
+ module ::Libsql
6
+ #
7
+ # Paths contains helpful methods to determine paths of files inside the
8
+ # ::Libsql library
9
+ #
10
+ module Paths
11
+ #
12
+ # The root directory of the project is considered to be the parent directory
13
+ # of the 'lib' directory.
14
+ #
15
+ # returns:: [String] The full expanded path of the parent directory of 'lib'
16
+ # going up the path from the current file. Trailing
17
+ # File::SEPARATOR is guaranteed.
18
+ #
19
+ def self.root_dir
20
+ @root_dir ||= (
21
+ path_parts = ::File.expand_path(__FILE__).split(::File::SEPARATOR)
22
+ lib_index = path_parts.rindex("lib")
23
+ path_parts[0...lib_index].join(::File::SEPARATOR) + ::File::SEPARATOR
24
+ )
25
+ return @root_dir
26
+ end
27
+
28
+ # returns:: [String] The full expanded path of the +config+ directory
29
+ # below _root_dir_. All parameters passed in are joined onto the
30
+ # result. Trailing File::SEPARATOR is guaranteed if _args_ are
31
+ # *not* present.
32
+ #
33
+ def self.config_path(*args)
34
+ self.sub_path("config", *args)
35
+ end
36
+
37
+ # returns:: [String] The full expanded path of the +data+ directory below
38
+ # _root_dir_. All parameters passed in are joined onto the
39
+ # result. Trailing File::SEPARATOR is guaranteed if
40
+ # _*args_ are *not* present.
41
+ #
42
+ def self.data_path(*args)
43
+ self.sub_path("data", *args)
44
+ end
45
+
46
+ # returns:: [String] The full expanded path of the +lib+ directory below
47
+ # _root_dir_. All parameters passed in are joined onto the
48
+ # result. Trailing File::SEPARATOR is guaranteed if
49
+ # _*args_ are *not* present.
50
+ #
51
+ def self.lib_path(*args)
52
+ self.sub_path("lib", *args)
53
+ end
54
+
55
+ # returns:: [String] The full expanded path of the +ext+ directory below
56
+ # _root_dir_. All parameters passed in are joined onto the
57
+ # result. Trailing File::SEPARATOR is guaranteed if
58
+ # _*args_ are *not* present.
59
+ #
60
+ def self.ext_path(*args)
61
+ self.sub_path("ext", *args)
62
+ end
63
+
64
+ # returns:: [String] The full expanded path of the +spec+ directory below
65
+ # _root_dir_. All parameters passed in are joined onto the
66
+ # result. Trailing File::SEPARATOR is guaranteed if
67
+ # _*args_ are *not* present.
68
+ #
69
+ def self.spec_path(*args)
70
+ self.sub_path("spec", *args)
71
+ end
72
+
73
+
74
+ def self.sub_path(sub,*args)
75
+ sp = ::File.join(root_dir, sub) + File::SEPARATOR
76
+ sp = ::File.join(sp, *args) if args
77
+ end
78
+ end
79
+ end
80
+
@@ -0,0 +1,131 @@
1
+ #--
2
+ # Copyright (c) 2023 Jeremy Hinegardner
3
+ # All rights reserved. See LICENSE and/or COPYING for details.
4
+ #++
5
+
6
+ module ::Libsql
7
+ #
8
+ # A ProfileSampler is a sampler of profile times. It aggregates up profile
9
+ # events that happen for the same source. It is based upon the RFuzz::Sampler
10
+ # class from the rfuzz gem
11
+ #
12
+ class ProfileSampler
13
+ #
14
+ # create a new sampler with the given name
15
+ #
16
+ def initialize( name )
17
+ @name = name
18
+ reset!
19
+ end
20
+
21
+ ##
22
+ # reset the internal state so it may be used again
23
+ #
24
+ def reset!
25
+ @sum = 0.0
26
+ @sumsq = 0.0
27
+ @n = 0
28
+ @min = 0.0
29
+ @max = 0.0
30
+ end
31
+
32
+ ##
33
+ # add a sample to the calculations
34
+ #
35
+ def sample( value )
36
+ @sum += value
37
+ @sumsq += (value * value)
38
+ if @n == 0 then
39
+ @min = @max = value
40
+ else
41
+ @min = value if value < @min
42
+ @max = value if value > @max
43
+ end
44
+ @n += 1
45
+ end
46
+
47
+ ##
48
+ # return the mean of the data
49
+ #
50
+ def mean
51
+ @sum / @n
52
+ end
53
+
54
+ ##
55
+ # returns the standard deviation of the data
56
+ #
57
+ def stddev
58
+ begin
59
+ return 0.0 if ( 1 == @n )
60
+ Math.sqrt( (@sumsq - ( @sum * @sum / @n)) / (@n-1) )
61
+ rescue Errno::EDOM
62
+ return 0.0
63
+ end
64
+ end
65
+
66
+ ##
67
+ # return all the values as an array
68
+ #
69
+ def to_a
70
+ [ @name, @sum, @sumsq, @n, mean, stddev, @min, @max ]
71
+ end
72
+
73
+ ##
74
+ # return all the values as a hash
75
+ #
76
+ def to_h
77
+ { 'name' => @name, 'n' => @n,
78
+ 'sum' => @sum, 'sumsq' => @sumsq, 'mean' => mean,
79
+ 'stddev' => stddev, 'min' => @min, 'max' => @max }
80
+ end
81
+
82
+ ##
83
+ # return a string containing the sampler summary
84
+ #
85
+ def to_s
86
+ "[%s] => sum: %d, sumsq: %d, n: %d, mean: %0.6f, stddev: %0.6f, min: %d, max: %d" % self.to_a
87
+ end
88
+
89
+ end
90
+
91
+ #
92
+ # A Profile Tap recives +profile+ events from SQLite which involve the number of
93
+ # nanoseconds in wall-clock time it took for a particular thing to happen. In
94
+ # general this +thing+ is an SQL statement.
95
+ #
96
+ # It has a well known +profile+ method which when invoked will write the event
97
+ # to a delegate object.
98
+ #
99
+ #
100
+ class ProfileTap
101
+
102
+ attr_reader :samplers
103
+
104
+ #
105
+ # Create a new ProfileTap object that wraps the given object and calls the
106
+ # method named in +send_to+ ever time a profile event happens.
107
+ #
108
+ def initialize( wrapped_obj, send_to = 'profile' )
109
+ unless wrapped_obj.respond_to?( send_to )
110
+ raise ::Libsql::Error, "#{wrapped_obj.class.name} does not respond to #{send_to.to_s} "
111
+ end
112
+
113
+ @delegate_obj = wrapped_obj
114
+ @delegate_method = send_to
115
+ @samplers = {}
116
+ end
117
+
118
+ #
119
+ # Record the profile information and send the delegate object the msg and
120
+ # time information.
121
+ #
122
+ def profile( msg, time )
123
+ msg = msg.gsub(/\s+/,' ')
124
+ unless sampler = @samplers[msg]
125
+ sampler = @samplers[msg] = ProfileSampler.new( msg )
126
+ end
127
+ sampler.sample( time )
128
+ @delegate_obj.send( @delegate_method, msg, time )
129
+ end
130
+ end
131
+ end
@@ -0,0 +1,21 @@
1
+ module ::Libsql
2
+ ##
3
+ # A base class for use in creating your own progress handler classes
4
+ #
5
+ class ProgressHandler
6
+ def to_proc
7
+ self
8
+ end
9
+
10
+ # the arity of the call method
11
+ def arity() 0 ; end
12
+
13
+ ##
14
+ # Override this method, returning +false+ if the SQLite should act as if
15
+ # +interrupt!+ had been invoked.
16
+ #
17
+ def call
18
+ raise NotImplementedError, "The progress handler call() method must be implemented"
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,225 @@
1
+ #--
2
+ # Copyright (c) 2023 Jeremy Hinegardner
3
+ # All rights reserved. See LICENSE and/or COPYING for details.
4
+ #++
5
+
6
+ require 'libsql/table'
7
+ require 'libsql/index'
8
+ require 'libsql/column'
9
+ require 'libsql/view'
10
+
11
+ module ::Libsql
12
+ #
13
+ # An object view of the schema in the SQLite database. If the schema changes
14
+ # after this class is created, it has no knowledge of that.
15
+ #
16
+ class Schema
17
+
18
+ # The internal database that this schema is for. Most of the time this will
19
+ # be 'main' for the main database. For the temp tables, this will be 'temp'
20
+ # and for any attached databsae, this is the name of attached database.
21
+ attr_reader :catalog
22
+
23
+ # The schema_version at the time this schema was taken.
24
+ attr_reader :schema_version
25
+
26
+ # The Amalagalite::Database this schema is associated with.
27
+ attr_reader :db
28
+
29
+ #
30
+ # Create a new instance of Schema
31
+ #
32
+ def initialize( db, catalog = 'main', master_table = 'sqlite_master' )
33
+ @db = db
34
+ @catalog = catalog
35
+ @schema_version = nil
36
+ @tables = {}
37
+ @views = {}
38
+ @master_table = master_table
39
+
40
+ if @master_table == 'sqlite_master' then
41
+ @temp_schema = ::Libsql::Schema.new( db, 'temp', 'sqlite_temp_master')
42
+ else
43
+ @temp_schema = nil
44
+ end
45
+ load_schema!
46
+ end
47
+
48
+ def catalog_master_table
49
+ "#{catalog}.#{@master_table}"
50
+ end
51
+
52
+ def temporary?
53
+ catalog == "temp"
54
+ end
55
+
56
+ def dirty?()
57
+ return true if (@schema_version != self.current_version)
58
+ return false unless @temp_schema
59
+ return @temp_schema.dirty?
60
+ end
61
+
62
+ def current_version
63
+ @db.first_value_from("PRAGMA #{catalog}.schema_version")
64
+ end
65
+
66
+ #
67
+ # load the schema from the database
68
+ def load_schema!
69
+ load_tables
70
+ load_views
71
+ if @temp_schema then
72
+ @temp_schema.load_schema!
73
+ end
74
+ @schema_version = self.current_version
75
+ nil
76
+ end
77
+
78
+ ##
79
+ # return the tables, reloading if dirty.
80
+ # If there is a temp table and a normal table with the same name, then the
81
+ # temp table is the one that is returned in the hash.
82
+ def tables
83
+ load_schema! if dirty?
84
+ t = @tables
85
+ if @temp_schema then
86
+ t = @tables.merge( @temp_schema.tables )
87
+ end
88
+ return t
89
+ end
90
+
91
+ ##
92
+ # load all the tables
93
+ #
94
+ def load_tables
95
+ @tables = {}
96
+ @db.execute("SELECT tbl_name FROM #{catalog_master_table} WHERE type = 'table' AND name != 'sqlite_sequence'") do |table_info|
97
+ table = load_table( table_info['tbl_name'] )
98
+ table.indexes = load_indexes( table )
99
+ @tables[table.name] = table
100
+ end
101
+ return @tables
102
+ end
103
+
104
+ ##
105
+ # Load a single table
106
+ def load_table( table_name )
107
+ rows = @db.execute("SELECT tbl_name, sql FROM #{catalog_master_table} WHERE type = 'table' AND tbl_name = ?", table_name)
108
+ table_info = rows.first
109
+ table = nil
110
+ if table_info then
111
+ table = ::Libsql::Table.new( table_info['tbl_name'], table_info['sql'] )
112
+ table.schema = self
113
+ table.columns = load_columns( table )
114
+ table.indexes = load_indexes( table )
115
+ @tables[table.name] = table
116
+ end
117
+ return table
118
+ end
119
+
120
+ ##
121
+ # load all the indexes for a particular table
122
+ #
123
+ def load_indexes( table )
124
+ indexes = {}
125
+
126
+ @db.prepare("SELECT name, sql FROM #{catalog_master_table} WHERE type ='index' and tbl_name = $name") do |idx_stmt|
127
+ idx_stmt.execute( "$name" => table.name) do |idx_info|
128
+ indexes[idx_info['name']] = ::Libsql::Index.new( idx_info['name'], idx_info['sql'], table )
129
+ end
130
+ end
131
+
132
+ @db.execute("PRAGMA index_list( #{@db.quote(table.name)} );") do |idx_list|
133
+ idx = indexes[idx_list['name']]
134
+
135
+ # temporary indexes do not show up in the previous list
136
+ if idx.nil? then
137
+ idx = ::Libsql::Index.new( idx_list['name'], nil, table )
138
+ indexes[idx_list['name']] = idx
139
+ end
140
+
141
+ idx.sequence_number = idx_list['seq']
142
+ idx.unique = Boolean.to_bool( idx_list['unique'] )
143
+
144
+ @db.execute("PRAGMA index_info( #{@db.quote(idx.name)} );") do |col_info|
145
+ idx.columns << table.columns[col_info['name']]
146
+ end
147
+ end
148
+ return indexes
149
+ end
150
+
151
+ ##
152
+ # load all the columns for a particular table
153
+ #
154
+ def load_columns( table )
155
+ cols = {}
156
+ idx = 0
157
+ @db.execute("PRAGMA #{catalog}.table_info(#{@db.quote(table.name)})") do |row|
158
+ col = ::Libsql::Column.new( catalog, table.name, row['name'], row['cid'])
159
+
160
+ col.default_value = row['dflt_value']
161
+
162
+ col.declared_data_type = row['type']
163
+ col.not_null_constraint = row['notnull']
164
+ col.primary_key = row['pk']
165
+
166
+ # need to remove leading and trailing ' or " from the default value
167
+ if col.default_value and col.default_value.kind_of?( String ) and ( col.default_value.length >= 2 ) then
168
+ fc = col.default_value[0].chr
169
+ lc = col.default_value[-1].chr
170
+ if fc == lc and ( fc == "'" || fc == '"' ) then
171
+ col.default_value = col.default_value[1..-2]
172
+ end
173
+ end
174
+
175
+ unless table.temporary? then
176
+ # get more exact information
177
+ @db.api.table_column_metadata( catalog, table.name, col.name ).each_pair do |key, value|
178
+ col.send("#{key}=", value)
179
+ end
180
+ end
181
+ col.schema = self
182
+ cols[col.name] = col
183
+ idx += 1
184
+ end
185
+ return cols
186
+ end
187
+
188
+ ##
189
+ # return the views, reloading if dirty
190
+ #
191
+ # If there is a temp view, and a regular view of the same name, then the
192
+ # temporary view is the one that is returned in the hash.
193
+ #
194
+ def views
195
+ reload_schema! if dirty?
196
+ v = @views
197
+ if @temp_schema then
198
+ v = @views.merge( @temp_schema.views )
199
+ end
200
+ return v
201
+ end
202
+
203
+ ##
204
+ # load a single view
205
+ #
206
+ def load_view( name )
207
+ rows = @db.execute("SELECT name, sql FROM #{catalog_master_table} WHERE type = 'view' AND name = ?", name )
208
+ view_info = rows.first
209
+ view = ::Libsql::View.new( view_info['name'], view_info['sql'] )
210
+ view.schema = self
211
+ return view
212
+ end
213
+
214
+ ##
215
+ # load all the views for the database
216
+ #
217
+ def load_views
218
+ @db.execute("SELECT name, sql FROM #{catalog_master_table} WHERE type = 'view'") do |view_info|
219
+ view = load_view( view_info['name'] )
220
+ @views[view.name] = view
221
+ end
222
+ return @views
223
+ end
224
+ end
225
+ end
@@ -0,0 +1,95 @@
1
+ #--
2
+ # Copyright (c) 2023 Jeremy Hinegardner
3
+ # All rights reserved. See LICENSE and/or COPYING for details.
4
+ #++
5
+ module ::Libsql::SQLite3
6
+ module Constants
7
+ module Helpers
8
+ #
9
+ # convert an integer value into the string representation of the associated
10
+ # constant. this is a helper method used by some of the other modules
11
+ #
12
+ def name_from_value( value )
13
+ unless defined? @const_map_from_value
14
+ @const_map_from_value = {}
15
+ constants.each do |const_name|
16
+ c_int = const_get( const_name )
17
+ @const_map_from_value[c_int] = const_name.to_s
18
+ end
19
+ end
20
+ return @const_map_from_value[ value ]
21
+ end
22
+
23
+ #
24
+ # convert a string into the constant value. This is helper method used by
25
+ # some of the other modules
26
+ #
27
+ def value_from_name( name )
28
+ unless defined? @const_map_from_name
29
+ @const_map_from_name = {}
30
+ constants.each do |const_name|
31
+ c_int = const_get( const_name )
32
+ @const_map_from_name[ const_name.to_s ] = c_int
33
+ end
34
+ end
35
+ return @const_map_from_name[ name.upcase ]
36
+ end
37
+ end
38
+
39
+
40
+ ##
41
+ # DataType defines the namespace for all possible SQLite data types.
42
+ #
43
+ module DataType
44
+ extend Helpers
45
+ end
46
+
47
+ ##
48
+ # Open defines the namespace for all possible flags to the Database.open
49
+ # method
50
+ #
51
+ module Open
52
+ extend Helpers
53
+ end
54
+
55
+ ##
56
+ # Status defines the namespace for all the possible status flags for
57
+ # ::Libsql::SQLite3::Status objects
58
+ #
59
+ module Status
60
+ extend Helpers
61
+ end
62
+
63
+ ##
64
+ # DBStatus defines the namespace for all the possible status codes for the
65
+ # ::Libsql::SQlite3::Database::Status objects.
66
+ #
67
+ module DBStatus
68
+ extend Helpers
69
+ end
70
+
71
+ ##
72
+ # ResultCode defines the namespace for all possible result codes from an
73
+ # SQLite API call.
74
+ #
75
+ module ResultCode
76
+ extend Helpers
77
+ end # end ResultCode
78
+
79
+ ##
80
+ # Config defines the namespace for all possible parameter for the
81
+ # sqlite config API.
82
+ #
83
+ module Config
84
+ extend Helpers
85
+ end
86
+
87
+ ##
88
+ # StatementStatus defines the namespace for all the possible status codes
89
+ # for the SQLite prepared statements
90
+ #
91
+ module StatementStatus
92
+ extend Helpers
93
+ end
94
+ end
95
+ end