sqlite-ruby 2.2.1 → 2.2.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,168 +0,0 @@
1
- #--
2
- # =============================================================================
3
- # Copyright (c) 2004, Jamis Buck (jgb3@email.byu.edu)
4
- # All rights reserved.
5
- #
6
- # Redistribution and use in source and binary forms, with or without
7
- # modification, are permitted provided that the following conditions are met:
8
- #
9
- # * Redistributions of source code must retain the above copyright notice,
10
- # this list of conditions and the following disclaimer.
11
- #
12
- # * Redistributions in binary form must reproduce the above copyright
13
- # notice, this list of conditions and the following disclaimer in the
14
- # documentation and/or other materials provided with the distribution.
15
- #
16
- # * The names of its contributors may not be used to endorse or promote
17
- # products derived from this software without specific prior written
18
- # permission.
19
- #
20
- # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21
- # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
- # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23
- # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
24
- # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
- # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26
- # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27
- # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28
- # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29
- # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
- # =============================================================================
31
- #++
32
-
33
- require 'sqlite_api'
34
-
35
- module SQLite
36
-
37
- # The ResultSet object encapsulates the enumerability of a query's output.
38
- # It is a simple cursor over the data that the query returns. It will
39
- # very rarely (if ever) be instantiated directly. Instead, client's should
40
- # obtain a ResultSet instance via Statement#execute.
41
- class ResultSet
42
- include Enumerable
43
-
44
- # A trivial module for adding a +types+ accessor to an object.
45
- module TypesContainer
46
- attr_accessor :types
47
- end
48
-
49
- # A trivial module for adding a +fields+ accessor to an object.
50
- module FieldsContainer
51
- attr_accessor :fields
52
- end
53
-
54
- # An array of the column names for this result set (may be empty)
55
- attr_reader :columns
56
-
57
- # An array of the column types for this result set (may be empty)
58
- attr_reader :types
59
-
60
- # Create a new ResultSet attached to the given database, using the
61
- # given sql text.
62
- def initialize( db, sql )
63
- @db = db
64
- @sql = sql
65
- commence
66
- end
67
-
68
- # A convenience method for compiling the virtual machine and stepping
69
- # to the first row of the result set.
70
- def commence
71
- @vm, = API.compile( @db.handle, @sql )
72
-
73
- @current_row = API.step( @vm )
74
-
75
- @columns = @current_row[ :columns ]
76
- @types = @current_row[ :types ]
77
-
78
- check_eof( @current_row )
79
- end
80
- private :commence
81
-
82
- # A convenience method for checking for EOF.
83
- def check_eof( row )
84
- @eof = !row.has_key?( :row )
85
- end
86
- private :check_eof
87
-
88
- # Close the result set. Attempting to perform any operation (including
89
- # #close) on a closed result set will have undefined results.
90
- def close
91
- API.finalize( @vm )
92
- end
93
-
94
- # Reset the cursor, so that a result set which has reached end-of-file
95
- # can be rewound and reiterated. _Note_: this uses an experimental API,
96
- # which is subject to change. Use at your own risk.
97
- def reset
98
- API.finalize( @vm )
99
- commence
100
- @eof = false
101
- end
102
-
103
- # Query whether the cursor has reached the end of the result set or not.
104
- def eof?
105
- @eof
106
- end
107
-
108
- # Obtain the next row from the cursor. If there are no more rows to be
109
- # had, this will return +nil+. If type translation is active on the
110
- # corresponding database, the values in the row will be translated
111
- # according to their types.
112
- #
113
- # The returned value will be an array, unless Database#results_as_hash has
114
- # been set to +true+, in which case the returned value will be a hash.
115
- #
116
- # For arrays, the column names are accessible via the +fields+ property,
117
- # and the column types are accessible via the +types+ property.
118
- #
119
- # For hashes, the column names are the keys of the hash, and the column
120
- # types are accessible via the +types+ property.
121
- def next
122
- return nil if @eof
123
-
124
- if @current_row
125
- result, @current_row = @current_row, nil
126
- else
127
- result = API.step( @vm )
128
- check_eof( result )
129
- end
130
-
131
- unless @eof
132
- row = result[:row]
133
-
134
- if @db.type_translation
135
- row = @types.zip( row ).map do |type, value|
136
- @db.translator.translate( type, value )
137
- end
138
- end
139
-
140
- if @db.results_as_hash
141
- new_row = Hash[ *( @columns.zip( row ).flatten ) ]
142
- row.each_with_index { |value,idx| new_row[idx] = value }
143
- row = new_row
144
- else
145
- row.extend FieldsContainer unless row.respond_to?(:fields)
146
- row.fields = @columns
147
- end
148
-
149
- row.extend TypesContainer
150
- row.types = @types
151
-
152
- return row
153
- end
154
-
155
- nil
156
- end
157
-
158
- # Required by the Enumerable mixin. Provides an internal iterator over the
159
- # rows of the result set.
160
- def each
161
- while row=self.next
162
- yield row
163
- end
164
- end
165
-
166
- end
167
-
168
- end
@@ -1,177 +0,0 @@
1
- #--
2
- # =============================================================================
3
- # Copyright (c) 2004, Jamis Buck (jgb3@email.byu.edu)
4
- # All rights reserved.
5
- #
6
- # Redistribution and use in source and binary forms, with or without
7
- # modification, are permitted provided that the following conditions are met:
8
- #
9
- # * Redistributions of source code must retain the above copyright notice,
10
- # this list of conditions and the following disclaimer.
11
- #
12
- # * Redistributions in binary form must reproduce the above copyright
13
- # notice, this list of conditions and the following disclaimer in the
14
- # documentation and/or other materials provided with the distribution.
15
- #
16
- # * The names of its contributors may not be used to endorse or promote
17
- # products derived from this software without specific prior written
18
- # permission.
19
- #
20
- # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21
- # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
- # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23
- # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
24
- # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
- # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26
- # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27
- # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28
- # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29
- # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
- # =============================================================================
31
- #++
32
-
33
- require 'sqlite_api'
34
- require 'sqlite/resultset'
35
- require 'sqlite/parsed_statement'
36
-
37
- module SQLite
38
-
39
- # A statement represents a prepared-but-unexecuted SQL query. It will rarely
40
- # (if ever) be instantiated directly by a client, and is most often obtained
41
- # via the Database#prepare method.
42
- class Statement
43
-
44
- # This is any text that followed the first valid SQL statement in the text
45
- # with which the statement was initialized. If there was no trailing text,
46
- # this will be the empty string.
47
- attr_reader :remainder
48
-
49
- # Create a new statement attached to the given Database instance, and which
50
- # encapsulates the given SQL text. If the text contains more than one
51
- # statement (i.e., separated by semicolons), then the #remainder property
52
- # will be set to the trailing text.
53
- def initialize( db, sql )
54
- @db = db
55
- @statement = ParsedStatement.new( sql )
56
- @remainder = @statement.trailing.strip
57
- @sql = @statement.to_s
58
- end
59
-
60
- # Binds the given variables to the corresponding placeholders in the SQL
61
- # text.
62
- #
63
- # See Database#execute for a description of the valid placeholder
64
- # syntaxes.
65
- #
66
- # Example:
67
- #
68
- # stmt = db.prepare( "select * from table where a=? and b=?" )
69
- # stmt.bind_params( 15, "hello" )
70
- #
71
- # See also #execute, #bind_param, Statement#bind_param, and
72
- # Statement#bind_params.
73
- def bind_params( *bind_vars )
74
- @statement.bind_params( *bind_vars )
75
- end
76
-
77
- # Binds value to the named (or positional) placeholder. If +param+ is a
78
- # Fixnum, it is treated as an index for a positional placeholder.
79
- # Otherwise it is used as the name of the placeholder to bind to.
80
- #
81
- # See also #bind_params.
82
- def bind_param( param, value )
83
- @statement.bind_param( param, value )
84
- end
85
-
86
- # Execute the statement. This creates a new ResultSet object for the
87
- # statement's virtual machine. If a block was given, the new ResultSet will
88
- # be yielded to it and then closed; otherwise, the ResultSet will be
89
- # returned. In that case, it is the client's responsibility to close the
90
- # ResultSet.
91
- #
92
- # Any parameters will be bound to the statement using #bind_params.
93
- #
94
- # Example:
95
- #
96
- # stmt = db.prepare( "select * from table" )
97
- # stmt.execute do |result|
98
- # ...
99
- # end
100
- #
101
- # See also #bind_params, #execute!.
102
- def execute( *bind_vars )
103
- bind_params *bind_vars unless bind_vars.empty?
104
- results = ResultSet.new( @db, @statement.to_s )
105
-
106
- if block_given?
107
- begin
108
- yield results
109
- ensure
110
- results.close
111
- end
112
- else
113
- return results
114
- end
115
- end
116
-
117
- # Execute the statement. If no block was given, this returns an array of
118
- # rows returned by executing the statement. Otherwise, each row will be
119
- # yielded to the block and then closed.
120
- #
121
- # Any parameters will be bound to the statement using #bind_params.
122
- #
123
- # Example:
124
- #
125
- # stmt = db.prepare( "select * from table" )
126
- # stmt.execute! do |row|
127
- # ...
128
- # end
129
- #
130
- # See also #bind_params, #execute.
131
- def execute!( *bind_vars )
132
- result = execute( *bind_vars )
133
- rows = [] unless block_given?
134
- while row = result.next
135
- if block_given?
136
- yield row
137
- else
138
- rows << row
139
- end
140
- end
141
- rows
142
- ensure
143
- result.close if result
144
- end
145
-
146
- # Return an array of the column names for this statement. Note that this
147
- # may execute the statement in order to obtain the metadata; this makes it
148
- # a (potentially) expensive operation.
149
- def columns
150
- get_metadata unless @columns
151
- return @columns
152
- end
153
-
154
- # Return an array of the data types for each column in this statement. Note
155
- # that this may execute the statement in order to obtain the metadata; this
156
- # makes it a (potentially) expensive operation.
157
- def types
158
- get_metadata unless @types
159
- return @types
160
- end
161
-
162
- # A convenience method for obtaining the metadata about the query. Note
163
- # that this will actually execute the SQL, which means it can be a
164
- # (potentially) expensive operation.
165
- def get_metadata
166
- vm, rest = API.compile( @db.handle, @statement.to_s )
167
- result = API.step( vm )
168
- API.finalize( vm )
169
-
170
- @columns = result[:columns]
171
- @types = result[:types]
172
- end
173
- private :get_metadata
174
-
175
- end
176
-
177
- end
@@ -1,135 +0,0 @@
1
- #--
2
- # =============================================================================
3
- # Copyright (c) 2004, Jamis Buck (jgb3@email.byu.edu)
4
- # All rights reserved.
5
- #
6
- # Redistribution and use in source and binary forms, with or without
7
- # modification, are permitted provided that the following conditions are met:
8
- #
9
- # * Redistributions of source code must retain the above copyright notice,
10
- # this list of conditions and the following disclaimer.
11
- #
12
- # * Redistributions in binary form must reproduce the above copyright
13
- # notice, this list of conditions and the following disclaimer in the
14
- # documentation and/or other materials provided with the distribution.
15
- #
16
- # * The names of its contributors may not be used to endorse or promote
17
- # products derived from this software without specific prior written
18
- # permission.
19
- #
20
- # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21
- # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
- # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23
- # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
24
- # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
- # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26
- # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27
- # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28
- # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29
- # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
- # =============================================================================
31
- #++
32
-
33
- require 'time'
34
-
35
- module SQLite
36
-
37
- # The Translator class encapsulates the logic and callbacks necessary for
38
- # converting string data to a value of some specified type. Every Database
39
- # instance may have a Translator instance, in order to assist in type
40
- # translation (Database#type_translation).
41
- #
42
- # Further, applications may define their own custom type translation logic
43
- # by registering translator blocks with the corresponding database's
44
- # translator instance (Database#translator).
45
- class Translator
46
-
47
- # Create a new Translator instance. It will be preinitialized with default
48
- # translators for most SQL data types.
49
- def initialize
50
- @translators = Hash.new( proc { |type,value| value } )
51
- register_default_translators
52
- end
53
-
54
- # Add a new translator block, which will be invoked to process type
55
- # translations to the given type. The type should be an SQL datatype, and
56
- # may include parentheses (i.e., "VARCHAR(30)"). However, any parenthetical
57
- # information is stripped off and discarded, so type translation decisions
58
- # are made solely on the "base" type name.
59
- #
60
- # The translator block itself should accept two parameters, "type" and
61
- # "value". In this case, the "type" is the full type name (including
62
- # parentheses), so the block itself may include logic for changing how a
63
- # type is translated based on the additional data. The "value" parameter
64
- # is the (string) data to convert.
65
- #
66
- # The block should return the translated value.
67
- def add_translator( type, &block ) # :yields: type, value
68
- @translators[ type_name( type ) ] = block
69
- end
70
-
71
- # Translate the given string value to a value of the given type. In the
72
- # absense of an installed translator block for the given type, the value
73
- # itself is always returned. Further, +nil+ values are never translated,
74
- # and are always passed straight through regardless of the type parameter.
75
- def translate( type, value )
76
- unless value.nil?
77
- @translators[ type_name( type ) ].call( type, value )
78
- end
79
- end
80
-
81
- # A convenience method for working with type names. This returns the "base"
82
- # type name, without any parenthetical data.
83
- def type_name( type )
84
- type = $1 if type =~ /^(.*?)\(/
85
- type.upcase
86
- end
87
- private :type_name
88
-
89
- # Register the default translators for the current Translator instance.
90
- # This includes translators for most major SQL data types.
91
- def register_default_translators
92
- [ "date",
93
- "datetime",
94
- "time" ].each { |type| add_translator( type ) { |t,v| Time.parse( v ) } }
95
-
96
- [ "decimal",
97
- "float",
98
- "numeric",
99
- "double",
100
- "real",
101
- "dec",
102
- "fixed" ].each { |type| add_translator( type ) { |t,v| v.to_f } }
103
-
104
- [ "integer",
105
- "smallint",
106
- "mediumint",
107
- "int",
108
- "bigint" ].each { |type| add_translator( type ) { |t,v| v.to_i } }
109
-
110
- [ "bit",
111
- "bool",
112
- "boolean" ].each do |type|
113
- add_translator( type ) do |t,v|
114
- !( v.strip.gsub(/00+/,"0") == "0" ||
115
- v.downcase == "false" ||
116
- v.downcase == "f" ||
117
- v.downcase == "no" ||
118
- v.downcase == "n" )
119
- end
120
- end
121
-
122
- add_translator( "timestamp" ) { |type, value| Time.at( value.to_i ) }
123
- add_translator( "tinyint" ) do |type, value|
124
- if type =~ /\(\s*1\s*\)/
125
- value.to_i == 1
126
- else
127
- value.to_i
128
- end
129
- end
130
- end
131
- private :register_default_translators
132
-
133
- end
134
-
135
- end