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.
Files changed (57) hide show
  1. data/CHANGELOG +1003 -0
  2. data/COPYING +18 -0
  3. data/README +81 -0
  4. data/Rakefile +176 -0
  5. data/bin/sequel +41 -0
  6. data/lib/sequel_core.rb +59 -0
  7. data/lib/sequel_core/adapters/adapter_skeleton.rb +68 -0
  8. data/lib/sequel_core/adapters/ado.rb +100 -0
  9. data/lib/sequel_core/adapters/db2.rb +158 -0
  10. data/lib/sequel_core/adapters/dbi.rb +126 -0
  11. data/lib/sequel_core/adapters/informix.rb +87 -0
  12. data/lib/sequel_core/adapters/jdbc.rb +108 -0
  13. data/lib/sequel_core/adapters/mysql.rb +269 -0
  14. data/lib/sequel_core/adapters/odbc.rb +145 -0
  15. data/lib/sequel_core/adapters/odbc_mssql.rb +93 -0
  16. data/lib/sequel_core/adapters/openbase.rb +90 -0
  17. data/lib/sequel_core/adapters/oracle.rb +99 -0
  18. data/lib/sequel_core/adapters/postgres.rb +519 -0
  19. data/lib/sequel_core/adapters/sqlite.rb +192 -0
  20. data/lib/sequel_core/array_keys.rb +296 -0
  21. data/lib/sequel_core/connection_pool.rb +152 -0
  22. data/lib/sequel_core/core_ext.rb +59 -0
  23. data/lib/sequel_core/core_sql.rb +191 -0
  24. data/lib/sequel_core/database.rb +433 -0
  25. data/lib/sequel_core/dataset.rb +409 -0
  26. data/lib/sequel_core/dataset/convenience.rb +321 -0
  27. data/lib/sequel_core/dataset/sequelizer.rb +354 -0
  28. data/lib/sequel_core/dataset/sql.rb +586 -0
  29. data/lib/sequel_core/exceptions.rb +45 -0
  30. data/lib/sequel_core/migration.rb +191 -0
  31. data/lib/sequel_core/model.rb +8 -0
  32. data/lib/sequel_core/pretty_table.rb +73 -0
  33. data/lib/sequel_core/schema.rb +8 -0
  34. data/lib/sequel_core/schema/schema_generator.rb +131 -0
  35. data/lib/sequel_core/schema/schema_sql.rb +131 -0
  36. data/lib/sequel_core/worker.rb +58 -0
  37. data/spec/adapters/informix_spec.rb +139 -0
  38. data/spec/adapters/mysql_spec.rb +330 -0
  39. data/spec/adapters/oracle_spec.rb +130 -0
  40. data/spec/adapters/postgres_spec.rb +189 -0
  41. data/spec/adapters/sqlite_spec.rb +345 -0
  42. data/spec/array_keys_spec.rb +679 -0
  43. data/spec/connection_pool_spec.rb +356 -0
  44. data/spec/core_ext_spec.rb +67 -0
  45. data/spec/core_sql_spec.rb +301 -0
  46. data/spec/database_spec.rb +812 -0
  47. data/spec/dataset_spec.rb +2381 -0
  48. data/spec/migration_spec.rb +261 -0
  49. data/spec/pretty_table_spec.rb +66 -0
  50. data/spec/rcov.opts +4 -0
  51. data/spec/schema_generator_spec.rb +86 -0
  52. data/spec/schema_spec.rb +230 -0
  53. data/spec/sequelizer_spec.rb +448 -0
  54. data/spec/spec.opts +5 -0
  55. data/spec/spec_helper.rb +44 -0
  56. data/spec/worker_spec.rb +96 -0
  57. 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