sqlanywhere-ffi 1.0.0
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/CHANGELOG +34 -0
- data/Gemfile +3 -0
- data/LICENSE +23 -0
- data/README.md +102 -0
- data/lib/api.rb +8 -0
- data/lib/bind_param.rb +92 -0
- data/lib/bind_param_info.rb +12 -0
- data/lib/bool.rb +13 -0
- data/lib/column_info.rb +18 -0
- data/lib/data_info.rb +12 -0
- data/lib/data_value.rb +60 -0
- data/lib/sql_anywhere_interface.rb +113 -0
- data/lib/sqlanywhere.rb +126 -0
- data/sqlanywhere-ffi.gemspec +15 -0
- data/test/sqlanywhere_test.rb +430 -0
- data/test/test.sql +92 -0
- data/test/test_iq.sql +92 -0
- metadata +106 -0
data/CHANGELOG
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
=CHANGE LOG
|
|
2
|
+
|
|
3
|
+
=====0.1.5 -- 2010/01/25
|
|
4
|
+
- Updated library to use DBCAPI 2.0
|
|
5
|
+
- Changed test suite to correctly test BIT and TINYINT types
|
|
6
|
+
- Added support for Ruby 1.9.1
|
|
7
|
+
|
|
8
|
+
=====0.1.4 -- 2009/03/25
|
|
9
|
+
- Changed Rakefile to automatically create lib directory
|
|
10
|
+
- Fixed bug that tried to build native extensions on binary distsributions
|
|
11
|
+
|
|
12
|
+
=====0.1.3 -- 2008/12/31
|
|
13
|
+
- Removed 'hint file' in lib directory
|
|
14
|
+
- Added extensions to gemspec to force a local compile
|
|
15
|
+
|
|
16
|
+
=====0.1.2 -- 2008/12/18
|
|
17
|
+
- Fixed bug when trying to read input value from OUTPUT parameter
|
|
18
|
+
- Added error checking to C2RB
|
|
19
|
+
- Fixed Rake to handle .bundle on OSX
|
|
20
|
+
|
|
21
|
+
=====0.1.1 -- 2008/11/06
|
|
22
|
+
- Created a source gem rake task
|
|
23
|
+
- Created a 'hint' file if the source gem is used directly
|
|
24
|
+
- Changed file permissions on archives
|
|
25
|
+
- Changed archives to be specific to platform (.zip on windows, .tar.gz
|
|
26
|
+
otherwise)
|
|
27
|
+
- Changed default rake task to only build library, not gem
|
|
28
|
+
- Added a gem rake task
|
|
29
|
+
|
|
30
|
+
=====0.1.0 -- 2008/10/15
|
|
31
|
+
- Initial Release
|
|
32
|
+
- Wraps DBCAPI functionality
|
|
33
|
+
- Includes a simple unit test suite
|
|
34
|
+
|
data/Gemfile
ADDED
data/LICENSE
ADDED
|
@@ -0,0 +1,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.md
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
SQL Anywhere Ruby Driver
|
|
2
|
+
------------------------
|
|
3
|
+
This is a native SQL Anywhere driver for Ruby. This library wraps the
|
|
4
|
+
functionality provided by the SQL Anywhere DBCAPI library. This driver
|
|
5
|
+
is intended to be a base-level library to be used by interface libraries
|
|
6
|
+
such as Ruby-DBI and ActiveRecord.
|
|
7
|
+
|
|
8
|
+
This driver can be used with SQL Anywhere 10 and later versions.
|
|
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/sqlanywhere.git
|
|
15
|
+
|
|
16
|
+
==Running Unit Tests==
|
|
17
|
+
|
|
18
|
+
1. Change to the the <tt>test</tt> directory
|
|
19
|
+
|
|
20
|
+
cd test
|
|
21
|
+
|
|
22
|
+
2. Create a testing database:
|
|
23
|
+
|
|
24
|
+
dbinit test
|
|
25
|
+
|
|
26
|
+
3. Start the testing database:
|
|
27
|
+
|
|
28
|
+
dbeng12 test.db
|
|
29
|
+
|
|
30
|
+
4. Create the test schema:
|
|
31
|
+
|
|
32
|
+
dbisql -c "eng=test;uid=dba;pwd=sql" test.sql
|
|
33
|
+
|
|
34
|
+
5. Run the unit tests:
|
|
35
|
+
|
|
36
|
+
ruby sqlanywhere_test.rb
|
|
37
|
+
|
|
38
|
+
<b>If the tests fail to run, make sure you have set up the SQL Anywhere environment variables correctly.</b> For more information,
|
|
39
|
+
review the online documentation here [http://dcx.sybase.com/index.html#1200/en/dbadmin/da-envvar.html].
|
|
40
|
+
|
|
41
|
+
Sample
|
|
42
|
+
------
|
|
43
|
+
|
|
44
|
+
This script makes a connection, prints <tt>Successful Ruby Connection</tt> to the SQL
|
|
45
|
+
Anywhere console, then disconnects.
|
|
46
|
+
|
|
47
|
+
# load the SQLAnywhere gem
|
|
48
|
+
|
|
49
|
+
begin
|
|
50
|
+
|
|
51
|
+
require 'rubygems'
|
|
52
|
+
|
|
53
|
+
gem 'sqlanywhere'
|
|
54
|
+
|
|
55
|
+
unless defined? SQLAnywhere
|
|
56
|
+
|
|
57
|
+
require 'sqlanywhere'
|
|
58
|
+
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# create an interface
|
|
64
|
+
|
|
65
|
+
api = SQLAnywhere::SQLAnywhereInterface.new()
|
|
66
|
+
|
|
67
|
+
# initialize the interface (loads the DLL/SO)
|
|
68
|
+
|
|
69
|
+
SQLAnywhere::API.sqlany_initialize_interface( api )
|
|
70
|
+
|
|
71
|
+
# initialize our api object
|
|
72
|
+
|
|
73
|
+
api.sqlany_init()
|
|
74
|
+
|
|
75
|
+
# create a connection
|
|
76
|
+
|
|
77
|
+
conn = api.sqlany_new_connection()
|
|
78
|
+
|
|
79
|
+
# establish a connection
|
|
80
|
+
|
|
81
|
+
api.sqlany_connect(conn, "uid=dba;pwd=sql")
|
|
82
|
+
|
|
83
|
+
# execute a query without a result set
|
|
84
|
+
|
|
85
|
+
api.sqlany_execute_immediate(conn, "MESSAGE 'Successful Ruby Connection'")
|
|
86
|
+
|
|
87
|
+
# disconnect from the database
|
|
88
|
+
|
|
89
|
+
api.sqlany_disconnect(conn)
|
|
90
|
+
|
|
91
|
+
# free the connection resources
|
|
92
|
+
|
|
93
|
+
api.sqlany_free_connection(conn)
|
|
94
|
+
|
|
95
|
+
# free resources the api object uses
|
|
96
|
+
|
|
97
|
+
api.sqlany_fini()
|
|
98
|
+
|
|
99
|
+
# close the interface
|
|
100
|
+
|
|
101
|
+
SQLAnywhere::API.sqlany_finalize_interface( api )
|
|
102
|
+
|
data/lib/api.rb
ADDED
data/lib/bind_param.rb
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
require 'ffi'
|
|
2
|
+
|
|
3
|
+
class SQLAnywhere::BindParam < FFI::Struct
|
|
4
|
+
|
|
5
|
+
layout(
|
|
6
|
+
:direction, SQLAnywhere::DataDirection,
|
|
7
|
+
:value, SQLAnywhere::DataValue,
|
|
8
|
+
:name, :string,
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
def get_name
|
|
12
|
+
self[:name]
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def get_direction
|
|
16
|
+
self[:direction]
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def set_direction d
|
|
20
|
+
self[:direction] = d
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def inspect
|
|
24
|
+
"<#{self.class} direction: #{self[:direction]}, name: #{self[:name]}, value: #{self[:value].inspect}>"
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def set_value(value)
|
|
28
|
+
|
|
29
|
+
self[:value][:is_null] = FFI::MemoryPointer.new(SQLAnywhere::Bool, 1, true)
|
|
30
|
+
|
|
31
|
+
if self[:direction] == :input
|
|
32
|
+
|
|
33
|
+
case value
|
|
34
|
+
when String
|
|
35
|
+
self[:value][:length] = FFI::MemoryPointer.new(SQLAnywhere::SIZE_T, 1, false)
|
|
36
|
+
length = value.bytesize
|
|
37
|
+
SQLAnywhere.write_size_t(self[:value][:length], length)
|
|
38
|
+
self[:value][:buffer] = FFI::MemoryPointer.new(:char, length + 1, false)
|
|
39
|
+
|
|
40
|
+
self[:value][:buffer].put_string(0, value)
|
|
41
|
+
self[:value][:type] = :string
|
|
42
|
+
when Fixnum
|
|
43
|
+
self[:value][:buffer] = FFI::MemoryPointer.new(:long, 1, false)
|
|
44
|
+
self[:value][:type] = :val64
|
|
45
|
+
byte_array = [value].pack('q')
|
|
46
|
+
byte_array.each_byte.each_with_index do |b, offset|
|
|
47
|
+
self[:value][:buffer].put_char(offset, b)
|
|
48
|
+
end
|
|
49
|
+
when Bignum
|
|
50
|
+
self[:value][:buffer] = FFI::MemoryPointer.new(:long_long, 1, false)
|
|
51
|
+
self[:value][:type] = :val64
|
|
52
|
+
byte_array = [value].pack('Q')
|
|
53
|
+
byte_array.each_byte.each_with_index do |b, offset|
|
|
54
|
+
self[:value][:buffer].put_char(offset, b)
|
|
55
|
+
end
|
|
56
|
+
when Float
|
|
57
|
+
self[:value][:buffer] = FFI::MemoryPointer.new(:double, 1, false)
|
|
58
|
+
self[:value][:buffer].write_double(value)
|
|
59
|
+
self[:value][:type] = :double
|
|
60
|
+
when nil
|
|
61
|
+
self[:value][:is_null].write_int(1)
|
|
62
|
+
self[:value][:buffer] = FFI::MemoryPointer.new(:int, 1, false)
|
|
63
|
+
self[:value][:type] = :val32
|
|
64
|
+
else
|
|
65
|
+
raise "Cannot convert type (#{value.class}). Must be STRING, FIXNUM, BIGNUM, FLOAT, or NIL"
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
else
|
|
69
|
+
self[:value][:buffer] = FFI::MemoryPointer.new(:char,
|
|
70
|
+
case self[:value][:type]
|
|
71
|
+
when :string
|
|
72
|
+
self[:value][:buffer_size]
|
|
73
|
+
when :double
|
|
74
|
+
FFI::Type::FLOAT.size # Is this right? it's what the old code does
|
|
75
|
+
when :val64, :uval64
|
|
76
|
+
FFI::Type::LONG_LONG.size
|
|
77
|
+
when :val32, :uval32
|
|
78
|
+
FFI::Type::INT.size
|
|
79
|
+
when :val16, :uval16
|
|
80
|
+
FFI::Type::SHORT.size
|
|
81
|
+
when :val8, :uval8
|
|
82
|
+
FFI::Type::CHAR.size
|
|
83
|
+
else
|
|
84
|
+
raise "Type unknown (#{self[:value][:type]})"
|
|
85
|
+
end
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
end
|
|
89
|
+
nil
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
require 'ffi'
|
|
2
|
+
|
|
3
|
+
# http://dcx.sybase.com/1200/en/dbprogramming/programming-sacpp-a-sqlany-bind-param-info-str.html
|
|
4
|
+
class SQLAnywhere::BindParamInfo < FFI::Struct
|
|
5
|
+
|
|
6
|
+
layout(
|
|
7
|
+
:name, :string,
|
|
8
|
+
:direction, SQLAnywhere::DataDirection,
|
|
9
|
+
:input_value, SQLAnywhere::DataValue,
|
|
10
|
+
:output_value, SQLAnywhere::DataValue,
|
|
11
|
+
)
|
|
12
|
+
end
|
data/lib/bool.rb
ADDED
data/lib/column_info.rb
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
require 'ffi'
|
|
2
|
+
|
|
3
|
+
# http://dcx.sybase.com/1200/en/dbprogramming/programming-sacpp-a-sqlany-column-info-str.html
|
|
4
|
+
class SQLAnywhere::ColumnInfo < FFI::Struct
|
|
5
|
+
|
|
6
|
+
layout(
|
|
7
|
+
# The name of the column (null-terminated).
|
|
8
|
+
# The string can be referenced as long as the result set object is not freed.
|
|
9
|
+
:name, :string,
|
|
10
|
+
:type, SQLAnywhere::DataType,
|
|
11
|
+
:native_type, SQLAnywhere::NativeType,
|
|
12
|
+
:precision, :ushort,
|
|
13
|
+
:scale, :ushort,
|
|
14
|
+
:max_size, SQLAnywhere::SIZE_T,
|
|
15
|
+
:nullable, SQLAnywhere::Bool,
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
end
|
data/lib/data_info.rb
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
require 'ffi'
|
|
2
|
+
|
|
3
|
+
# http://dcx.sybase.com/1200/en/dbprogramming/programming-sacpp-a-sqlany-data-info-str.html
|
|
4
|
+
class SQLAnywhere::DataInfo < FFI::Struct
|
|
5
|
+
|
|
6
|
+
layout(
|
|
7
|
+
:type, SQLAnywhere::DataType,
|
|
8
|
+
:is_null, SQLAnywhere::Bool,
|
|
9
|
+
:data_size, SQLAnywhere::SIZE_T,
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
end
|
data/lib/data_value.rb
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
require 'ffi'
|
|
2
|
+
|
|
3
|
+
#
|
|
4
|
+
class SQLAnywhere::DataValue < FFI::Struct
|
|
5
|
+
|
|
6
|
+
layout(
|
|
7
|
+
:buffer, :pointer, # deliberately not a string
|
|
8
|
+
:buffer_size, SQLAnywhere::SIZE_T,
|
|
9
|
+
:length, :pointer,
|
|
10
|
+
:type, SQLAnywhere::DataType,
|
|
11
|
+
:is_null, :pointer,
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
def inspect
|
|
15
|
+
"<#{self.class} value: #{self.value}, buffer_size: #{self[:buffer_size]}, is_null: #{self.is_null?}, length: #{self.length}, type: #{self[:type]}, buffer: #{self[:buffer]}, length_pointer: #{self[:length]}>"
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def is_null?
|
|
20
|
+
return nil if self[:is_null].null?
|
|
21
|
+
self[:is_null].read_uint == 1
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def length
|
|
25
|
+
return nil if self[:length].null?
|
|
26
|
+
self[:length].read_uint
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def value
|
|
30
|
+
return nil if is_null?
|
|
31
|
+
|
|
32
|
+
case self[:type]
|
|
33
|
+
#when :invalid_type
|
|
34
|
+
when :binary, :string
|
|
35
|
+
self[:buffer].get_string(0, length)
|
|
36
|
+
when :double
|
|
37
|
+
self[:buffer].read_double
|
|
38
|
+
when :val64 # 64 bit integer
|
|
39
|
+
self[:buffer].read_long_long
|
|
40
|
+
when :unsigned_val64 # 64 bit unsigned integer
|
|
41
|
+
self[:buffer].read_ulong_long
|
|
42
|
+
when :val32
|
|
43
|
+
self[:buffer].read_int
|
|
44
|
+
when :unsigned_val32
|
|
45
|
+
self[:buffer].read_uint
|
|
46
|
+
when :val16
|
|
47
|
+
self[:buffer].read_short
|
|
48
|
+
when :unsigned_val16
|
|
49
|
+
self[:buffer].read_ushort
|
|
50
|
+
when :val8
|
|
51
|
+
self[:buffer].read_char
|
|
52
|
+
when :unsigned_val8
|
|
53
|
+
self[:buffer].read_uchar
|
|
54
|
+
else
|
|
55
|
+
raise "Type not yet implemented #{self[:type]}"
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
end
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
require 'ffi'
|
|
2
|
+
|
|
3
|
+
class SQLAnywhere::SQLAnywhereInterface
|
|
4
|
+
|
|
5
|
+
extend FFI::Library
|
|
6
|
+
ffi_lib 'dbcapi'
|
|
7
|
+
|
|
8
|
+
def sqlany_init(app_name = "RUBY", api_version = SQLAnywhere::API_VERSION_2, version_available = FFI::MemoryPointer.new(:int, 1, false))
|
|
9
|
+
sqlany_init_ app_name, api_version, version_available
|
|
10
|
+
end
|
|
11
|
+
# http://dcx.sybase.com/1200/en/dbprogramming/programming-sacpp-sacapi-h-fil-sqlany-init-met.html
|
|
12
|
+
attach_function :sqlany_init_, :sqlany_init, [:string, :uint, :pointer], :int
|
|
13
|
+
|
|
14
|
+
# http://dcx.sybase.com/1200/en/dbprogramming/programming-sacpp-sacapi-h-fil-sqlany-new-connection-met.html
|
|
15
|
+
attach_function :sqlany_new_connection, [], :pointer
|
|
16
|
+
|
|
17
|
+
# http://dcx.sybase.com/1200/en/dbprogramming/programming-sacpp-sacapi-h-fil-sqlany-connect-met.html
|
|
18
|
+
attach_function :sqlany_connect, [:pointer, :string], :int
|
|
19
|
+
|
|
20
|
+
def sqlany_error(connection)
|
|
21
|
+
size = 255
|
|
22
|
+
buffer = FFI::MemoryPointer.new(:char, size, false)
|
|
23
|
+
code = sqlany_error_ connection, buffer, size
|
|
24
|
+
return code, buffer.read_string
|
|
25
|
+
end
|
|
26
|
+
# http://dcx.sybase.com/1200/en/dbprogramming/programming-sacpp-sacapi-h-fil-sqlany-error-met.html
|
|
27
|
+
attach_function :sqlany_error_, :sqlany_error, [:pointer, :pointer, SQLAnywhere::SIZE_T], :int
|
|
28
|
+
|
|
29
|
+
# http://dcx.sybase.com/1200/en/dbprogramming/programming-sacpp-sacapi-h-fil-sqlany-execute-direct-met.html
|
|
30
|
+
attach_function :sqlany_execute_direct, [:pointer, :string], :pointer
|
|
31
|
+
|
|
32
|
+
# http://dcx.sybase.com/1200/en/dbprogramming/programming-sacpp-sacapi-h-fil-sqlany-fetch-next-met.html
|
|
33
|
+
attach_function :sqlany_fetch_next, [:pointer], :int
|
|
34
|
+
|
|
35
|
+
def sqlany_get_column(statement, column_number)
|
|
36
|
+
buffer = SQLAnywhere::DataValue.new
|
|
37
|
+
result = sqlany_get_column_(statement, column_number, buffer)
|
|
38
|
+
return [0, nil] if result == 0
|
|
39
|
+
[result, buffer.value]
|
|
40
|
+
end
|
|
41
|
+
# http://dcx.sybase.com/1200/en/dbprogramming/programming-sacpp-sacapi-h-fil-sqlany-get-column-met.html
|
|
42
|
+
attach_function :sqlany_get_column_, :sqlany_get_column, [:pointer, :uint32, :pointer], :int
|
|
43
|
+
|
|
44
|
+
# http://dcx.sybase.com/1200/en/dbprogramming/programming-sacpp-sacapi-h-fil-sqlany-free-stmt-met.html
|
|
45
|
+
attach_function :sqlany_free_stmt, [:pointer], :void
|
|
46
|
+
|
|
47
|
+
# http://dcx.sybase.com/1200/en/dbprogramming/programming-sacpp-sacapi-h-fil-sqlany-execute-immediate-met.html
|
|
48
|
+
attach_function :sqlany_execute_immediate, [:pointer, :string], :int
|
|
49
|
+
|
|
50
|
+
def sqlany_disconnect(connection)
|
|
51
|
+
sqlany_disconnect_(connection)
|
|
52
|
+
return nil
|
|
53
|
+
end
|
|
54
|
+
# http://dcx.sybase.com/1200/en/dbprogramming/programming-sacpp-sacapi-h-fil-sqlany-disconnect-met.html
|
|
55
|
+
attach_function :sqlany_disconnect_, :sqlany_disconnect, [:pointer], :int
|
|
56
|
+
|
|
57
|
+
# http://dcx.sybase.com/1200/en/dbprogramming/programming-sacpp-sacapi-h-fil-sqlany-free-connection-met.html
|
|
58
|
+
attach_function :sqlany_free_connection, [:pointer], :void
|
|
59
|
+
|
|
60
|
+
# http://dcx.sybase.com/1200/en/dbprogramming/programming-sacpp-sacapi-h-fil-sqlany-fini-met.html
|
|
61
|
+
attach_function :sqlany_fini, [], :void
|
|
62
|
+
|
|
63
|
+
# http://dcx.sybase.com/1200/en/dbprogramming/programming-sacpp-sacapi-h-fil-sqlany-prepare-met.html
|
|
64
|
+
attach_function :sqlany_prepare, [:pointer, :string], :pointer
|
|
65
|
+
|
|
66
|
+
# http://dcx.sybase.com/1200/en/dbprogramming/programming-sacpp-sacapi-h-fil-sqlany-num-cols-met.html
|
|
67
|
+
attach_function :sqlany_num_cols, [:pointer], :int
|
|
68
|
+
|
|
69
|
+
# http://dcx.sybase.com/1200/en/dbprogramming/programming-sacpp-sacapi-h-fil-sqlany-commit-met.html
|
|
70
|
+
attach_function :sqlany_commit, [:pointer], :int
|
|
71
|
+
|
|
72
|
+
# http://dcx.sybase.com/1200/en/dbprogramming/programming-sacpp-sacapi-h-fil-sqlany-execute-met.html
|
|
73
|
+
attach_function :sqlany_execute, [:pointer], :int
|
|
74
|
+
|
|
75
|
+
# http://dcx.sybase.com/1200/en/dbprogramming/programming-sacpp-sacapi-h-fil-sqlany-rollback-met.html
|
|
76
|
+
attach_function :sqlany_rollback, [:pointer], :int
|
|
77
|
+
|
|
78
|
+
def sqlany_describe_bind_param(statement, index)
|
|
79
|
+
bind_parameter = SQLAnywhere::BindParam.new
|
|
80
|
+
result = sqlany_describe_bind_param_(statement, index, bind_parameter)
|
|
81
|
+
[result, bind_parameter]
|
|
82
|
+
end
|
|
83
|
+
# http://dcx.sybase.com/1200/en/dbprogramming/programming-sacpp-sacapi-h-fil-sqlany-describe-bind-param-met.html
|
|
84
|
+
attach_function :sqlany_describe_bind_param_, :sqlany_describe_bind_param, [:pointer, :uint32, :pointer], :int
|
|
85
|
+
|
|
86
|
+
# http://dcx.sybase.com/1200/en/dbprogramming/programming-sacpp-sacapi-h-fil-sqlany-bind-param-met.html
|
|
87
|
+
attach_function :sqlany_bind_param, [:pointer, :uint, :pointer], :int
|
|
88
|
+
|
|
89
|
+
def sqlany_get_column_info(statement, column_number)
|
|
90
|
+
|
|
91
|
+
info = SQLAnywhere::ColumnInfo.new
|
|
92
|
+
|
|
93
|
+
result = sqlany_get_column_info_(statement, column_number, info)
|
|
94
|
+
[result, column_number, info[:name], info[:type], info[:native_type], info[:precision], info[:scale], info[:max_size], info[:nullable].read]
|
|
95
|
+
end
|
|
96
|
+
# http://dcx.sybase.com/1200/en/dbprogramming/programming-sacpp-sacapi-h-fil-sqlany-get-column-info-met.html
|
|
97
|
+
attach_function :sqlany_get_column_info_, :sqlany_get_column_info, [:pointer, :uint, :pointer], :int
|
|
98
|
+
|
|
99
|
+
def sqlany_sqlstate(connection)
|
|
100
|
+
size = 255
|
|
101
|
+
buffer = FFI::MemoryPointer.new(:char, size, false)
|
|
102
|
+
used = sqlany_sqlstate_(connection, buffer, size)
|
|
103
|
+
buffer.read_string(used)
|
|
104
|
+
end
|
|
105
|
+
# http://dcx.sybase.com/1200/en/dbprogramming/programming-sacpp-sacapi-h-fil-sqlany-sqlstate-met.html
|
|
106
|
+
attach_function :sqlany_sqlstate_, :sqlany_sqlstate, [:pointer, :pointer, SQLAnywhere::SIZE_T], SQLAnywhere::SIZE_T
|
|
107
|
+
|
|
108
|
+
# http://dcx.sybase.com/1200/en/dbprogramming/programming-sacpp-sacapi-h-fil-sqlany-clear-error-met.html
|
|
109
|
+
attach_function :sqlany_clear_error, [:pointer], :void
|
|
110
|
+
|
|
111
|
+
# http://dcx.sybase.com/1200/en/dbprogramming/programming-sacpp-sacapi-h-fil-sqlany-num-params-met.html
|
|
112
|
+
attach_function :sqlany_num_params, [:pointer], :int
|
|
113
|
+
end
|