sequel 2.2.0 → 2.3.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 +1551 -4
- data/README +306 -19
- data/Rakefile +84 -56
- data/bin/sequel +106 -0
- data/doc/cheat_sheet.rdoc +225 -0
- data/doc/dataset_filtering.rdoc +182 -0
- data/lib/sequel_core.rb +136 -0
- data/lib/sequel_core/adapters/adapter_skeleton.rb +54 -0
- data/lib/sequel_core/adapters/ado.rb +80 -0
- data/lib/sequel_core/adapters/db2.rb +148 -0
- data/lib/sequel_core/adapters/dbi.rb +117 -0
- data/lib/sequel_core/adapters/informix.rb +78 -0
- data/lib/sequel_core/adapters/jdbc.rb +186 -0
- data/lib/sequel_core/adapters/jdbc/mysql.rb +55 -0
- data/lib/sequel_core/adapters/jdbc/postgresql.rb +66 -0
- data/lib/sequel_core/adapters/jdbc/sqlite.rb +47 -0
- data/lib/sequel_core/adapters/mysql.rb +231 -0
- data/lib/sequel_core/adapters/odbc.rb +155 -0
- data/lib/sequel_core/adapters/odbc_mssql.rb +106 -0
- data/lib/sequel_core/adapters/openbase.rb +64 -0
- data/lib/sequel_core/adapters/oracle.rb +170 -0
- data/lib/sequel_core/adapters/postgres.rb +199 -0
- data/lib/sequel_core/adapters/shared/mysql.rb +275 -0
- data/lib/sequel_core/adapters/shared/postgres.rb +351 -0
- data/lib/sequel_core/adapters/shared/sqlite.rb +146 -0
- data/lib/sequel_core/adapters/sqlite.rb +138 -0
- data/lib/sequel_core/connection_pool.rb +194 -0
- data/lib/sequel_core/core_ext.rb +203 -0
- data/lib/sequel_core/core_sql.rb +184 -0
- data/lib/sequel_core/database.rb +471 -0
- data/lib/sequel_core/database/schema.rb +156 -0
- data/lib/sequel_core/dataset.rb +457 -0
- data/lib/sequel_core/dataset/callback.rb +13 -0
- data/lib/sequel_core/dataset/convenience.rb +245 -0
- data/lib/sequel_core/dataset/pagination.rb +96 -0
- data/lib/sequel_core/dataset/query.rb +41 -0
- data/lib/sequel_core/dataset/schema.rb +15 -0
- data/lib/sequel_core/dataset/sql.rb +889 -0
- data/lib/sequel_core/deprecated.rb +26 -0
- data/lib/sequel_core/exceptions.rb +42 -0
- data/lib/sequel_core/migration.rb +187 -0
- data/lib/sequel_core/object_graph.rb +216 -0
- data/lib/sequel_core/pretty_table.rb +71 -0
- data/lib/sequel_core/schema.rb +2 -0
- data/lib/sequel_core/schema/generator.rb +239 -0
- data/lib/sequel_core/schema/sql.rb +325 -0
- data/lib/sequel_core/sql.rb +812 -0
- data/lib/sequel_model.rb +5 -1
- data/lib/sequel_model/association_reflection.rb +3 -8
- data/lib/sequel_model/base.rb +15 -10
- data/lib/sequel_model/inflector.rb +3 -5
- data/lib/sequel_model/plugins.rb +1 -1
- data/lib/sequel_model/record.rb +11 -3
- data/lib/sequel_model/schema.rb +4 -4
- data/lib/sequel_model/validations.rb +6 -1
- data/spec/adapters/ado_spec.rb +17 -0
- data/spec/adapters/informix_spec.rb +96 -0
- data/spec/adapters/mysql_spec.rb +764 -0
- data/spec/adapters/oracle_spec.rb +222 -0
- data/spec/adapters/postgres_spec.rb +441 -0
- data/spec/adapters/spec_helper.rb +7 -0
- data/spec/adapters/sqlite_spec.rb +400 -0
- data/spec/integration/dataset_test.rb +51 -0
- data/spec/integration/eager_loader_test.rb +702 -0
- data/spec/integration/schema_test.rb +102 -0
- data/spec/integration/spec_helper.rb +44 -0
- data/spec/integration/type_test.rb +43 -0
- data/spec/rcov.opts +2 -0
- data/spec/sequel_core/connection_pool_spec.rb +363 -0
- data/spec/sequel_core/core_ext_spec.rb +156 -0
- data/spec/sequel_core/core_sql_spec.rb +427 -0
- data/spec/sequel_core/database_spec.rb +964 -0
- data/spec/sequel_core/dataset_spec.rb +2977 -0
- data/spec/sequel_core/expression_filters_spec.rb +346 -0
- data/spec/sequel_core/migration_spec.rb +261 -0
- data/spec/sequel_core/object_graph_spec.rb +234 -0
- data/spec/sequel_core/pretty_table_spec.rb +58 -0
- data/spec/sequel_core/schema_generator_spec.rb +122 -0
- data/spec/sequel_core/schema_spec.rb +497 -0
- data/spec/sequel_core/spec_helper.rb +51 -0
- data/spec/{association_reflection_spec.rb → sequel_model/association_reflection_spec.rb} +6 -6
- data/spec/{associations_spec.rb → sequel_model/associations_spec.rb} +47 -18
- data/spec/{base_spec.rb → sequel_model/base_spec.rb} +2 -1
- data/spec/{caching_spec.rb → sequel_model/caching_spec.rb} +0 -0
- data/spec/{dataset_methods_spec.rb → sequel_model/dataset_methods_spec.rb} +13 -1
- data/spec/{eager_loading_spec.rb → sequel_model/eager_loading_spec.rb} +75 -14
- data/spec/{hooks_spec.rb → sequel_model/hooks_spec.rb} +4 -4
- data/spec/sequel_model/inflector_spec.rb +119 -0
- data/spec/{model_spec.rb → sequel_model/model_spec.rb} +30 -11
- data/spec/{plugins_spec.rb → sequel_model/plugins_spec.rb} +0 -0
- data/spec/{record_spec.rb → sequel_model/record_spec.rb} +47 -6
- data/spec/{schema_spec.rb → sequel_model/schema_spec.rb} +18 -4
- data/spec/{spec_helper.rb → sequel_model/spec_helper.rb} +3 -2
- data/spec/{validations_spec.rb → sequel_model/validations_spec.rb} +37 -17
- data/spec/spec_config.rb +9 -0
- data/spec/spec_config.rb.example +10 -0
- metadata +110 -37
- data/spec/inflector_spec.rb +0 -34
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
require 'informix'
|
|
2
|
+
|
|
3
|
+
module Sequel
|
|
4
|
+
module Informix
|
|
5
|
+
class Database < Sequel::Database
|
|
6
|
+
set_adapter_scheme :informix
|
|
7
|
+
|
|
8
|
+
# AUTO_INCREMENT = 'IDENTITY(1,1)'.freeze
|
|
9
|
+
#
|
|
10
|
+
# def auto_increment_sql
|
|
11
|
+
# AUTO_INCREMENT
|
|
12
|
+
# end
|
|
13
|
+
|
|
14
|
+
def connect
|
|
15
|
+
::Informix.connect(@opts[:database], @opts[:user], @opts[:password])
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def disconnect
|
|
19
|
+
@pool.disconnect {|c| c.close}
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def dataset(opts = nil)
|
|
23
|
+
Sequel::Informix::Dataset.new(self, opts)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Returns number of rows affected
|
|
27
|
+
def execute_dui(sql)
|
|
28
|
+
log_info(sql)
|
|
29
|
+
@pool.hold {|c| c.immediate(sql)}
|
|
30
|
+
end
|
|
31
|
+
alias_method :do, :execute_dui
|
|
32
|
+
|
|
33
|
+
def execute(sql, &block)
|
|
34
|
+
log_info(sql)
|
|
35
|
+
@pool.hold {|c| block[c.cursor(sql)]}
|
|
36
|
+
end
|
|
37
|
+
alias_method :query, :execute
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
class Dataset < Sequel::Dataset
|
|
41
|
+
def literal(v)
|
|
42
|
+
case v
|
|
43
|
+
when Time
|
|
44
|
+
literal(v.iso8601)
|
|
45
|
+
when Date, DateTime
|
|
46
|
+
literal(v.to_s)
|
|
47
|
+
else
|
|
48
|
+
super
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def select_sql(opts = nil)
|
|
53
|
+
limit = opts.delete(:limit)
|
|
54
|
+
offset = opts.delete(:offset)
|
|
55
|
+
sql = super
|
|
56
|
+
if limit
|
|
57
|
+
limit = "FIRST #{limit}"
|
|
58
|
+
offset = offset ? "SKIP #{offset}" : ""
|
|
59
|
+
sql.sub!(/^select /i,"SELECT #{offset} #{limit} ")
|
|
60
|
+
end
|
|
61
|
+
sql
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def fetch_rows(sql, &block)
|
|
65
|
+
@db.synchronize do
|
|
66
|
+
@db.execute(sql) do |cursor|
|
|
67
|
+
begin
|
|
68
|
+
cursor.open.each_hash(&block)
|
|
69
|
+
ensure
|
|
70
|
+
cursor.drop
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
self
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
require 'java'
|
|
2
|
+
|
|
3
|
+
module Sequel
|
|
4
|
+
module JDBC
|
|
5
|
+
module JavaLang; include_package 'java.lang'; end
|
|
6
|
+
module JavaSQL; include_package 'java.sql'; end
|
|
7
|
+
DATABASE_SETUP = {:postgresql=>proc do |db|
|
|
8
|
+
require 'sequel_core/adapters/jdbc/postgresql'
|
|
9
|
+
db.extend(Sequel::JDBC::Postgres::DatabaseMethods)
|
|
10
|
+
JDBC.load_gem('postgres')
|
|
11
|
+
org.postgresql.Driver
|
|
12
|
+
end,
|
|
13
|
+
:mysql=>proc do |db|
|
|
14
|
+
require 'sequel_core/adapters/jdbc/mysql'
|
|
15
|
+
db.extend(Sequel::JDBC::MySQL::DatabaseMethods)
|
|
16
|
+
JDBC.load_gem('mysql')
|
|
17
|
+
com.mysql.jdbc.Driver
|
|
18
|
+
end,
|
|
19
|
+
:sqlite=>proc do |db|
|
|
20
|
+
require 'sequel_core/adapters/jdbc/sqlite'
|
|
21
|
+
db.extend(Sequel::JDBC::SQLite::DatabaseMethods)
|
|
22
|
+
JDBC.load_gem('sqlite3')
|
|
23
|
+
org.sqlite.JDBC
|
|
24
|
+
end,
|
|
25
|
+
:oracle=>proc{oracle.jdbc.driver.OracleDriver},
|
|
26
|
+
:sqlserver=>proc{com.microsoft.sqlserver.jdbc.SQLServerDriver}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
def self.load_gem(name)
|
|
30
|
+
begin
|
|
31
|
+
require "jdbc/#{name}"
|
|
32
|
+
rescue LoadError
|
|
33
|
+
# jdbc gem not used, hopefully the user has the .jar in their CLASSPATH
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
class Database < Sequel::Database
|
|
38
|
+
set_adapter_scheme :jdbc
|
|
39
|
+
|
|
40
|
+
# The type of database we are connecting to
|
|
41
|
+
attr_reader :database_type
|
|
42
|
+
|
|
43
|
+
def initialize(opts)
|
|
44
|
+
super(opts)
|
|
45
|
+
raise(Error, "No connection string specified") unless uri
|
|
46
|
+
if match = /\Ajdbc:([^:]+)/.match(uri) and prok = DATABASE_SETUP[match[1].to_sym]
|
|
47
|
+
prok.call(self)
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def connect
|
|
52
|
+
setup_connection(JavaSQL::DriverManager.getConnection(uri))
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def dataset(opts = nil)
|
|
56
|
+
JDBC::Dataset.new(self, opts)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def disconnect
|
|
60
|
+
@pool.disconnect {|c| c.close}
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def execute(sql)
|
|
64
|
+
log_info(sql)
|
|
65
|
+
@pool.hold do |conn|
|
|
66
|
+
stmt = conn.createStatement
|
|
67
|
+
begin
|
|
68
|
+
yield stmt.executeQuery(sql)
|
|
69
|
+
rescue NativeException, JavaSQL::SQLException => e
|
|
70
|
+
raise Error, e.message
|
|
71
|
+
ensure
|
|
72
|
+
stmt.close
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def execute_ddl(sql)
|
|
78
|
+
log_info(sql)
|
|
79
|
+
@pool.hold do |conn|
|
|
80
|
+
stmt = conn.createStatement
|
|
81
|
+
begin
|
|
82
|
+
stmt.execute(sql)
|
|
83
|
+
rescue NativeException, JavaSQL::SQLException => e
|
|
84
|
+
raise Error, e.message
|
|
85
|
+
ensure
|
|
86
|
+
stmt.close
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def execute_dui(sql)
|
|
92
|
+
log_info(sql)
|
|
93
|
+
@pool.hold do |conn|
|
|
94
|
+
stmt = conn.createStatement
|
|
95
|
+
begin
|
|
96
|
+
stmt.executeUpdate(sql)
|
|
97
|
+
rescue NativeException, JavaSQL::SQLException => e
|
|
98
|
+
raise Error, e.message
|
|
99
|
+
ensure
|
|
100
|
+
stmt.close
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def setup_connection(conn)
|
|
106
|
+
conn
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def transaction
|
|
110
|
+
@pool.hold do |conn|
|
|
111
|
+
@transactions ||= []
|
|
112
|
+
return yield(conn) if @transactions.include?(Thread.current)
|
|
113
|
+
stmt = conn.createStatement
|
|
114
|
+
begin
|
|
115
|
+
log_info(Sequel::Database::SQL_BEGIN)
|
|
116
|
+
stmt.execute(Sequel::Database::SQL_BEGIN)
|
|
117
|
+
@transactions << Thread.current
|
|
118
|
+
yield(conn)
|
|
119
|
+
rescue Exception => e
|
|
120
|
+
log_info(Sequel::Database::SQL_ROLLBACK)
|
|
121
|
+
stmt.execute(Sequel::Database::SQL_ROLLBACK)
|
|
122
|
+
raise e unless Error::Rollback === e
|
|
123
|
+
ensure
|
|
124
|
+
unless e
|
|
125
|
+
log_info(Sequel::Database::SQL_COMMIT)
|
|
126
|
+
stmt.execute(Sequel::Database::SQL_COMMIT)
|
|
127
|
+
end
|
|
128
|
+
stmt.close
|
|
129
|
+
@transactions.delete(Thread.current)
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def uri
|
|
135
|
+
ur = @opts[:uri] || @opts[:url] || @opts[:database]
|
|
136
|
+
ur =~ /^\Ajdbc:/ ? ur : "jdbc:#{ur}"
|
|
137
|
+
end
|
|
138
|
+
alias url uri
|
|
139
|
+
|
|
140
|
+
private
|
|
141
|
+
|
|
142
|
+
def connection_pool_default_options
|
|
143
|
+
super.merge(:pool_convert_exceptions=>false)
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
class Dataset < Sequel::Dataset
|
|
148
|
+
def literal(v)
|
|
149
|
+
case v
|
|
150
|
+
when Time
|
|
151
|
+
literal(v.iso8601)
|
|
152
|
+
when Date, DateTime, Java::JavaSql::Timestamp
|
|
153
|
+
literal(v.to_s)
|
|
154
|
+
else
|
|
155
|
+
super
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
def fetch_rows(sql, &block)
|
|
160
|
+
@db.synchronize do
|
|
161
|
+
@db.execute(sql) do |result|
|
|
162
|
+
# get column names
|
|
163
|
+
meta = result.getMetaData
|
|
164
|
+
column_count = meta.getColumnCount
|
|
165
|
+
@columns = []
|
|
166
|
+
column_count.times {|i| @columns << meta.getColumnName(i+1).to_sym}
|
|
167
|
+
|
|
168
|
+
# get rows
|
|
169
|
+
while result.next
|
|
170
|
+
row = {}
|
|
171
|
+
@columns.each_with_index {|v, i| row[v] = result.getObject(i+1)}
|
|
172
|
+
yield row
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
self
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
class Java::JavaSQL::Timestamp
|
|
183
|
+
def usec
|
|
184
|
+
getNanos/1000
|
|
185
|
+
end
|
|
186
|
+
end
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
require 'sequel_core/adapters/shared/mysql'
|
|
2
|
+
|
|
3
|
+
module Sequel
|
|
4
|
+
module JDBC
|
|
5
|
+
module MySQL
|
|
6
|
+
module DatabaseMethods
|
|
7
|
+
include Sequel::MySQL::DatabaseMethods
|
|
8
|
+
|
|
9
|
+
def dataset(opts=nil)
|
|
10
|
+
Sequel::JDBC::MySQL::Dataset.new(self, opts)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def execute_insert(sql)
|
|
14
|
+
begin
|
|
15
|
+
log_info(sql)
|
|
16
|
+
@pool.hold do |conn|
|
|
17
|
+
stmt = conn.createStatement
|
|
18
|
+
begin
|
|
19
|
+
stmt.executeUpdate(sql)
|
|
20
|
+
rs = stmt.executeQuery('SELECT LAST_INSERT_ID()')
|
|
21
|
+
rs.next
|
|
22
|
+
rs.getInt(1)
|
|
23
|
+
rescue NativeException, JavaSQL::SQLException => e
|
|
24
|
+
raise Error, e.message
|
|
25
|
+
ensure
|
|
26
|
+
stmt.close
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
rescue NativeException, JavaSQL::SQLException => e
|
|
30
|
+
raise Error, "#{sql}\r\n#{e.message}"
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
private
|
|
35
|
+
|
|
36
|
+
def database_name
|
|
37
|
+
u = URI.parse(uri.sub(/\Ajdbc:/, ''))
|
|
38
|
+
(m = /\/(.*)/.match(u.path)) && m[1]
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
class Dataset < JDBC::Dataset
|
|
43
|
+
include Sequel::MySQL::DatasetMethods
|
|
44
|
+
|
|
45
|
+
def insert(*values)
|
|
46
|
+
@db.execute_insert(insert_sql(*values))
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def replace(*args)
|
|
50
|
+
@db.execute_insert(replace_sql(*args))
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
require 'sequel_core/adapters/shared/postgres'
|
|
2
|
+
|
|
3
|
+
module Sequel
|
|
4
|
+
Postgres::CONVERTED_EXCEPTIONS << NativeException
|
|
5
|
+
|
|
6
|
+
module JDBC
|
|
7
|
+
module Postgres
|
|
8
|
+
module AdapterMethods
|
|
9
|
+
include Sequel::Postgres::AdapterMethods
|
|
10
|
+
|
|
11
|
+
def execute(sql, method=:execute)
|
|
12
|
+
method = :executeQuery if block_given?
|
|
13
|
+
stmt = createStatement
|
|
14
|
+
begin
|
|
15
|
+
rows = stmt.send(method, sql)
|
|
16
|
+
yield(rows) if block_given?
|
|
17
|
+
rescue NativeException => e
|
|
18
|
+
raise Error, e.message
|
|
19
|
+
ensure
|
|
20
|
+
stmt.close
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def result_set_values(r, *vals)
|
|
25
|
+
return if r.nil?
|
|
26
|
+
r.next
|
|
27
|
+
return if r.getRow == 0
|
|
28
|
+
case vals.length
|
|
29
|
+
when 1
|
|
30
|
+
r.getString(vals.first+1)
|
|
31
|
+
else
|
|
32
|
+
vals.collect{|col| r.getString(col+1)}
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
module DatabaseMethods
|
|
38
|
+
include Sequel::Postgres::DatabaseMethods
|
|
39
|
+
|
|
40
|
+
def dataset(opts=nil)
|
|
41
|
+
Sequel::JDBC::Postgres::Dataset.new(self, opts)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def setup_connection(conn)
|
|
45
|
+
conn.extend(Sequel::JDBC::Postgres::AdapterMethods)
|
|
46
|
+
conn
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
class Dataset < JDBC::Dataset
|
|
51
|
+
include Sequel::Postgres::DatasetMethods
|
|
52
|
+
|
|
53
|
+
def literal(v)
|
|
54
|
+
case v
|
|
55
|
+
when SQL::Blob
|
|
56
|
+
"'#{v.gsub(/[\000-\037\047\134\177-\377]/){|b| "\\#{ b[0].to_s(8).rjust(3, '0') }"}}'"
|
|
57
|
+
when Java::JavaSql::Timestamp
|
|
58
|
+
"TIMESTAMP #{literal(v.to_s)}"
|
|
59
|
+
else
|
|
60
|
+
super
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
require 'sequel_core/adapters/shared/sqlite'
|
|
2
|
+
|
|
3
|
+
module Sequel
|
|
4
|
+
module JDBC
|
|
5
|
+
module SQLite
|
|
6
|
+
module DatabaseMethods
|
|
7
|
+
include Sequel::SQLite::DatabaseMethods
|
|
8
|
+
|
|
9
|
+
def dataset(opts=nil)
|
|
10
|
+
Sequel::JDBC::SQLite::Dataset.new(self, opts)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def execute_insert(sql)
|
|
14
|
+
begin
|
|
15
|
+
log_info(sql)
|
|
16
|
+
@pool.hold do |conn|
|
|
17
|
+
stmt = conn.createStatement
|
|
18
|
+
begin
|
|
19
|
+
stmt.executeUpdate(sql)
|
|
20
|
+
rs = stmt.executeQuery('SELECT last_insert_rowid()')
|
|
21
|
+
rs.next
|
|
22
|
+
rs.getInt(1)
|
|
23
|
+
rescue NativeException, JavaSQL::SQLException => e
|
|
24
|
+
raise Error, e.message
|
|
25
|
+
ensure
|
|
26
|
+
stmt.close
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
rescue NativeException, JavaSQL::SQLException => e
|
|
30
|
+
raise Error, "#{sql}\r\n#{e.message}"
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
private
|
|
35
|
+
|
|
36
|
+
def connection_pool_default_options
|
|
37
|
+
o = super
|
|
38
|
+
uri == 'jdbc:sqlite::memory:' ? o.merge(:max_connections=>1) : o
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
class Dataset < JDBC::Dataset
|
|
43
|
+
include Sequel::SQLite::DatasetMethods
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
require 'mysql'
|
|
2
|
+
require 'sequel_core/adapters/shared/mysql'
|
|
3
|
+
|
|
4
|
+
# Monkey patch Mysql::Result to yield hashes with symbol keys
|
|
5
|
+
class Mysql::Result
|
|
6
|
+
MYSQL_TYPES = {
|
|
7
|
+
0 => :to_d, # MYSQL_TYPE_DECIMAL
|
|
8
|
+
1 => :to_i, # MYSQL_TYPE_TINY
|
|
9
|
+
2 => :to_i, # MYSQL_TYPE_SHORT
|
|
10
|
+
3 => :to_i, # MYSQL_TYPE_LONG
|
|
11
|
+
4 => :to_f, # MYSQL_TYPE_FLOAT
|
|
12
|
+
5 => :to_f, # MYSQL_TYPE_DOUBLE
|
|
13
|
+
# 6 => ??, # MYSQL_TYPE_NULL
|
|
14
|
+
7 => :to_sequel_time, # MYSQL_TYPE_TIMESTAMP
|
|
15
|
+
8 => :to_i, # MYSQL_TYPE_LONGLONG
|
|
16
|
+
9 => :to_i, # MYSQL_TYPE_INT24
|
|
17
|
+
10 => :to_date, # MYSQL_TYPE_DATE
|
|
18
|
+
11 => :to_time, # MYSQL_TYPE_TIME
|
|
19
|
+
12 => :to_sequel_time, # MYSQL_TYPE_DATETIME
|
|
20
|
+
13 => :to_i, # MYSQL_TYPE_YEAR
|
|
21
|
+
14 => :to_date, # MYSQL_TYPE_NEWDATE
|
|
22
|
+
# 15 => :to_s # MYSQL_TYPE_VARCHAR
|
|
23
|
+
# 16 => :to_s, # MYSQL_TYPE_BIT
|
|
24
|
+
246 => :to_d, # MYSQL_TYPE_NEWDECIMAL
|
|
25
|
+
247 => :to_i, # MYSQL_TYPE_ENUM
|
|
26
|
+
248 => :to_i, # MYSQL_TYPE_SET
|
|
27
|
+
249 => :to_blob, # MYSQL_TYPE_TINY_BLOB
|
|
28
|
+
250 => :to_blob, # MYSQL_TYPE_MEDIUM_BLOB
|
|
29
|
+
251 => :to_blob, # MYSQL_TYPE_LONG_BLOB
|
|
30
|
+
252 => :to_blob, # MYSQL_TYPE_BLOB
|
|
31
|
+
# 253 => :to_s, # MYSQL_TYPE_VAR_STRING
|
|
32
|
+
# 254 => :to_s, # MYSQL_TYPE_STRING
|
|
33
|
+
# 255 => :to_s # MYSQL_TYPE_GEOMETRY
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
def convert_type(v, type)
|
|
37
|
+
if v
|
|
38
|
+
if type == 1 && Sequel.convert_tinyint_to_bool
|
|
39
|
+
# We special case tinyint here to avoid adding
|
|
40
|
+
# a method to an ancestor of Fixnum
|
|
41
|
+
v.to_i == 0 ? false : true
|
|
42
|
+
else
|
|
43
|
+
(t = MYSQL_TYPES[type]) ? v.send(t) : v
|
|
44
|
+
end
|
|
45
|
+
else
|
|
46
|
+
nil
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def columns(with_table = nil)
|
|
51
|
+
unless @columns
|
|
52
|
+
@column_types = []
|
|
53
|
+
@columns = fetch_fields.map do |f|
|
|
54
|
+
@column_types << f.type
|
|
55
|
+
(with_table ? "#{f.table}.#{f.name}" : f.name).to_sym
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
@columns
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def each_array(with_table = nil)
|
|
62
|
+
c = columns
|
|
63
|
+
while row = fetch_row
|
|
64
|
+
c.each_with_index do |f, i|
|
|
65
|
+
if (t = MYSQL_TYPES[@column_types[i]]) && (v = row[i])
|
|
66
|
+
row[i] = v.send(t)
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
yield row
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def sequel_each_hash(with_table = nil)
|
|
74
|
+
c = columns
|
|
75
|
+
while row = fetch_row
|
|
76
|
+
h = {}
|
|
77
|
+
c.each_with_index {|f, i| h[f] = convert_type(row[i], @column_types[i])}
|
|
78
|
+
yield h
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
module Sequel
|
|
85
|
+
module MySQL
|
|
86
|
+
class Database < Sequel::Database
|
|
87
|
+
include Sequel::MySQL::DatabaseMethods
|
|
88
|
+
|
|
89
|
+
set_adapter_scheme :mysql
|
|
90
|
+
|
|
91
|
+
def connect
|
|
92
|
+
conn = Mysql.init
|
|
93
|
+
conn.options(Mysql::OPT_LOCAL_INFILE, "client")
|
|
94
|
+
conn.real_connect(
|
|
95
|
+
@opts[:host] || 'localhost',
|
|
96
|
+
@opts[:user],
|
|
97
|
+
@opts[:password],
|
|
98
|
+
@opts[:database],
|
|
99
|
+
@opts[:port],
|
|
100
|
+
@opts[:socket],
|
|
101
|
+
Mysql::CLIENT_MULTI_RESULTS +
|
|
102
|
+
Mysql::CLIENT_MULTI_STATEMENTS +
|
|
103
|
+
Mysql::CLIENT_COMPRESS
|
|
104
|
+
)
|
|
105
|
+
conn.query_with_result = false
|
|
106
|
+
if encoding = @opts[:encoding] || @opts[:charset]
|
|
107
|
+
conn.query("set character_set_connection = '#{encoding}'")
|
|
108
|
+
conn.query("set character_set_client = '#{encoding}'")
|
|
109
|
+
conn.query("set character_set_database = '#{encoding}'")
|
|
110
|
+
conn.query("set character_set_server = '#{encoding}'")
|
|
111
|
+
conn.query("set character_set_results = '#{encoding}'")
|
|
112
|
+
end
|
|
113
|
+
conn.reconnect = true
|
|
114
|
+
conn
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def dataset(opts = nil)
|
|
118
|
+
MySQL::Dataset.new(self, opts)
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def disconnect
|
|
122
|
+
@pool.disconnect {|c| c.close}
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def execute(sql, &block)
|
|
126
|
+
begin
|
|
127
|
+
log_info(sql)
|
|
128
|
+
@pool.hold do |conn|
|
|
129
|
+
conn.query(sql)
|
|
130
|
+
block[conn] if block
|
|
131
|
+
end
|
|
132
|
+
rescue Mysql::Error => e
|
|
133
|
+
raise Error.new(e.message)
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
def execute_select(sql, &block)
|
|
138
|
+
execute(sql) do |c|
|
|
139
|
+
r = c.use_result
|
|
140
|
+
begin
|
|
141
|
+
block[r]
|
|
142
|
+
ensure
|
|
143
|
+
r.free
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def server_version
|
|
149
|
+
@server_version ||= (synchronize{|conn| conn.server_version if conn.respond_to?(:server_version)} || super)
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
def tables
|
|
153
|
+
@pool.hold do |conn|
|
|
154
|
+
conn.list_tables.map {|t| t.to_sym}
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
def transaction
|
|
159
|
+
@pool.hold do |conn|
|
|
160
|
+
@transactions ||= []
|
|
161
|
+
return yield(conn) if @transactions.include? Thread.current
|
|
162
|
+
log_info(SQL_BEGIN)
|
|
163
|
+
conn.query(SQL_BEGIN)
|
|
164
|
+
begin
|
|
165
|
+
@transactions << Thread.current
|
|
166
|
+
yield(conn)
|
|
167
|
+
rescue ::Exception => e
|
|
168
|
+
log_info(SQL_ROLLBACK)
|
|
169
|
+
conn.query(SQL_ROLLBACK)
|
|
170
|
+
raise (Mysql::Error === e ? Error.new(e.message) : e) unless Error::Rollback === e
|
|
171
|
+
ensure
|
|
172
|
+
unless e
|
|
173
|
+
log_info(SQL_COMMIT)
|
|
174
|
+
conn.query(SQL_COMMIT)
|
|
175
|
+
end
|
|
176
|
+
@transactions.delete(Thread.current)
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
private
|
|
182
|
+
|
|
183
|
+
def connection_pool_default_options
|
|
184
|
+
super.merge(:pool_convert_exceptions=>false)
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
def database_name
|
|
188
|
+
@opts[:database]
|
|
189
|
+
end
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
class Dataset < Sequel::Dataset
|
|
193
|
+
include Sequel::MySQL::DatasetMethods
|
|
194
|
+
|
|
195
|
+
def delete(opts = nil)
|
|
196
|
+
@db.execute(delete_sql(opts)) {|c| c.affected_rows}
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
def fetch_rows(sql)
|
|
200
|
+
@db.execute_select(sql) do |r|
|
|
201
|
+
@columns = r.columns
|
|
202
|
+
r.sequel_each_hash {|row| yield row}
|
|
203
|
+
end
|
|
204
|
+
self
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
def insert(*values)
|
|
208
|
+
@db.execute(insert_sql(*values)) {|c| c.insert_id}
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
def literal(v)
|
|
212
|
+
case v
|
|
213
|
+
when LiteralString
|
|
214
|
+
v
|
|
215
|
+
when String
|
|
216
|
+
"'#{::Mysql.quote(v)}'"
|
|
217
|
+
else
|
|
218
|
+
super
|
|
219
|
+
end
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
def replace(*args)
|
|
223
|
+
@db.execute(replace_sql(*args)) {|c| c.insert_id}
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
def update(*args)
|
|
227
|
+
@db.execute(update_sql(*args)) {|c| c.affected_rows}
|
|
228
|
+
end
|
|
229
|
+
end
|
|
230
|
+
end
|
|
231
|
+
end
|