dbd-sqlanywhere 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,58 +1,102 @@
1
- #====================================================
2
- #
3
- # Copyright 2008 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
- module DBI::DBD::SQLAnywhere
26
- class Driver < DBI::BaseDriver
27
- include Utility
28
-
29
- def initialize
30
- super("0.4.0")
31
- end
32
-
33
- def connect( dbname, user, auth, attr )
34
- conn = SA.instance.api.sqlany_new_connection()
35
- conn_str = "uid=#{user};pwd=#{auth};";
36
-
37
- if !dbname.nil?
38
- conn_str += "eng=#{dbname};";
39
- end
40
-
41
- attr.keys.each do |option|
42
- conn_str += "#{option}=#{attr[option]};"
43
- end
44
-
45
- SA.instance.api.sqlany_connect(conn, conn_str)
46
- return Database.new(conn, attr)
47
- end
48
-
49
- def default_user
50
- return ['dba', 'sql']
51
- end
52
-
53
- def disconnect_all
54
- SA.instance.api.sqlany_fini()
55
- SA.instance.free_api
56
- end
57
- end
58
- end
1
+ #====================================================
2
+ #
3
+ # Copyright 2008-2009 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
+ module DBI::DBD::SQLAnywhere
26
+ class Driver < DBI::BaseDriver
27
+ include Utility
28
+
29
+ def initialize
30
+ super("0.4.0")
31
+ end
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 and auth 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 ommited,
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
+ # The attr parameter is ignored.
61
+
62
+ def connect( dbname, user, auth, attr )
63
+ conn = SA.instance.api.sqlany_new_connection()
64
+
65
+ conn_str = ''
66
+
67
+ unless dbname.nil?
68
+ if dbname =~ /^[^=:;]+$/
69
+ conn_str = "eng=#{dbname};"
70
+ elsif dbname =~ /^[^=:;]+:[^=:;]+$/
71
+ eng_name, db_name = dbname.split(":")
72
+ conn_str = "eng=#{eng_name};dbn=#{db_name};"
73
+ else
74
+ conn_str = dbname;
75
+ conn_str << ';' unless conn_str.length == 0 or conn_str[conn_str.length - 1, 1] == ';'
76
+ end
77
+ end
78
+
79
+ unless user.nil?
80
+ raise DBI::ProgrammingError.new("UID is specified twice. Once in the connection string AND once as a connect() parameter. It can only be specified once.") if conn_str =~ /uid=/i
81
+ conn_str << "uid=#{user};"
82
+ end
83
+
84
+ unless auth.nil?
85
+ raise DBI::ProgrammingError.new("PWD is specified twice. Once in the connection string AND once as a connect() parameter. It can only be specifed once.") if conn_str =~ /pwd=/i
86
+ conn_str << "pwd=#{auth};"
87
+ end
88
+
89
+ SA.instance.api.sqlany_connect(conn, conn_str)
90
+ return Database.new(conn, attr)
91
+ end
92
+
93
+ def default_user
94
+ return ['dba', 'sql']
95
+ end
96
+
97
+ def disconnect_all
98
+ SA.instance.api.sqlany_fini()
99
+ SA.instance.free_api
100
+ end
101
+ end
102
+ end
@@ -1,209 +1,211 @@
1
- #====================================================
2
- #
3
- # Copyright 2008 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
- module DBI::DBD::SQLAnywhere
26
- class Statement < DBI::BaseStatement
27
- include Utility
28
-
29
-
30
- # Conversion table between SQL Anywhere E-SQL types and DBI SQL Types
31
- SQLANY_NATIVE_TYPES = {
32
- 0 => DBI::SQL_LONGVARCHAR,
33
- 384 => DBI::SQL_DATE,
34
- 388 => DBI::SQL_TIME,
35
- 392 => DBI::SQL_TIMESTAMP,
36
- 448 => DBI::SQL_VARCHAR,
37
- 452 => DBI::SQL_CHAR,
38
- 456 => DBI::SQL_LONGVARCHAR,
39
- 460 => DBI::SQL_LONGVARCHAR,
40
- 480 => DBI::SQL_DOUBLE,
41
- 482 => DBI::SQL_FLOAT,
42
- 484 => DBI::SQL_DECIMAL,
43
- 496 => DBI::SQL_INTEGER,
44
- 500 => DBI::SQL_SMALLINT,
45
- 524 => DBI::SQL_BINARY,
46
- 528 => DBI::SQL_LONGVARBINARY,
47
- 604 => DBI::SQL_TINYINT,
48
- 608 => DBI::SQL_BIGINT,
49
- 612 => DBI::SQL_INTEGER,
50
- 616 => DBI::SQL_SMALLINT,
51
- 620 => DBI::SQL_BIGINT,
52
- 624 => DBI::SQL_BIT,
53
- 640 => DBI::SQL_LONGVARCHAR
54
- }
55
-
56
- def initialize(handle, conn, bound = {} )
57
- @handle = handle
58
- @conn = conn
59
- @arr = []
60
- @bound = bound
61
- @offset = -1
62
- end
63
-
64
- def __bound_param(name)
65
- if !@bound[name].nil?
66
- res, param = SA.instance.api.sqlany_get_bind_param_info(@handle, @bound[name])
67
- raise error() if res == 0
68
- return param.get_output()
69
- end
70
- end
71
-
72
- # Although SQL Anywhere allows multiple result sets,
73
- # the @fetchable variable disallows there use
74
- #
75
- #def __next_resultset
76
- # return SA.instance.api.sqlany_get_next_result(@handle)
77
- #end
78
-
79
- def bind_param(param, value, attribs)
80
- param -= 1
81
- res, param_description = SA.instance.api.sqlany_describe_bind_param(@handle, param)
82
- raise error() if res == 0 or param_description.nil?
83
- do_bind!(@handle, param_description, value, param, @bound)
84
- param_description.finish
85
- end
86
-
87
- def execute()
88
- res = SA.instance.api.sqlany_execute(@handle)
89
- raise error() if res == 0
90
- end
91
-
92
- def fetch()
93
- return fetch_scroll(DBI::SQL_FETCH_NEXT, 1)
94
- end
95
-
96
- def fetch_all()
97
- rows = []
98
- loop {
99
- new_row = self.fetch_scroll(DBI::SQL_FETCH_NEXT, 1)
100
- break if new_row.nil?
101
- rows << new_row.clone
102
- }
103
- return rows
104
- end
105
-
106
- def fetch_scroll(direction, offset)
107
- res = 0
108
- new_offset = @offset
109
-
110
- case direction
111
- when DBI::SQL_FETCH_NEXT
112
- res = SA.instance.api.sqlany_fetch_next(@handle)
113
- new_offset += 1
114
- when DBI::SQL_FETCH_PRIOR
115
- res = SA.instance.api.sqlany_fetch_absolute(@handle, @offset)
116
- new_offset -= 1
117
- when DBI::SQL_FETCH_FIRST
118
- res = SA.instance.api.sqlany_fetch_absolute(@handle, 1)
119
- new_offset = 0
120
- when DBI::SQL_FETCH_LAST
121
- res = SA.instance.api.sqlany_fetch_absolute(@handle, -1)
122
- new_offset = self.rows() - 1
123
- when DBI::SQL_FETCH_ABSOLUTE
124
- res = SA.instance.api.sqlany_fetch_absolute(@handle, offset)
125
- if offset <= 0
126
- new_offset = self.rows() + offset
127
- else
128
- new_offset = offset - 1
129
- end
130
- when DBI::SQL_FETCH_RELATIVE
131
- res = SA.instance.api.sqlany_fetch_absolute(@handle, @offset + offset + 1)
132
- new_offset += offset
133
- end
134
-
135
- if (res == 1)
136
- retrieve_row_data()
137
- @offset = new_offset
138
- return @arr
139
- else
140
- return nil
141
- end
142
- end
143
-
144
- def column_info
145
- columns = []
146
- if !@handle.nil?
147
- max_cols = SA.instance.api.sqlany_num_cols(@handle)
148
- raise error() if max_cols == -1
149
- max_cols.times do |cols|
150
- columns << {}
151
- res, holder, col_name, type, native_type, precision, scale, max_size, nullable = SA.instance.api.sqlany_get_column_info(@handle, cols)
152
- raise error() if res == 0 or col_name.nil?
153
- columns[cols]["name"] = col_name
154
- sql_type = SQLANY_NATIVE_TYPES[native_type]
155
- columns[cols]["sql_type"] = sql_type
156
- columns[cols]["type_name"] = DBI::SQL_TYPE_NAMES[sql_type]
157
- precision = max_size if precision == 0 and max_size != 0
158
- columns[cols]["precision"] = precision
159
- columns[cols]["scale"] = scale
160
- columns[cols]["nullable"] = (nullable == 0)
161
-
162
- columns[cols]["dbi_type"] = DBI::Type::Boolean if sql_type == DBI::SQL_BIT
163
- end
164
- end
165
- return columns
166
- end
167
-
168
- def rows
169
- if @handle.nil?
170
- res = SA.instance.api.sqlany_affected_rows(@handle)
171
- raise error() if res == -1
172
- return res
173
- else
174
- 0
175
- end
176
- end
177
-
178
- def finish
179
- if !@handle.nil?
180
- SA.instance.api.sqlany_free_stmt(@handle);
181
- @handle = nil
182
- end
183
- end
184
-
185
- def cancel
186
- end
187
-
188
- protected
189
- def error(*custom_msg)
190
- code, msg = SA.instance.api.sqlany_error(@conn)
191
- state = SA.instance.api.sqlany_sqlstate(@conn)
192
- SA.instance.api.sqlany_clear_error(@conn)
193
- if !custom_msg.nil?
194
- msg = "#{custom_msg}. #{msg}"
195
- end
196
- return DBI::DatabaseError.new(code, msg, state)
197
- end
198
-
199
- def retrieve_row_data
200
- max_cols = SA.instance.api.sqlany_num_cols(@handle)
201
- raise error() if max_cols == -1
202
- max_cols.times do |cols|
203
- res, col_val = SA.instance.api.sqlany_get_column(@handle, cols)
204
- raise error() if res == 0
205
- @arr[cols] = col_val
206
- end
207
- end
208
- end
209
- end
1
+ #====================================================
2
+ #
3
+ # Copyright 2008-2009 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
+ module DBI::DBD::SQLAnywhere
26
+ class Statement < DBI::BaseStatement
27
+ include Utility
28
+
29
+
30
+ # Conversion table between SQL Anywhere E-SQL types and DBI SQL Types
31
+ SQLANY_NATIVE_TYPES = {
32
+ 0 => DBI::SQL_LONGVARCHAR,
33
+ 384 => DBI::SQL_DATE,
34
+ 388 => DBI::SQL_TIME,
35
+ 392 => DBI::SQL_TIMESTAMP,
36
+ 448 => DBI::SQL_VARCHAR,
37
+ 452 => DBI::SQL_CHAR,
38
+ 456 => DBI::SQL_LONGVARCHAR,
39
+ 460 => DBI::SQL_LONGVARCHAR,
40
+ 480 => DBI::SQL_DOUBLE,
41
+ 482 => DBI::SQL_FLOAT,
42
+ 484 => DBI::SQL_DECIMAL,
43
+ 496 => DBI::SQL_INTEGER,
44
+ 500 => DBI::SQL_SMALLINT,
45
+ 524 => DBI::SQL_BINARY,
46
+ 528 => DBI::SQL_LONGVARBINARY,
47
+ 604 => DBI::SQL_TINYINT,
48
+ 608 => DBI::SQL_BIGINT,
49
+ 612 => DBI::SQL_INTEGER,
50
+ 616 => DBI::SQL_SMALLINT,
51
+ 620 => DBI::SQL_BIGINT,
52
+ 624 => DBI::SQL_BIT,
53
+ 640 => DBI::SQL_LONGVARCHAR
54
+ }
55
+
56
+ def initialize(handle, conn, bound = {} )
57
+ @handle = handle
58
+ @conn = conn
59
+ @arr = []
60
+ @bound = bound
61
+ @offset = -1
62
+ end
63
+
64
+ def __bound_param(name)
65
+ if !@bound[name].nil?
66
+ res, param = SA.instance.api.sqlany_get_bind_param_info(@handle, @bound[name])
67
+ raise error() if res == 0
68
+ return param.get_output()
69
+ end
70
+ end
71
+
72
+ # Although SQL Anywhere allows multiple result sets,
73
+ # the @fetchable variable disallows there use
74
+ #
75
+ #def __next_resultset
76
+ # return SA.instance.api.sqlany_get_next_result(@handle)
77
+ #end
78
+
79
+ def bind_param(param, value, attribs)
80
+ param -= 1
81
+ res, param_description = SA.instance.api.sqlany_describe_bind_param(@handle, param)
82
+ raise error() if res == 0 or param_description.nil?
83
+ do_bind!(@handle, param_description, value, param, @bound)
84
+ param_description.finish
85
+ end
86
+
87
+ def execute()
88
+ res = SA.instance.api.sqlany_execute(@handle)
89
+ raise error() if res == 0
90
+ end
91
+
92
+ def fetch()
93
+ return fetch_scroll(DBI::SQL_FETCH_NEXT, 1)
94
+ end
95
+
96
+ def fetch_all()
97
+ rows = []
98
+ loop {
99
+ new_row = self.fetch_scroll(DBI::SQL_FETCH_NEXT, 1)
100
+ break if new_row.nil?
101
+ rows << new_row.clone
102
+ }
103
+ return rows
104
+ end
105
+
106
+ def fetch_scroll(direction, offset)
107
+ res = 0
108
+ new_offset = @offset
109
+
110
+ case direction
111
+ when DBI::SQL_FETCH_NEXT
112
+ res = SA.instance.api.sqlany_fetch_next(@handle)
113
+ new_offset += 1
114
+ when DBI::SQL_FETCH_PRIOR
115
+ res = SA.instance.api.sqlany_fetch_absolute(@handle, @offset)
116
+ new_offset -= 1
117
+ when DBI::SQL_FETCH_FIRST
118
+ res = SA.instance.api.sqlany_fetch_absolute(@handle, 1)
119
+ new_offset = 0
120
+ when DBI::SQL_FETCH_LAST
121
+ res = SA.instance.api.sqlany_fetch_absolute(@handle, -1)
122
+ new_offset = self.rows() - 1
123
+ when DBI::SQL_FETCH_ABSOLUTE
124
+ res = SA.instance.api.sqlany_fetch_absolute(@handle, offset)
125
+ if offset <= 0
126
+ new_offset = self.rows() + offset
127
+ else
128
+ new_offset = offset - 1
129
+ end
130
+ when DBI::SQL_FETCH_RELATIVE
131
+ res = SA.instance.api.sqlany_fetch_absolute(@handle, @offset + offset + 1)
132
+ new_offset += offset
133
+ end
134
+
135
+ if (res == 1)
136
+ retrieve_row_data()
137
+ @offset = new_offset
138
+ return @arr
139
+ else
140
+ return nil
141
+ end
142
+ end
143
+
144
+ def column_info
145
+ columns = []
146
+ if !@handle.nil?
147
+ max_cols = SA.instance.api.sqlany_num_cols(@handle)
148
+ raise error() if max_cols == -1
149
+ max_cols.times do |cols|
150
+ columns << {}
151
+ res, holder, col_name, type, native_type, precision, scale, max_size, nullable = SA.instance.api.sqlany_get_column_info(@handle, cols)
152
+ raise error() if res == 0 or col_name.nil?
153
+ columns[cols]["name"] = col_name
154
+ sql_type = SQLANY_NATIVE_TYPES[native_type]
155
+ columns[cols]["sql_type"] = sql_type
156
+ columns[cols]["type_name"] = DBI::SQL_TYPE_NAMES[sql_type]
157
+ precision = max_size if precision == 0 and max_size != 0
158
+ columns[cols]["precision"] = precision
159
+ columns[cols]["scale"] = scale
160
+ columns[cols]["nullable"] = (nullable == 0)
161
+
162
+ columns[cols]["dbi_type"] = DBI::Type::Boolean if sql_type == DBI::SQL_BIT
163
+ end
164
+ end
165
+ return columns
166
+ end
167
+
168
+ def rows
169
+ if @handle.nil?
170
+ res = SA.instance.api.sqlany_affected_rows(@handle)
171
+ raise error() if res == -1
172
+ return res
173
+ else
174
+ 0
175
+ end
176
+ end
177
+
178
+ def finish
179
+ if !@handle.nil?
180
+ SA.instance.api.sqlany_free_stmt(@handle);
181
+ @handle = nil
182
+ end
183
+ end
184
+
185
+ def cancel
186
+ end
187
+
188
+ protected
189
+ def error(*custom_msg)
190
+ code, msg = SA.instance.api.sqlany_error(@conn)
191
+ state = SA.instance.api.sqlany_sqlstate(@conn)
192
+ SA.instance.api.sqlany_clear_error(@conn)
193
+ if !custom_msg.nil?
194
+ if custom_msg.length != 0
195
+ msg = "#{custom_msg}. #{msg}"
196
+ end
197
+ end
198
+ return DBI::DatabaseError.new(msg, code, state)
199
+ end
200
+
201
+ def retrieve_row_data
202
+ max_cols = SA.instance.api.sqlany_num_cols(@handle)
203
+ raise error() if max_cols == -1
204
+ max_cols.times do |cols|
205
+ res, col_val = SA.instance.api.sqlany_get_column(@handle, cols)
206
+ raise error() if res == 0
207
+ @arr[cols] = col_val
208
+ end
209
+ end
210
+ end
211
+ end