amalgalite 0.10.1-x86-mingw32

Sign up to get free protection for your applications and to get access to all the features.
Files changed (100) hide show
  1. data/HISTORY +201 -0
  2. data/LICENSE +29 -0
  3. data/README +51 -0
  4. data/bin/amalgalite-pack +126 -0
  5. data/examples/a.rb +9 -0
  6. data/examples/blob.rb +88 -0
  7. data/examples/bootstrap.rb +36 -0
  8. data/examples/define_aggregate.rb +75 -0
  9. data/examples/define_function.rb +104 -0
  10. data/examples/gem-db.rb +94 -0
  11. data/examples/gems.db +0 -0
  12. data/examples/require_me.rb +11 -0
  13. data/examples/requires.rb +42 -0
  14. data/examples/schema-info.rb +34 -0
  15. data/ext/amalgalite/amalgalite3.c +290 -0
  16. data/ext/amalgalite/amalgalite3.h +151 -0
  17. data/ext/amalgalite/amalgalite3_blob.c +240 -0
  18. data/ext/amalgalite/amalgalite3_constants.c +221 -0
  19. data/ext/amalgalite/amalgalite3_database.c +1148 -0
  20. data/ext/amalgalite/amalgalite3_requires_bootstrap.c +210 -0
  21. data/ext/amalgalite/amalgalite3_statement.c +639 -0
  22. data/ext/amalgalite/extconf.rb +36 -0
  23. data/ext/amalgalite/gen_constants.rb +130 -0
  24. data/ext/amalgalite/sqlite3.c +106729 -0
  25. data/ext/amalgalite/sqlite3.h +5626 -0
  26. data/ext/amalgalite/sqlite3_options.h +4 -0
  27. data/ext/amalgalite/sqlite3ext.h +380 -0
  28. data/gemspec.rb +60 -0
  29. data/lib/amalgalite.rb +43 -0
  30. data/lib/amalgalite/1.8/amalgalite3.so +0 -0
  31. data/lib/amalgalite/1.9/amalgalite3.so +0 -0
  32. data/lib/amalgalite/aggregate.rb +67 -0
  33. data/lib/amalgalite/blob.rb +186 -0
  34. data/lib/amalgalite/boolean.rb +42 -0
  35. data/lib/amalgalite/busy_timeout.rb +47 -0
  36. data/lib/amalgalite/column.rb +97 -0
  37. data/lib/amalgalite/core_ext/kernel/require.rb +21 -0
  38. data/lib/amalgalite/database.rb +947 -0
  39. data/lib/amalgalite/function.rb +61 -0
  40. data/lib/amalgalite/index.rb +43 -0
  41. data/lib/amalgalite/packer.rb +226 -0
  42. data/lib/amalgalite/paths.rb +70 -0
  43. data/lib/amalgalite/profile_tap.rb +131 -0
  44. data/lib/amalgalite/progress_handler.rb +21 -0
  45. data/lib/amalgalite/requires.rb +120 -0
  46. data/lib/amalgalite/schema.rb +191 -0
  47. data/lib/amalgalite/sqlite3.rb +6 -0
  48. data/lib/amalgalite/sqlite3/constants.rb +80 -0
  49. data/lib/amalgalite/sqlite3/database/function.rb +48 -0
  50. data/lib/amalgalite/sqlite3/database/status.rb +68 -0
  51. data/lib/amalgalite/sqlite3/status.rb +60 -0
  52. data/lib/amalgalite/sqlite3/version.rb +37 -0
  53. data/lib/amalgalite/statement.rb +414 -0
  54. data/lib/amalgalite/table.rb +90 -0
  55. data/lib/amalgalite/taps.rb +2 -0
  56. data/lib/amalgalite/taps/console.rb +27 -0
  57. data/lib/amalgalite/taps/io.rb +71 -0
  58. data/lib/amalgalite/trace_tap.rb +35 -0
  59. data/lib/amalgalite/type_map.rb +63 -0
  60. data/lib/amalgalite/type_maps/default_map.rb +167 -0
  61. data/lib/amalgalite/type_maps/storage_map.rb +40 -0
  62. data/lib/amalgalite/type_maps/text_map.rb +22 -0
  63. data/lib/amalgalite/version.rb +37 -0
  64. data/lib/amalgalite/view.rb +26 -0
  65. data/spec/aggregate_spec.rb +169 -0
  66. data/spec/amalgalite_spec.rb +4 -0
  67. data/spec/blob_spec.rb +81 -0
  68. data/spec/boolean_spec.rb +23 -0
  69. data/spec/busy_handler.rb +165 -0
  70. data/spec/database_spec.rb +494 -0
  71. data/spec/default_map_spec.rb +87 -0
  72. data/spec/function_spec.rb +94 -0
  73. data/spec/integeration_spec.rb +111 -0
  74. data/spec/packer_spec.rb +60 -0
  75. data/spec/paths_spec.rb +28 -0
  76. data/spec/progress_handler_spec.rb +105 -0
  77. data/spec/requires_spec.rb +23 -0
  78. data/spec/rtree_spec.rb +71 -0
  79. data/spec/schema_spec.rb +120 -0
  80. data/spec/spec_helper.rb +27 -0
  81. data/spec/sqlite3/constants_spec.rb +65 -0
  82. data/spec/sqlite3/database_status_spec.rb +36 -0
  83. data/spec/sqlite3/status_spec.rb +18 -0
  84. data/spec/sqlite3/version_spec.rb +14 -0
  85. data/spec/sqlite3_spec.rb +53 -0
  86. data/spec/statement_spec.rb +161 -0
  87. data/spec/storage_map_spec.rb +41 -0
  88. data/spec/tap_spec.rb +59 -0
  89. data/spec/text_map_spec.rb +23 -0
  90. data/spec/type_map_spec.rb +17 -0
  91. data/spec/version_spec.rb +15 -0
  92. data/tasks/announce.rake +43 -0
  93. data/tasks/config.rb +107 -0
  94. data/tasks/distribution.rake +77 -0
  95. data/tasks/documentation.rake +32 -0
  96. data/tasks/extension.rake +141 -0
  97. data/tasks/rspec.rake +33 -0
  98. data/tasks/rubyforge.rake +59 -0
  99. data/tasks/utils.rb +80 -0
  100. metadata +237 -0
Binary file
Binary file
@@ -0,0 +1,67 @@
1
+ require 'amalgalite/sqlite3/database/function'
2
+ module Amalgalite
3
+ #
4
+ # A Base class to inherit from for creating your own SQL aggregate functions
5
+ # in ruby.
6
+ #
7
+ # These are SQL functions similar to _max(X)_, _count(X)_, _avg(X)_. The built
8
+ # in SQLite aggregate functions are:
9
+ #
10
+ # * http://www.sqlite.org/lang_aggfunc.html
11
+ #
12
+ # If you choose to use Aggregate as a parent class of your SQL scalar function
13
+ # implementation you must:
14
+ #
15
+ # * implement _initalize_ with 0 arguments
16
+ # * set the @arity data member
17
+ # * set the @name data member
18
+ # * implement _step_ with arity of +@arity+
19
+ # * implement _finalize_ with arity of 0
20
+ #
21
+ # For instance to implement a <i>unique_word_count(X)</i> aggregate function you could
22
+ # implement it as:
23
+ #
24
+ # class UniqueWordCount < ::Amalgalite::Aggregate
25
+ # attr_accessor :words
26
+ #
27
+ # def initialize
28
+ # @name = 'unique_word_count'
29
+ # @arity = 1
30
+ # @words = Hash.new { |h,k| h[k] = 0 }
31
+ # end
32
+ #
33
+ # def step( str )
34
+ # str.split(/\W+/).each do |word|
35
+ # words[ word.downcase ] += 1
36
+ # end
37
+ # return nil
38
+ # end
39
+ #
40
+ # def finalize
41
+ # return words.size
42
+ # end
43
+ # end
44
+ #
45
+ #
46
+ class Aggregate
47
+ # The name of the SQL function
48
+ attr_accessor :name
49
+
50
+ # The arity of the SQL function
51
+ attr_accessor :arity
52
+
53
+ # finalize should return the final value of the aggregate function
54
+ def finalize
55
+ raise NotImplementedError, "Aggregate#finalize must be implemented"
56
+ end
57
+
58
+ # <b>Do Not Override</b>
59
+ #
60
+ # The function signature for use by the Amaglaite datase in tracking
61
+ # function creation.
62
+ #
63
+ def signature
64
+ @signature ||= ::Amalgalite::SQLite3::Database::Function.signature( self.name, self.arity )
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,186 @@
1
+ #--
2
+ # Copyright (c) 2008 Jeremy Hinegardner
3
+ # All rights reserved. See LICENSE and/or COPYING for details.
4
+ #++
5
+ module Amalgalite
6
+ ##
7
+ # This is the interface to allow Blob objects to be written to and read from
8
+ # the SQLite database. When using statements, use a Blob object as
9
+ # the wrapper around the source to be written to the row, and a Blob object is
10
+ # returned if the the type mapping warrents during select queries.
11
+ #
12
+ # For instance during an insert:
13
+ #
14
+ # blob_column = db.schema.tables['blobs'].columns['data']
15
+ # db.execute("INSERT INTO blobs(name, data) VALUES ( $name, $blob )",
16
+ # { "$name" => "/path/to/file",
17
+ # "$blob" => Amalgalite::Blob.new( :file => '/path/to/file',
18
+ # :column => blob_column) } )
19
+ #
20
+ # db.execute("INSERT INTO blobs(id, data) VALUES ($id, $blob )",
21
+ # { "$name" => 'blobname',
22
+ # "$blob" => Amalgalite::Blob.new( :io => "something with .read and .length methods",
23
+ # :column => blob_column) } )
24
+ #
25
+ # On select the blob data needs to be read into an IO object
26
+ #
27
+ # all_rows = db.execute("SELECT name, blob FROM blobs WHERE name = '/path/to/file' ")
28
+ # blob_row = all_rows.first
29
+ # blob_row['blob'].write_to_file( blob_row['name'] )
30
+ #
31
+ # Or write to an IO object
32
+ #
33
+ # blob_results = {}
34
+ # db.execute("SELECT name, blob FROM blobs") do |row|
35
+ # io = StringIO.new
36
+ # row['blob'].write_to_io( io )
37
+ # blob_results[row['name']] = io
38
+ # # or use a shortcut
39
+ # # blob_results[row['name']] = row['blob'].to_string_io
40
+ # end
41
+ #
42
+ # If using a Blob as a conditional, for instance in a WHERE clause then the
43
+ # Blob must resolvable to a String.
44
+ #
45
+ # db.execute("SELECT FROM blobs(name, data) WHERE data = $blob",
46
+ # { "$blob' => Amalgalite::Blob.new( :string => "A string of data" ) })
47
+ #
48
+ class Blob
49
+ class Error < ::Amalgalite::Error; end
50
+ class << self
51
+ def valid_source_params
52
+ @valid_source_params ||= [ :file, :io, :string, :db_blob ]
53
+ end
54
+
55
+ def default_block_size
56
+ @default_block_size ||= 8192
57
+ end
58
+ end
59
+
60
+ # the object representing the source of the blob
61
+ attr_reader :source
62
+
63
+ # the size in bytes of the of the blob
64
+ attr_reader :length
65
+
66
+ # the size in bytes of the blocks of data to move from the source
67
+ attr_reader :block_size
68
+
69
+ # the column the blob is associated with
70
+ attr_reader :column
71
+
72
+ ##
73
+ # Initialize a new blob, it takes a single parameter, a hash which describes
74
+ # the source of the blob. The keys of the hash are one of:
75
+ #
76
+ # :file : the value is the path to a file on the file system
77
+ # :io : the value is an object that responds to the the methods +read+
78
+ # and +length+. +read+ should have the behavior of IO#read
79
+ # :db_blob : not normally used by an end user, used to initialize a blob
80
+ # object that is returned from an SQL query.
81
+ # :string : used when a Blob is part of a WHERE clause or result
82
+ #
83
+ # And additional key of :block_size may be used to indicate the maximum size
84
+ # of a single block of data to move from the source to the destination, this
85
+ # defaults ot 8192.
86
+ #
87
+ def initialize( params )
88
+ if (Blob.valid_source_params & params.keys).size > 1 then
89
+ raise Blob::Error, "Only a one of #{Blob.valid_source_params.join(', ')} is allowed to initialize a Blob. #{params.keys.join(', ')} were sent"
90
+ end
91
+
92
+ @source = nil
93
+ @source_length = 0
94
+ @close_source_after_read = false
95
+ @incremental = true
96
+ @block_size = params[:block_size] || Blob.default_block_size
97
+ @column = params[:column]
98
+
99
+ raise Blob::Error, "A :column parameter is required for a Blob" unless @column or params.has_key?( :string )
100
+
101
+ if params.has_key?( :file ) then
102
+ @source = File.open( params[:file], "r" )
103
+ @length = File.size( params[:file] )
104
+ @close_source_after_read = true
105
+ elsif params.has_key?( :io ) then
106
+ @source = params[:io]
107
+ @length = @source.length
108
+ elsif params.has_key?( :db_blob ) then
109
+ @source = params[:db_blob]
110
+ @length = @source.length
111
+ @close_source_after_read = true
112
+ elsif params.has_key?( :string ) then
113
+ @source = params[:string]
114
+ @length = @source.length
115
+ @incremental = false
116
+ end
117
+ end
118
+
119
+ ##
120
+ # close the source when done reading from it
121
+ #
122
+ def close_source_after_read?
123
+ @close_source_after_read
124
+ end
125
+
126
+ ##
127
+ # is this an incremental Blob or not
128
+ #
129
+ def incremental?
130
+ @incremental
131
+ end
132
+
133
+ ##
134
+ # Write the Blob to an IO object
135
+ #
136
+ def write_to_io( io )
137
+ if source.respond_to?( :read ) then
138
+ while buf = source.read( block_size ) do
139
+ io.write( buf )
140
+ end
141
+ else
142
+ io.write( source.to_s )
143
+ end
144
+
145
+ if close_source_after_read? then
146
+ source.close
147
+ end
148
+ end
149
+
150
+ ##
151
+ # conver the blob to a string
152
+ #
153
+ def to_s
154
+ to_string_io.string
155
+ end
156
+
157
+ ##
158
+ # write the Blob contents to a StringIO
159
+ #
160
+ def to_string_io
161
+ sio = StringIO.new
162
+ write_to_io( sio )
163
+ return sio
164
+ end
165
+
166
+ ##
167
+ # Write the Blob contents to a File.
168
+ #
169
+ def write_to_file( filename, modestring="w" )
170
+ File.open(filename, modestring) do |f|
171
+ write_to_io( f )
172
+ end
173
+ end
174
+
175
+ ##
176
+ # Write the Blob contents to the column. This assumes that the row_id to
177
+ # insert into is the last row that was inserted into the db
178
+ #
179
+ def write_to_column!
180
+ last_rowid = column.schema.db.last_insert_rowid
181
+ SQLite3::Blob.new( column.schema.db.api, column.db, column.table, column.name, last_rowid, "w" ) do |sqlite_blob|
182
+ write_to_io( sqlite_blob )
183
+ end
184
+ end
185
+ end
186
+ end
@@ -0,0 +1,42 @@
1
+ #--
2
+ # Copyright (c) 2008 Jeremy Hinegardner
3
+ # All rights reserved. See LICENSE and/or COPYING for details.
4
+ #++
5
+ module Amalgalite
6
+ ##
7
+ # Do type conversion on values that could be boolen values into
8
+ # real 'true' or 'false'
9
+ #
10
+ # This is pulled from the possible boolean values from PostgreSQL
11
+ #
12
+ class Boolean
13
+ class << self
14
+ #
15
+ # list of downcased strings are potential true values
16
+ #
17
+ def true_values
18
+ @true_values ||= %w[ true t yes y 1 ]
19
+ end
20
+
21
+ #
22
+ # list of downcased strings are potential false values
23
+ #
24
+ def false_values
25
+ @false_values ||= %w[ false f no n 0 ]
26
+ end
27
+
28
+ #
29
+ # Convert +val+ to a string and attempt to convert it to +true+ or +false+
30
+ #
31
+ def to_bool( val )
32
+ return false if val.nil?
33
+ unless defined? @to_bool
34
+ @to_bool = {}
35
+ true_values.each { |t| @to_bool[t] = true }
36
+ false_values.each { |f| @to_bool[f] = false }
37
+ end
38
+ return @to_bool[val.to_s.downcase]
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,47 @@
1
+ module Amalgalite
2
+ ##
3
+ # A base class for use in creating your own busy handler classes
4
+ #
5
+ class BusyHandler
6
+ def to_proc
7
+ self
8
+ end
9
+
10
+ # the arity of the call method
11
+ def arity() 1 ; end
12
+
13
+ ##
14
+ # Override this method, returning +false+ if the SQLite should return
15
+ # SQLITE_BUSY for all parties involved in the lock, and anything else if the
16
+ # lock attempt should be tried again.
17
+ def call( count )
18
+ raise NotImplementedError, "The busy handler call(N) method must be implemented"
19
+ end
20
+ end
21
+
22
+ ##
23
+ # A busy time out class for use in Database#define_busy_handler
24
+ #
25
+ class BusyTimeout < BusyHandler
26
+ attr_reader :call_count
27
+ ##
28
+ # intialize by setting _count_ and _duration_ ( in milliseconds ).
29
+ #
30
+ def initialize( count = 20 , duration = 50 )
31
+ @count = count
32
+ @duration = duration.to_f / 1_000
33
+ @call_count = 0
34
+ end
35
+
36
+ ##
37
+ # return +false+ if _callcount_ is > _count_ otherwise sleep for _duration_
38
+ # milliseconds and then return +true+
39
+ #
40
+ def call( call_count )
41
+ @call_count = call_count
42
+ return false if ( call_count > @count )
43
+ sleep @duration
44
+ return true
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,97 @@
1
+ #--
2
+ # Copyright (c) 2008 Jeremy Hinegardner
3
+ # All rights reserved. See LICENSE and/or COPYING for details.
4
+ #++
5
+
6
+ require 'amalgalite/boolean'
7
+ require 'amalgalite/blob'
8
+
9
+ module Amalgalite
10
+ ##
11
+ # a class representing the meta information about an SQLite column, this class
12
+ # serves both for general Schema level information, and for result set
13
+ # information from a SELECT query.
14
+ #
15
+ class Column
16
+ # the schema object this column is associated with
17
+ attr_accessor :schema
18
+
19
+ # the database name this column belongs to
20
+ attr_accessor :db
21
+
22
+ # the column name
23
+ attr_accessor :name
24
+
25
+ # the table to which this column belongs
26
+ attr_accessor :table
27
+
28
+ # the default value of the column. This may not have a value and that
29
+ # either means that there is no default value, or one could not be
30
+ # determined.
31
+ #
32
+ attr_accessor :default_value
33
+
34
+ # the declared data type of the column in the original sql that created the
35
+ # column
36
+ attr_accessor :declared_data_type
37
+
38
+ # the collation sequence name of the column
39
+ attr_accessor :collation_sequence_name
40
+
41
+ # The index (starting with 0) of this column in the table definition
42
+ # or result set
43
+ attr_accessor :order
44
+
45
+ ##
46
+ # Create a column with its name and associated table
47
+ #
48
+ def initialize( db, table, name, order)
49
+ @db = db
50
+ @name = name
51
+ @table = table
52
+ @order = Float(order).to_i
53
+ @declared_data_type = nil
54
+ @default_value = nil
55
+ end
56
+
57
+ # true if the column has a default value
58
+ def has_default_value?
59
+ not default_value.nil?
60
+ end
61
+
62
+ # true if the column may have a NULL value
63
+ def nullable?
64
+ @not_null_constraint == false
65
+ end
66
+
67
+ # set whether or not the column has a not null constraint
68
+ def not_null_constraint=( other )
69
+ @not_null_constraint = Boolean.to_bool( other )
70
+ end
71
+
72
+ # true if the column as a NOT NULL constraint
73
+ def not_null_constraint?
74
+ @not_null_constraint
75
+ end
76
+
77
+ # set whether or not the column is a primary key column
78
+ def primary_key=( other )
79
+ @primary_key = Boolean.to_bool( other )
80
+ end
81
+
82
+ # true if the column is a primary key column
83
+ def primary_key?
84
+ @primary_key
85
+ end
86
+
87
+ # set whether or not the column is auto increment
88
+ def auto_increment=( other )
89
+ @auto_increment = Boolean.to_bool( other )
90
+ end
91
+
92
+ # true if the column is auto increment
93
+ def auto_increment?
94
+ @auto_increment
95
+ end
96
+ end
97
+ end