sequel 0.4.0 → 0.4.1

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 (48) hide show
  1. data/CHANGELOG +4 -0
  2. data/README +1 -6
  3. data/Rakefile +1 -1
  4. data/bin/sequel +1 -3
  5. data/lib/sequel.rb +18 -1
  6. data/lib/sequel/adapters/ado.rb +104 -0
  7. data/lib/sequel/adapters/db2.rb +160 -0
  8. data/lib/sequel/adapters/dbi.rb +130 -0
  9. data/lib/sequel/adapters/informix.rb +78 -0
  10. data/lib/sequel/adapters/mysql.rb +256 -0
  11. data/lib/sequel/adapters/odbc.rb +144 -0
  12. data/lib/sequel/adapters/oracle.rb +109 -0
  13. data/lib/sequel/adapters/postgres.rb +507 -0
  14. data/lib/sequel/adapters/sqlite.rb +186 -0
  15. data/lib/sequel/ado.rb +2 -104
  16. data/lib/{sequel-core → sequel}/array_keys.rb +0 -0
  17. data/lib/{sequel-core → sequel}/connection_pool.rb +0 -0
  18. data/lib/{sequel-core → sequel}/core_ext.rb +0 -0
  19. data/lib/{sequel-core → sequel}/core_sql.rb +0 -0
  20. data/lib/{sequel-core → sequel}/database.rb +10 -20
  21. data/lib/{sequel-core → sequel}/dataset.rb +0 -0
  22. data/lib/{sequel-core → sequel}/dataset/convenience.rb +0 -0
  23. data/lib/{sequel-core → sequel}/dataset/sequelizer.rb +0 -0
  24. data/lib/{sequel-core → sequel}/dataset/sql.rb +0 -0
  25. data/lib/sequel/db2.rb +2 -160
  26. data/lib/sequel/dbi.rb +2 -130
  27. data/lib/{sequel-core → sequel}/error.rb +0 -0
  28. data/lib/sequel/informix.rb +2 -78
  29. data/lib/{sequel-core → sequel}/migration.rb +0 -0
  30. data/lib/{sequel-core → sequel}/model.rb +0 -0
  31. data/lib/{sequel-core → sequel}/model/base.rb +0 -0
  32. data/lib/{sequel-core → sequel}/model/caching.rb +0 -0
  33. data/lib/{sequel-core → sequel}/model/hooks.rb +0 -0
  34. data/lib/{sequel-core → sequel}/model/record.rb +0 -0
  35. data/lib/{sequel-core → sequel}/model/relations.rb +0 -0
  36. data/lib/{sequel-core → sequel}/model/schema.rb +0 -0
  37. data/lib/sequel/mysql.rb +2 -256
  38. data/lib/sequel/odbc.rb +2 -144
  39. data/lib/sequel/oracle.rb +2 -109
  40. data/lib/sequel/postgres.rb +2 -507
  41. data/lib/{sequel-core → sequel}/pretty_table.rb +0 -0
  42. data/lib/{sequel-core → sequel}/schema.rb +0 -0
  43. data/lib/{sequel-core → sequel}/schema/schema_generator.rb +0 -0
  44. data/lib/{sequel-core → sequel}/schema/schema_sql.rb +0 -0
  45. data/lib/sequel/sqlite.rb +2 -186
  46. data/lib/{sequel-core → sequel}/worker.rb +0 -0
  47. data/spec/database_spec.rb +7 -9
  48. metadata +39 -29
data/CHANGELOG CHANGED
@@ -1,3 +1,7 @@
1
+ === 0.4.1 (2007-11-25)
2
+
3
+ * Put adapter files in lib/sequel/adapters. Requiring sequel/<adapter> is now deprecated. Users can now just require 'sequel' and adapters are automagically loaded (#93).
4
+
1
5
  === 0.4.0 (2007-11-24)
2
6
 
3
7
  * Reorganized lib directory structure.
data/README CHANGED
@@ -79,14 +79,9 @@ Much of Sequel is still undocumented (especially the part relating to model clas
79
79
 
80
80
  === Connecting to a database
81
81
 
82
- Before connecting to a database, you should require the corresponding adaptor, for example:
83
-
84
- require 'sequel/sqlite'
85
-
86
- Note: you don't need to require 'sequel' separately before that, as each adapter requires 'sequel' if it hasn't yet been required.
87
-
88
82
  To connect to a database you simply provide Sequel with a URL:
89
83
 
84
+ require 'sequel'
90
85
  DB = Sequel.open 'sqlite:///blog.db'
91
86
 
92
87
  The connection URL can also include such stuff as the user name and password:
data/Rakefile CHANGED
@@ -6,7 +6,7 @@ require 'fileutils'
6
6
  include FileUtils
7
7
 
8
8
  NAME = "sequel"
9
- VERS = "0.4.0"
9
+ VERS = "0.4.1"
10
10
  CLEAN.include ['**/.*.sw?', 'pkg/*', '.config', 'doc/*', 'coverage/*']
11
11
  RDOC_OPTS = ['--quiet', '--title', "Sequel: Concise ORM for Ruby",
12
12
  "--opname", "index.html",
data/bin/sequel CHANGED
@@ -22,8 +22,7 @@ if db.nil? || db.empty?
22
22
  end
23
23
 
24
24
  begin
25
- scheme = URI.parse(db).scheme
26
- require File.join('sequel', scheme)
25
+ DB = Sequel.connect db
27
26
  rescue LoadError => e
28
27
  puts "Failed to load #{scheme} adapter: #{e.message}"
29
28
  exit
@@ -32,7 +31,6 @@ rescue => e
32
31
  exit
33
32
  end
34
33
 
35
- DB = Sequel.connect db
36
34
  begin
37
35
  DB.test_connection
38
36
  rescue => e
data/lib/sequel.rb CHANGED
@@ -6,7 +6,7 @@ files = %w[
6
6
  core_ext core_sql array_keys error connection_pool pretty_table
7
7
  dataset migration model schema database worker
8
8
  ]
9
- dir = File.join(File.dirname(__FILE__), 'sequel-core')
9
+ dir = File.join(File.dirname(__FILE__), 'sequel')
10
10
  files.each {|f| require(File.join(dir, f))}
11
11
 
12
12
  module Sequel #:nodoc:
@@ -29,6 +29,23 @@ module Sequel #:nodoc:
29
29
  def single_threaded=(value)
30
30
  Database.single_threaded = value
31
31
  end
32
+
33
+ def method_missing(m, *args)
34
+ c = Database.adapter_class(m)
35
+ begin
36
+ case args.size
37
+ when 1: # Sequel.dbi(db_name)
38
+ opts = {:database => args[0]}
39
+ when 0 # Sequel.dbi
40
+ opts = {}
41
+ else # Sequel.dbi(db_name, opts)
42
+ opts = args[1].merge(:database => args[0])
43
+ end
44
+ rescue
45
+ raise SequelError, "Invalid parameters specified"
46
+ end
47
+ c.new(opts)
48
+ end
32
49
  end
33
50
  end
34
51
 
@@ -0,0 +1,104 @@
1
+ if !Object.const_defined?('Sequel')
2
+ require File.join(File.dirname(__FILE__), '../../sequel')
3
+ end
4
+
5
+ require 'win32ole'
6
+
7
+ module Sequel
8
+ # The ADO adapter provides connectivity to ADO databases in Windows. ADO
9
+ # databases can be opened using a URL with the ado schema:
10
+ #
11
+ # DB = Sequel.open('ado://mydb')
12
+ #
13
+ # or using the Sequel.ado method:
14
+ #
15
+ # DB = Sequel.ado('mydb')
16
+ #
17
+ module ADO
18
+ class Database < Sequel::Database
19
+ set_adapter_scheme :ado
20
+
21
+ AUTO_INCREMENT = 'IDENTITY(1,1)'.freeze
22
+
23
+ def auto_increment_sql
24
+ AUTO_INCREMENT
25
+ end
26
+
27
+ def connect
28
+ dbname = @opts[:database]
29
+ handle = WIN32OLE.new('ADODB.Connection')
30
+ handle.Open(dbname)
31
+ handle
32
+ end
33
+
34
+ def disconnect
35
+ # how do we disconnect? couldn't find anything in the docs
36
+ end
37
+
38
+ def dataset(opts = nil)
39
+ ADO::Dataset.new(self, opts)
40
+ end
41
+
42
+ def execute(sql)
43
+ @logger.info(sql) if @logger
44
+ @pool.hold {|conn| conn.Execute(sql)}
45
+ end
46
+
47
+ alias_method :do, :execute
48
+ end
49
+
50
+ class Dataset < Sequel::Dataset
51
+ def literal(v)
52
+ case v
53
+ when Time: literal(v.iso8601)
54
+ else
55
+ super
56
+ end
57
+ end
58
+
59
+ def fetch_rows(sql, &block)
60
+ @db.synchronize do
61
+ s = @db.execute sql
62
+
63
+ @columns = s.Fields.extend(Enumerable).map {|x| x.Name.to_sym}
64
+
65
+ s.moveFirst
66
+ s.getRows.transpose.each {|r| yield hash_row(r)}
67
+ end
68
+ self
69
+ end
70
+
71
+ def hash_row(row)
72
+ @columns.inject({}) do |m, c|
73
+ m[c] = row.shift
74
+ m
75
+ end
76
+ end
77
+
78
+ def array_tuples_fetch_rows(sql, &block)
79
+ @db.synchronize do
80
+ s = @db.execute sql
81
+
82
+ @columns = s.Fields.extend(Enumerable).map {|x| x.Name.to_sym}
83
+
84
+ s.moveFirst
85
+ s.getRows.transpose.each {|r| r.keys = @columns; yield r}
86
+ end
87
+ self
88
+ end
89
+
90
+ def insert(*values)
91
+ @db.do insert_sql(*values)
92
+ end
93
+
94
+ def update(values, opts = nil)
95
+ @db.do update_sql(values, opts)
96
+ self
97
+ end
98
+
99
+ def delete(opts = nil)
100
+ @db.do delete_sql(opts)
101
+ end
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,160 @@
1
+ if !Object.const_defined?('Sequel')
2
+ require File.join(File.dirname(__FILE__), '../../sequel')
3
+ end
4
+
5
+ require 'db2/db2cli'
6
+
7
+ module Sequel
8
+ module DB2
9
+ class Database < Sequel::Database
10
+ set_adapter_scheme :db2
11
+ include DB2CLI
12
+
13
+ # AUTO_INCREMENT = 'IDENTITY(1,1)'.freeze
14
+ #
15
+ # def auto_increment_sql
16
+ # AUTO_INCREMENT
17
+ # end
18
+
19
+ def check_error(rc, msg)
20
+ case rc
21
+ when SQL_SUCCESS, SQL_SUCCESS_WITH_INFO: nil
22
+ else
23
+ raise SequelError, msg
24
+ end
25
+ end
26
+
27
+ rc, @@env = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE)
28
+ check_error(rc, "Could not allocate DB2 environment")
29
+
30
+ def connect
31
+ rc, dbc = SQLAllocHandle(SQL_HANDLE_DBC, @@env)
32
+ check_error(rc, "Could not allocate database connection")
33
+
34
+ rc = SQLConnect(dbc, @opts[:database], @opts[:user], @opts[:password])
35
+ check_error(rc, "Could not connect to database")
36
+
37
+ dbc
38
+ end
39
+
40
+ def disconnect
41
+ @pool.disconnect do |conn|
42
+ rc = SQLDisconnect(conn)
43
+ check_error(rc, "Could not disconnect from database")
44
+
45
+ rc = SQLFreeHandle(SQL_HANDLE_DBC, conn)
46
+ check_error(rc, "Could not free Database handle")
47
+ end
48
+ end
49
+
50
+ def test_connection
51
+ @pool.hold {|conn|}
52
+ true
53
+ end
54
+
55
+ def dataset(opts = nil)
56
+ DB2::Dataset.new(self, opts)
57
+ end
58
+
59
+ def execute(sql, &block)
60
+ @logger.info(sql) if @logger
61
+ @pool.hold do |conn|
62
+ rc, sth = SQLAllocHandle(SQL_HANDLE_STMT, @handle)
63
+ check_error(rc, "Could not allocate statement")
64
+
65
+ begin
66
+ rc = SQLExecDirect(sth, sql)
67
+ check_error(rc, "Could not execute statement")
68
+
69
+ block[sth] if block
70
+
71
+ rc, rpc = SQLRowCount(sth)
72
+ check_error(rc, "Could not get RPC")
73
+ rpc
74
+ ensure
75
+ rc = SQLFreeHandle(SQL_HANDLE_STMT, sth)
76
+ check_error(rc, "Could not free statement")
77
+ end
78
+ end
79
+ end
80
+ alias_method :do, :execute
81
+ end
82
+
83
+ class Dataset < Sequel::Dataset
84
+ def literal(v)
85
+ case v
86
+ when Time: literal(v.iso8601)
87
+ else
88
+ super
89
+ end
90
+ end
91
+
92
+ def fetch_rows(sql, &block)
93
+ @db.synchronize do
94
+ @db.execute(sql) do |sth|
95
+ @column_info = get_column_info(sth)
96
+ @columns = @column_info.map {|c| c[:name]}
97
+ while (rc = SQLFetch(@handle)) != SQL_NO_DATA_FOUND
98
+ @db.check_error(rc, "Could not fetch row")
99
+ yield hash_row(sth)
100
+ end
101
+ end
102
+ end
103
+ self
104
+ end
105
+
106
+ MAX_COL_SIZE = 256
107
+
108
+ def get_column_info(sth)
109
+ rc, column_count = SQLNumResultCols(sth)
110
+ @db.check_error(rc, "Could not get number of result columns")
111
+
112
+ (1..column_count).map do |i|
113
+ rc, name, buflen, datatype, size, digits, nullable = SQLDescribeCol(sth, i, MAX_COL_SIZE)
114
+ @b.check_error(rc, "Could not describe column")
115
+
116
+ {:name => name, :db2_type => datatype, :precision => size}
117
+ end
118
+ end
119
+
120
+ def hash_row(sth)
121
+ row = {}
122
+ @column_info.each_with_index do |c, i|
123
+ rc, v = SQLGetData(sth, i+1, c[:db2_type], c[:precision])
124
+ @db.check_error(rc, "Could not get data")
125
+
126
+ @row[c[:name]] = convert_type(v)
127
+ end
128
+ row
129
+ end
130
+
131
+ def convert_type(v)
132
+ case v
133
+ when DB2CLI::Date
134
+ DBI::Date.new(v.year, v.month, v.day)
135
+ when DB2CLI::Time
136
+ DBI::Time.new(v.hour, v.minute, v.second)
137
+ when DB2CLI::Timestamp
138
+ DBI::Timestamp.new(v.year, v.month, v.day,
139
+ v.hour, v.minute, v.second, v.fraction)
140
+ when DB2CLI::Null
141
+ nil
142
+ else
143
+ v
144
+ end
145
+ end
146
+
147
+ def insert(*values)
148
+ @db.do insert_sql(*values)
149
+ end
150
+
151
+ def update(values, opts = nil)
152
+ @db.do update_sql(values, opts)
153
+ end
154
+
155
+ def delete(opts = nil)
156
+ @db.do delete_sql(opts)
157
+ end
158
+ end
159
+ end
160
+ end
@@ -0,0 +1,130 @@
1
+ if !Object.const_defined?('Sequel')
2
+ require File.join(File.dirname(__FILE__), '../../sequel')
3
+ end
4
+
5
+ require 'dbi'
6
+
7
+ module Sequel
8
+ module DBI
9
+ class Database < Sequel::Database
10
+ set_adapter_scheme :dbi
11
+
12
+ DBI_ADAPTERS = {
13
+ :ado => "ADO",
14
+ :db2 => "DB2",
15
+ :frontbase => "FrontBase",
16
+ :interbase => "InterBase",
17
+ :msql => "Msql",
18
+ :mysql => "Mysql",
19
+ :odbc => "ODBC",
20
+ :oracle => "Oracle",
21
+ :pg => "Pg",
22
+ :proxy => "Proxy",
23
+ :sqlite => "SQLite",
24
+ :sqlrelay => "SQLRelay"
25
+ }
26
+
27
+ # Converts a uri to an options hash. These options are then passed
28
+ # to a newly created database object.
29
+ def self.uri_to_options(uri)
30
+ database = (uri.path =~ /\/(.*)/) && ($1)
31
+ if uri.scheme =~ /dbi-(.+)/
32
+ adapter = DBI_ADAPTERS[$1.to_sym] || $1
33
+ database = "#{adapter}:#{database}"
34
+ end
35
+ {
36
+ :user => uri.user,
37
+ :password => uri.password,
38
+ :host => uri.host,
39
+ :port => uri.port,
40
+ :database => database
41
+ }
42
+ end
43
+
44
+
45
+ def connect
46
+ dbname = @opts[:database]
47
+ dbname = 'DBI:' + dbname unless dbname =~ /^DBI:/
48
+ ::DBI.connect(dbname, @opts[:user], @opts[:password])
49
+ end
50
+
51
+ def disconnect
52
+ @pool.disconnect {|c| c.disconnect}
53
+ end
54
+
55
+ def dataset(opts = nil)
56
+ DBI::Dataset.new(self, opts)
57
+ end
58
+
59
+ def execute(sql)
60
+ @logger.info(sql) if @logger
61
+ @pool.hold do |conn|
62
+ conn.execute(sql)
63
+ end
64
+ end
65
+
66
+ def do(sql)
67
+ @logger.info(sql) if @logger
68
+ @pool.hold do |conn|
69
+ conn.do(sql)
70
+ end
71
+ end
72
+ end
73
+
74
+ class Dataset < Sequel::Dataset
75
+ def literal(v)
76
+ case v
77
+ when Time: literal(v.iso8601)
78
+ else
79
+ super
80
+ end
81
+ end
82
+
83
+ def fetch_rows(sql, &block)
84
+ @db.synchronize do
85
+ s = @db.execute sql
86
+ begin
87
+ @columns = s.column_names.map {|c| c.to_sym}
88
+ s.fetch {|r| yield hash_row(s, r)}
89
+ ensure
90
+ s.finish rescue nil
91
+ end
92
+ end
93
+ self
94
+ end
95
+
96
+ def array_tuples_fetch_rows(sql, &block)
97
+ @db.synchronize do
98
+ s = @db.execute sql
99
+ begin
100
+ @columns = s.column_names.map {|c| c.to_sym}
101
+ s.fetch {|r| r.keys = @columns; yield r}
102
+ ensure
103
+ s.finish rescue nil
104
+ end
105
+ end
106
+ self
107
+ end
108
+
109
+ def hash_row(stmt, row)
110
+ @columns.inject({}) do |m, c|
111
+ m[c] = row.shift
112
+ m
113
+ end
114
+ end
115
+
116
+ def insert(*values)
117
+ @db.do insert_sql(*values)
118
+ end
119
+
120
+ def update(values, opts = nil)
121
+ @db.do update_sql(values, opts)
122
+ self
123
+ end
124
+
125
+ def delete(opts = nil)
126
+ @db.do delete_sql(opts)
127
+ end
128
+ end
129
+ end
130
+ end