sequel 0.4.0 → 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
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