amalgalite 0.10.1-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 (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
@@ -0,0 +1,90 @@
1
+ #--
2
+ # Copyright (c) 2008 Jeremy Hinegardner
3
+ # All rights reserved. See LICENSE and/or COPYING for details.
4
+ #++
5
+ require 'set'
6
+ module Amalgalite
7
+ #
8
+ # a class representing the meta information about an SQLite table
9
+ #
10
+ class Table
11
+ # the schema object the table is associated with
12
+ attr_accessor :schema
13
+
14
+ # the table name
15
+ attr_reader :name
16
+
17
+ # the original sql that was used to create this table
18
+ attr_reader :sql
19
+
20
+ # hash of Index objects holding the meta informationa about the indexes
21
+ # on this table. The keys of the indexes variable is the index name
22
+ attr_accessor :indexes
23
+
24
+ # a hash of Column objects holding the meta information about the columns
25
+ # in this table. keys are the column names
26
+ attr_accessor :columns
27
+
28
+ def initialize( name, sql = nil )
29
+ @name = name
30
+ @sql = sql
31
+ @indexes = {}
32
+ @columns = {}
33
+ end
34
+
35
+ # Is the table a temporary table or not
36
+ def temporary?
37
+ !sql
38
+ end
39
+
40
+
41
+ # the Columns in original definition order
42
+ def columns_in_order
43
+ @columns.values.sort_by { |c| c.order }
44
+ end
45
+
46
+ # the column names in original definition order
47
+ def column_names
48
+ columns_in_order.map { |c| c.name }
49
+ end
50
+
51
+ # the columns that make up the primary key
52
+ def primary_key_columns
53
+ @columns.values.find_all { |c| c.primary_key? }
54
+ end
55
+
56
+ # the array of colmuns that make up the primary key of the table
57
+ # since a primary key has an index, we loop over all the indexes for the
58
+ # table and pick the first one that is unique, and all the columns in the
59
+ # index have primary_key? as true.
60
+ #
61
+ # we do this instead of just looking for the columns where primary key is
62
+ # true because we want the columns in primary key order
63
+ def primary_key
64
+ unless @primary_key
65
+ pk_column_names = Set.new( primary_key_columns.collect { |c| c.name } )
66
+ unique_indexes = indexes.values.find_all { |i| i.unique? }
67
+
68
+ pk_result = []
69
+
70
+ unique_indexes.each do |idx|
71
+ idx_column_names = Set.new( idx.columns.collect { |c| c.name } )
72
+ r = idx_column_names ^ pk_column_names
73
+ if r.size == 0 then
74
+ pk_result = idx.columns
75
+ break
76
+ end
77
+ end
78
+
79
+ # no joy, see about just using all the columns that say the are primary
80
+ # keys
81
+ if pk_result.empty? then
82
+ pk_result = self.primary_key_columns
83
+ end
84
+ @primary_key = pk_result
85
+ end
86
+ return @primary_key
87
+ end
88
+ end
89
+ end
90
+
@@ -0,0 +1,2 @@
1
+ require 'amalgalite/taps/console'
2
+ require 'amalgalite/taps/io'
@@ -0,0 +1,27 @@
1
+ #--
2
+ # Copyright (c) 2008 Jeremy Hinegardner
3
+ # All rights reserved. See LICENSE and/or COPYING for details.
4
+ #++
5
+
6
+ require 'amalgalite/taps/io'
7
+
8
+ module Amalgalite::Taps
9
+ #
10
+ # Class provide an IO tap that can write to $stdout
11
+ #
12
+ class Stdout < ::Amalgalite::Taps::IO
13
+ def initialize
14
+ super( $stdout )
15
+ end
16
+ end
17
+
18
+ #
19
+ # This class provide an IO tap that can write to $stderr
20
+ #
21
+ class Stderr < ::Amalgalite::Taps::IO
22
+ def initialize
23
+ super( $stderr )
24
+ end
25
+ end
26
+
27
+ end
@@ -0,0 +1,71 @@
1
+ #--
2
+ # Copyright (c) 2008 Jeremy Hinegardner
3
+ # All rights reserved. See LICENSE and/or COPYING for details.
4
+ #++
5
+
6
+ require 'amalgalite/profile_tap'
7
+ require 'stringio'
8
+
9
+ module Amalgalite
10
+ module Taps
11
+ #
12
+ # An IOTap is an easy way to send all top information to andy IO based
13
+ # object. Both profile and trace tap information can be captured
14
+ # This means you can send the events to STDOUT with:
15
+ #
16
+ # db.profile_tap = db.trace_tap = Amalgalite::Taps::Stdout.new
17
+ #
18
+ #
19
+ class IO
20
+
21
+ attr_reader :profile_tap
22
+ attr_reader :io
23
+
24
+ def initialize( io )
25
+ @io = io
26
+ @profile_tap = ProfileTap.new( self, 'output_profile_event' )
27
+ end
28
+
29
+ def trace( msg )
30
+ io.puts msg
31
+ end
32
+
33
+ # need a profile method, it routes through the profile tap which calls back
34
+ # to output_profile_event
35
+ def profile( msg, time )
36
+ @profile_tap.profile(msg, time)
37
+ end
38
+
39
+ def output_profile_event( msg, time )
40
+ io.puts "#{time} : #{msg}"
41
+ end
42
+
43
+ def dump_profile
44
+ samplers.each_pair do |k,v|
45
+ io.puts v.to_s
46
+ end
47
+ end
48
+
49
+ def samplers
50
+ profile_tap.samplers
51
+ end
52
+ end
53
+
54
+ #
55
+ # This class provides an IO tap that writes to a StringIO. The result is
56
+ # available via .to_s or .string.
57
+ #
58
+ class StringIO < ::Amalgalite::Taps::IO
59
+ def initialize
60
+ @stringio = ::StringIO.new
61
+ super( @stringio )
62
+ end
63
+
64
+ def to_s
65
+ @stringio.string
66
+ end
67
+ alias :string :to_s
68
+ end
69
+ end
70
+ end
71
+
@@ -0,0 +1,35 @@
1
+ #--
2
+ # Copyright (c) 2008 Jeremy Hinegardner
3
+ # All rights reserved. See LICENSE and/or COPYING for details.
4
+ #++
5
+
6
+ module Amalgalite
7
+ #
8
+ # A TraceTap receives tracing information from SQLite3. It receives the SQL
9
+ # statement being executed as a +msg+ just before the statement first begins
10
+ # executing.
11
+ #
12
+ # A TraceTap is a wrapper around another object and a method. The Tap object
13
+ # will receive the call to +trace+ and redirect that call to another object
14
+ # and method.
15
+ #
16
+ class TraceTap
17
+
18
+ attr_reader :delegate_obj
19
+ attr_reader :delegate_method
20
+
21
+ def initialize( wrapped_obj, send_to = 'trace' )
22
+ unless wrapped_obj.respond_to?( send_to )
23
+ raise Amalgalite::Error, "#{wrapped_obj.class.name} does not respond to #{send_to.to_s} "
24
+ end
25
+
26
+ @delegate_obj = wrapped_obj
27
+ @delegate_method = send_to
28
+ end
29
+
30
+ def trace( msg )
31
+ delegate_obj.send( delegate_method, msg )
32
+ end
33
+ end
34
+ end
35
+
@@ -0,0 +1,63 @@
1
+ #--
2
+ # Copyright (c) 2008 Jeremy Hinegardner
3
+ # All rights reserved. See LICENSE and/or COPYING for details.
4
+ #++
5
+ module Amalgalite
6
+ ##
7
+ # TypeMap defines the protocol used between Ruby and SQLite for mapping
8
+ # binding types, used in prepared statements; and result types, used in
9
+ # returning objects from a query.
10
+ #
11
+ #
12
+ class TypeMap
13
+ ##
14
+ # :call-seq:
15
+ # map.bind_type_of( obj ) -> DataType constant
16
+ #
17
+ # bind_type_of is called during the Statement#bind process to convert the
18
+ # bind parameter to the appropriate SQLite types. This method MUST return
19
+ # one of the valid constants in the namespace
20
+ # Amalgalite::SQLite::Constants::DataType
21
+ #
22
+ def bind_type_of( obj )
23
+ raise NotImplementedError, "bind_type_of has not been implemented"
24
+ end
25
+
26
+ ##
27
+ # :call-seq:
28
+ # map.result_value_of( declared_type, value ) -> String
29
+ #
30
+ # result_value_of is called during the result processing of column values
31
+ # to convert an SQLite database value into the appropriate Ruby class.
32
+ #
33
+ # +declared_type+ is the string from the original CREATE TABLE statment
34
+ # from which the column value originates. It may also be nil if the origin
35
+ # column cannot be determined.
36
+ #
37
+ # +value+ is the SQLite value from the column as either a Ruby String,
38
+ # Integer, Float or Amalgalite::Blob.
39
+ #
40
+ # result_value should return the value that is to be put into the result set
41
+ # for the query. It may do nothing, or it may do massive amounts of
42
+ # conversion.
43
+ def result_value_of( delcared_type, value )
44
+ raise NotImplementedError, "result_value_of has not been implemented"
45
+ end
46
+ end
47
+
48
+ ##
49
+ # The TypeMaps module holds all typemaps that ship with Amagalite. They
50
+ # currently are:
51
+ #
52
+ # DefaultMap:: does a 'best-guess' mapping to convert as many types as
53
+ # possible to known ruby classes from known SQL types.
54
+ # StorageMap:: converts to a limited set of classes directly based
55
+ # upon the SQLite storage types
56
+ # TextMap:: Everything is Text ... everything everything everything
57
+ #
58
+ module TypeMaps
59
+ end
60
+ end
61
+ require 'amalgalite/type_maps/default_map'
62
+ require 'amalgalite/type_maps/storage_map'
63
+ require 'amalgalite/type_maps/text_map'
@@ -0,0 +1,167 @@
1
+ #--
2
+ # Copyright (c) 2008 Jeremy Hinegardner
3
+ # All rights reserved. See LICENSE and/or COPYING for details.
4
+ #++
5
+
6
+ require 'amalgalite/type_map'
7
+ require 'time'
8
+ require 'date'
9
+
10
+ module Amalgalite::TypeMaps
11
+ ##
12
+ # An Amalgalite::TypeMap that does its best to convert between Ruby classes
13
+ # and known SQL data types.
14
+ #
15
+ # Upon instantiation, DefaultMap generates a conversion map to try to figure
16
+ # out the best way to convert between populate SQL 'types' and ruby classes
17
+ #
18
+ class DefaultMap
19
+ class << self
20
+ def methods_handling_sql_types # :nodoc:
21
+ @methods_handling_sql_types ||= {
22
+ 'date' => %w[ date ],
23
+ 'datetime' => %w[ datetime ],
24
+ 'time' => %w[ timestamp time ],
25
+ 'float' => %w[ double real numeric decimal ],
26
+ 'integer' => %w[ integer tinyint smallint int int2 int4 int8 bigint serial bigserial ],
27
+ 'string' => %w[ text char varchar character ],
28
+ 'boolean' => %w[ bool boolean ],
29
+ 'blob' => %w[ binary blob ],
30
+ }
31
+ end
32
+
33
+ # say what method to call to convert an sql type to a ruby type
34
+ #
35
+ def sql_to_method( sql_type ) # :nodoc:
36
+ unless defined? @sql_to_method
37
+ @sql_to_method = {}
38
+ methods_handling_sql_types.each_pair do |method, sql_types|
39
+ sql_types.each { |t| @sql_to_method[t] = method }
40
+ end
41
+ end
42
+ return_method = @sql_to_method[sql_type]
43
+
44
+ # the straight lookup didn't work, try iterating through the types and
45
+ # see what is found
46
+ unless return_method
47
+ @sql_to_method.each_pair do |sql, method|
48
+ if sql_type.index(sql) then
49
+ return_method = method
50
+ break
51
+ end
52
+ end
53
+ end
54
+ return return_method
55
+ end
56
+ end
57
+
58
+ def initialize
59
+ end
60
+
61
+ ##
62
+ # A straight logical mapping (for me at least) of basic Ruby classes to SQLite types, if
63
+ # nothing can be found then default to TEXT.
64
+ #
65
+ def bind_type_of( obj )
66
+ case obj
67
+ when Float
68
+ ::Amalgalite::SQLite3::Constants::DataType::FLOAT
69
+ when Fixnum
70
+ ::Amalgalite::SQLite3::Constants::DataType::INTEGER
71
+ when NilClass
72
+ ::Amalgalite::SQLite3::Constants::DataType::NULL
73
+ when ::Amalgalite::Blob
74
+ ::Amalgalite::SQLite3::Constants::DataType::BLOB
75
+ else
76
+ ::Amalgalite::SQLite3::Constants::DataType::TEXT
77
+ end
78
+ end
79
+
80
+ ##
81
+ # Map the incoming value to an outgoing value. For some incoming values,
82
+ # there will be no change, but for some (i.e. Dates and Times) there is some
83
+ # conversion
84
+ #
85
+ def result_value_of( declared_type, value )
86
+ case value
87
+ when Numeric
88
+ return value
89
+ when NilClass
90
+ return value
91
+ when Amalgalite::Blob
92
+ return value
93
+ when String
94
+ if declared_type then
95
+ conversion_method = DefaultMap.sql_to_method( declared_type.downcase )
96
+ if conversion_method then
97
+ return send(conversion_method, value)
98
+ else
99
+ raise ::Amalgalite::Error, "Unable to convert SQL type of #{declared_type} to a Ruby class"
100
+ end
101
+ else
102
+ # unable to do any other conversion, just return what we have.
103
+ return value
104
+ end
105
+ else
106
+ raise ::Amalgalite::Error, "Unable to convert a class #{value.class.name} with value #{value.inspect}"
107
+ end
108
+ end
109
+
110
+ ##
111
+ # convert a string to a date
112
+ #
113
+ def date( str )
114
+ Date.parse( str )
115
+ end
116
+
117
+ ##
118
+ # convert a string to a datetime, if no timzone is found in the parsed
119
+ # string, set it to the local offset.
120
+ #
121
+ def datetime( str )
122
+ DateTime.parse( str )
123
+ end
124
+
125
+ ##
126
+ # convert a string to a Time
127
+ #
128
+ def time( str )
129
+ Time.parse( str )
130
+ end
131
+
132
+ ##
133
+ # convert a string to a Float
134
+ #
135
+ def float( str )
136
+ Float( str )
137
+ end
138
+
139
+ ##
140
+ # convert an string to an Integer
141
+ #
142
+ def integer( str )
143
+ Float( str ).to_i
144
+ end
145
+
146
+ ##
147
+ # convert a string to a String, yes redundant I know.
148
+ #
149
+ def string( str )
150
+ str
151
+ end
152
+
153
+ ##
154
+ # convert a string to true of false
155
+ #
156
+ def boolean( str )
157
+ ::Amalgalite::Boolean.to_bool( str )
158
+ end
159
+
160
+ ##
161
+ # convert a string to a blob
162
+ #
163
+ def blob( str )
164
+ ::Amalgalite::Blob.new( :string => str )
165
+ end
166
+ end
167
+ end