sequel_core 1.0

Sign up to get free protection for your applications and to get access to all the features.
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
data/COPYING ADDED
@@ -0,0 +1,18 @@
1
+ Copyright (c) 2006-2007 Sharon Rosner
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to
5
+ deal in the Software without restriction, including without limitation the
6
+ rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7
+ sell copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
16
+ THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
17
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
18
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README ADDED
@@ -0,0 +1,81 @@
1
+ == Sequel: Concise ORM for Ruby
2
+
3
+ Sequel is an ORM framework for Ruby. Sequel provides thread safety, connection pooling, and a concise DSL for constructing queries and table schemas.
4
+
5
+ Sequel makes it easy to deal with multiple records without having to break your teeth on SQL.
6
+
7
+ == Resources
8
+
9
+ * {Project page}[http://code.google.com/p/ruby-sequel/]
10
+ * {Source code}[http://ruby-sequel.googlecode.com/svn/]
11
+ * {Bug tracking}[http://code.google.com/p/ruby-sequel/issues/list]
12
+ * {Google group}[http://groups.google.com/group/sequel-talk]
13
+ * {RubyForge page}[http://rubyforge.org/projects/sequel/]
14
+
15
+ To check out the source code:
16
+
17
+ svn co http://ruby-sequel.googlecode.com/svn/trunk
18
+
19
+ === Contact
20
+
21
+ If you have any comments or suggestions please send an email to ciconia at gmail.com and I'll get back to you.
22
+
23
+ == Installation
24
+
25
+ sudo gem install sequel
26
+
27
+ Note: as of version 0.5, Sequel models are distributed in a separate gem. In order to use sequel models, you should install the sequel_model gem:
28
+
29
+ sudo gem install sequel_model
30
+
31
+ == Supported Databases
32
+
33
+ Sequel currently supports:
34
+
35
+ * ADO (on Windows)
36
+ * DBI
37
+ * Informix
38
+ * MySQL
39
+ * ODBC
40
+ * Oracle
41
+ * PostgreSQL
42
+ * SQLite 3
43
+
44
+ There are also experimental adapters for DB2, OpenBase and JDBC (on JRuby).
45
+
46
+ == The Sequel Console
47
+
48
+ Sequel includes an IRB console for quick'n'dirty access to databases. You can use it like this:
49
+
50
+ sequel sqlite:///test.db
51
+
52
+ You get an IRB session with the database object stored in DB.
53
+
54
+ == An Introduction
55
+
56
+ Sequel was designed to take the hassle away from connecting to databases and manipulating them. Sequel deals with all the boring stuff like maintaining connections, formatting SQL correctly and fetching records so you can concentrate on your application.
57
+
58
+ Sequel uses the concept of datasets to retrieve data. A Dataset object encapsulates an SQL query and supports chainability, letting you fetch data using a convenient Ruby DSL that is both concise and infinitely flexible.
59
+
60
+ For example, the following one-liner returns the average GDP for the five biggest countries in the middle east region:
61
+
62
+ DB[:countries].filter(:region => 'Middle East').reverse_order(:area).limit(5).avg(:GDP)
63
+
64
+ Which is equivalent to:
65
+
66
+ SELECT avg(GDP) FROM countries WHERE region = 'Middle East' ORDER BY area DESC LIMIT 5
67
+
68
+ Since datasets retrieve records only when needed, they can be stored and later reused. Records are fetched as hashes (they can also be fetched as custom model objects), and are accessed using an Enumerable interface:
69
+
70
+ middle_east = DB[:countries].filter(:region => 'Middle East')
71
+ middle_east.order(:name).each {|r| puts r[:name]}
72
+
73
+ Sequel also offers convenience methods for extracting data from Datasets, such as an extended map method:
74
+
75
+ middle_east.map(:name) #=> ['Egypt', 'Greece', 'Israel', ...]
76
+
77
+ Or getting results as a transposed hash, with one column as key and another as value:
78
+
79
+ middle_east.to_hash(:name, :area) #=> {'Israel' => 20000, 'Greece' => 120000, ...}
80
+
81
+ You can find more information on getting started with Sequel {here}[http://code.google.com/p/ruby-sequel/wiki/GettingStarted]
@@ -0,0 +1,176 @@
1
+ require "rake"
2
+ require "rake/clean"
3
+ require "rake/gempackagetask"
4
+ require "rake/rdoctask"
5
+ require "fileutils"
6
+ include FileUtils
7
+
8
+ ##############################################################################
9
+ # Configuration
10
+ ##############################################################################
11
+ NAME = "sequel_core"
12
+ VERS = "1.0"
13
+ CLEAN.include ["**/.*.sw?", "pkg/*", ".config", "doc/*", "coverage/*"]
14
+ RDOC_OPTS = [
15
+ "--quiet",
16
+ "--title", "Sequel: Database access for Ruby",
17
+ "--opname", "index.html",
18
+ "--line-numbers",
19
+ "--main", "README",
20
+ "--inline-source"
21
+ ]
22
+
23
+ ##############################################################################
24
+ # RDoc
25
+ ##############################################################################
26
+ task :doc => [:rdoc]
27
+
28
+ Rake::RDocTask.new do |rdoc|
29
+ rdoc.rdoc_dir = "doc/rdoc"
30
+ rdoc.options += RDOC_OPTS
31
+ rdoc.main = "README"
32
+ rdoc.title = "Sequel: Database access for Ruby"
33
+ rdoc.rdoc_files.add ["README", "COPYING", "lib/sequel_core.rb", "lib/**/*.rb"]
34
+ end
35
+
36
+ ##############################################################################
37
+ # Gem packaging
38
+ ##############################################################################
39
+ desc "Packages up Sequel."
40
+ task :default => [:package]
41
+ task :package => [:clean]
42
+
43
+ spec = Gem::Specification.new do |s|
44
+ s.name = NAME
45
+ s.rubyforge_project = 'sequel'
46
+ s.version = VERS
47
+ s.platform = Gem::Platform::RUBY
48
+ s.has_rdoc = true
49
+ s.extra_rdoc_files = ["README", "CHANGELOG", "COPYING"]
50
+ s.rdoc_options += RDOC_OPTS +
51
+ ["--exclude", "^(examples|extras)\/", "--exclude", "lib/sequel_core.rb"]
52
+ s.summary = "Database access for Ruby"
53
+ s.description = s.summary
54
+ s.author = "Sharon Rosner"
55
+ s.email = "ciconia@gmail.com"
56
+ s.homepage = "http://sequel.rubyforge.org"
57
+ s.executables = ["sequel"]
58
+ s.required_ruby_version = ">= 1.8.4"
59
+
60
+ s.add_dependency("metaid")
61
+
62
+ case RUBY_PLATFORM
63
+ when /mswin/
64
+ s.platform = Gem::Platform::CURRENT
65
+ s.add_dependency("RubyInline", ">= 3.6.6")
66
+ s.add_dependency("ParseTree", ">= 2.1.1")
67
+ s.add_dependency("ruby2ruby")
68
+ when /java/
69
+ s.platform = "jruby"
70
+ else
71
+ s.platform = Gem::Platform::RUBY
72
+ # ParseTree on win32 requires PT2.1.1 and RI3.6.6
73
+ s.add_dependency("RubyInline", ">= 3.6.6")
74
+ s.add_dependency("ParseTree", ">= 2.1.1")
75
+ s.add_dependency("ruby2ruby")
76
+ end
77
+
78
+ s.files = %w(COPYING README Rakefile) + Dir.glob("{bin,doc,spec,lib}/**/*")
79
+
80
+ s.require_path = "lib"
81
+ s.bindir = "bin"
82
+ end
83
+
84
+ Rake::GemPackageTask.new(spec) do |p|
85
+ p.need_tar = true
86
+ p.gem_spec = spec
87
+ end
88
+
89
+ ##############################################################################
90
+ # installation & removal
91
+ ##############################################################################
92
+ task :install do
93
+ sh %{rake package}
94
+ sh %{sudo gem install pkg/#{NAME}-#{VERS}}
95
+ end
96
+
97
+ task :install_no_docs do
98
+ sh %{rake package}
99
+ sh %{sudo gem install pkg/#{NAME}-#{VERS} --no-rdoc --no-ri}
100
+ end
101
+
102
+ task :uninstall => [:clean] do
103
+ sh %{sudo gem uninstall #{NAME}}
104
+ end
105
+
106
+ task :tag do
107
+ cwd = FileUtils.pwd
108
+ sh %{cd ../.. && svn copy #{cwd} tags/#{NAME}-#{VERS} && svn commit -m "#{NAME}-#{VERS} tag." tags}
109
+ end
110
+
111
+ ##############################################################################
112
+ # gem and rdoc release
113
+ ##############################################################################
114
+ task :release => [:package] do
115
+ sh %{rubyforge login}
116
+ sh %{rubyforge add_release sequel #{NAME} #{VERS} pkg/#{NAME}-#{VERS}.tgz}
117
+ sh %{rubyforge add_file sequel #{NAME} #{VERS} pkg/#{NAME}-#{VERS}.gem}
118
+ end
119
+
120
+ ##############################################################################
121
+ # specs
122
+ ##############################################################################
123
+ require "spec/rake/spectask"
124
+
125
+ desc "Run specs with coverage"
126
+ Spec::Rake::SpecTask.new("spec") do |t|
127
+ t.spec_files = FileList["spec/*_spec.rb"]
128
+ t.spec_opts = File.read("spec/spec.opts").split("\n")
129
+ t.rcov_opts = File.read("spec/rcov.opts").split("\n")
130
+ t.rcov = true
131
+ end
132
+
133
+ desc "Run specs without coverage"
134
+ Spec::Rake::SpecTask.new("spec_no_cov") do |t|
135
+ t.spec_files = FileList["spec/*_spec.rb"]
136
+ t.spec_opts = File.read("spec/spec.opts").split("\n")
137
+ end
138
+
139
+ desc "Run adapter specs without coverage"
140
+ Spec::Rake::SpecTask.new("spec_adapters") do |t|
141
+ t.spec_files = FileList["spec/adapters/*_spec.rb"]
142
+ t.spec_opts = File.read("spec/spec.opts").split("\n")
143
+ end
144
+
145
+ desc "Run all specs with coverage"
146
+ Spec::Rake::SpecTask.new("spec_all") do |t|
147
+ t.spec_files = FileList["spec/*_spec.rb", "spec/adapters/*_spec.rb"]
148
+ t.rcov_opts = File.read("spec/rcov.opts").split("\n")
149
+ t.spec_opts = File.read("spec/spec.opts").split("\n")
150
+ t.rcov = true
151
+ end
152
+
153
+ desc "Run rcov only"
154
+ Spec::Rake::SpecTask.new("rcov") do |t|
155
+ t.rcov_opts = File.read("spec/rcov.opts").split("\n")
156
+ t.spec_opts = File.read("spec/spec.opts").split("\n")
157
+ t.spec_files = FileList["spec/*_spec.rb"]
158
+ t.rcov = true
159
+ end
160
+
161
+ ##############################################################################
162
+ # Statistics
163
+ ##############################################################################
164
+
165
+ STATS_DIRECTORIES = [
166
+ %w(Code lib/),
167
+ %w(Spec spec/)
168
+ ].collect { |name, dir| [ name, "./#{dir}" ] }.select { |name, dir| File.directory?(dir) }
169
+
170
+ desc "Report code statistics (KLOCs, etc) from the application"
171
+ task :stats do
172
+ require "extra/stats"
173
+ verbose = true
174
+ CodeStatistics.new(*STATS_DIRECTORIES).to_s
175
+ end
176
+
@@ -0,0 +1,41 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'sequel_core'
5
+
6
+ usage = <<END
7
+ Usage: sequel <connection URI>
8
+ Sequel: Lightweight ORM library for Ruby
9
+
10
+ Examples:
11
+ sequel sqlite:///blog.db
12
+ sequel postgres://localhost/my_blog
13
+
14
+ For more information see http://code.google.com/p/ruby-sequel
15
+ END
16
+
17
+ db = ARGV.shift
18
+
19
+ if db.nil? || db.empty?
20
+ puts usage
21
+ exit
22
+ end
23
+
24
+ begin
25
+ DB = Sequel.connect db
26
+ rescue => e
27
+ puts e.message
28
+ exit
29
+ end
30
+
31
+ begin
32
+ DB.test_connection
33
+ rescue => e
34
+ puts e.message
35
+ puts e.backtrace.first
36
+ exit
37
+ end
38
+
39
+ require 'irb'
40
+ puts "Your database is stored in DB..."
41
+ IRB.start
@@ -0,0 +1,59 @@
1
+ require "metaid"
2
+ require "bigdecimal"
3
+ require "bigdecimal/util"
4
+
5
+ files = %w[
6
+ core_ext core_sql array_keys exceptions connection_pool pretty_table
7
+ dataset migration model schema database worker
8
+ ]
9
+ dir = File.join(File.dirname(__FILE__), "sequel_core")
10
+ files.each {|f| require(File.join(dir, f))}
11
+
12
+ module Sequel #:nodoc:
13
+ class << self
14
+ # call-seq:
15
+ # Sequel::Database.connect(conn_string)
16
+ # Sequel.connect(conn_string)
17
+ # Sequel.open(conn_string)
18
+ #
19
+ # Creates a new database object based on the supplied connection string.
20
+ # The specified scheme determines the database class used, and the rest
21
+ # of the string specifies the connection options. For example:
22
+ # DB = Sequel.open 'sqlite:///blog.db'
23
+ def connect(*args)
24
+ Database.connect(*args)
25
+ end
26
+ alias_method :open, :connect
27
+
28
+ def single_threaded=(value)
29
+ Database.single_threaded = value
30
+ end
31
+
32
+ def method_missing(m, *args)
33
+ c = Database.adapter_class(m)
34
+ begin
35
+ # three ways to invoke this:
36
+ # 0 arguments: Sequel.dbi
37
+ # 1 argument: Sequel.dbi(db_name)
38
+ # more args: Sequel.dbi(db_name, opts)
39
+ case args.size
40
+ when 0
41
+ opts = {}
42
+ when 1
43
+ opts = args[0].is_a?(Hash) ? args[0] : {:database => args[0]}
44
+ else
45
+ opts = args[1].merge(:database => args[0])
46
+ end
47
+ rescue
48
+ raise Error::AdapterNotFound, "Unknown adapter (#{m})"
49
+ end
50
+ c.new(opts)
51
+ end
52
+ end
53
+ end
54
+
55
+ class Object
56
+ def Sequel(*args)
57
+ Sequel.connect(*args)
58
+ end
59
+ end
@@ -0,0 +1,68 @@
1
+ # require 'adapter_lib'
2
+
3
+ module Sequel
4
+ module Adapter
5
+ class Database < Sequel::Database
6
+ set_adapter_scheme :adapter
7
+
8
+ def connect
9
+ AdapterDB.new(@opts[:database], @opts[:user], @opts[:password])
10
+ end
11
+
12
+ def disconnect
13
+ @pool.disconnect {|c| c.disconnect}
14
+ end
15
+
16
+ def dataset(opts = nil)
17
+ Adapter::Dataset.new(self, opts)
18
+ end
19
+
20
+ def execute(sql)
21
+ @logger.info(sql) if @logger
22
+ @pool.hold {|conn| conn.exec(sql)}
23
+ end
24
+
25
+ alias_method :do, :execute
26
+ end
27
+
28
+ class Dataset < Sequel::Dataset
29
+ def literal(v)
30
+ case v
31
+ when Time
32
+ literal(v.iso8601)
33
+ else
34
+ super
35
+ end
36
+ end
37
+
38
+ def fetch_rows(sql, &block)
39
+ @db.synchronize do
40
+ cursor = @db.execute sql
41
+ begin
42
+ @columns = cursor.get_col_names.map {|c| c.to_sym}
43
+ while r = cursor.fetch
44
+ row = {}
45
+ r.each_with_index {|v, i| row[@columns[i]] = v}
46
+ yield row
47
+ end
48
+ ensure
49
+ cursor.close
50
+ end
51
+ end
52
+ self
53
+ end
54
+
55
+ def insert(*values)
56
+ @db.do insert_sql(*values)
57
+ end
58
+
59
+ def update(*args, &block)
60
+ @db.do update_sql(*args, &block)
61
+ end
62
+
63
+ def delete(opts = nil)
64
+ @db.do delete_sql(opts)
65
+ end
66
+ end
67
+ end
68
+ end