dbd-sqlanywhere 0.1.2 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +21 -12
- data/LICENSE +23 -23
- data/README +150 -150
- data/lib/dbd/SQLAnywhere.rb +176 -176
- data/lib/dbd/sqlanywhere/database.rb +266 -255
- data/lib/dbd/sqlanywhere/driver.rb +108 -102
- data/lib/dbd/sqlanywhere/statement.rb +216 -211
- data/test/dbd/sqlanywhere/base.rb +26 -26
- data/test/dbd/sqlanywhere/down.sql +19 -19
- data/test/dbd/sqlanywhere/up.sql +28 -28
- metadata +77 -67
- data/test/DBD_TESTS +0 -48
- data/test/dbd/general/test_database.rb +0 -157
- data/test/dbd/general/test_statement.rb +0 -249
- data/test/dbd/general/test_types.rb +0 -253
- data/test/ts_dbd.rb +0 -118
data/CHANGELOG
CHANGED
@@ -1,12 +1,21 @@
|
|
1
|
-
=CHANGE LOG
|
2
|
-
|
3
|
-
=====0.
|
4
|
-
- Changed
|
5
|
-
- Changed
|
6
|
-
|
7
|
-
-
|
8
|
-
|
9
|
-
=====0.1.
|
10
|
-
-
|
11
|
-
|
12
|
-
|
1
|
+
=CHANGE LOG
|
2
|
+
|
3
|
+
=====1.0.0 -- 2012/08/29
|
4
|
+
- Changed to have each row element to be stored as String object by "default" so that dbh.convert_types = false would return the String element properly.
|
5
|
+
- Changed sth.column_info not to assign any value "precision" and "scale" for the datatype that does not specify the precision or length.
|
6
|
+
- Changed sth.rows to return proper value for the number of the affected rows
|
7
|
+
- Changed rakefile to use rdoc/task instead of rake/rdoctask(deprecated)
|
8
|
+
|
9
|
+
=====0.1.2 -- 2009/03/27
|
10
|
+
- Changed the order and type of parameter for connection
|
11
|
+
|
12
|
+
=====0.1.1 -- 2008/11/06
|
13
|
+
- Changed file permissions on archives
|
14
|
+
- Changed archives to be specific to platform (.zip on windows, .tar.gz
|
15
|
+
otherwise)
|
16
|
+
- Removed the default rake task
|
17
|
+
|
18
|
+
=====0.1.0 -- 2008/10/29
|
19
|
+
- Initial Release
|
20
|
+
- Wraps DBCAPI functionality
|
21
|
+
- Tested against DBI 0.4
|
data/LICENSE
CHANGED
@@ -1,23 +1,23 @@
|
|
1
|
-
/*====================================================
|
2
|
-
*
|
3
|
-
* Copyright
|
4
|
-
*
|
5
|
-
* Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
-
* you may not use this file except in compliance with the License.
|
7
|
-
* You may obtain a copy of the License at
|
8
|
-
*
|
9
|
-
*
|
10
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
11
|
-
*
|
12
|
-
* Unless required by applicable law or agreed to in writing, software
|
13
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
-
*
|
16
|
-
* See the License for the specific language governing permissions and
|
17
|
-
* limitations under the License.
|
18
|
-
*
|
19
|
-
* While not a requirement of the license, if you do modify this file, we
|
20
|
-
* would appreciate hearing about it. Please email sqlany_interfaces@sybase.com
|
21
|
-
*
|
22
|
-
*
|
23
|
-
*====================================================*/
|
1
|
+
/*====================================================
|
2
|
+
*
|
3
|
+
* Copyright 2012 iAnywhere Solutions, Inc.
|
4
|
+
*
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
* you may not use this file except in compliance with the License.
|
7
|
+
* You may obtain a copy of the License at
|
8
|
+
*
|
9
|
+
*
|
10
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
*
|
12
|
+
* Unless required by applicable law or agreed to in writing, software
|
13
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
*
|
16
|
+
* See the License for the specific language governing permissions and
|
17
|
+
* limitations under the License.
|
18
|
+
*
|
19
|
+
* While not a requirement of the license, if you do modify this file, we
|
20
|
+
* would appreciate hearing about it. Please email sqlany_interfaces@sybase.com
|
21
|
+
*
|
22
|
+
*
|
23
|
+
*====================================================*/
|
data/README
CHANGED
@@ -1,150 +1,150 @@
|
|
1
|
-
=SQL Anywhere DBD Driver for Ruby-DBI
|
2
|
-
|
3
|
-
This is a SQL Anywhere driver for Ruby DBI (http://ruby-dbi.rubyforge.org/). This driver requires the
|
4
|
-
native SQL Anywhere Ruby driver. To get the native driver, use:
|
5
|
-
|
6
|
-
gem install sqlanywhere
|
7
|
-
|
8
|
-
This driver is designed for use with DBI 0.4 and greater.
|
9
|
-
|
10
|
-
This driver is licensed under the Apache License, Version 2.
|
11
|
-
|
12
|
-
The official code repository is located on GitHub. The repository can be cloned with:
|
13
|
-
|
14
|
-
git clone git://github.com/sqlanywhere/dbd-sqlanywhere.git
|
15
|
-
|
16
|
-
==Making a Connection
|
17
|
-
|
18
|
-
The following code is a sample database configuration object that connects
|
19
|
-
to a database called 'Test'.
|
20
|
-
|
21
|
-
require 'dbi'
|
22
|
-
|
23
|
-
DBI.connect('DBI:SQLAnywhere:Test') do | dbh |
|
24
|
-
if dbh.ping
|
25
|
-
print "Successfully Connected"
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
The connection function takes the general form:
|
30
|
-
|
31
|
-
dbh = DBI.connect(DBNAME, [USER_NAME], [PASSWORD])
|
32
|
-
|
33
|
-
The DBNAME string can be specified in the following forms:
|
34
|
-
|
35
|
-
"DBI:SQLAnywhere:"
|
36
|
-
"DBI:SQLAnywhere:{ENG}"
|
37
|
-
"DBI:SQLAnywhere:{ENG}:{DBN}"
|
38
|
-
"DBI:SQLAnywhere:{CONNECTION_STRING}" # where CONNECTION_STRING ~= "key1=val1;key2=val2;..."
|
39
|
-
|
40
|
-
For the first form, nothing will be added to the connection string. With the second and third forms
|
41
|
-
the driver will add ENG and DBN to the connection string accordingly. The fourth form will pass
|
42
|
-
the supplied connection string through unmolested.
|
43
|
-
|
44
|
-
The USER_NAME and PASSWORD can be passed into the function and they will be automatically appended to the
|
45
|
-
connection string. Since Ruby DBI will automatically fill in the username and password with defaults if they are omitted,
|
46
|
-
you should NEVER include a "UID=" or "PWD=" in your connection string or an exception will be thrown.
|
47
|
-
|
48
|
-
Examples:
|
49
|
-
|
50
|
-
Function Call ==> Generated Connection String
|
51
|
-
==============================================================================================
|
52
|
-
DBI.connect("DBI:SQLAnywhere:") ==> "uid=dba;pwd=sql"
|
53
|
-
DBI.connect("DBI:SQLAnywhere:Demo") ==> "eng=Demo;uid=dba;pwd=sql"
|
54
|
-
DBI.connect("DBI:SQLAnywhere:Demo:Test") ==> "eng=Demo;dbn=Test;uid=dba;pwd=sql"
|
55
|
-
DBI.connect("DBI:SQLAnywhere:Demo:Test", 'john', 'doe') ==> "eng=Demo;dbn=Test;uid=john;pwd=doe"
|
56
|
-
DBI.connect("DBI:SQLAnywhere:eng=Demo;dbn=Test") ==> "eng=Demo;dbn=Test;uid=dba;pwd=sql"
|
57
|
-
DBI.connect("DBI:SQLAnywhere:eng=Demo;dbn=Test;uid=john") ==> EXCEPTION! UID cannot be specified in the connection string
|
58
|
-
DBI.connect("DBI:SQLAnywhere:CommLinks=tcpip(port=2638)") ==> "CommLinks=tcpip(port=2638);uid=dba;pwd=sql"
|
59
|
-
|
60
|
-
|
61
|
-
==Running Test Suite
|
62
|
-
|
63
|
-
For information on running the Ruby/DBI DBD Tests, please see
|
64
|
-
|
65
|
-
test/DBD_TESTS
|
66
|
-
|
67
|
-
==Driver-Specific Features
|
68
|
-
|
69
|
-
At the time of this writing, there was no standard way to handle INOUT and OUT parameters
|
70
|
-
from stored procedures in DBI.
|
71
|
-
|
72
|
-
When binding to an OUT parameter, you must bind a hash that contains a key called
|
73
|
-
:name. This :name will be used to retrieve the OUT value after execution. If the
|
74
|
-
OUT column is of string or binary type, you must also pass a key called :length
|
75
|
-
with the expected maximum length of the OUT parameter.
|
76
|
-
|
77
|
-
In the case of an INOUT parameter, the :name and :length keys are the same as for
|
78
|
-
OUT parameters, but an additional :value parameter holds the value to be passed
|
79
|
-
into the stored procedure.
|
80
|
-
|
81
|
-
After execution, you can use the statement-specific function :bound_param
|
82
|
-
to retrieve the output value using the :name supplied at binding time.
|
83
|
-
|
84
|
-
===Example of using OUT and INOUT parameters
|
85
|
-
|
86
|
-
# The result that should be printed to console is:
|
87
|
-
# Complete string is PREFIX-some_string-SUFFIX and is 25 chars long
|
88
|
-
# Complete string is PREFIXPREFIX-some_string-SUFFIXSUFFIX and is 37 chars long
|
89
|
-
|
90
|
-
require 'dbi'
|
91
|
-
|
92
|
-
begin
|
93
|
-
DBI.connect("DBI:SQLAnywhere:test") do |dbh|
|
94
|
-
|
95
|
-
sql = <<SQL
|
96
|
-
IF EXISTS(SELECT * FROM SYS.SYSPROCEDURE where proc_name = 'foo') THEN
|
97
|
-
DROP PROCEDURE foo;
|
98
|
-
END IF
|
99
|
-
SQL
|
100
|
-
|
101
|
-
dbh.do(sql);
|
102
|
-
|
103
|
-
sql = <<SQL
|
104
|
-
create procedure foo
|
105
|
-
( IN prefix char(10),
|
106
|
-
INOUT buffer varchar(256),
|
107
|
-
OUT str_len int,
|
108
|
-
IN suffix char(10)
|
109
|
-
)
|
110
|
-
begin
|
111
|
-
set buffer = prefix || buffer || suffix;
|
112
|
-
select length( buffer ) into str_len;
|
113
|
-
end
|
114
|
-
SQL
|
115
|
-
|
116
|
-
dbh.do(sql);
|
117
|
-
|
118
|
-
buffer = "-some_string-"
|
119
|
-
prefix = "PREFIX"
|
120
|
-
|
121
|
-
# preparing the statement
|
122
|
-
sth = dbh.prepare("call foo( ?, ?, ?, ? )")
|
123
|
-
|
124
|
-
# Binding buffer column as :buf, and str_len column as :len
|
125
|
-
# Note that we must supply a :value for :buf since it is an INOUT
|
126
|
-
# And we must supply a :length for :buf since it is a string column
|
127
|
-
sth.execute( prefix, {:name => :buf, :value => buffer, :length => 255}, {:name => :len}, "SUFFIX")
|
128
|
-
|
129
|
-
# Retrieve the OUT value from buffer
|
130
|
-
new_buffer = sth.func(:bound_param, :buf)
|
131
|
-
|
132
|
-
# Retrieve the OUT value from str_len
|
133
|
-
length = sth.func(:bound_param, :len)
|
134
|
-
puts "Complete string is #{new_buffer} and is #{length} chars long"
|
135
|
-
|
136
|
-
# Add the results back into the string, and re-execute
|
137
|
-
sth.execute("PREFIX", {:name => :buf, :value => new_buffer, :length => 255}, {:name => :len}, "SUFFIX")
|
138
|
-
new_buffer = sth.func(:bound_param, :buf)
|
139
|
-
length = sth.func(:bound_param, :len)
|
140
|
-
puts "Complete string is #{new_buffer} and is #{length} chars long"
|
141
|
-
end
|
142
|
-
|
143
|
-
rescue DBI::DatabaseError => e
|
144
|
-
puts "An error occurred"
|
145
|
-
puts "Error code: #{e.err}"
|
146
|
-
puts "Error message: #{e.errstr}"
|
147
|
-
puts "Error SQLSTATE: #{e.state}"
|
148
|
-
ensure
|
149
|
-
DBI.disconnect_all
|
150
|
-
end
|
1
|
+
=SQL Anywhere DBD Driver for Ruby-DBI
|
2
|
+
|
3
|
+
This is a SQL Anywhere driver for Ruby DBI (http://ruby-dbi.rubyforge.org/). This driver requires the
|
4
|
+
native SQL Anywhere Ruby driver. To get the native driver, use:
|
5
|
+
|
6
|
+
gem install sqlanywhere
|
7
|
+
|
8
|
+
This driver is designed for use with DBI 0.4 and greater.
|
9
|
+
|
10
|
+
This driver is licensed under the Apache License, Version 2.
|
11
|
+
|
12
|
+
The official code repository is located on GitHub. The repository can be cloned with:
|
13
|
+
|
14
|
+
git clone git://github.com/sqlanywhere/dbd-sqlanywhere.git
|
15
|
+
|
16
|
+
==Making a Connection
|
17
|
+
|
18
|
+
The following code is a sample database configuration object that connects
|
19
|
+
to a database called 'Test'.
|
20
|
+
|
21
|
+
require 'dbi'
|
22
|
+
|
23
|
+
DBI.connect('DBI:SQLAnywhere:Test') do | dbh |
|
24
|
+
if dbh.ping
|
25
|
+
print "Successfully Connected"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
The connection function takes the general form:
|
30
|
+
|
31
|
+
dbh = DBI.connect(DBNAME, [USER_NAME], [PASSWORD])
|
32
|
+
|
33
|
+
The DBNAME string can be specified in the following forms:
|
34
|
+
|
35
|
+
"DBI:SQLAnywhere:"
|
36
|
+
"DBI:SQLAnywhere:{ENG}"
|
37
|
+
"DBI:SQLAnywhere:{ENG}:{DBN}"
|
38
|
+
"DBI:SQLAnywhere:{CONNECTION_STRING}" # where CONNECTION_STRING ~= "key1=val1;key2=val2;..."
|
39
|
+
|
40
|
+
For the first form, nothing will be added to the connection string. With the second and third forms
|
41
|
+
the driver will add ENG and DBN to the connection string accordingly. The fourth form will pass
|
42
|
+
the supplied connection string through unmolested.
|
43
|
+
|
44
|
+
The USER_NAME and PASSWORD can be passed into the function and they will be automatically appended to the
|
45
|
+
connection string. Since Ruby DBI will automatically fill in the username and password with defaults if they are omitted,
|
46
|
+
you should NEVER include a "UID=" or "PWD=" in your connection string or an exception will be thrown.
|
47
|
+
|
48
|
+
Examples:
|
49
|
+
|
50
|
+
Function Call ==> Generated Connection String
|
51
|
+
==============================================================================================
|
52
|
+
DBI.connect("DBI:SQLAnywhere:") ==> "uid=dba;pwd=sql"
|
53
|
+
DBI.connect("DBI:SQLAnywhere:Demo") ==> "eng=Demo;uid=dba;pwd=sql"
|
54
|
+
DBI.connect("DBI:SQLAnywhere:Demo:Test") ==> "eng=Demo;dbn=Test;uid=dba;pwd=sql"
|
55
|
+
DBI.connect("DBI:SQLAnywhere:Demo:Test", 'john', 'doe') ==> "eng=Demo;dbn=Test;uid=john;pwd=doe"
|
56
|
+
DBI.connect("DBI:SQLAnywhere:eng=Demo;dbn=Test") ==> "eng=Demo;dbn=Test;uid=dba;pwd=sql"
|
57
|
+
DBI.connect("DBI:SQLAnywhere:eng=Demo;dbn=Test;uid=john") ==> EXCEPTION! UID cannot be specified in the connection string
|
58
|
+
DBI.connect("DBI:SQLAnywhere:CommLinks=tcpip(port=2638)") ==> "CommLinks=tcpip(port=2638);uid=dba;pwd=sql"
|
59
|
+
|
60
|
+
|
61
|
+
==Running Test Suite
|
62
|
+
|
63
|
+
For information on running the Ruby/DBI DBD Tests, please see
|
64
|
+
|
65
|
+
test/DBD_TESTS
|
66
|
+
|
67
|
+
==Driver-Specific Features
|
68
|
+
|
69
|
+
At the time of this writing, there was no standard way to handle INOUT and OUT parameters
|
70
|
+
from stored procedures in DBI.
|
71
|
+
|
72
|
+
When binding to an OUT parameter, you must bind a hash that contains a key called
|
73
|
+
:name. This :name will be used to retrieve the OUT value after execution. If the
|
74
|
+
OUT column is of string or binary type, you must also pass a key called :length
|
75
|
+
with the expected maximum length of the OUT parameter.
|
76
|
+
|
77
|
+
In the case of an INOUT parameter, the :name and :length keys are the same as for
|
78
|
+
OUT parameters, but an additional :value parameter holds the value to be passed
|
79
|
+
into the stored procedure.
|
80
|
+
|
81
|
+
After execution, you can use the statement-specific function :bound_param
|
82
|
+
to retrieve the output value using the :name supplied at binding time.
|
83
|
+
|
84
|
+
===Example of using OUT and INOUT parameters
|
85
|
+
|
86
|
+
# The result that should be printed to console is:
|
87
|
+
# Complete string is PREFIX-some_string-SUFFIX and is 25 chars long
|
88
|
+
# Complete string is PREFIXPREFIX-some_string-SUFFIXSUFFIX and is 37 chars long
|
89
|
+
|
90
|
+
require 'dbi'
|
91
|
+
|
92
|
+
begin
|
93
|
+
DBI.connect("DBI:SQLAnywhere:test") do |dbh|
|
94
|
+
|
95
|
+
sql = <<SQL
|
96
|
+
IF EXISTS(SELECT * FROM SYS.SYSPROCEDURE where proc_name = 'foo') THEN
|
97
|
+
DROP PROCEDURE foo;
|
98
|
+
END IF
|
99
|
+
SQL
|
100
|
+
|
101
|
+
dbh.do(sql);
|
102
|
+
|
103
|
+
sql = <<SQL
|
104
|
+
create procedure foo
|
105
|
+
( IN prefix char(10),
|
106
|
+
INOUT buffer varchar(256),
|
107
|
+
OUT str_len int,
|
108
|
+
IN suffix char(10)
|
109
|
+
)
|
110
|
+
begin
|
111
|
+
set buffer = prefix || buffer || suffix;
|
112
|
+
select length( buffer ) into str_len;
|
113
|
+
end
|
114
|
+
SQL
|
115
|
+
|
116
|
+
dbh.do(sql);
|
117
|
+
|
118
|
+
buffer = "-some_string-"
|
119
|
+
prefix = "PREFIX"
|
120
|
+
|
121
|
+
# preparing the statement
|
122
|
+
sth = dbh.prepare("call foo( ?, ?, ?, ? )")
|
123
|
+
|
124
|
+
# Binding buffer column as :buf, and str_len column as :len
|
125
|
+
# Note that we must supply a :value for :buf since it is an INOUT
|
126
|
+
# And we must supply a :length for :buf since it is a string column
|
127
|
+
sth.execute( prefix, {:name => :buf, :value => buffer, :length => 255}, {:name => :len}, "SUFFIX")
|
128
|
+
|
129
|
+
# Retrieve the OUT value from buffer
|
130
|
+
new_buffer = sth.func(:bound_param, :buf)
|
131
|
+
|
132
|
+
# Retrieve the OUT value from str_len
|
133
|
+
length = sth.func(:bound_param, :len)
|
134
|
+
puts "Complete string is #{new_buffer} and is #{length} chars long"
|
135
|
+
|
136
|
+
# Add the results back into the string, and re-execute
|
137
|
+
sth.execute("PREFIX", {:name => :buf, :value => new_buffer, :length => 255}, {:name => :len}, "SUFFIX")
|
138
|
+
new_buffer = sth.func(:bound_param, :buf)
|
139
|
+
length = sth.func(:bound_param, :len)
|
140
|
+
puts "Complete string is #{new_buffer} and is #{length} chars long"
|
141
|
+
end
|
142
|
+
|
143
|
+
rescue DBI::DatabaseError => e
|
144
|
+
puts "An error occurred"
|
145
|
+
puts "Error code: #{e.err}"
|
146
|
+
puts "Error message: #{e.errstr}"
|
147
|
+
puts "Error SQLSTATE: #{e.state}"
|
148
|
+
ensure
|
149
|
+
DBI.disconnect_all
|
150
|
+
end
|
data/lib/dbd/SQLAnywhere.rb
CHANGED
@@ -1,176 +1,176 @@
|
|
1
|
-
#====================================================
|
2
|
-
#
|
3
|
-
# Copyright
|
4
|
-
#
|
5
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
-
# you may not use this file except in compliance with the License.
|
7
|
-
# You may obtain a copy of the License at
|
8
|
-
#
|
9
|
-
#
|
10
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
-
#
|
12
|
-
# Unless required by applicable law or agreed to in writing, software
|
13
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
-
#
|
16
|
-
# See the License for the specific language governing permissions and
|
17
|
-
# limitations under the License.
|
18
|
-
#
|
19
|
-
# While not a requirement of the license, if you do modify this file, we
|
20
|
-
# would appreciate hearing about it. Please email sqlany_interfaces@sybase.com
|
21
|
-
#
|
22
|
-
#
|
23
|
-
#====================================================
|
24
|
-
|
25
|
-
begin
|
26
|
-
require 'rubygems'
|
27
|
-
gem 'sqlanywhere'
|
28
|
-
gem 'dbi'
|
29
|
-
rescue LoadError => e
|
30
|
-
end
|
31
|
-
|
32
|
-
require 'dbi'
|
33
|
-
require 'dbi/typeutil'
|
34
|
-
require 'sqlanywhere'
|
35
|
-
require 'singleton'
|
36
|
-
|
37
|
-
module DBI
|
38
|
-
module DBD
|
39
|
-
module SQLAnywhere
|
40
|
-
|
41
|
-
VERSION = "0.
|
42
|
-
|
43
|
-
def self.driver_name
|
44
|
-
"SQLAnywhere"
|
45
|
-
end
|
46
|
-
|
47
|
-
class SA
|
48
|
-
include Singleton
|
49
|
-
attr_accessor :api
|
50
|
-
|
51
|
-
def initialize
|
52
|
-
unless defined? SQLAnywhere
|
53
|
-
require 'sqlanywhere'
|
54
|
-
end
|
55
|
-
|
56
|
-
@api = ::SQLAnywhere::SQLAnywhereInterface.new()
|
57
|
-
result = ::SQLAnywhere::API.sqlany_initialize_interface( @api )
|
58
|
-
if result == 0
|
59
|
-
raise LoadError, "Could not load SQLAnywhere DLL"
|
60
|
-
end
|
61
|
-
result = @api.sqlany_init()
|
62
|
-
if result == 0
|
63
|
-
raise LoadError, "Could not initialize SQLAnywhere DLL"
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
def free_api
|
68
|
-
::SQLAnywhere::API.sqlany_finalize_interface( @api );
|
69
|
-
@api = nil
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
|
74
|
-
DBI::TypeUtil.register_conversion(driver_name) do |obj|
|
75
|
-
case obj
|
76
|
-
when DBI::Binary # these need to be handled specially by the driver
|
77
|
-
obj.to_s
|
78
|
-
when ::NilClass
|
79
|
-
nil
|
80
|
-
when ::TrueClass
|
81
|
-
1
|
82
|
-
when ::FalseClass
|
83
|
-
0
|
84
|
-
when ::Time
|
85
|
-
obj.strftime("%H:%M:%S")
|
86
|
-
when ::Date
|
87
|
-
obj.strftime("%Y/%m/%d")
|
88
|
-
when ::DateTime, DBI::Timestamp
|
89
|
-
DateTime.parse(obj.to_s).strftime("%Y/%m/%d %H:%M:%S")
|
90
|
-
when ::String
|
91
|
-
obj
|
92
|
-
when ::BigDecimal
|
93
|
-
obj.to_s("F")
|
94
|
-
when ::Numeric
|
95
|
-
obj.to_s
|
96
|
-
else
|
97
|
-
obj
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
|
-
|
102
|
-
# This module provides functionality that is used by all the DBD classes
|
103
|
-
module Utility
|
104
|
-
|
105
|
-
NO_DIRECTION = 0
|
106
|
-
INPUT_ONLY = 1
|
107
|
-
OUTPUT_ONLY = 2
|
108
|
-
INPUT_OUTPUT = 3
|
109
|
-
|
110
|
-
# do_bind takes the following arguments:
|
111
|
-
# * +prep_stmt+ : a handle the prepared Statement object
|
112
|
-
# * +param+ : the parameter to bound, obtained by sqlany_describe_bind_param
|
113
|
-
# * +bindvar+ : the actual value to bind the the parameter. Can be a +VALUE+, or a +HASH+.
|
114
|
-
# * +i+ : the parameter number to bind. Should be the same as used in sqlany_describe_bind_param
|
115
|
-
# * +bound+ : hash used to track INOUT, and OUT parameters
|
116
|
-
#
|
117
|
-
# +IN+ parameters will be bound once with +INPUT_ONLY+.
|
118
|
-
# +OUT+ parameters will be bound once with +OUTPUT_ONLY+.
|
119
|
-
# +INOUT+ parameters will be be bound twice, once as +INPUT_ONLY+, and once as +OUTPUT_ONLY+. +INOUT+ parameters
|
120
|
-
# will use *different* buffers to pass the input and output values to the DLL.
|
121
|
-
#
|
122
|
-
# If the parameter to be bound is +INPUT_ONLY+, +bindvar+ *must* be a regular value type such as
|
123
|
-
# Bignum, Fixnum, String, etc. This value will be bound to the input parameter
|
124
|
-
#
|
125
|
-
# If the parameter to be bound is +OUTPUT_ONLY+, +bindvar+ *must* be a hash with keys:
|
126
|
-
# ::name => This is the name that you will be used later to retrieve the output value
|
127
|
-
# ::length => If the output will be a string or binary, the expected length must be stated. If this length is exceeded
|
128
|
-
# a DatabaseError (truncation) will be raised.
|
129
|
-
#
|
130
|
-
# If the parameter to be bound is +INPUT_OUTPUT+, +bindvar+ *must* be a hash with keys:
|
131
|
-
# ::name => This is the name that you will be used later to retrieve the output value
|
132
|
-
# ::value => The value to bind to the input.
|
133
|
-
# ::length => If the output will be a string or binary, the expected length must be stated. If this length is exceeded
|
134
|
-
# a DatabaseError (truncation) will be raised.
|
135
|
-
#
|
136
|
-
def do_bind!(prep_stmt, param, bindvar, i, bound)
|
137
|
-
# Get the direction
|
138
|
-
orig_direction = param.get_direction;
|
139
|
-
|
140
|
-
# Bind INPUT
|
141
|
-
if orig_direction == INPUT_ONLY or orig_direction == INPUT_OUTPUT
|
142
|
-
param.set_direction(INPUT_ONLY)
|
143
|
-
# Obtain the value out of the hash if neccessary
|
144
|
-
if bindvar.class == Hash
|
145
|
-
raise DBI::ProgrammingError.new("Parameter hash must contain :value key") if !bindvar.has_key?(:value)
|
146
|
-
param.set_value(bindvar[:value])
|
147
|
-
else
|
148
|
-
param.set_value(bindvar)
|
149
|
-
end
|
150
|
-
raise error() if SA.instance.api.sqlany_bind_param(prep_stmt, i, param) == 0
|
151
|
-
end
|
152
|
-
|
153
|
-
# Bind OUTPUT
|
154
|
-
if orig_direction == OUTPUT_ONLY or orig_direction == INPUT_OUTPUT
|
155
|
-
param.set_direction(OUTPUT_ONLY)
|
156
|
-
# Add the +::name+ to the +bound+ hash so its output value can be retrieved later
|
157
|
-
raise DBI::ProgrammingError.new("Parameter hash must contain :name key") if !bindvar.has_key?(:name)
|
158
|
-
bound[bindvar[:name]] = i if !bound.nil?
|
159
|
-
# set the buffer length if appropriate
|
160
|
-
if bindvar.has_key?(:length)
|
161
|
-
param.set_buffer_size(bindvar[:length])
|
162
|
-
end
|
163
|
-
# +set_value+ sets up the receiveing buffer
|
164
|
-
param.set_value(nil)
|
165
|
-
raise error() if SA.instance.api.sqlany_bind_param(prep_stmt, i, param) == 0
|
166
|
-
end
|
167
|
-
end
|
168
|
-
end
|
169
|
-
|
170
|
-
end # module SQLAnywhere
|
171
|
-
end # module DBD
|
172
|
-
end # module DBI
|
173
|
-
|
174
|
-
require 'dbd/sqlanywhere/driver'
|
175
|
-
require 'dbd/sqlanywhere/database'
|
176
|
-
require 'dbd/sqlanywhere/statement'
|
1
|
+
#====================================================
|
2
|
+
#
|
3
|
+
# Copyright 2012 iAnywhere Solutions, Inc.
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
#
|
16
|
+
# See the License for the specific language governing permissions and
|
17
|
+
# limitations under the License.
|
18
|
+
#
|
19
|
+
# While not a requirement of the license, if you do modify this file, we
|
20
|
+
# would appreciate hearing about it. Please email sqlany_interfaces@sybase.com
|
21
|
+
#
|
22
|
+
#
|
23
|
+
#====================================================
|
24
|
+
|
25
|
+
begin
|
26
|
+
require 'rubygems'
|
27
|
+
gem 'sqlanywhere'
|
28
|
+
gem 'dbi'
|
29
|
+
rescue LoadError => e
|
30
|
+
end
|
31
|
+
|
32
|
+
require 'dbi'
|
33
|
+
require 'dbi/typeutil'
|
34
|
+
require 'sqlanywhere'
|
35
|
+
require 'singleton'
|
36
|
+
|
37
|
+
module DBI
|
38
|
+
module DBD
|
39
|
+
module SQLAnywhere
|
40
|
+
|
41
|
+
VERSION = "1.0.0"
|
42
|
+
|
43
|
+
def self.driver_name
|
44
|
+
"SQLAnywhere"
|
45
|
+
end
|
46
|
+
|
47
|
+
class SA
|
48
|
+
include Singleton
|
49
|
+
attr_accessor :api
|
50
|
+
|
51
|
+
def initialize
|
52
|
+
unless defined? SQLAnywhere
|
53
|
+
require 'sqlanywhere'
|
54
|
+
end
|
55
|
+
|
56
|
+
@api = ::SQLAnywhere::SQLAnywhereInterface.new()
|
57
|
+
result = ::SQLAnywhere::API.sqlany_initialize_interface( @api )
|
58
|
+
if result == 0
|
59
|
+
raise LoadError, "Could not load SQLAnywhere DLL"
|
60
|
+
end
|
61
|
+
result = @api.sqlany_init()
|
62
|
+
if result == 0
|
63
|
+
raise LoadError, "Could not initialize SQLAnywhere DLL"
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def free_api
|
68
|
+
::SQLAnywhere::API.sqlany_finalize_interface( @api );
|
69
|
+
@api = nil
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
|
74
|
+
DBI::TypeUtil.register_conversion(driver_name) do |obj|
|
75
|
+
case obj
|
76
|
+
when DBI::Binary # these need to be handled specially by the driver
|
77
|
+
obj.to_s
|
78
|
+
when ::NilClass
|
79
|
+
nil
|
80
|
+
when ::TrueClass
|
81
|
+
1
|
82
|
+
when ::FalseClass
|
83
|
+
0
|
84
|
+
when ::Time
|
85
|
+
obj.strftime("%H:%M:%S")
|
86
|
+
when ::Date
|
87
|
+
obj.strftime("%Y/%m/%d")
|
88
|
+
when ::DateTime, DBI::Timestamp
|
89
|
+
DateTime.parse(obj.to_s).strftime("%Y/%m/%d %H:%M:%S")
|
90
|
+
when ::String
|
91
|
+
obj
|
92
|
+
when ::BigDecimal
|
93
|
+
obj.to_s("F")
|
94
|
+
when ::Numeric
|
95
|
+
obj.to_s
|
96
|
+
else
|
97
|
+
obj
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
|
102
|
+
# This module provides functionality that is used by all the DBD classes
|
103
|
+
module Utility
|
104
|
+
|
105
|
+
NO_DIRECTION = 0
|
106
|
+
INPUT_ONLY = 1
|
107
|
+
OUTPUT_ONLY = 2
|
108
|
+
INPUT_OUTPUT = 3
|
109
|
+
|
110
|
+
# do_bind takes the following arguments:
|
111
|
+
# * +prep_stmt+ : a handle the prepared Statement object
|
112
|
+
# * +param+ : the parameter to bound, obtained by sqlany_describe_bind_param
|
113
|
+
# * +bindvar+ : the actual value to bind the the parameter. Can be a +VALUE+, or a +HASH+.
|
114
|
+
# * +i+ : the parameter number to bind. Should be the same as used in sqlany_describe_bind_param
|
115
|
+
# * +bound+ : hash used to track INOUT, and OUT parameters
|
116
|
+
#
|
117
|
+
# +IN+ parameters will be bound once with +INPUT_ONLY+.
|
118
|
+
# +OUT+ parameters will be bound once with +OUTPUT_ONLY+.
|
119
|
+
# +INOUT+ parameters will be be bound twice, once as +INPUT_ONLY+, and once as +OUTPUT_ONLY+. +INOUT+ parameters
|
120
|
+
# will use *different* buffers to pass the input and output values to the DLL.
|
121
|
+
#
|
122
|
+
# If the parameter to be bound is +INPUT_ONLY+, +bindvar+ *must* be a regular value type such as
|
123
|
+
# Bignum, Fixnum, String, etc. This value will be bound to the input parameter
|
124
|
+
#
|
125
|
+
# If the parameter to be bound is +OUTPUT_ONLY+, +bindvar+ *must* be a hash with keys:
|
126
|
+
# ::name => This is the name that you will be used later to retrieve the output value
|
127
|
+
# ::length => If the output will be a string or binary, the expected length must be stated. If this length is exceeded
|
128
|
+
# a DatabaseError (truncation) will be raised.
|
129
|
+
#
|
130
|
+
# If the parameter to be bound is +INPUT_OUTPUT+, +bindvar+ *must* be a hash with keys:
|
131
|
+
# ::name => This is the name that you will be used later to retrieve the output value
|
132
|
+
# ::value => The value to bind to the input.
|
133
|
+
# ::length => If the output will be a string or binary, the expected length must be stated. If this length is exceeded
|
134
|
+
# a DatabaseError (truncation) will be raised.
|
135
|
+
#
|
136
|
+
def do_bind!(prep_stmt, param, bindvar, i, bound)
|
137
|
+
# Get the direction
|
138
|
+
orig_direction = param.get_direction;
|
139
|
+
|
140
|
+
# Bind INPUT
|
141
|
+
if orig_direction == INPUT_ONLY or orig_direction == INPUT_OUTPUT
|
142
|
+
param.set_direction(INPUT_ONLY)
|
143
|
+
# Obtain the value out of the hash if neccessary
|
144
|
+
if bindvar.class == Hash
|
145
|
+
raise DBI::ProgrammingError.new("Parameter hash must contain :value key") if !bindvar.has_key?(:value)
|
146
|
+
param.set_value(bindvar[:value])
|
147
|
+
else
|
148
|
+
param.set_value(bindvar)
|
149
|
+
end
|
150
|
+
raise error() if SA.instance.api.sqlany_bind_param(prep_stmt, i, param) == 0
|
151
|
+
end
|
152
|
+
|
153
|
+
# Bind OUTPUT
|
154
|
+
if orig_direction == OUTPUT_ONLY or orig_direction == INPUT_OUTPUT
|
155
|
+
param.set_direction(OUTPUT_ONLY)
|
156
|
+
# Add the +::name+ to the +bound+ hash so its output value can be retrieved later
|
157
|
+
raise DBI::ProgrammingError.new("Parameter hash must contain :name key") if !bindvar.has_key?(:name)
|
158
|
+
bound[bindvar[:name]] = i if !bound.nil?
|
159
|
+
# set the buffer length if appropriate
|
160
|
+
if bindvar.has_key?(:length)
|
161
|
+
param.set_buffer_size(bindvar[:length])
|
162
|
+
end
|
163
|
+
# +set_value+ sets up the receiveing buffer
|
164
|
+
param.set_value(nil)
|
165
|
+
raise error() if SA.instance.api.sqlany_bind_param(prep_stmt, i, param) == 0
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
end # module SQLAnywhere
|
171
|
+
end # module DBD
|
172
|
+
end # module DBI
|
173
|
+
|
174
|
+
require 'dbd/sqlanywhere/driver'
|
175
|
+
require 'dbd/sqlanywhere/database'
|
176
|
+
require 'dbd/sqlanywhere/statement'
|