sqlite-ruby 2.0.3
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.
- data/README +34 -0
- data/doc/faq/faq.html +390 -0
- data/doc/faq/faq.rb +145 -0
- data/doc/faq/faq.yml +453 -0
- data/ext/extconf.rb +8 -0
- data/ext/sqlite-api.c +1412 -0
- data/lib/sqlite/database.rb +682 -0
- data/lib/sqlite/parsed_statement.rb +233 -0
- data/lib/sqlite/pragmas.rb +236 -0
- data/lib/sqlite/resultset.rb +168 -0
- data/lib/sqlite/statement.rb +145 -0
- data/lib/sqlite/translator.rb +135 -0
- data/lib/sqlite/version.rb +45 -0
- data/lib/sqlite.rb +34 -0
- data/test/db/fixtures.sql +25 -0
- data/test/tc_api_core.rb +201 -0
- data/test/tc_arrayfields.rb +74 -0
- data/test/tc_database.rb +335 -0
- data/test/tc_parsed_statement.rb +160 -0
- data/test/tc_pragmas.rb +207 -0
- data/test/tc_translator.rb +115 -0
- data/test/tc_type_translation.rb +55 -0
- data/test/tests.rb +133 -0
- metadata +67 -0
@@ -0,0 +1,145 @@
|
|
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
|
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
|
+
# Example:
|
93
|
+
#
|
94
|
+
# stmt = db.prepare( "select * from table" )
|
95
|
+
# stmt.execute do |result|
|
96
|
+
# ...
|
97
|
+
# end
|
98
|
+
#
|
99
|
+
# See also #bind_params.
|
100
|
+
def execute
|
101
|
+
results = ResultSet.new( @db, @statement.to_s )
|
102
|
+
|
103
|
+
if block_given?
|
104
|
+
begin
|
105
|
+
yield results
|
106
|
+
ensure
|
107
|
+
results.close
|
108
|
+
end
|
109
|
+
else
|
110
|
+
return results
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
# Return an array of the column names for this statement. Note that this
|
115
|
+
# may execute the statement in order to obtain the metadata; this makes it
|
116
|
+
# a (potentially) expensive operation.
|
117
|
+
def columns
|
118
|
+
get_metadata unless @columns
|
119
|
+
return @columns
|
120
|
+
end
|
121
|
+
|
122
|
+
# Return an array of the data types for each column in this statement. Note
|
123
|
+
# that this may execute the statement in order to obtain the metadata; this
|
124
|
+
# makes it a (potentially) expensive operation.
|
125
|
+
def types
|
126
|
+
get_metadata unless @types
|
127
|
+
return @types
|
128
|
+
end
|
129
|
+
|
130
|
+
# A convenience method for obtaining the metadata about the query. Note
|
131
|
+
# that this will actually execute the SQL, which means it can be a
|
132
|
+
# (potentially) expensive operation.
|
133
|
+
def get_metadata
|
134
|
+
vm, rest = API.compile( @db.handle, @statement.to_s )
|
135
|
+
result = API.step( vm )
|
136
|
+
API.finalize( vm )
|
137
|
+
|
138
|
+
@columns = result[:columns]
|
139
|
+
@types = result[:types]
|
140
|
+
end
|
141
|
+
private :get_metadata
|
142
|
+
|
143
|
+
end
|
144
|
+
|
145
|
+
end
|
@@ -0,0 +1,135 @@
|
|
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
|
@@ -0,0 +1,45 @@
|
|
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
|
+
module SQLite
|
34
|
+
|
35
|
+
module Version
|
36
|
+
|
37
|
+
MAJOR = 2
|
38
|
+
MINOR = 0
|
39
|
+
TINY = 3
|
40
|
+
|
41
|
+
STRING = [ MAJOR, MINOR, TINY ].join( "." )
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
data/lib/sqlite.rb
ADDED
@@ -0,0 +1,34 @@
|
|
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/database'
|
34
|
+
require 'sqlite/version'
|
@@ -0,0 +1,25 @@
|
|
1
|
+
create table A
|
2
|
+
(
|
3
|
+
name VARCHAR(60),
|
4
|
+
age INTEGER
|
5
|
+
);
|
6
|
+
|
7
|
+
insert into A values ( 'Zephyr', 1 );
|
8
|
+
insert into A values ( 'Timothy', 2 );
|
9
|
+
insert into A values ( 'Juniper', 3 );
|
10
|
+
insert into A values ( 'Cinnamon', 4 );
|
11
|
+
insert into A values ( 'Amber', 5 );
|
12
|
+
insert into A values ( NULL, 6 );
|
13
|
+
|
14
|
+
create table B
|
15
|
+
(
|
16
|
+
id INTEGER PRIMARY KEY,
|
17
|
+
name VARCHAR(60)
|
18
|
+
);
|
19
|
+
|
20
|
+
create index B_idx on B ( name );
|
21
|
+
|
22
|
+
create table D
|
23
|
+
(
|
24
|
+
b_id INTEGER REFERENCES B ( id )
|
25
|
+
);
|
data/test/tc_api_core.rb
ADDED
@@ -0,0 +1,201 @@
|
|
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
|
+
$:.unshift "lib"
|
34
|
+
|
35
|
+
require 'sqlite_api'
|
36
|
+
require 'test/unit'
|
37
|
+
|
38
|
+
# MISSING TESTS FOR:
|
39
|
+
# SQLite::Exceptions::BusyException (and related cases)
|
40
|
+
# API.interrupt
|
41
|
+
# API.busy_handler
|
42
|
+
# API.busy_timeout
|
43
|
+
# API.function_type
|
44
|
+
# API.set_result_error
|
45
|
+
|
46
|
+
class TC_APICore < Test::Unit::TestCase
|
47
|
+
include SQLite
|
48
|
+
|
49
|
+
def test_constants
|
50
|
+
assert_equal( "constant", defined? API::VERSION )
|
51
|
+
assert_equal( "constant", defined? API::ENCODING )
|
52
|
+
assert_equal( "constant", defined? API::NUMERIC )
|
53
|
+
assert_equal( "constant", defined? API::TEXT )
|
54
|
+
assert_equal( "constant", defined? API::ARGS )
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_open_new
|
58
|
+
assert !File.exist?( "db/dummy.db" )
|
59
|
+
db = API.open( "db/dummy.db", 0 )
|
60
|
+
assert File.exist?( "db/dummy.db" )
|
61
|
+
API.close db
|
62
|
+
File.delete "db/dummy.db"
|
63
|
+
end
|
64
|
+
|
65
|
+
def test_compile
|
66
|
+
db = API.open( "db/fixtures.db", 0 )
|
67
|
+
vm, rest = API.compile( db, "select name, age from A order by name;extra" )
|
68
|
+
assert_equal "extra", rest
|
69
|
+
result = API.step( vm )
|
70
|
+
assert_nil result[:row][0]
|
71
|
+
assert_equal ["name","age"], result[:columns]
|
72
|
+
result = API.step( vm )
|
73
|
+
assert_equal 'Amber', result[:row][0]
|
74
|
+
result = API.step( vm )
|
75
|
+
assert_equal 'Cinnamon', result[:row][0]
|
76
|
+
result = API.step( vm )
|
77
|
+
assert_equal 'Juniper', result[:row][0]
|
78
|
+
result = API.step( vm )
|
79
|
+
assert_equal 'Timothy', result[:row][0]
|
80
|
+
result = API.step( vm )
|
81
|
+
assert_equal 'Zephyr', result[:row][0]
|
82
|
+
result = API.step( vm )
|
83
|
+
assert !result.has_key?(:row)
|
84
|
+
|
85
|
+
assert_raise( SQLite::Exceptions::MisuseException ) do
|
86
|
+
API.step( vm )
|
87
|
+
end
|
88
|
+
|
89
|
+
API.finalize( vm )
|
90
|
+
API.close( db )
|
91
|
+
end
|
92
|
+
|
93
|
+
def test_bad_compile
|
94
|
+
db = API.open( "db/fixtures.db", 0 )
|
95
|
+
assert_raise( SQLite::Exceptions::SQLException ) do
|
96
|
+
API.compile( db, "select name, age from BOGUS order by name" )
|
97
|
+
end
|
98
|
+
API.close( db )
|
99
|
+
end
|
100
|
+
|
101
|
+
def test_empty_compile
|
102
|
+
db = API.open( "db/fixtures.db", 0 )
|
103
|
+
vm, rest = API.compile( db, "select * from B order by name" )
|
104
|
+
result = API.step( vm )
|
105
|
+
assert !result.has_key?(:row)
|
106
|
+
assert_equal ["id","name"], result[:columns]
|
107
|
+
API.finalize( vm )
|
108
|
+
API.close( db )
|
109
|
+
end
|
110
|
+
|
111
|
+
def test_last_insert_row_id
|
112
|
+
db = API.open( "db/dummy.db", 0 )
|
113
|
+
|
114
|
+
vm, rest = API.compile( db, "create table Z ( a integer primary key, b varchar(60) )" )
|
115
|
+
API.step(vm)
|
116
|
+
API.finalize(vm)
|
117
|
+
|
118
|
+
vm, rest = API.compile( db, "insert into Z values ( 14, 'Hello' )" )
|
119
|
+
API.step(vm)
|
120
|
+
API.finalize(vm)
|
121
|
+
|
122
|
+
assert_equal 14, API.last_insert_row_id( db )
|
123
|
+
|
124
|
+
API.close(db)
|
125
|
+
|
126
|
+
ensure
|
127
|
+
File.delete( "db/dummy.db" )
|
128
|
+
end
|
129
|
+
|
130
|
+
def test_changes
|
131
|
+
db = API.open( "db/dummy.db", 0 )
|
132
|
+
|
133
|
+
vm, rest = API.compile( db, "create table Z ( a integer primary key, b varchar(60) )" )
|
134
|
+
API.step(vm)
|
135
|
+
API.finalize(vm)
|
136
|
+
|
137
|
+
vm, rest = API.compile( db, "insert into Z values ( 14, 'Hello' )" )
|
138
|
+
API.step(vm)
|
139
|
+
API.finalize(vm)
|
140
|
+
|
141
|
+
assert_equal 1, API.changes( db )
|
142
|
+
|
143
|
+
vm, rest = API.compile( db, "insert into Z values ( 15, 'Hello' )" )
|
144
|
+
API.step(vm)
|
145
|
+
API.finalize(vm)
|
146
|
+
|
147
|
+
vm, rest = API.compile( db, "delete from Z where 1" )
|
148
|
+
API.step(vm)
|
149
|
+
API.finalize(vm)
|
150
|
+
|
151
|
+
assert_equal 2, API.changes( db )
|
152
|
+
|
153
|
+
API.close(db)
|
154
|
+
|
155
|
+
ensure
|
156
|
+
File.delete( "db/dummy.db" )
|
157
|
+
end
|
158
|
+
|
159
|
+
def test_complete
|
160
|
+
sql = "select * from"
|
161
|
+
assert !API.complete( sql )
|
162
|
+
sql << "a_table;"
|
163
|
+
assert API.complete( sql )
|
164
|
+
end
|
165
|
+
|
166
|
+
def test_create_function
|
167
|
+
db = API.open( "db/fixtures.db", 0 )
|
168
|
+
|
169
|
+
API.create_function( db, "maim", 1, proc { |func,arg| API.set_result( func, arg.split(//).sort.join ) } )
|
170
|
+
|
171
|
+
vm, rest = API.compile( db, "select maim(name) from A where name = 'Amber'" )
|
172
|
+
result = API.step( vm )
|
173
|
+
assert_equal "Abemr", result[:row][0]
|
174
|
+
API.finalize( vm )
|
175
|
+
|
176
|
+
API.close( db )
|
177
|
+
end
|
178
|
+
|
179
|
+
def test_create_aggregate
|
180
|
+
db = API.open( "db/fixtures.db", 0 )
|
181
|
+
|
182
|
+
API.create_aggregate( db, "lengths", 1,
|
183
|
+
proc { |func,arg|
|
184
|
+
ctx = API.aggregate_context( func )
|
185
|
+
ctx[:count] = API.aggregate_count( func )
|
186
|
+
ctx[:len] ||= 0
|
187
|
+
ctx[:len] += ( arg.nil? ? 0 : arg.length )
|
188
|
+
},
|
189
|
+
proc { |func|
|
190
|
+
ctx = API.aggregate_context( func )
|
191
|
+
API.set_result( func, "#{ctx[:len] || 0}/#{ctx[:count] || 0}" )
|
192
|
+
} )
|
193
|
+
|
194
|
+
vm, rest = API.compile( db, "select lengths(name) from A" )
|
195
|
+
result = API.step( vm )
|
196
|
+
assert_equal "33/6", result[:row][0]
|
197
|
+
API.finalize( vm )
|
198
|
+
|
199
|
+
API.close( db )
|
200
|
+
end
|
201
|
+
end
|
@@ -0,0 +1,74 @@
|
|
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
|
+
$:.unshift "lib"
|
34
|
+
|
35
|
+
require 'sqlite'
|
36
|
+
require 'test/unit'
|
37
|
+
|
38
|
+
begin
|
39
|
+
|
40
|
+
require 'arrayfields'
|
41
|
+
|
42
|
+
class TC_ArrayFields < Test::Unit::TestCase
|
43
|
+
|
44
|
+
def setup
|
45
|
+
@db = SQLite::Database.open( "db/fixtures.db" )
|
46
|
+
@db.type_translation = true
|
47
|
+
end
|
48
|
+
|
49
|
+
def teardown
|
50
|
+
@db.close
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_fields
|
54
|
+
row = @db.get_first_row "select * from A"
|
55
|
+
assert_equal( [ "name", "age" ], row.fields )
|
56
|
+
end
|
57
|
+
|
58
|
+
def test_name_access
|
59
|
+
row = @db.get_first_row "select * from A"
|
60
|
+
assert_equal( "Zephyr", row["name"] )
|
61
|
+
assert_equal( 1, row["age"] )
|
62
|
+
end
|
63
|
+
|
64
|
+
def test_index_access
|
65
|
+
row = @db.get_first_row "select * from A"
|
66
|
+
assert_equal( "Zephyr", row[0] )
|
67
|
+
assert_equal( 1, row[1] )
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
rescue LoadError => e
|
73
|
+
puts "'arrayfields' does not appear to exist... skipping arrayfields integration test"
|
74
|
+
end
|