sequel_core 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/CHANGELOG +1003 -0
- data/COPYING +18 -0
- data/README +81 -0
- data/Rakefile +176 -0
- data/bin/sequel +41 -0
- data/lib/sequel_core.rb +59 -0
- data/lib/sequel_core/adapters/adapter_skeleton.rb +68 -0
- data/lib/sequel_core/adapters/ado.rb +100 -0
- data/lib/sequel_core/adapters/db2.rb +158 -0
- data/lib/sequel_core/adapters/dbi.rb +126 -0
- data/lib/sequel_core/adapters/informix.rb +87 -0
- data/lib/sequel_core/adapters/jdbc.rb +108 -0
- data/lib/sequel_core/adapters/mysql.rb +269 -0
- data/lib/sequel_core/adapters/odbc.rb +145 -0
- data/lib/sequel_core/adapters/odbc_mssql.rb +93 -0
- data/lib/sequel_core/adapters/openbase.rb +90 -0
- data/lib/sequel_core/adapters/oracle.rb +99 -0
- data/lib/sequel_core/adapters/postgres.rb +519 -0
- data/lib/sequel_core/adapters/sqlite.rb +192 -0
- data/lib/sequel_core/array_keys.rb +296 -0
- data/lib/sequel_core/connection_pool.rb +152 -0
- data/lib/sequel_core/core_ext.rb +59 -0
- data/lib/sequel_core/core_sql.rb +191 -0
- data/lib/sequel_core/database.rb +433 -0
- data/lib/sequel_core/dataset.rb +409 -0
- data/lib/sequel_core/dataset/convenience.rb +321 -0
- data/lib/sequel_core/dataset/sequelizer.rb +354 -0
- data/lib/sequel_core/dataset/sql.rb +586 -0
- data/lib/sequel_core/exceptions.rb +45 -0
- data/lib/sequel_core/migration.rb +191 -0
- data/lib/sequel_core/model.rb +8 -0
- data/lib/sequel_core/pretty_table.rb +73 -0
- data/lib/sequel_core/schema.rb +8 -0
- data/lib/sequel_core/schema/schema_generator.rb +131 -0
- data/lib/sequel_core/schema/schema_sql.rb +131 -0
- data/lib/sequel_core/worker.rb +58 -0
- data/spec/adapters/informix_spec.rb +139 -0
- data/spec/adapters/mysql_spec.rb +330 -0
- data/spec/adapters/oracle_spec.rb +130 -0
- data/spec/adapters/postgres_spec.rb +189 -0
- data/spec/adapters/sqlite_spec.rb +345 -0
- data/spec/array_keys_spec.rb +679 -0
- data/spec/connection_pool_spec.rb +356 -0
- data/spec/core_ext_spec.rb +67 -0
- data/spec/core_sql_spec.rb +301 -0
- data/spec/database_spec.rb +812 -0
- data/spec/dataset_spec.rb +2381 -0
- data/spec/migration_spec.rb +261 -0
- data/spec/pretty_table_spec.rb +66 -0
- data/spec/rcov.opts +4 -0
- data/spec/schema_generator_spec.rb +86 -0
- data/spec/schema_spec.rb +230 -0
- data/spec/sequelizer_spec.rb +448 -0
- data/spec/spec.opts +5 -0
- data/spec/spec_helper.rb +44 -0
- data/spec/worker_spec.rb +96 -0
- metadata +162 -0
@@ -0,0 +1,100 @@
|
|
1
|
+
require 'win32ole'
|
2
|
+
|
3
|
+
module Sequel
|
4
|
+
# The ADO adapter provides connectivity to ADO databases in Windows. ADO
|
5
|
+
# databases can be opened using a URL with the ado schema:
|
6
|
+
#
|
7
|
+
# DB = Sequel.open('ado://mydb')
|
8
|
+
#
|
9
|
+
# or using the Sequel.ado method:
|
10
|
+
#
|
11
|
+
# DB = Sequel.ado('mydb')
|
12
|
+
#
|
13
|
+
module ADO
|
14
|
+
class Database < Sequel::Database
|
15
|
+
set_adapter_scheme :ado
|
16
|
+
|
17
|
+
AUTO_INCREMENT = 'IDENTITY(1,1)'.freeze
|
18
|
+
|
19
|
+
def auto_increment_sql
|
20
|
+
AUTO_INCREMENT
|
21
|
+
end
|
22
|
+
|
23
|
+
def connect
|
24
|
+
dbname = @opts[:database]
|
25
|
+
handle = WIN32OLE.new('ADODB.Connection')
|
26
|
+
handle.Open(dbname)
|
27
|
+
handle
|
28
|
+
end
|
29
|
+
|
30
|
+
def disconnect
|
31
|
+
# how do we disconnect? couldn't find anything in the docs
|
32
|
+
end
|
33
|
+
|
34
|
+
def dataset(opts = nil)
|
35
|
+
ADO::Dataset.new(self, opts)
|
36
|
+
end
|
37
|
+
|
38
|
+
def execute(sql)
|
39
|
+
@logger.info(sql) if @logger
|
40
|
+
@pool.hold {|conn| conn.Execute(sql)}
|
41
|
+
end
|
42
|
+
|
43
|
+
alias_method :do, :execute
|
44
|
+
end
|
45
|
+
|
46
|
+
class Dataset < Sequel::Dataset
|
47
|
+
def literal(v)
|
48
|
+
case v
|
49
|
+
when Time
|
50
|
+
literal(v.iso8601)
|
51
|
+
else
|
52
|
+
super
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def fetch_rows(sql, &block)
|
57
|
+
@db.synchronize do
|
58
|
+
s = @db.execute sql
|
59
|
+
|
60
|
+
@columns = s.Fields.extend(Enumerable).map {|x| x.Name.to_sym}
|
61
|
+
|
62
|
+
s.moveFirst
|
63
|
+
s.getRows.transpose.each {|r| yield hash_row(r)}
|
64
|
+
end
|
65
|
+
self
|
66
|
+
end
|
67
|
+
|
68
|
+
def hash_row(row)
|
69
|
+
@columns.inject({}) do |m, c|
|
70
|
+
m[c] = row.shift
|
71
|
+
m
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def array_tuples_fetch_rows(sql, &block)
|
76
|
+
@db.synchronize do
|
77
|
+
s = @db.execute sql
|
78
|
+
|
79
|
+
@columns = s.Fields.extend(Enumerable).map {|x| x.Name.to_sym}
|
80
|
+
|
81
|
+
s.moveFirst
|
82
|
+
s.getRows.transpose.each {|r| r.keys = @columns; yield r}
|
83
|
+
end
|
84
|
+
self
|
85
|
+
end
|
86
|
+
|
87
|
+
def insert(*values)
|
88
|
+
@db.do insert_sql(*values)
|
89
|
+
end
|
90
|
+
|
91
|
+
def update(*args, &block)
|
92
|
+
@db.do update_sql(*args, &block)
|
93
|
+
end
|
94
|
+
|
95
|
+
def delete(opts = nil)
|
96
|
+
@db.do delete_sql(opts)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,158 @@
|
|
1
|
+
require 'db2/db2cli'
|
2
|
+
|
3
|
+
module Sequel
|
4
|
+
module DB2
|
5
|
+
class Database < Sequel::Database
|
6
|
+
set_adapter_scheme :db2
|
7
|
+
include DB2CLI
|
8
|
+
|
9
|
+
# AUTO_INCREMENT = 'IDENTITY(1,1)'.freeze
|
10
|
+
#
|
11
|
+
# def auto_increment_sql
|
12
|
+
# AUTO_INCREMENT
|
13
|
+
# end
|
14
|
+
|
15
|
+
def check_error(rc, msg)
|
16
|
+
case rc
|
17
|
+
when SQL_SUCCESS, SQL_SUCCESS_WITH_INFO
|
18
|
+
nil
|
19
|
+
else
|
20
|
+
raise Error, msg
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
rc, @@env = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE)
|
25
|
+
check_error(rc, "Could not allocate DB2 environment")
|
26
|
+
|
27
|
+
def connect
|
28
|
+
rc, dbc = SQLAllocHandle(SQL_HANDLE_DBC, @@env)
|
29
|
+
check_error(rc, "Could not allocate database connection")
|
30
|
+
|
31
|
+
rc = SQLConnect(dbc, @opts[:database], @opts[:user], @opts[:password])
|
32
|
+
check_error(rc, "Could not connect to database")
|
33
|
+
|
34
|
+
dbc
|
35
|
+
end
|
36
|
+
|
37
|
+
def disconnect
|
38
|
+
@pool.disconnect do |conn|
|
39
|
+
rc = SQLDisconnect(conn)
|
40
|
+
check_error(rc, "Could not disconnect from database")
|
41
|
+
|
42
|
+
rc = SQLFreeHandle(SQL_HANDLE_DBC, conn)
|
43
|
+
check_error(rc, "Could not free Database handle")
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_connection
|
48
|
+
@pool.hold {|conn|}
|
49
|
+
true
|
50
|
+
end
|
51
|
+
|
52
|
+
def dataset(opts = nil)
|
53
|
+
DB2::Dataset.new(self, opts)
|
54
|
+
end
|
55
|
+
|
56
|
+
def execute(sql, &block)
|
57
|
+
@logger.info(sql) if @logger
|
58
|
+
@pool.hold do |conn|
|
59
|
+
rc, sth = SQLAllocHandle(SQL_HANDLE_STMT, @handle)
|
60
|
+
check_error(rc, "Could not allocate statement")
|
61
|
+
|
62
|
+
begin
|
63
|
+
rc = SQLExecDirect(sth, sql)
|
64
|
+
check_error(rc, "Could not execute statement")
|
65
|
+
|
66
|
+
block[sth] if block
|
67
|
+
|
68
|
+
rc, rpc = SQLRowCount(sth)
|
69
|
+
check_error(rc, "Could not get RPC")
|
70
|
+
rpc
|
71
|
+
ensure
|
72
|
+
rc = SQLFreeHandle(SQL_HANDLE_STMT, sth)
|
73
|
+
check_error(rc, "Could not free statement")
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
alias_method :do, :execute
|
78
|
+
end
|
79
|
+
|
80
|
+
class Dataset < Sequel::Dataset
|
81
|
+
def literal(v)
|
82
|
+
case v
|
83
|
+
when Time
|
84
|
+
literal(v.iso8601)
|
85
|
+
else
|
86
|
+
super
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def fetch_rows(sql, &block)
|
91
|
+
@db.synchronize do
|
92
|
+
@db.execute(sql) do |sth|
|
93
|
+
@column_info = get_column_info(sth)
|
94
|
+
@columns = @column_info.map {|c| c[:name]}
|
95
|
+
while (rc = SQLFetch(@handle)) != SQL_NO_DATA_FOUND
|
96
|
+
@db.check_error(rc, "Could not fetch row")
|
97
|
+
yield hash_row(sth)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
self
|
102
|
+
end
|
103
|
+
|
104
|
+
MAX_COL_SIZE = 256
|
105
|
+
|
106
|
+
def get_column_info(sth)
|
107
|
+
rc, column_count = SQLNumResultCols(sth)
|
108
|
+
@db.check_error(rc, "Could not get number of result columns")
|
109
|
+
|
110
|
+
(1..column_count).map do |i|
|
111
|
+
rc, name, buflen, datatype, size, digits, nullable = SQLDescribeCol(sth, i, MAX_COL_SIZE)
|
112
|
+
@b.check_error(rc, "Could not describe column")
|
113
|
+
|
114
|
+
{:name => name, :db2_type => datatype, :precision => size}
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def hash_row(sth)
|
119
|
+
row = {}
|
120
|
+
@column_info.each_with_index do |c, i|
|
121
|
+
rc, v = SQLGetData(sth, i+1, c[:db2_type], c[:precision])
|
122
|
+
@db.check_error(rc, "Could not get data")
|
123
|
+
|
124
|
+
@row[c[:name]] = convert_type(v)
|
125
|
+
end
|
126
|
+
row
|
127
|
+
end
|
128
|
+
|
129
|
+
def convert_type(v)
|
130
|
+
case v
|
131
|
+
when DB2CLI::Date
|
132
|
+
DBI::Date.new(v.year, v.month, v.day)
|
133
|
+
when DB2CLI::Time
|
134
|
+
DBI::Time.new(v.hour, v.minute, v.second)
|
135
|
+
when DB2CLI::Timestamp
|
136
|
+
DBI::Timestamp.new(v.year, v.month, v.day,
|
137
|
+
v.hour, v.minute, v.second, v.fraction)
|
138
|
+
when DB2CLI::Null
|
139
|
+
nil
|
140
|
+
else
|
141
|
+
v
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
def insert(*values)
|
146
|
+
@db.do insert_sql(*values)
|
147
|
+
end
|
148
|
+
|
149
|
+
def update(*args, &block)
|
150
|
+
@db.do update_sql(*args, &block)
|
151
|
+
end
|
152
|
+
|
153
|
+
def delete(opts = nil)
|
154
|
+
@db.do delete_sql(opts)
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
@@ -0,0 +1,126 @@
|
|
1
|
+
require 'dbi'
|
2
|
+
|
3
|
+
module Sequel
|
4
|
+
module DBI
|
5
|
+
class Database < Sequel::Database
|
6
|
+
set_adapter_scheme :dbi
|
7
|
+
|
8
|
+
DBI_ADAPTERS = {
|
9
|
+
:ado => "ADO",
|
10
|
+
:db2 => "DB2",
|
11
|
+
:frontbase => "FrontBase",
|
12
|
+
:interbase => "InterBase",
|
13
|
+
:msql => "Msql",
|
14
|
+
:mysql => "Mysql",
|
15
|
+
:odbc => "ODBC",
|
16
|
+
:oracle => "Oracle",
|
17
|
+
:pg => "Pg",
|
18
|
+
:proxy => "Proxy",
|
19
|
+
:sqlite => "SQLite",
|
20
|
+
:sqlrelay => "SQLRelay"
|
21
|
+
}
|
22
|
+
|
23
|
+
# Converts a uri to an options hash. These options are then passed
|
24
|
+
# to a newly created database object.
|
25
|
+
def self.uri_to_options(uri)
|
26
|
+
database = (uri.path =~ /\/(.*)/) && ($1)
|
27
|
+
if uri.scheme =~ /dbi-(.+)/
|
28
|
+
adapter = DBI_ADAPTERS[$1.to_sym] || $1
|
29
|
+
database = "#{adapter}:#{database}"
|
30
|
+
end
|
31
|
+
{
|
32
|
+
:user => uri.user,
|
33
|
+
:password => uri.password,
|
34
|
+
:host => uri.host,
|
35
|
+
:port => uri.port,
|
36
|
+
:database => database
|
37
|
+
}
|
38
|
+
end
|
39
|
+
|
40
|
+
|
41
|
+
def connect
|
42
|
+
dbname = @opts[:database]
|
43
|
+
dbname = 'DBI:' + dbname unless dbname =~ /^DBI:/
|
44
|
+
::DBI.connect(dbname, @opts[:user], @opts[:password])
|
45
|
+
end
|
46
|
+
|
47
|
+
def disconnect
|
48
|
+
@pool.disconnect {|c| c.disconnect}
|
49
|
+
end
|
50
|
+
|
51
|
+
def dataset(opts = nil)
|
52
|
+
DBI::Dataset.new(self, opts)
|
53
|
+
end
|
54
|
+
|
55
|
+
def execute(sql)
|
56
|
+
@logger.info(sql) if @logger
|
57
|
+
@pool.hold do |conn|
|
58
|
+
conn.execute(sql)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def do(sql)
|
63
|
+
@logger.info(sql) if @logger
|
64
|
+
@pool.hold do |conn|
|
65
|
+
conn.do(sql)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
class Dataset < Sequel::Dataset
|
71
|
+
def literal(v)
|
72
|
+
case v
|
73
|
+
when Time
|
74
|
+
literal(v.iso8601)
|
75
|
+
else
|
76
|
+
super
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def fetch_rows(sql, &block)
|
81
|
+
@db.synchronize do
|
82
|
+
s = @db.execute sql
|
83
|
+
begin
|
84
|
+
@columns = s.column_names.map {|c| c.to_sym}
|
85
|
+
s.fetch {|r| yield hash_row(s, r)}
|
86
|
+
ensure
|
87
|
+
s.finish rescue nil
|
88
|
+
end
|
89
|
+
end
|
90
|
+
self
|
91
|
+
end
|
92
|
+
|
93
|
+
def array_tuples_fetch_rows(sql, &block)
|
94
|
+
@db.synchronize do
|
95
|
+
s = @db.execute sql
|
96
|
+
begin
|
97
|
+
@columns = s.column_names.map {|c| c.to_sym}
|
98
|
+
s.fetch {|r| r.keys = @columns; yield r}
|
99
|
+
ensure
|
100
|
+
s.finish rescue nil
|
101
|
+
end
|
102
|
+
end
|
103
|
+
self
|
104
|
+
end
|
105
|
+
|
106
|
+
def hash_row(stmt, row)
|
107
|
+
@columns.inject({}) do |m, c|
|
108
|
+
m[c] = row.shift
|
109
|
+
m
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def insert(*values)
|
114
|
+
@db.do insert_sql(*values)
|
115
|
+
end
|
116
|
+
|
117
|
+
def update(*args, &block)
|
118
|
+
@db.do update_sql(*args, &block)
|
119
|
+
end
|
120
|
+
|
121
|
+
def delete(opts = nil)
|
122
|
+
@db.do delete_sql(opts)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
@@ -0,0 +1,87 @@
|
|
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(sql)
|
28
|
+
@logger.info(sql) if @logger
|
29
|
+
@pool.hold {|c| c.do(sql)}
|
30
|
+
end
|
31
|
+
alias_method :do, :execute
|
32
|
+
|
33
|
+
def query(sql, &block)
|
34
|
+
@logger.info(sql) if @logger
|
35
|
+
@pool.hold {|c| block[c.cursor(sql)]}
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
class Dataset < Sequel::Dataset
|
40
|
+
def literal(v)
|
41
|
+
case v
|
42
|
+
when Time
|
43
|
+
literal(v.iso8601)
|
44
|
+
else
|
45
|
+
super
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def select_sql(opts = nil)
|
50
|
+
limit = opts.delete(:limit)
|
51
|
+
offset = opts.delete(:offset)
|
52
|
+
sql = super
|
53
|
+
if limit
|
54
|
+
limit = "FIRST #{limit}"
|
55
|
+
offset = offset ? "SKIP #{offset}" : ""
|
56
|
+
sql.sub!(/^select /i,"SELECT #{offset} #{limit} ")
|
57
|
+
end
|
58
|
+
sql
|
59
|
+
end
|
60
|
+
|
61
|
+
def fetch_rows(sql, &block)
|
62
|
+
@db.synchronize do
|
63
|
+
@db.query(sql) do |cursor|
|
64
|
+
begin
|
65
|
+
cursor.open.each_hash {|r| block[r]}
|
66
|
+
ensure
|
67
|
+
cursor.drop
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
self
|
72
|
+
end
|
73
|
+
|
74
|
+
def insert(*values)
|
75
|
+
@db.do insert_sql(*values)
|
76
|
+
end
|
77
|
+
|
78
|
+
def update(*args, &block)
|
79
|
+
@db.do update_sql(*args, &block)
|
80
|
+
end
|
81
|
+
|
82
|
+
def delete(opts = nil)
|
83
|
+
@db.do delete_sql(opts)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|