db-mariadb 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: e48fc978d5a9616b176cfd22ebaac97ef4aa64ef46e8741c4842f3ac22bffd0f
4
+ data.tar.gz: '0349fcd36f4b9a4fa36c4c75fca6a3d780b02056dc418a941118533b60ffe16b'
5
+ SHA512:
6
+ metadata.gz: 950fed54c6d1eb1c71c4f81657b49ee82aa0b2fed6f2598d62757064522db8b94dd8a80bc38131ffbdc12d950334e46e6258242876d261cd1bb263c3da4ea36a
7
+ data.tar.gz: e4d6eaca7a2ce5b095301f8af3d34b84e20594db296e7f2842e12886cf5faecf5dfe3ffbef6ddb6ac247f8cf7478437aa182fe2da6abfa7e883658ca9619f71c
Binary file
@@ -0,0 +1,27 @@
1
+ # Copyright, 2018, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
21
+ require_relative 'mariadb/native'
22
+ require_relative 'mariadb/connection'
23
+
24
+ require_relative 'mariadb/adapter'
25
+
26
+ require 'db/adapters'
27
+ DB::Adapters.register(:mysql, DB::MariaDB::Adapter)
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright, 2020, by Samuel G. D. Williams. <http://www.codeotaku.com>
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the "Software"), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in
13
+ # all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ # THE SOFTWARE.
22
+
23
+ require_relative 'connection'
24
+
25
+ module DB
26
+ module MariaDB
27
+ LOCAL = "mysql://localhost/test"
28
+
29
+ class Adapter
30
+ def initialize(connection_string = LOCAL)
31
+ @connection_string = connection_string
32
+ end
33
+
34
+ attr :connection_string
35
+
36
+ def call
37
+ Connection.new(self.connection_string)
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright, 2020, by Samuel G. D. Williams. <http://www.codeotaku.com>
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the "Software"), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in
13
+ # all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ # THE SOFTWARE.
22
+
23
+ require 'async/pool/resource'
24
+ require_relative 'native/connection'
25
+
26
+ module DB
27
+ module MariaDB
28
+ # This implements the interface between the underyling native interface interface and "standardised" connection interface.
29
+ class Connection < Async::Pool::Resource
30
+ def initialize(**options)
31
+ @native = Native::Connection.connect(**options)
32
+
33
+ super()
34
+ end
35
+
36
+ def close
37
+ @native.close
38
+
39
+ super
40
+ end
41
+
42
+ def append_string(value, buffer = String.new)
43
+ buffer << "'" << @native.escape(value) << "'"
44
+
45
+ return buffer
46
+ end
47
+
48
+ def append_literal(value, buffer = String.new)
49
+ case value
50
+ when Numeric
51
+ buffer << value.to_s
52
+ when nil
53
+ buffer << "NULL"
54
+ else
55
+ append_string(value, buffer)
56
+ end
57
+
58
+ return buffer
59
+ end
60
+
61
+ def append_identifier(value, buffer = String.new)
62
+ buffer << "`" << @native.escape(value) << "`"
63
+
64
+ return buffer
65
+ end
66
+
67
+ def status
68
+ @native.status
69
+ end
70
+
71
+ def send_query(statement)
72
+ @native.send_query(statement)
73
+ end
74
+
75
+ def next_result
76
+ @native.next_result
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,31 @@
1
+ # Copyright, 2018, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
21
+ require 'ffi'
22
+
23
+ module DB
24
+ module MariaDB
25
+ module Native
26
+ extend FFI::Library
27
+
28
+ ffi_lib 'mariadb'
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,216 @@
1
+ # Copyright, 2018, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
21
+ require_relative 'result'
22
+ require 'async/io/generic'
23
+
24
+ module DB
25
+ module MariaDB
26
+ module Native
27
+ MYSQL_OPT_NONBLOCK = 6000
28
+
29
+ MYSQL_WAIT_READ = 1
30
+ MYSQL_WAIT_WRITE = 2
31
+ MYSQL_WAIT_EXCEPT = 4
32
+ MYSQL_WAIT_TIMEOUT = 8
33
+
34
+ CLIENT_COMPRESS = 0x00000020
35
+ CLIENT_LOCAL_FILES = 0x00000080
36
+ CLIENT_MULTI_STATEMENT = 0x00010000
37
+ CLIENT_MULTI_RESULTS = 0x00020000
38
+
39
+ attach_function :mysql_init, [:pointer], :pointer
40
+ attach_function :mysql_options, [:pointer, :int, :pointer], :int
41
+ attach_function :mysql_get_socket, [:pointer], :int
42
+
43
+ attach_function :mysql_real_connect_start, [:pointer, :pointer, :string, :string, :string, :string, :int, :string, :long], :int
44
+ attach_function :mysql_real_connect_cont, [:pointer, :pointer, :int], :int
45
+
46
+ attach_function :mysql_real_query_start, [:pointer, :pointer, :string, :ulong], :int
47
+ attach_function :mysql_real_query_cont, [:pointer, :pointer, :int], :int
48
+
49
+ attach_function :mysql_use_result, [:pointer], :pointer
50
+ attach_function :mysql_next_result, [:pointer], :int
51
+ attach_function :mysql_free_result, [:pointer], :void
52
+
53
+ attach_function :mysql_affected_rows, [:pointer], :uint64
54
+ attach_function :mysql_insert_id, [:pointer], :uint64
55
+ attach_function :mysql_info, [:pointer], :string
56
+
57
+ attach_function :mysql_close, [:pointer], :void
58
+ attach_function :mysql_errno, [:pointer], :uint
59
+ attach_function :mysql_error, [:pointer], :string
60
+
61
+ attach_function :mysql_stat, [:pointer], :string
62
+
63
+ attach_function :mysql_real_escape_string, [:pointer, :pointer, :string, :size_t], :size_t
64
+
65
+ module IO
66
+ def self.new(fd, mode)
67
+ Async::IO::Generic.new(::IO.new(fd, mode, autoclose: false))
68
+ end
69
+ end
70
+
71
+ class Connection < FFI::Pointer
72
+ def self.connect(host: 'localhost', user: nil, password: nil, database: nil, port: 0, unix_socket: nil, client_flags: 0, compression: false, types: DEFAULT_TYPES, **options)
73
+ pointer = Native.mysql_init(nil)
74
+ Native.mysql_options(pointer, MYSQL_OPT_NONBLOCK, nil)
75
+
76
+ client_flags |= CLIENT_MULTI_STATEMENT | CLIENT_MULTI_RESULTS
77
+
78
+ if compression
79
+ client_flags |= CLIENT_COMPRESSION
80
+ end
81
+
82
+ result = FFI::MemoryPointer.new(:pointer)
83
+
84
+ status = Native.mysql_real_connect_start(result, pointer, host, user, password, database, port, unix_socket, client_flags);
85
+
86
+ if status > 0
87
+ io = IO.new(Native.mysql_get_socket(pointer), "r+")
88
+
89
+ while status > 0
90
+ if status & MYSQL_WAIT_READ
91
+ io.wait_readable
92
+ elsif status & MYSQL_WAIT_WRITE
93
+ io.wait_writable
94
+ else
95
+ io.wait_any
96
+ end
97
+
98
+ status = Native.mysql_real_connect_cont(result, pointer, status)
99
+ end
100
+ end
101
+
102
+ if result.read_pointer.null?
103
+ raise "Could not connect: #{Native.mysql_error(pointer)}!"
104
+ end
105
+
106
+ return self.new(pointer, io, types: types, **options)
107
+ end
108
+
109
+ def initialize(address, io, types: {})
110
+ super(address)
111
+
112
+ @io = io
113
+ @result = nil
114
+
115
+ @types = types
116
+ end
117
+
118
+ def wait_for(status)
119
+ if status & MYSQL_WAIT_READ
120
+ @io.wait_readable
121
+ elsif status & MYSQL_WAIT_WRITE
122
+ @io.wait_writable
123
+ end
124
+ end
125
+
126
+ def check_error!(message)
127
+ if Native.mysql_errno(self) != 0
128
+ raise "#{message}: #{Native.mysql_error(self)}!"
129
+ end
130
+ end
131
+
132
+ def status
133
+ Native.mysql_stat(self)
134
+ end
135
+
136
+ def free_result
137
+ if @result
138
+ Native.mysql_free_result(@result)
139
+
140
+ @result = nil
141
+ end
142
+ end
143
+
144
+ def close
145
+ self.free_result
146
+
147
+ Native.mysql_close(self)
148
+
149
+ @io.close
150
+ end
151
+
152
+ def escape(value)
153
+ value = value.to_s
154
+
155
+ maximum_length = value.bytesize * 2 + 1
156
+ out = FFI::MemoryPointer.new(:char, maximum_length)
157
+
158
+ Native.mysql_real_escape_string(self, out, value, value.bytesize)
159
+
160
+ return out.read_string
161
+ end
162
+
163
+ def send_query(statement)
164
+ self.free_result
165
+
166
+ error = FFI::MemoryPointer.new(:int)
167
+
168
+ status = Native.mysql_real_query_start(error, self, statement, statement.bytesize)
169
+
170
+ while status != 0
171
+ self.wait_for(status)
172
+
173
+ status = Native.mysql_real_query_cont(error, self, status)
174
+ end
175
+
176
+ if error.read_int != 0
177
+ raise "Could not send query: #{Native.mysql_error(self)}!"
178
+ end
179
+ end
180
+
181
+ def next_result(types: @types)
182
+ if @result
183
+ self.free_result
184
+
185
+ # Successful and there are no more results:
186
+ return if Native.mysql_next_result(self) == -1
187
+
188
+ check_error!("Next result")
189
+ end
190
+
191
+ @result = Native.mysql_use_result(self)
192
+
193
+ if @result.null?
194
+ check_error!("Next result")
195
+
196
+ return nil
197
+ else
198
+ return Result.new(self, types, @result)
199
+ end
200
+ end
201
+
202
+ def affected_rows
203
+ Native.mysql_affected_rows(self)
204
+ end
205
+
206
+ def insert_id
207
+ Native.mysql_insert_id(self)
208
+ end
209
+
210
+ def info
211
+ Native.mysql_info(self)
212
+ end
213
+ end
214
+ end
215
+ end
216
+ end
@@ -0,0 +1,114 @@
1
+ # Copyright, 2018, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
21
+ require_relative '../native'
22
+
23
+ require_relative 'types'
24
+
25
+ module DB
26
+ module MariaDB
27
+ module Native
28
+ Type = enum(FFI::Type::UCHAR,
29
+ :decimal,
30
+ :tiny,
31
+ :short,
32
+ :long,
33
+ :float,
34
+ :double,
35
+ :null,
36
+ :timestamp,
37
+ :longlong,
38
+ :int24,
39
+ :date,
40
+ :time,
41
+ :datetime,
42
+ :year,
43
+ :newdate,
44
+ :varchar,
45
+ :bit,
46
+ :json, 245,
47
+ :newdecimal,
48
+ :enum,
49
+ :set,
50
+ :tiny_blob,
51
+ :medium_blob,
52
+ :long_blob,
53
+ :blob,
54
+ :var_string,
55
+ :string,
56
+ :geometry,
57
+ )
58
+
59
+ DEFAULT_TYPES = {
60
+ decimal: Types::Decimal,
61
+ tiny: Types::Integer,
62
+ short: Types::Integer,
63
+ long: Types::Integer,
64
+ float: Types::Float,
65
+ double: Types::Float,
66
+ timestamp: Types::DateTime,
67
+ longlong: Types::Integer,
68
+ int24: Types::Integer,
69
+ date: Date,
70
+ datetime: Types::DateTime,
71
+ year: Types::Integer,
72
+ newdate: Types::DateTime,
73
+ bit: Types::Integer,
74
+ json: JSON,
75
+ newdecimal: Types::Decimal,
76
+ enum: Types::Symbol,
77
+ set: Types::Integer,
78
+ }
79
+
80
+ class Field < FFI::Struct
81
+ layout(
82
+ :name, :string,
83
+ :org_name, :string,
84
+ :table, :string,
85
+ :org_table, :string,
86
+ :db, :string,
87
+ :catalog, :string,
88
+ :def, :string,
89
+ :length, :ulong,
90
+ :max_length, :ulong,
91
+ :name_length, :uint,
92
+ :org_name_length, :uint,
93
+ :table_length, :uint,
94
+ :org_table_length, :uint,
95
+ :db_length, :uint,
96
+ :catalog_length, :uint,
97
+ :def_length, :uint,
98
+ :flags, :uint,
99
+ :decimals, :uint,
100
+ :charsetnr, :uint,
101
+ :type, Type
102
+ )
103
+
104
+ def name
105
+ self[:name]
106
+ end
107
+
108
+ def type
109
+ self[:type]
110
+ end
111
+ end
112
+ end
113
+ end
114
+ end
@@ -0,0 +1,124 @@
1
+ # Copyright, 2018, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
21
+ require_relative 'field'
22
+
23
+ module DB
24
+ module MariaDB
25
+ module Native
26
+ attach_function :mysql_fetch_row_start, [:pointer, :pointer], :int
27
+ attach_function :mysql_fetch_row_cont, [:pointer, :pointer, :int], :int
28
+
29
+ attach_function :mysql_num_rows, [:pointer], :uint64
30
+ attach_function :mysql_num_fields, [:pointer], :uint32
31
+
32
+ attach_function :mysql_fetch_fields, [:pointer], :pointer
33
+
34
+ class Result < FFI::Pointer
35
+ def initialize(connection, types = {}, address)
36
+ super(address)
37
+
38
+ @connection = connection
39
+ @fields = nil
40
+ @types = types
41
+ @casts = nil
42
+ end
43
+
44
+ def field_count
45
+ Native.mysql_num_fields(self)
46
+ end
47
+
48
+ def fields
49
+ unless @fields
50
+ pointer = Native.mysql_fetch_fields(self)
51
+
52
+ @fields = field_count.times.map do |index|
53
+ Field.new(pointer + index * Field.size)
54
+ end
55
+ end
56
+
57
+ return @fields
58
+ end
59
+
60
+ def field_names
61
+ fields.map(&:name)
62
+ end
63
+
64
+ def field_types
65
+ fields.map{|field| @types[field.type]}
66
+ end
67
+
68
+ def row_count
69
+ Native.mysql_num_rows(self)
70
+ end
71
+
72
+ alias count row_count
73
+ alias keys field_names
74
+
75
+ def cast!(row)
76
+ @casts ||= self.field_types
77
+
78
+ row.size.times do |index|
79
+ if cast = @casts[index]
80
+ row[index] = cast.parse(row[index])
81
+ end
82
+ end
83
+
84
+ return row
85
+ end
86
+
87
+ def each
88
+ row = FFI::MemoryPointer.new(:pointer)
89
+ field_count = self.field_count
90
+
91
+ while true
92
+ status = Native.mysql_fetch_row_start(row, self)
93
+
94
+ while status != 0
95
+ @connection.wait_for(status)
96
+
97
+ status = Native.mysql_fetch_row_cont(row, self, status)
98
+ end
99
+
100
+ pointer = row.read_pointer
101
+
102
+ if pointer.null?
103
+ break
104
+ else
105
+ yield cast!(pointer.get_array_of_string(0, field_count))
106
+ end
107
+ end
108
+
109
+ @connection.check_error!("Reading recordset")
110
+ end
111
+
112
+ def to_a
113
+ rows = []
114
+
115
+ self.each do |row|
116
+ rows << row
117
+ end
118
+
119
+ return rows
120
+ end
121
+ end
122
+ end
123
+ end
124
+ end
@@ -0,0 +1,64 @@
1
+ # Copyright, 2018, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
21
+ require 'ffi'
22
+
23
+ require 'json'
24
+ require 'bigdecimal'
25
+
26
+ module DB
27
+ module MariaDB
28
+ module Native
29
+ module Types
30
+ module Integer
31
+ def self.parse(string)
32
+ Integer(string)
33
+ end
34
+ end
35
+
36
+ module Decimal
37
+ def self.parse(string)
38
+ BigDecimal(string)
39
+ end
40
+ end
41
+
42
+ module Float
43
+ def self.parse(string)
44
+ Float(string)
45
+ end
46
+ end
47
+
48
+ module Symbol
49
+ def self.parse(string)
50
+ string.to_sym
51
+ end
52
+ end
53
+
54
+ module DateTime
55
+ def self.parse(string)
56
+ parts = string.split(/[\-\s:]/)
57
+
58
+ return Time.utc(*parts)
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,25 @@
1
+ # Copyright, 2018, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
21
+ module DB
22
+ module MariaDB
23
+ VERSION = "0.1.0"
24
+ end
25
+ end
metadata ADDED
@@ -0,0 +1,150 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: db-mariadb
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Samuel Williams
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-06-30 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: ffi
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: async-io
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: async-rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: bake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: covered
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: bundler
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rspec
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '3.6'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '3.6'
111
+ description:
112
+ email:
113
+ executables: []
114
+ extensions: []
115
+ extra_rdoc_files: []
116
+ files:
117
+ - lib/.DS_Store
118
+ - lib/db/mariadb.rb
119
+ - lib/db/mariadb/adapter.rb
120
+ - lib/db/mariadb/connection.rb
121
+ - lib/db/mariadb/native.rb
122
+ - lib/db/mariadb/native/connection.rb
123
+ - lib/db/mariadb/native/field.rb
124
+ - lib/db/mariadb/native/result.rb
125
+ - lib/db/mariadb/native/types.rb
126
+ - lib/db/mariadb/version.rb
127
+ homepage:
128
+ licenses:
129
+ - MIT
130
+ metadata: {}
131
+ post_install_message:
132
+ rdoc_options: []
133
+ require_paths:
134
+ - lib
135
+ required_ruby_version: !ruby/object:Gem::Requirement
136
+ requirements:
137
+ - - ">="
138
+ - !ruby/object:Gem::Version
139
+ version: '2.5'
140
+ required_rubygems_version: !ruby/object:Gem::Requirement
141
+ requirements:
142
+ - - ">="
143
+ - !ruby/object:Gem::Version
144
+ version: '0'
145
+ requirements: []
146
+ rubygems_version: 3.1.2
147
+ signing_key:
148
+ specification_version: 4
149
+ summary: An event-driven interface for MariaDB and MySQL servers.
150
+ test_files: []