amalgalite 1.6.0-x64-mingw32

Sign up to get free protection for your applications and to get access to all the features.
Files changed (111) hide show
  1. checksums.yaml +7 -0
  2. data/CONTRIBUTING.md +49 -0
  3. data/HISTORY.md +346 -0
  4. data/LICENSE +31 -0
  5. data/Manifest.txt +104 -0
  6. data/README.md +65 -0
  7. data/Rakefile +26 -0
  8. data/TODO.md +57 -0
  9. data/bin/amalgalite-pack +147 -0
  10. data/examples/a.rb +9 -0
  11. data/examples/blob.rb +88 -0
  12. data/examples/bootstrap.rb +36 -0
  13. data/examples/define_aggregate.rb +75 -0
  14. data/examples/define_function.rb +104 -0
  15. data/examples/fts5.rb +152 -0
  16. data/examples/gem-db.rb +94 -0
  17. data/examples/require_me.rb +11 -0
  18. data/examples/requires.rb +42 -0
  19. data/examples/schema-info.rb +34 -0
  20. data/ext/amalgalite/c/amalgalite.c +355 -0
  21. data/ext/amalgalite/c/amalgalite.h +151 -0
  22. data/ext/amalgalite/c/amalgalite_blob.c +240 -0
  23. data/ext/amalgalite/c/amalgalite_constants.c +1226 -0
  24. data/ext/amalgalite/c/amalgalite_database.c +1178 -0
  25. data/ext/amalgalite/c/amalgalite_requires_bootstrap.c +282 -0
  26. data/ext/amalgalite/c/amalgalite_statement.c +649 -0
  27. data/ext/amalgalite/c/extconf.rb +62 -0
  28. data/ext/amalgalite/c/gen_constants.rb +330 -0
  29. data/ext/amalgalite/c/notes.txt +134 -0
  30. data/ext/amalgalite/c/sqlite3.c +205352 -0
  31. data/ext/amalgalite/c/sqlite3.h +10727 -0
  32. data/ext/amalgalite/c/sqlite3_options.h +4 -0
  33. data/ext/amalgalite/c/sqlite3ext.h +578 -0
  34. data/lib/amalgalite.rb +51 -0
  35. data/lib/amalgalite/2.0/amalgalite.so +0 -0
  36. data/lib/amalgalite/2.1/amalgalite.so +0 -0
  37. data/lib/amalgalite/2.2/amalgalite.so +0 -0
  38. data/lib/amalgalite/2.3/amalgalite.so +0 -0
  39. data/lib/amalgalite/2.4/amalgalite.so +0 -0
  40. data/lib/amalgalite/aggregate.rb +67 -0
  41. data/lib/amalgalite/blob.rb +186 -0
  42. data/lib/amalgalite/boolean.rb +42 -0
  43. data/lib/amalgalite/busy_timeout.rb +47 -0
  44. data/lib/amalgalite/column.rb +99 -0
  45. data/lib/amalgalite/core_ext/kernel/require.rb +21 -0
  46. data/lib/amalgalite/csv_table_importer.rb +74 -0
  47. data/lib/amalgalite/database.rb +984 -0
  48. data/lib/amalgalite/function.rb +61 -0
  49. data/lib/amalgalite/index.rb +43 -0
  50. data/lib/amalgalite/memory_database.rb +15 -0
  51. data/lib/amalgalite/packer.rb +231 -0
  52. data/lib/amalgalite/paths.rb +80 -0
  53. data/lib/amalgalite/profile_tap.rb +131 -0
  54. data/lib/amalgalite/progress_handler.rb +21 -0
  55. data/lib/amalgalite/requires.rb +151 -0
  56. data/lib/amalgalite/schema.rb +225 -0
  57. data/lib/amalgalite/sqlite3.rb +6 -0
  58. data/lib/amalgalite/sqlite3/constants.rb +95 -0
  59. data/lib/amalgalite/sqlite3/database/function.rb +48 -0
  60. data/lib/amalgalite/sqlite3/database/status.rb +68 -0
  61. data/lib/amalgalite/sqlite3/status.rb +60 -0
  62. data/lib/amalgalite/sqlite3/version.rb +55 -0
  63. data/lib/amalgalite/statement.rb +418 -0
  64. data/lib/amalgalite/table.rb +91 -0
  65. data/lib/amalgalite/taps.rb +2 -0
  66. data/lib/amalgalite/taps/console.rb +27 -0
  67. data/lib/amalgalite/taps/io.rb +71 -0
  68. data/lib/amalgalite/trace_tap.rb +35 -0
  69. data/lib/amalgalite/type_map.rb +63 -0
  70. data/lib/amalgalite/type_maps/default_map.rb +166 -0
  71. data/lib/amalgalite/type_maps/storage_map.rb +38 -0
  72. data/lib/amalgalite/type_maps/text_map.rb +21 -0
  73. data/lib/amalgalite/version.rb +8 -0
  74. data/lib/amalgalite/view.rb +26 -0
  75. data/spec/aggregate_spec.rb +154 -0
  76. data/spec/amalgalite_spec.rb +4 -0
  77. data/spec/blob_spec.rb +78 -0
  78. data/spec/boolean_spec.rb +24 -0
  79. data/spec/busy_handler.rb +157 -0
  80. data/spec/data/iso-3166-country.txt +242 -0
  81. data/spec/data/iso-3166-schema.sql +22 -0
  82. data/spec/data/iso-3166-subcountry.txt +3995 -0
  83. data/spec/data/make-iso-db.sh +12 -0
  84. data/spec/database_spec.rb +508 -0
  85. data/spec/default_map_spec.rb +92 -0
  86. data/spec/function_spec.rb +78 -0
  87. data/spec/integeration_spec.rb +97 -0
  88. data/spec/iso_3166_database.rb +58 -0
  89. data/spec/packer_spec.rb +60 -0
  90. data/spec/paths_spec.rb +28 -0
  91. data/spec/progress_handler_spec.rb +91 -0
  92. data/spec/requires_spec.rb +54 -0
  93. data/spec/rtree_spec.rb +66 -0
  94. data/spec/schema_spec.rb +131 -0
  95. data/spec/spec_helper.rb +48 -0
  96. data/spec/sqlite3/constants_spec.rb +108 -0
  97. data/spec/sqlite3/database_status_spec.rb +36 -0
  98. data/spec/sqlite3/status_spec.rb +22 -0
  99. data/spec/sqlite3/version_spec.rb +28 -0
  100. data/spec/sqlite3_spec.rb +53 -0
  101. data/spec/statement_spec.rb +168 -0
  102. data/spec/storage_map_spec.rb +38 -0
  103. data/spec/tap_spec.rb +57 -0
  104. data/spec/text_map_spec.rb +20 -0
  105. data/spec/type_map_spec.rb +14 -0
  106. data/spec/version_spec.rb +8 -0
  107. data/tasks/custom.rake +102 -0
  108. data/tasks/default.rake +240 -0
  109. data/tasks/extension.rake +38 -0
  110. data/tasks/this.rb +208 -0
  111. metadata +318 -0
@@ -0,0 +1,65 @@
1
+ ## Amalgalite
2
+
3
+ * [Homepage](http://github.com/copiousfreetime/amalgalite)
4
+ * email jeremy at copiousfreetime dot org
5
+ * `git clone git://github.com/copiousfreetime/amalgalite.git`
6
+ * [Github](http://github.com/copiousfreetime/amalgalite/)
7
+ * [Bug Tracking](http://github.com/copiousfreetime/amalgalite/issues)
8
+
9
+ ## Articles
10
+
11
+ * [Writing SQL Functions in Ruby](http://copiousfreetime.org/articles/2009/01/10/writing-sql-functions-in-ruby.html)
12
+
13
+ ## INSTALL
14
+
15
+ * `gem install amalgalite`
16
+
17
+ ## DESCRIPTION
18
+
19
+ Amalgalite embeds the SQLite database engine in a ruby extension. There is no
20
+ need to install SQLite separately.
21
+
22
+ Look in the examples/ directory to see
23
+
24
+ * general usage
25
+ * blob io
26
+ * schema information
27
+ * custom functions
28
+ * custom aggregates
29
+ * requiring ruby code from a database
30
+ * full text search
31
+
32
+ Also Scroll through Amalgalite::Database for a quick example, and a general
33
+ overview of the API.
34
+
35
+ Amalgalite adds in the following additional non-default SQLite extensions:
36
+
37
+ * [R*Tree index extension](http://sqlite.org/rtree.html)
38
+ * [Full Text Search](http://sqlite.org/fts3.html)
39
+
40
+ ## BUILDING FOR WINDOWS
41
+
42
+ This is done using https://github.com/rake-compiler/rake-compiler-dock
43
+
44
+ 1. have VirtualBox installed
45
+ 2. Install boot2docker `brew install boot2docker`
46
+ 3. `gem install rake-compiler-dock`
47
+ 4. `rake-compiler-dock`
48
+ 5. `bundle`
49
+ 6. `rake cross native gem`
50
+
51
+ ## CREDITS
52
+
53
+ * Jamis Buck for the first [ruby sqlite implementation](http://www.rubyforge.org/projects/sqlite-ruby)
54
+
55
+ ## CHANGES
56
+
57
+ Read the HISTORY.rdoc file.
58
+
59
+ ## LICENSE
60
+
61
+ Copyright (c) 2008 Jeremy Hinegardner
62
+
63
+ All rights reserved.
64
+
65
+ See LICENSE and/or COPYING for details.
@@ -0,0 +1,26 @@
1
+ # vim: syntax=ruby
2
+ load 'tasks/this.rb'
3
+
4
+ This.name = "amalgalite"
5
+ This.author = "Jeremy Hinegardner"
6
+ This.email = "jeremy@copiousfreetime.org"
7
+ This.homepage = "http://github.com/copiousfreetime/#{ This.name }"
8
+
9
+ This.ruby_gemspec do |spec|
10
+ spec.add_dependency( 'arrayfields', '~> 4.9' )
11
+
12
+ spec.add_development_dependency( 'rspec' , '~> 3.0' )
13
+ spec.add_development_dependency( 'rake' , '~> 12.0')
14
+ spec.add_development_dependency( 'rake-compiler', '~> 1.0' )
15
+ spec.add_development_dependency( 'rake-compiler-dock', '~> 0.6' )
16
+ spec.add_development_dependency( 'rdoc' , '~> 5.0' )
17
+ spec.add_development_dependency( 'simplecov' , '~> 0.14' )
18
+ spec.add_development_dependency( 'zip' , '~> 2.0' )
19
+
20
+ spec.extensions.concat This.extension_conf_files
21
+ spec.license = "BSD"
22
+ end
23
+
24
+ load 'tasks/default.rake'
25
+ load 'tasks/extension.rake'
26
+ 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
+ - amalgalite 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
+
@@ -0,0 +1,147 @@
1
+ #!/usr/bin/env ruby
2
+ require 'optparse'
3
+ require 'pathname'
4
+
5
+ #
6
+ # add relative paths to the load path if we are not a gem and calculate what the
7
+ # strip path will be if we decide to pack --self
8
+ #
9
+ this_path = Pathname.new( File.expand_path( __FILE__ ) )
10
+ gem_path = Pathname.new( Gem.dir )
11
+ rel_path = this_path.relative_path_from( gem_path )
12
+ if ".." == rel_path.to_s.split( File::SEPARATOR ).first then
13
+ lib_path = File.join( File.dirname( __FILE__ ), "../lib" )
14
+ $:.unshift lib_path
15
+ $:.unshift File.join( File.dirname( __FILE__ ), "../ext" )
16
+ end
17
+
18
+ #
19
+ # snapshot of what is needed for amalgalite requires, this info may only be used
20
+ # when packing amalgalite itself
21
+ #
22
+ loaded_features_before = $LOADED_FEATURES.dup
23
+ require 'amalgalite/packer'
24
+ loaded_features_after = $LOADED_FEATURES.dup
25
+ load_diff = loaded_features_after - loaded_features_before
26
+
27
+ #
28
+ # strip off any LOAD_PATH elements from the front of load_diff since that
29
+ # will conflict with Amalgalite::Packer.amalgalite_require_order. Also
30
+ # strip out any 'rubygems' items since those are not used by Amalgalite
31
+ # and show as a side effect fo the "require 'amalgalite/packer'"
32
+ #
33
+ strip_paths = $LOAD_PATH.sort.reverse
34
+ amalgalite_needs = []
35
+ load_diff.each do |f|
36
+ next if f.split( File::SEPARATOR ).include?( "rubygems" )
37
+ appended = false
38
+ strip_paths.each do |path|
39
+ if 0 == f.index(path ) then
40
+ rel_path = f.sub( path, '' ).sub(%r{\A#{File::SEPARATOR}},'')
41
+ amalgalite_needs << rel_path
42
+ appended = true
43
+ break
44
+ end
45
+ end
46
+ amalgalite_needs << f unless appended
47
+ end
48
+
49
+ #
50
+ # Commandline parser
51
+ #
52
+ options = {}
53
+ begin
54
+ parser = OptionParser.new do |op|
55
+ op.banner = "Usage: #{op.program_name} [options] <files>"
56
+ op.separator ""
57
+
58
+ op.on("--dbfile DB", "The Database file in which to pack files") do |d|
59
+ options[:dbfile] = d
60
+ end
61
+
62
+ op.on("--drop-table", "Drop the table before inserting rows") do |t|
63
+ options[:drop_table] = t
64
+ end
65
+
66
+ op.on("-m", "--merge", "Merge these files into the existing table overwriting rows that conflict") do |m|
67
+ options[:merge] = true
68
+ end
69
+
70
+ op.on("--require-order", "Dump Amalgalite's require order" ) do |m|
71
+ puts amalgalite_needs
72
+ exit 0
73
+ end
74
+
75
+ op.on("--self", "pack amalgalite itself into the database") do |d|
76
+ options[:self] = true
77
+ end
78
+
79
+ op.on("--strip-prefix PREFIX", "strip this path prefix off the front of each file") do |p|
80
+ options[:strip_prefix] = File.expand_path( p )
81
+ end
82
+
83
+ op.on("-t", "--table TABLE", "the table name to pack into") do |t|
84
+ options[:table_name] = t
85
+ end
86
+
87
+ op.on("--verbose", "Be verbose about output") do |v|
88
+ options[:verbose] = v
89
+ end
90
+
91
+ op.on("-z", "--compressed", "compress the file contents on storage") do |z|
92
+ options[:compressed] = true
93
+ end
94
+
95
+ end
96
+
97
+ parser.parse!
98
+ require 'amalgalite/packer'
99
+ file_list = ARGV.dup
100
+
101
+
102
+ if options[:self] then
103
+ options[:table_name] = Amalgalite::Requires::Bootstrap::DEFAULT_BOOTSTRAP_TABLE
104
+ core_libs = (amalgalite_needs - Amalgalite::Packer.amalgalite_require_order).delete_if { |l| l.index(".rb").nil? }
105
+
106
+ #
107
+ # check and make sure nothing is missed
108
+ #
109
+ core_libs.each do |l|
110
+ if l.index("amalgalite") then
111
+ STDERR.puts "ERROR! require_order needs an update #{l}"
112
+ exit 2
113
+ end
114
+ end
115
+ file_list = core_libs.concat( Amalgalite::Packer.amalgalite_require_order )
116
+ if options[:compressed] then
117
+ STDERR.puts "Compressing --self is not allowed, reverting to uncompressed"
118
+ options[:compressed] = false
119
+ end
120
+ end
121
+ STDERR.puts parser if file_list.empty?
122
+
123
+ packer = Amalgalite::Packer.new( options )
124
+ packer.pack( file_list )
125
+
126
+ rescue OptionParser::ParseError => pe
127
+ STDERR.puts "ERROR : #{pe}"
128
+ STDERR.puts parser
129
+ exit 1
130
+ end
131
+
132
+ __END__
133
+
134
+ puts <<-text
135
+
136
+ Packing complete. To utilize the bootstrapping in #{dbfile} you must do
137
+ one of the following:
138
+
139
+ * statically compile the amalgalite C extension into your application
140
+ * require 'amalgalite/#{RUBY_VERSION.sub(/\.\d$/,'')}/amalgalite3'
141
+
142
+ Once one of those is working you can boostrap the Amalgalite library with
143
+ this line in your code:
144
+
145
+ Amalgalite::Requries::Boostrap.lift( 'dbfile' => '#{dbfile}' )
146
+
147
+ text
@@ -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
@@ -0,0 +1,88 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ #
4
+ # An Amalgalite 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 'amalgalite'
23
+ require 'amalgalite/packer'
24
+ VALID_ACTIONS = %w[ list retrieve store ]
25
+ def usage
26
+ STDERR.puts "Usage: #{File.basename($0)} ( #{VALID_ACTIONS.join(' | ')} ) file(s)"
27
+ exit 1
28
+ end
29
+
30
+ #
31
+ # This does the basic command line parsing
32
+ #
33
+ usage if ARGV.size < 1
34
+ action = ARGV.shift
35
+ usage unless VALID_ACTIONS.include? action
36
+ file_list = ARGV
37
+
38
+ #
39
+ # create the database if it doesn't exist
40
+ #
41
+ db = Amalgalite::Database.new( "filestore.db" )
42
+
43
+ case action
44
+ #
45
+ # list all the files that are stored in the database
46
+ #
47
+ when 'list'
48
+ db.execute("SELECT filename FROM rubylibs") do |row|
49
+ puts row['filename']
50
+ end
51
+
52
+ #
53
+ # if we are doing the store action, then loop over the files and store them in
54
+ # the database. This will use incremental IO to store the files directly from
55
+ # the file names.
56
+ #
57
+ # It is slightly strange in that you have to tell the Blob object what column
58
+ # it is going to, but that is necessary at this point to be able to hook
59
+ # automatically into the lower level incremental blob IO api.
60
+ #
61
+ # This also shows using the $var syntax for binding name sql values in a
62
+ # prepared statement.
63
+ #
64
+ when 'store'
65
+ usage if file_list.empty?
66
+ require 'amalgalite/packer'
67
+
68
+ packer = Amalgalite::Packer.new( :dbfile => 'filestore.db',
69
+ :compressed => false )
70
+ packer.pack( file_list )
71
+
72
+ #
73
+ # dump the file that matches the right path to stdout. This also shows
74
+ # positional sql varible binding using the '?' syntax.
75
+ #
76
+ when 'retrieve'
77
+ usage if file_list.empty?
78
+ db.execute("SELECT id, compressed, filename, contents FROM rubylibs WHERE filename = ?", file_list.first) do |row|
79
+ STDERR.puts "Dumping #{row['filename']} to stdout"
80
+ if row['compressed'] then
81
+ s = row['contents'].to_s
82
+ STDOUT.puts Amalgalite::Packer.gunzip( s )
83
+ else
84
+ row['contents'].write_to_io( STDOUT )
85
+ end
86
+ end
87
+ end
88
+ db.close
@@ -0,0 +1,36 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # An example of requiring all the files in a table via the Bootstrap::lift
4
+ # method.
5
+ #
6
+ # First use the blob.rb example in this same directory to load the a.rb file
7
+ # into an example database:
8
+ #
9
+ # ruby blob.rb store a.rb
10
+ #
11
+ # Then run this example.
12
+ #
13
+
14
+ # Require "ONLY" then binary extension, do not +require+ the ruby based code
15
+ $: << "../ext"
16
+ require 'amalgalite/amalgalite3'
17
+
18
+ # See what the load path is, notice that it is very small
19
+ puts "Before $\" : #{$LOADED_FEATURES.inspect}"
20
+
21
+ # tell the binary extension to "require" every file in the filestore.db in the
22
+ # table 'files' orderd by column 'id'. The 'path' column is added to $LOADED_FEATURES and the
23
+ # code in 'data' is evaled.
24
+ Amalgalite::Requires::Bootstrap.lift( "dbfile" => "filestore.db",
25
+ "table_name" => "rubylibs",
26
+ "rowid_column" => "id",
27
+ "filename_column" => "filename",
28
+ "contents_column" => "contents" )
29
+
30
+ # Notice that a.rb is in the list of files that has been required
31
+ puts "After $\" : #{$LOADED_FEATURES.inspect}"
32
+
33
+ # and look we prove that the code was eval'd appropriately
34
+ a = A.new
35
+ a.a
36
+
@@ -0,0 +1,75 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ $: << "../lib"
5
+ $: << "../ext"
6
+ require 'amalgalite'
7
+
8
+ #--
9
+ # Create a database and a table to put some results from the functions in
10
+ #--
11
+ db = Amalgalite::Database.new( ":memory:" )
12
+ db.execute( "CREATE TABLE atest( words )" )
13
+
14
+ #------------------------------------------------------------------------------
15
+ # Create unique word count aggregate
16
+ #------------------------------------------------------------------------------
17
+ class UniqueWordCount < ::Amalgalite::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