dbd-sqlanywhere 0.1.1 → 0.1.2

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.
@@ -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