drizzle 0.1.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/LICENSE +20 -0
- data/README.rdoc +7 -0
- data/Rakefile +58 -0
- data/VERSION +1 -0
- data/lib/drizzle.rb +15 -0
- data/lib/drizzle/connection.rb +207 -0
- data/lib/drizzle/drizzle.rb +58 -0
- data/lib/drizzle/exceptions.rb +28 -0
- data/lib/drizzle/ffidrizzle.rb +130 -0
- data/lib/drizzle/result.rb +95 -0
- data/test/helper.rb +28 -0
- data/test/test_basic.rb +103 -0
- data/test/test_complex.rb +133 -0
- metadata +88 -0
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2010 Padraig O'Sullivan
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
require 'rake/testtask'
|
4
|
+
require 'rake/rdoctask'
|
5
|
+
|
6
|
+
begin
|
7
|
+
require 'jeweler'
|
8
|
+
Jeweler::Tasks.new do |gem|
|
9
|
+
gem.name = "drizzle"
|
10
|
+
gem.summary = "A ruby interface to Drizzle using libdrizzle"
|
11
|
+
gem.description = "An interface to Drizzle for Ruby that uses libdrizzle"
|
12
|
+
gem.email = "osullivan.padraig@gmail.com"
|
13
|
+
gem.homepage = "http://github.com/posulliv/drizzle-ruby"
|
14
|
+
gem.authors = ["Padraig O'Sullivan"]
|
15
|
+
gem.rubyforge_project = "drizzle-ruby"
|
16
|
+
gem.add_development_dependency "thoughtbot-shoulda", ">= 0"
|
17
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
18
|
+
end
|
19
|
+
Jeweler::GemcutterTasks.new
|
20
|
+
Jeweler::RubyforgeTasks.new do |rubyforge|
|
21
|
+
rubyforge.doc_task = "rdoc"
|
22
|
+
end
|
23
|
+
rescue LoadError
|
24
|
+
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
25
|
+
exit(1)
|
26
|
+
end
|
27
|
+
|
28
|
+
Rake::TestTask.new(:test) do |test|
|
29
|
+
test.libs << 'lib' << 'test'
|
30
|
+
test.pattern = 'test/**/test_*.rb'
|
31
|
+
test.verbose = true
|
32
|
+
end
|
33
|
+
|
34
|
+
begin
|
35
|
+
require 'rcov/rcovtask'
|
36
|
+
Rcov::RcovTask.new do |test|
|
37
|
+
test.libs << 'test'
|
38
|
+
test.pattern = 'test/**/test_*.rb'
|
39
|
+
test.verbose = true
|
40
|
+
end
|
41
|
+
rescue LoadError
|
42
|
+
task :rcov do
|
43
|
+
abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
task :test => :check_dependencies
|
48
|
+
|
49
|
+
task :default => :test
|
50
|
+
|
51
|
+
Rake::RDocTask.new do |rdoc|
|
52
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
53
|
+
|
54
|
+
rdoc.rdoc_dir = 'rdoc'
|
55
|
+
rdoc.title = "drizzle #{version}"
|
56
|
+
rdoc.rdoc_files.include('README*')
|
57
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
58
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.0
|
data/lib/drizzle.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
# rubygems
|
2
|
+
require 'rubygems'
|
3
|
+
|
4
|
+
# 3rd party
|
5
|
+
require 'ffi'
|
6
|
+
|
7
|
+
# internal requires
|
8
|
+
require 'drizzle/ffidrizzle'
|
9
|
+
require 'drizzle/drizzle'
|
10
|
+
require 'drizzle/result'
|
11
|
+
require 'drizzle/connection'
|
12
|
+
require 'drizzle/exceptions'
|
13
|
+
|
14
|
+
module Drizzle
|
15
|
+
end
|
@@ -0,0 +1,207 @@
|
|
1
|
+
require 'drizzle/ffidrizzle'
|
2
|
+
require 'drizzle/exceptions'
|
3
|
+
|
4
|
+
module Drizzle
|
5
|
+
|
6
|
+
class ConnectionPtr < FFI::AutoPointer
|
7
|
+
def self.release(ptr)
|
8
|
+
LibDrizzle.drizzle_con_free(ptr)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
#
|
13
|
+
# map of keywords that will be used with the SQL injection
|
14
|
+
# prevention plugin in drizzle
|
15
|
+
#
|
16
|
+
Keywords =
|
17
|
+
{
|
18
|
+
"add" => true,
|
19
|
+
"all" => true,
|
20
|
+
"alter" => true,
|
21
|
+
"analyze" => true,
|
22
|
+
"and" => true,
|
23
|
+
"any" => true,
|
24
|
+
"as" => true,
|
25
|
+
"asc" => true,
|
26
|
+
"before" => true,
|
27
|
+
"between" => true,
|
28
|
+
"by" => true,
|
29
|
+
"count" => true,
|
30
|
+
"distinct" => true,
|
31
|
+
"drop" => true,
|
32
|
+
"from" => true,
|
33
|
+
"having" => true,
|
34
|
+
"or" => true,
|
35
|
+
"select" => true,
|
36
|
+
"union" => true,
|
37
|
+
"where" => true
|
38
|
+
}
|
39
|
+
|
40
|
+
|
41
|
+
#
|
42
|
+
# connection options
|
43
|
+
#
|
44
|
+
NONE = 0
|
45
|
+
ALLOCATED = 1
|
46
|
+
MYSQL = 2
|
47
|
+
RAW_PACKET = 4
|
48
|
+
RAW_SCRAMBLE = 8
|
49
|
+
READY = 16
|
50
|
+
NO_RESULT_READ = 32
|
51
|
+
INJECTION_PREVENTION = 64
|
52
|
+
|
53
|
+
#
|
54
|
+
# A drizzle connection
|
55
|
+
#
|
56
|
+
class Connection
|
57
|
+
|
58
|
+
attr_accessor :host, :port, :db
|
59
|
+
|
60
|
+
#
|
61
|
+
# Creates a connection instance
|
62
|
+
#
|
63
|
+
# == parameters
|
64
|
+
#
|
65
|
+
# * host the hostname for the connection
|
66
|
+
# * port the port number for the connection
|
67
|
+
# * db the database name for the connection
|
68
|
+
# * opts connection options
|
69
|
+
# * drizzle_ptr FFI pointer to a drizzle_st object
|
70
|
+
#
|
71
|
+
# Some examples :
|
72
|
+
#
|
73
|
+
# c = Drizzle::Connection.new
|
74
|
+
# c = Drizzle::Connection.new("my_host", 4427)
|
75
|
+
# c = Drizzle::Connection.new("my_host", 4427, "my_db")
|
76
|
+
# c = Drizzle::Connection.new("my_host", 4427, "my_db", [Drizzle::NONE])
|
77
|
+
#
|
78
|
+
def initialize(host = "localhost", port = 4427, db = nil, opts = [], drizzle_ptr = nil)
|
79
|
+
@host = host
|
80
|
+
@port = port
|
81
|
+
@db = db
|
82
|
+
@drizzle_handle = drizzle_ptr || DrizzlePtr.new(LibDrizzle.drizzle_create(nil))
|
83
|
+
@con_ptr = ConnectionPtr.new(LibDrizzle.drizzle_con_create(@drizzle_handle, nil))
|
84
|
+
@rand_key = ""
|
85
|
+
|
86
|
+
opts.each do |opt|
|
87
|
+
if opt == INJECTION_PREVENTION
|
88
|
+
@randomize_queries = true
|
89
|
+
next
|
90
|
+
end
|
91
|
+
LibDrizzle.drizzle_con_add_options(@con_ptr, LibDrizzle::ConnectionOptions[opt])
|
92
|
+
end
|
93
|
+
LibDrizzle.drizzle_con_set_tcp(@con_ptr, @host, @port)
|
94
|
+
LibDrizzle.drizzle_con_set_db(@con_ptr, @db) if @db
|
95
|
+
@ret_ptr = FFI::MemoryPointer.new(:int)
|
96
|
+
|
97
|
+
#
|
98
|
+
# if SQL injection prevention is enabled, we need to retrieve
|
99
|
+
# the key to use for randomization from the server
|
100
|
+
#
|
101
|
+
if @randomize_queries == true
|
102
|
+
query = "show variables like '%stad_key%'"
|
103
|
+
res = LibDrizzle.drizzle_query_str(@con_ptr, nil, query, @ret_ptr)
|
104
|
+
check_return_code
|
105
|
+
result = Result.new(res)
|
106
|
+
result.buffer_result
|
107
|
+
result.each do |row|
|
108
|
+
@rand_key = row[1]
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
#
|
114
|
+
# set the host and port for the connection
|
115
|
+
#
|
116
|
+
def set_tcp(host, port)
|
117
|
+
@host = host
|
118
|
+
@port = port
|
119
|
+
LibDrizzle.drizzle_con_set_tcp(@con_ptr, @host, @port)
|
120
|
+
end
|
121
|
+
|
122
|
+
#
|
123
|
+
# set the database name for the connection
|
124
|
+
#
|
125
|
+
def set_db(db_name)
|
126
|
+
@db = db_name
|
127
|
+
LibDrizzle.drizzle_con_set_db(@con_ptr, @db)
|
128
|
+
end
|
129
|
+
|
130
|
+
#
|
131
|
+
# execute a query and construct a result object
|
132
|
+
#
|
133
|
+
def query(query)
|
134
|
+
res = LibDrizzle.drizzle_query_str(@con_ptr, nil, query, @ret_ptr)
|
135
|
+
check_return_code
|
136
|
+
Result.new(res)
|
137
|
+
end
|
138
|
+
|
139
|
+
#
|
140
|
+
# tokenize the input query and append the randomization key to
|
141
|
+
# keywords
|
142
|
+
#
|
143
|
+
def randomize_query(query)
|
144
|
+
if @rand_key.empty?
|
145
|
+
return query
|
146
|
+
end
|
147
|
+
toks = query.split(" ")
|
148
|
+
new_query = ""
|
149
|
+
toks.each do |token|
|
150
|
+
if Keywords[token.downcase] == true
|
151
|
+
token << @rand_key
|
152
|
+
end
|
153
|
+
new_query << token << " "
|
154
|
+
end
|
155
|
+
new_query
|
156
|
+
end
|
157
|
+
|
158
|
+
def check_return_code()
|
159
|
+
case LibDrizzle::ReturnCode[@ret_ptr.get_int(0)]
|
160
|
+
when :DRIZZLE_RETURN_IO_WAIT
|
161
|
+
raise IoWait.new(LibDrizzle.drizzle_error(@drizzle_handle))
|
162
|
+
when :DRIZZLE_RETURN_PAUSE
|
163
|
+
raise Pause.new(LibDrizzle.drizzle_error(@drizzle_handle))
|
164
|
+
when :DRIZZLE_RETURN_ROW_BREAK
|
165
|
+
raise RowBreak.new(LibDrizzle.drizzle_error(@drizzle_handle))
|
166
|
+
when :DRIZZLE_RETURN_MEMORY
|
167
|
+
raise Memory.new(LibDrizzle.drizzle_error(@drizzle_handle))
|
168
|
+
when :DRIZZLE_RETURN_INTERNAL_ERROR
|
169
|
+
raise InternalError.new(LibDrizzle.drizzle_error(@drizzle_handle))
|
170
|
+
when :DRIZZLE_RETURN_NOT_READY
|
171
|
+
raise NotReady.new(LibDrizzle.drizzle_error(@drizzle_handle))
|
172
|
+
when :DRIZZLE_RETURN_BAD_PACKET_NUMBER
|
173
|
+
raise BadPacketNumber.new(LibDrizzle.drizzle_error(@drizzle_handle))
|
174
|
+
when :DRIZZLE_RETURN_BAD_HANDSHAKE_PACKET
|
175
|
+
raise BadHandshake.new(LibDrizzle.drizzle_error(@drizzle_handle))
|
176
|
+
when :DRIZZLE_RETURN_BAD_PACKET
|
177
|
+
raise BadPacket.new(LibDrizzle.drizzle_error(@drizzle_handle))
|
178
|
+
when :DRIZZLE_RETURN_PROTOCOL_NOT_SUPPORTED
|
179
|
+
raise ProtocolNotSupported.new(LibDrizzle.drizzle_error(@drizzle_handle))
|
180
|
+
when :DRIZZLE_RETURN_UNEXPECTED_DATA
|
181
|
+
raise UnexpectedData.new(LibDrizzle.drizzle_error(@drizzle_handle))
|
182
|
+
when :DRIZZLE_RETURN_NO_SCRAMBLE
|
183
|
+
raise NoScramble.new(LibDrizzle.drizzle_error(@drizzle_handle))
|
184
|
+
when :DRIZZLE_RETURN_AUTH_FAILED
|
185
|
+
raise AuthFailed.new(LibDrizzle.drizzle_error(@drizzle_handle))
|
186
|
+
when :DRIZZLE_RETURN_NULL_SIZE
|
187
|
+
raise NullSize.new(LibDrizzle.drizzle_error(@drizzle_handle))
|
188
|
+
when :DRIZZLE_RETURN_TOO_MANY_COLUMNS
|
189
|
+
raise TooManyColumns.new(LibDrizzle.drizzle_error(@drizzle_handle))
|
190
|
+
when :DRIZZLE_RETURN_ROW_END
|
191
|
+
raise RowEnd.new(LibDrizzle.drizzle_error(@drizzle_handle))
|
192
|
+
when :DRIZZLE_RETURN_LOST_CONNECTION
|
193
|
+
raise LostConnection.new(LibDrizzle.drizzle_error(@drizzle_handle))
|
194
|
+
when :DRIZZLE_RETURN_COULD_NOT_CONNECT
|
195
|
+
raise CouldNotConnect.new(LibDrizzle.drizzle_error(@drizzle_handle))
|
196
|
+
when :DRIZZLE_RETURN_NO_ACTIVE_CONNECTIONS
|
197
|
+
raise NoActiveConnections.new(LibDrizzle.drizzle_error(@drizzle_handle))
|
198
|
+
when :DRIZZLE_RETURN_HANDSHAKE_FAILED
|
199
|
+
raise HandshakeFailed.new(LibDrizzle.drizzle_error(@drizzle_handle))
|
200
|
+
when :DRIZZLE_RETURN_TIMEOUT
|
201
|
+
raise ReturnTimeout.new(LibDrizzle.drizzle_error(@drizzle_handle))
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
end
|
206
|
+
|
207
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'drizzle/ffidrizzle'
|
2
|
+
|
3
|
+
module Drizzle
|
4
|
+
|
5
|
+
class DrizzlePtr < FFI::AutoPointer
|
6
|
+
def self.release(ptr)
|
7
|
+
LibDrizzle.drizzle_free(ptr)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
#
|
12
|
+
# A Drizzle instance
|
13
|
+
#
|
14
|
+
class Drizzle
|
15
|
+
|
16
|
+
#
|
17
|
+
# creates a drizzle instance
|
18
|
+
#
|
19
|
+
def initialize()
|
20
|
+
@handle = DrizzlePtr.new(LibDrizzle.drizzle_create(nil))
|
21
|
+
end
|
22
|
+
|
23
|
+
#
|
24
|
+
# create a client connection
|
25
|
+
#
|
26
|
+
def create_client_connection(host, port, db)
|
27
|
+
Connection.new(host, port, db, @handle)
|
28
|
+
end
|
29
|
+
|
30
|
+
#
|
31
|
+
# return the libdrizzle API version
|
32
|
+
#
|
33
|
+
def version()
|
34
|
+
LibDrizzle.drizzle_version
|
35
|
+
end
|
36
|
+
|
37
|
+
#
|
38
|
+
# return the bug report URL to file libdrizzle bugs at
|
39
|
+
#
|
40
|
+
def bug_report_url()
|
41
|
+
LibDrizzle.drizzle_bugreport
|
42
|
+
end
|
43
|
+
|
44
|
+
#
|
45
|
+
# add a query to be run concurrently
|
46
|
+
#
|
47
|
+
def add_query(conn, query, query_num, opts = [])
|
48
|
+
end
|
49
|
+
|
50
|
+
#
|
51
|
+
# execute all queries concurrently
|
52
|
+
#
|
53
|
+
def run_all()
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'drizzle/ffidrizzle'
|
2
|
+
|
3
|
+
module Drizzle
|
4
|
+
|
5
|
+
class IoWait < RuntimeError; end
|
6
|
+
class Pause < RuntimeError; end
|
7
|
+
class RowBreak < RuntimeError; end
|
8
|
+
class Memory < RuntimeError; end
|
9
|
+
class InternalError < RuntimeError; end
|
10
|
+
class NotReady < RuntimeError; end
|
11
|
+
class BadPacketNumber < RuntimeError; end
|
12
|
+
class BadHandshake < RuntimeError; end
|
13
|
+
class BadPacket < RuntimeError; end
|
14
|
+
class ProtocolNotSupported < RuntimeError; end
|
15
|
+
class UnexpectedData < RuntimeError; end
|
16
|
+
class NoScramble < RuntimeError; end
|
17
|
+
class AuthFailed < RuntimeError; end
|
18
|
+
class NullSize < RuntimeError; end
|
19
|
+
class TooManyColumns < RuntimeError; end
|
20
|
+
class RowEnd < RuntimeError; end
|
21
|
+
class LostConnection < RuntimeError; end
|
22
|
+
class CouldNotConnect < RuntimeError; end
|
23
|
+
class NoActiveConnections < RuntimeError; end
|
24
|
+
class HandshakeFailed < RuntimeError; end
|
25
|
+
class Timeout < RuntimeError; end
|
26
|
+
class GeneralError < RuntimeError; end
|
27
|
+
|
28
|
+
end
|
@@ -0,0 +1,130 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'ffi'
|
3
|
+
|
4
|
+
module LibDrizzle
|
5
|
+
extend FFI::Library
|
6
|
+
ffi_lib 'drizzle'
|
7
|
+
|
8
|
+
# constants
|
9
|
+
MAX_ERROR_SIZE = 2048
|
10
|
+
MAX_USER_SIZE = 64
|
11
|
+
MAX_PASSWORD_SIZE = 32
|
12
|
+
MAX_DB_SIZE = 64
|
13
|
+
MAX_INFO_SIZE = 2048
|
14
|
+
MAX_SQLSTATE_SIZE = 5
|
15
|
+
MAX_CATALOG_SIZE = 128
|
16
|
+
MAX_TABLE_SIZE = 128
|
17
|
+
|
18
|
+
# return codes
|
19
|
+
ReturnCode = enum( :DRIZZLE_RETURN_OK, 0,
|
20
|
+
:DRIZZLE_RETURN_IO_WAIT,
|
21
|
+
:DRIZZLE_RETURN_PAUSE,
|
22
|
+
:DRIZZLE_RETURN_ROW_BREAK,
|
23
|
+
:DRIZZLE_RETURN_MEMORY,
|
24
|
+
:DRIZZLE_RETURN_ERRNO,
|
25
|
+
:DRIZZLE_RETURN_INTERNAL_ERROR,
|
26
|
+
:DRIZZLE_RETURN_GETADDRINFO,
|
27
|
+
:DRIZZLE_RETURN_NOT_READY,
|
28
|
+
:DRIZZLE_RETURN_BAD_PACKET_NUMBER,
|
29
|
+
:DRIZZLE_RETURN_BAD_HANDSHAKE_PACKET,
|
30
|
+
:DRIZZLE_RETURN_BAD_PACKET,
|
31
|
+
:DRIZZLE_RETURN_PROTOCOL_NOT_SUPPORTED,
|
32
|
+
:DRIZZLE_RETURN_UNEXPECTED_DATA,
|
33
|
+
:DRIZZLE_RETURN_NO_SCRAMBLE,
|
34
|
+
:DRIZZLE_RETURN_AUTH_FAILED,
|
35
|
+
:DRIZZLE_RETURN_NULL_SIZE,
|
36
|
+
:DRIZZLE_RETURN_ERROR_CODE,
|
37
|
+
:DRIZZLE_RETURN_TOO_MANY_COLUMNS,
|
38
|
+
:DRIZZLE_RETURN_ROW_END,
|
39
|
+
:DRIZZLE_RETURN_LOST_CONNECTION,
|
40
|
+
:DRIZZLE_RETURN_COULD_NOT_CONNECT,
|
41
|
+
:DRIZZLE_RETURN_NO_ACTIVE_CONNECTIONS,
|
42
|
+
:DRIZZLE_RETURN_HANDSHAKE_FAILED,
|
43
|
+
:DRIZZLE_RETURN_TIMEOUT,
|
44
|
+
:DRIZZLE_RETURN_MAX )
|
45
|
+
|
46
|
+
# verbosity levels
|
47
|
+
VerbosityLevel = enum( :DRIZZLE_VERBOSE_NEVER, 0,
|
48
|
+
:DRIZZLE_VERBOSE_FATAL,
|
49
|
+
:DRIZZLE_VERBOSE_ERROR,
|
50
|
+
:DRIZZLE_VERBOSE_INFO,
|
51
|
+
:DRIZZLE_VERBOSE_DEBUG,
|
52
|
+
:DRIZZLE_VERBOSE_CRAZY,
|
53
|
+
:DRIZZLE_VERBOSE_MAX )
|
54
|
+
|
55
|
+
# options for the Drizzle protocol functions.
|
56
|
+
CommandTypes = enum( :DRIZZLE_COMMAND_DRIZZLE_SLEEP, 0,
|
57
|
+
:DRIZZLE_COMMAND_DRIZZLE_QUIT,
|
58
|
+
:DRIZZLE_COMMAND_DRIZZLE_INIT_DB,
|
59
|
+
:DRIZZLE_COMMAND_DRIZZLE_QUERY,
|
60
|
+
:DRIZZLE_COMMAND_DRIZZLE_SHUTDOWN,
|
61
|
+
:DRIZZLE_COMMAND_DRIZZLE_CONNECT,
|
62
|
+
:DRIZZLE_COMMAND_DRIZZLE_PING,
|
63
|
+
:DRIZZLE_COMMAND_DRIZZLE_END )
|
64
|
+
|
65
|
+
# Status flags for a drizzle connection
|
66
|
+
ConnectionStatus = enum( :DRIZZLE_CON_STATUS_NONE, 0,
|
67
|
+
:DRIZZLE_CON_STATUS_IN_TRANS, (1 << 0),
|
68
|
+
:DRIZZLE_CON_STATUS_AUTOCOMMIT, (1 << 1),
|
69
|
+
:DRIZZLE_CON_STATUS_MORE_RESULTS_EXIST, (1 << 3),
|
70
|
+
:DRIZZLE_CON_STATUS_QUERY_NO_GOOD_INDEX_USED, (1 << 4),
|
71
|
+
:DRIZZLE_CON_STATUS_QUERY_NO_INDEX_USED, (1 << 5),
|
72
|
+
:DRIZZLE_CON_STATUS_CURSOR_EXISTS, (1 << 6),
|
73
|
+
:DRIZZLE_CON_STATUS_LAST_ROW_SENT, (1 << 7),
|
74
|
+
:DRIZZLE_CON_STATUS_DB_DROPPED, (1 << 8),
|
75
|
+
:DRIZZLE_CON_STATUS_NO_BACKSLASH_ESCAPES, (1 << 9),
|
76
|
+
:DRIZZLE_CON_STATUS_QUERY_WAS_SLOW, (1 << 10) )
|
77
|
+
|
78
|
+
# Options for connections
|
79
|
+
ConnectionOptions = enum( :DRIZZLE_CON_NONE, 0,
|
80
|
+
:DRIZZLE_CON_ALLOCATED, (1 << 0),
|
81
|
+
:DRIZZLE_CON_MYSQL, (1 << 1),
|
82
|
+
:DRIZZLE_CON_RAW_PACKET, (1 << 2),
|
83
|
+
:DRIZZLE_CON_RAW_SCRAMBLE, (1 << 3),
|
84
|
+
:DRIZZLE_CON_READY, (1 << 4),
|
85
|
+
:DRIZZLE_CON_NO_RESULT_READ, (1 << 5) )
|
86
|
+
|
87
|
+
# query options
|
88
|
+
QueryOptions = enum( :DRIZZLE_QUERY_ALLOCATED, (1 << 0) )
|
89
|
+
|
90
|
+
# options for main drizzle structure
|
91
|
+
Options = enum( :DRIZZLE_NONE, 0,
|
92
|
+
:DRIZZLE_ALLOCATED, (1 << 0),
|
93
|
+
:DRIZZLE_NON_BLOCKING, (1 << 1),
|
94
|
+
:DRIZZLE_FREE_OBJECTS, (1 << 2),
|
95
|
+
:DRIZZLE_ASSERT_DANGLING, (1 << 3) )
|
96
|
+
|
97
|
+
attach_function :drizzle_create, [ :pointer ], :pointer
|
98
|
+
attach_function :drizzle_free, [ :pointer ], :void
|
99
|
+
attach_function :drizzle_set_verbose, [ :pointer, VerbosityLevel ], :void
|
100
|
+
|
101
|
+
# connection related functions
|
102
|
+
attach_function :drizzle_con_create, [ :pointer, :pointer ], :pointer
|
103
|
+
attach_function :drizzle_con_free, [ :pointer ], :void
|
104
|
+
attach_function :drizzle_con_set_tcp, [ :pointer, :string, :int ], :void
|
105
|
+
attach_function :drizzle_con_set_db, [ :pointer, :string ], :void
|
106
|
+
attach_function :drizzle_con_add_options, [ :pointer, ConnectionOptions ], :void
|
107
|
+
attach_function :drizzle_con_fd, [ :pointer ], :int
|
108
|
+
|
109
|
+
# query related functions
|
110
|
+
attach_function :drizzle_query_str, [ :pointer, :pointer, :string, :pointer ], :pointer
|
111
|
+
attach_function :drizzle_query_add, [ :pointer, :pointer, :pointer, :pointer, :string, :size_t, QueryOptions, :pointer ], :pointer
|
112
|
+
attach_function :drizzle_result_read, [ :pointer, :pointer, :pointer ], :pointer
|
113
|
+
attach_function :drizzle_row_buffer, [ :pointer, :pointer ], :pointer
|
114
|
+
attach_function :drizzle_row_free, [ :pointer ], :void
|
115
|
+
attach_function :drizzle_result_buffer, [ :pointer ], ReturnCode
|
116
|
+
attach_function :drizzle_result_free, [ :pointer ], :void
|
117
|
+
attach_function :drizzle_row_next, [ :pointer ], :pointer
|
118
|
+
attach_function :drizzle_column_next, [ :pointer ], :pointer
|
119
|
+
attach_function :drizzle_column_name, [ :pointer ], :string
|
120
|
+
attach_function :drizzle_column_buffer, [ :pointer ], ReturnCode
|
121
|
+
attach_function :drizzle_result_column_count, [ :pointer ], :uint16
|
122
|
+
attach_function :drizzle_result_affected_rows, [ :pointer ], :uint64
|
123
|
+
attach_function :drizzle_result_insert_id, [ :pointer ], :uint64
|
124
|
+
|
125
|
+
# miscellaneous functions
|
126
|
+
attach_function :drizzle_version, [], :string
|
127
|
+
attach_function :drizzle_bugreport, [], :string
|
128
|
+
attach_function :drizzle_error, [ :pointer ], :string
|
129
|
+
|
130
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
require 'drizzle/ffidrizzle'
|
2
|
+
|
3
|
+
module Drizzle
|
4
|
+
|
5
|
+
#
|
6
|
+
# a result set from a drizzle query
|
7
|
+
#
|
8
|
+
class Result
|
9
|
+
|
10
|
+
attr_reader :columns, :rows, :affected_rows, :insert_id
|
11
|
+
|
12
|
+
#
|
13
|
+
# creates a result set instance
|
14
|
+
# This result set does not buffer any results until instructed
|
15
|
+
# to do so. Results can be fully buffered or buffered at the
|
16
|
+
# row level.
|
17
|
+
#
|
18
|
+
# == parameters
|
19
|
+
#
|
20
|
+
# * res_ptr FFI memory pointer to a drizzle_result_t object
|
21
|
+
#
|
22
|
+
def initialize(res_ptr)
|
23
|
+
@columns, @rows = [], []
|
24
|
+
@res_ptr = res_ptr
|
25
|
+
@affected_rows = LibDrizzle.drizzle_result_affected_rows(@res_ptr)
|
26
|
+
@insert_id = LibDrizzle.drizzle_result_insert_id(@res_ptr)
|
27
|
+
end
|
28
|
+
|
29
|
+
#
|
30
|
+
# buffer all rows and columns and copy them into ruby arrays
|
31
|
+
# Free the FFI pointer afterwards
|
32
|
+
#
|
33
|
+
def buffer_result()
|
34
|
+
ret = LibDrizzle.drizzle_result_buffer(@res_ptr)
|
35
|
+
if LibDrizzle::ReturnCode[ret] != LibDrizzle::ReturnCode[:DRIZZLE_RETURN_OK]
|
36
|
+
LibDrizzle.drizzle_result_free(@res_ptr)
|
37
|
+
end
|
38
|
+
|
39
|
+
loop do
|
40
|
+
col_ptr = LibDrizzle.drizzle_column_next(@res_ptr)
|
41
|
+
break if col_ptr.null?
|
42
|
+
@columns << LibDrizzle.drizzle_column_name(col_ptr).to_sym
|
43
|
+
end
|
44
|
+
|
45
|
+
loop do
|
46
|
+
row_ptr = LibDrizzle.drizzle_row_next(@res_ptr)
|
47
|
+
break if row_ptr.null?
|
48
|
+
@rows << row_ptr.get_array_of_string(0, @columns.size)
|
49
|
+
end
|
50
|
+
|
51
|
+
LibDrizzle.drizzle_result_free(@res_ptr)
|
52
|
+
end
|
53
|
+
|
54
|
+
#
|
55
|
+
# buffer an individual row.
|
56
|
+
#
|
57
|
+
def buffer_row()
|
58
|
+
# if the columns have not been read for this result
|
59
|
+
# set yet, then we need to do that here. If this is not
|
60
|
+
# performed here, we will receive a bad packet error
|
61
|
+
read_columns if @columns.empty?
|
62
|
+
ret_ptr = FFI::MemoryPointer.new(:int)
|
63
|
+
row_ptr = LibDrizzle.drizzle_row_buffer(@res_ptr, ret_ptr)
|
64
|
+
if LibDrizzle::ReturnCode[ret_ptr.get_int(0)] != :DRIZZLE_RETURN_OK
|
65
|
+
LibDrizzle.drizzle_result_free(@res_ptr)
|
66
|
+
end
|
67
|
+
if row_ptr.null?
|
68
|
+
LibDrizzle.drizzle_result_free(@res_ptr)
|
69
|
+
return nil
|
70
|
+
end
|
71
|
+
num_of_cols = LibDrizzle.drizzle_result_column_count(@res_ptr)
|
72
|
+
row = row_ptr.get_array_of_string(0, @columns.size)
|
73
|
+
end
|
74
|
+
|
75
|
+
#
|
76
|
+
# buffer all columns for this result set
|
77
|
+
#
|
78
|
+
def read_columns
|
79
|
+
ret = LibDrizzle.drizzle_column_buffer(@res_ptr)
|
80
|
+
loop do
|
81
|
+
col_ptr = LibDrizzle.drizzle_column_next(@res_ptr)
|
82
|
+
break if col_ptr.null?
|
83
|
+
@columns << LibDrizzle.drizzle_column_name(col_ptr).to_sym
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def each
|
88
|
+
@rows.each do |row|
|
89
|
+
yield row if block_given?
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
data/test/helper.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
|
3
|
+
require File.join(File.dirname(__FILE__), *%w[.. lib drizzle])
|
4
|
+
|
5
|
+
require 'test/unit'
|
6
|
+
require 'shoulda'
|
7
|
+
require 'rr'
|
8
|
+
|
9
|
+
include Drizzle
|
10
|
+
|
11
|
+
PORT = 4427
|
12
|
+
|
13
|
+
class Test::Unit::TestCase
|
14
|
+
include RR::Adapters::TestUnit
|
15
|
+
|
16
|
+
def dest_dir(*subdirs)
|
17
|
+
File.join(File.dirname(__FILE__), 'dest', *subdirs)
|
18
|
+
end
|
19
|
+
|
20
|
+
def source_dir(*subdirs)
|
21
|
+
File.join(File.dirname(__FILE__), 'source', *subdirs)
|
22
|
+
end
|
23
|
+
|
24
|
+
def clear_dest
|
25
|
+
FileUtils.rm_rf(dest_dir)
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
data/test/test_basic.rb
ADDED
@@ -0,0 +1,103 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/helper'
|
2
|
+
|
3
|
+
class TestBasic < Test::Unit::TestCase
|
4
|
+
|
5
|
+
should "retrieve libdrizzle API version" do
|
6
|
+
drizzle = Drizzle::Drizzle.new
|
7
|
+
assert_equal "0.7", drizzle.version
|
8
|
+
end
|
9
|
+
|
10
|
+
should "retrieve libdrizzle bug report url" do
|
11
|
+
drizzle = Drizzle::Drizzle.new
|
12
|
+
assert_equal "https://launchpad.net/libdrizzle", drizzle.bug_report_url
|
13
|
+
end
|
14
|
+
|
15
|
+
should "connect to drizzle successfully" do
|
16
|
+
conn = Drizzle::Connection.new("localhost", PORT)
|
17
|
+
assert_equal conn.class, Drizzle::Connection
|
18
|
+
end
|
19
|
+
|
20
|
+
should "perform a simple query and buffer all results" do
|
21
|
+
conn = Drizzle::Connection.new("localhost", PORT, "data_dictionary")
|
22
|
+
res = conn.query("SELECT module_name, module_author FROM MODULES where module_name = 'SchemaEngine'")
|
23
|
+
assert_equal res.class, Drizzle::Result
|
24
|
+
res.buffer_result
|
25
|
+
assert_equal 2, res.columns.size
|
26
|
+
res.each do |row|
|
27
|
+
assert_equal "Brian Aker", row[1]
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
should "perform another simple query and buffer all results" do
|
32
|
+
conn = Drizzle::Connection.new("localhost", PORT, "information_schema", [Drizzle::NONE])
|
33
|
+
res = conn.query("SELECT table_schema, table_name FROM TABLES WHERE table_schema = 'DATA_DICTIONARY' AND table_name = 'GLOBAL_STATUS'")
|
34
|
+
assert_equal res.class, Drizzle::Result
|
35
|
+
res.buffer_result
|
36
|
+
assert_equal 2, res.columns.size
|
37
|
+
res.each do |row|
|
38
|
+
assert_equal "DATA_DICTIONARY", row[0]
|
39
|
+
assert_equal "GLOBAL_STATUS", row[1]
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
should "perform a simple query and buffer rows" do
|
44
|
+
conn = Drizzle::Connection.new("localhost", PORT, "information_schema")
|
45
|
+
res = conn.query("SELECT COUNT(*) FROM COLUMNS WHERE table_name = 'GLOBAL_STATUS'")
|
46
|
+
assert_equal res.class, Drizzle::Result
|
47
|
+
until (row = res.buffer_row).nil?
|
48
|
+
assert_equal "2", row[0]
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
should "create and drop a database" do
|
53
|
+
conn = Drizzle::Connection.new("localhost", PORT)
|
54
|
+
res = conn.query("CREATE DATABASE padraig")
|
55
|
+
res = conn.query("select table_schema from information_schema.tables where table_schema = 'padraig'")
|
56
|
+
assert_equal res.class, Drizzle::Result
|
57
|
+
res.buffer_result
|
58
|
+
assert_equal 1, res.columns.size
|
59
|
+
res.each do |row|
|
60
|
+
assert_equal "padraig", row[0]
|
61
|
+
end
|
62
|
+
res = conn.query("DROP DATABASE padraig")
|
63
|
+
res = conn.query("select table_schema from information_schema.tables where table_schema = 'padraig'")
|
64
|
+
assert_equal res.class, Drizzle::Result
|
65
|
+
res.buffer_result
|
66
|
+
assert_equal 1, res.columns.size
|
67
|
+
assert_equal true, res.rows.empty?
|
68
|
+
end
|
69
|
+
|
70
|
+
should "use different connection options" do
|
71
|
+
conn = Drizzle::Connection.new("localhost", PORT, "information_schema", [Drizzle::NONE])
|
72
|
+
res = conn.query("SELECT COUNT(*) FROM COLUMNS WHERE table_name = 'GLOBAL_STATUS'")
|
73
|
+
assert_equal res.class, Drizzle::Result
|
74
|
+
until (row = res.buffer_row).nil?
|
75
|
+
assert_equal "2", row[0]
|
76
|
+
end
|
77
|
+
conn = Drizzle::Connection.new("localhost", PORT, "information_schema", [Drizzle::NONE, Drizzle::MYSQL])
|
78
|
+
res = conn.query("SELECT COUNT(*) FROM COLUMNS WHERE table_name = 'GLOBAL_STATUS'")
|
79
|
+
assert_equal res.class, Drizzle::Result
|
80
|
+
until (row = res.buffer_row).nil?
|
81
|
+
assert_equal "2", row[0]
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
should "perform a query with a code block" do
|
86
|
+
conn = Drizzle::Connection.new("localhost", PORT, "information_schema", [Drizzle::NONE])
|
87
|
+
conn.query("SELECT COUNT(*) FROM COLUMNS WHERE table_name = 'GLOBAL_STATUS'") do |res|
|
88
|
+
assert_equal res.class, Drizzle::Result
|
89
|
+
until (row = res.buffer_row).nil?
|
90
|
+
assert_equal "2", row[0]
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
should "perform a simple show variables command" do
|
96
|
+
conn = Drizzle::Connection.new("localhost", PORT, "information_schema", [Drizzle::NONE])
|
97
|
+
assert_equal conn.class, Drizzle::Connection
|
98
|
+
res = conn.query("show variables")
|
99
|
+
assert_equal res.class, Drizzle::Result
|
100
|
+
res.buffer_result
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
@@ -0,0 +1,133 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/helper'
|
2
|
+
|
3
|
+
class TestBasic < Test::Unit::TestCase
|
4
|
+
|
5
|
+
def setup
|
6
|
+
conn = Drizzle::Connection.new("localhost", PORT)
|
7
|
+
res = conn.query("CREATE DATABASE drizzleruby")
|
8
|
+
end
|
9
|
+
|
10
|
+
def teardown
|
11
|
+
conn = Drizzle::Connection.new("localhost", PORT)
|
12
|
+
res = conn.query("DROP DATABASE drizzleruby")
|
13
|
+
end
|
14
|
+
|
15
|
+
should "create and drop a table" do
|
16
|
+
conn = Drizzle::Connection.new("localhost", PORT, "drizzleruby")
|
17
|
+
res = conn.query("select table_schema from information_schema.tables where table_schema = 'drizzleruby'")
|
18
|
+
assert_equal res.class, Drizzle::Result
|
19
|
+
res.buffer_result
|
20
|
+
assert_equal 1, res.columns.size
|
21
|
+
res.each do |row|
|
22
|
+
assert_equal "drizzleruby", row[0]
|
23
|
+
end
|
24
|
+
res = conn.query("create table t1(a int, b varchar(255))")
|
25
|
+
res = conn.query("select table_schema, table_name from information_schema.tables where table_schema = 'drizzleruby'")
|
26
|
+
res.buffer_result
|
27
|
+
assert_equal 2, res.columns.size
|
28
|
+
res.each do |row|
|
29
|
+
assert_equal "t1", row[1]
|
30
|
+
end
|
31
|
+
res = conn.query("DROP TABLE t1")
|
32
|
+
res = conn.query("select table_name from information_schema.tables where table_schema = 'drizzleruby'")
|
33
|
+
assert_equal res.class, Drizzle::Result
|
34
|
+
res.buffer_result
|
35
|
+
assert_equal 1, res.columns.size
|
36
|
+
assert_equal true, res.rows.empty?
|
37
|
+
end
|
38
|
+
|
39
|
+
should "update affected rows appropriately" do
|
40
|
+
conn = Drizzle::Connection.new("localhost", PORT, "drizzleruby")
|
41
|
+
res = conn.query("select table_schema from information_schema.tables where table_schema = 'drizzleruby'")
|
42
|
+
assert_equal res.class, Drizzle::Result
|
43
|
+
res.buffer_result
|
44
|
+
assert_equal 1, res.columns.size
|
45
|
+
res.each do |row|
|
46
|
+
assert_equal "drizzleruby", row[0]
|
47
|
+
end
|
48
|
+
res = conn.query("create table t1(a int, b varchar(255))")
|
49
|
+
res = conn.query("select table_schema, table_name from information_schema.tables where table_schema = 'drizzleruby'")
|
50
|
+
res.buffer_result
|
51
|
+
assert_equal 2, res.columns.size
|
52
|
+
res.each do |row|
|
53
|
+
assert_equal "t1", row[1]
|
54
|
+
end
|
55
|
+
res = conn.query("insert into t1 values (1, 'padraig')")
|
56
|
+
assert_equal 1, res.affected_rows
|
57
|
+
assert_equal 0, res.insert_id
|
58
|
+
res = conn.query("insert into t1 values (2, 'sarah')")
|
59
|
+
assert_equal 1, res.affected_rows
|
60
|
+
assert_equal 0, res.insert_id
|
61
|
+
res = conn.query("select * from t1 where a = 2")
|
62
|
+
res.buffer_result
|
63
|
+
assert_equal 2, res.columns.size
|
64
|
+
res.each do |row|
|
65
|
+
assert_equal "2", row[0]
|
66
|
+
assert_equal "sarah", row[1]
|
67
|
+
end
|
68
|
+
res = conn.query("DROP TABLE t1")
|
69
|
+
res = conn.query("select table_name from information_schema.tables where table_schema = 'drizzleruby'")
|
70
|
+
assert_equal res.class, Drizzle::Result
|
71
|
+
res.buffer_result
|
72
|
+
assert_equal 1, res.columns.size
|
73
|
+
assert_equal true, res.rows.empty?
|
74
|
+
end
|
75
|
+
|
76
|
+
should "perform a multi-insert statement correctly" do
|
77
|
+
conn = Drizzle::Connection.new("localhost", PORT, "drizzleruby")
|
78
|
+
res = conn.query("select table_schema from information_schema.tables where table_schema = 'drizzleruby'")
|
79
|
+
assert_equal res.class, Drizzle::Result
|
80
|
+
res.buffer_result
|
81
|
+
assert_equal 1, res.columns.size
|
82
|
+
res.each do |row|
|
83
|
+
assert_equal "drizzleruby", row[0]
|
84
|
+
end
|
85
|
+
res = conn.query("create table t1(a int, b varchar(255))")
|
86
|
+
res = conn.query("select table_schema, table_name from information_schema.tables where table_schema = 'drizzleruby'")
|
87
|
+
res.buffer_result
|
88
|
+
assert_equal 2, res.columns.size
|
89
|
+
res.each do |row|
|
90
|
+
assert_equal "t1", row[1]
|
91
|
+
end
|
92
|
+
res = conn.query("insert into t1 values (1, 'padraig'), (2, 'sarah'), (3, 'tomas')")
|
93
|
+
assert_equal 3, res.affected_rows
|
94
|
+
res = conn.query("select * from t1 where a = 2")
|
95
|
+
res.buffer_result
|
96
|
+
assert_equal 2, res.columns.size
|
97
|
+
res.each do |row|
|
98
|
+
assert_equal "2", row[0]
|
99
|
+
assert_equal "sarah", row[1]
|
100
|
+
end
|
101
|
+
res = conn.query("DROP TABLE t1")
|
102
|
+
res = conn.query("select table_name from information_schema.tables where table_schema = 'drizzleruby'")
|
103
|
+
assert_equal res.class, Drizzle::Result
|
104
|
+
res.buffer_result
|
105
|
+
assert_equal 1, res.columns.size
|
106
|
+
assert_equal true, res.rows.empty?
|
107
|
+
end
|
108
|
+
|
109
|
+
should "insert and fetch a blob value correctly" do
|
110
|
+
conn = Drizzle::Connection.new("localhost", PORT, "drizzleruby")
|
111
|
+
res = conn.query("create table t1(a int, b blob)")
|
112
|
+
res = conn.query("insert into t1 values (1, 'padraig'), (2, 'sarah'), (3, 'tomas')")
|
113
|
+
assert_equal 3, res.affected_rows
|
114
|
+
res = conn.query("insert into t1 values (4, null), (5, 'blahblahblah'), (6, 'southy')")
|
115
|
+
assert_equal 3, res.affected_rows
|
116
|
+
res = conn.query("select * from t1 where a = 2")
|
117
|
+
res.buffer_result
|
118
|
+
assert_equal 2, res.columns.size
|
119
|
+
res.each do |row|
|
120
|
+
assert_equal "2", row[0]
|
121
|
+
assert_equal "sarah", row[1]
|
122
|
+
end
|
123
|
+
res = conn.query("select * from t1 where a = 4")
|
124
|
+
res.buffer_result
|
125
|
+
assert_equal 2, res.columns.size
|
126
|
+
res.each do |row|
|
127
|
+
assert_equal "4", row[0]
|
128
|
+
assert_equal nil, row[1]
|
129
|
+
end
|
130
|
+
res = conn.query("DROP TABLE t1")
|
131
|
+
end
|
132
|
+
|
133
|
+
end
|
metadata
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: drizzle
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 1
|
8
|
+
- 0
|
9
|
+
version: 0.1.0
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Padraig O'Sullivan
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2011-04-13 00:00:00 -07:00
|
18
|
+
default_executable:
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: thoughtbot-shoulda
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
segments:
|
28
|
+
- 0
|
29
|
+
version: "0"
|
30
|
+
type: :development
|
31
|
+
version_requirements: *id001
|
32
|
+
description: An interface to Drizzle for Ruby that uses libdrizzle
|
33
|
+
email: osullivan.padraig@gmail.com
|
34
|
+
executables: []
|
35
|
+
|
36
|
+
extensions: []
|
37
|
+
|
38
|
+
extra_rdoc_files:
|
39
|
+
- LICENSE
|
40
|
+
- README.rdoc
|
41
|
+
files:
|
42
|
+
- LICENSE
|
43
|
+
- README.rdoc
|
44
|
+
- Rakefile
|
45
|
+
- VERSION
|
46
|
+
- lib/drizzle.rb
|
47
|
+
- lib/drizzle/connection.rb
|
48
|
+
- lib/drizzle/drizzle.rb
|
49
|
+
- lib/drizzle/exceptions.rb
|
50
|
+
- lib/drizzle/ffidrizzle.rb
|
51
|
+
- lib/drizzle/result.rb
|
52
|
+
- test/helper.rb
|
53
|
+
- test/test_basic.rb
|
54
|
+
- test/test_complex.rb
|
55
|
+
has_rdoc: true
|
56
|
+
homepage: http://github.com/posulliv/drizzle-ruby
|
57
|
+
licenses: []
|
58
|
+
|
59
|
+
post_install_message:
|
60
|
+
rdoc_options: []
|
61
|
+
|
62
|
+
require_paths:
|
63
|
+
- lib
|
64
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
segments:
|
69
|
+
- 0
|
70
|
+
version: "0"
|
71
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
segments:
|
76
|
+
- 0
|
77
|
+
version: "0"
|
78
|
+
requirements: []
|
79
|
+
|
80
|
+
rubyforge_project: drizzle-ruby
|
81
|
+
rubygems_version: 1.3.6
|
82
|
+
signing_key:
|
83
|
+
specification_version: 3
|
84
|
+
summary: A ruby interface to Drizzle using libdrizzle
|
85
|
+
test_files:
|
86
|
+
- test/helper.rb
|
87
|
+
- test/test_basic.rb
|
88
|
+
- test/test_complex.rb
|