sequel_core 2.2.0 → 3.8.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.
- metadata +30 -101
- data/CHANGELOG +0 -1519
- data/COPYING +0 -19
- data/README +0 -313
- data/Rakefile +0 -158
- data/bin/sequel +0 -117
- data/doc/cheat_sheet.rdoc +0 -225
- data/doc/dataset_filtering.rdoc +0 -182
- data/lib/sequel_core.rb +0 -136
- data/lib/sequel_core/adapters/adapter_skeleton.rb +0 -68
- data/lib/sequel_core/adapters/ado.rb +0 -90
- data/lib/sequel_core/adapters/db2.rb +0 -160
- data/lib/sequel_core/adapters/dbi.rb +0 -127
- data/lib/sequel_core/adapters/informix.rb +0 -89
- data/lib/sequel_core/adapters/jdbc.rb +0 -110
- data/lib/sequel_core/adapters/mysql.rb +0 -486
- data/lib/sequel_core/adapters/odbc.rb +0 -167
- data/lib/sequel_core/adapters/odbc_mssql.rb +0 -106
- data/lib/sequel_core/adapters/openbase.rb +0 -76
- data/lib/sequel_core/adapters/oracle.rb +0 -182
- data/lib/sequel_core/adapters/postgres.rb +0 -560
- data/lib/sequel_core/adapters/sqlite.rb +0 -270
- data/lib/sequel_core/connection_pool.rb +0 -194
- data/lib/sequel_core/core_ext.rb +0 -197
- data/lib/sequel_core/core_sql.rb +0 -184
- data/lib/sequel_core/database.rb +0 -462
- data/lib/sequel_core/database/schema.rb +0 -156
- data/lib/sequel_core/dataset.rb +0 -457
- data/lib/sequel_core/dataset/callback.rb +0 -13
- data/lib/sequel_core/dataset/convenience.rb +0 -245
- data/lib/sequel_core/dataset/pagination.rb +0 -96
- data/lib/sequel_core/dataset/query.rb +0 -41
- data/lib/sequel_core/dataset/schema.rb +0 -15
- data/lib/sequel_core/dataset/sql.rb +0 -889
- data/lib/sequel_core/deprecated.rb +0 -26
- data/lib/sequel_core/exceptions.rb +0 -42
- data/lib/sequel_core/migration.rb +0 -187
- data/lib/sequel_core/object_graph.rb +0 -216
- data/lib/sequel_core/pretty_table.rb +0 -71
- data/lib/sequel_core/schema.rb +0 -2
- data/lib/sequel_core/schema/generator.rb +0 -239
- data/lib/sequel_core/schema/sql.rb +0 -326
- data/lib/sequel_core/sql.rb +0 -812
- data/lib/sequel_core/worker.rb +0 -68
- data/spec/adapters/informix_spec.rb +0 -96
- data/spec/adapters/mysql_spec.rb +0 -765
- data/spec/adapters/oracle_spec.rb +0 -222
- data/spec/adapters/postgres_spec.rb +0 -441
- data/spec/adapters/sqlite_spec.rb +0 -413
- data/spec/connection_pool_spec.rb +0 -363
- data/spec/core_ext_spec.rb +0 -156
- data/spec/core_sql_spec.rb +0 -427
- data/spec/database_spec.rb +0 -963
- data/spec/dataset_spec.rb +0 -2933
- data/spec/expression_filters_spec.rb +0 -316
- data/spec/migration_spec.rb +0 -261
- data/spec/object_graph_spec.rb +0 -230
- data/spec/pretty_table_spec.rb +0 -58
- data/spec/rcov.opts +0 -6
- data/spec/schema_generator_spec.rb +0 -122
- data/spec/schema_spec.rb +0 -422
- data/spec/spec.opts +0 -0
- data/spec/spec_config.rb +0 -7
- data/spec/spec_config.rb.example +0 -8
- data/spec/spec_helper.rb +0 -55
- data/spec/worker_spec.rb +0 -96
@@ -1,26 +0,0 @@
|
|
1
|
-
module Sequel
|
2
|
-
# This module makes it easy to add deprecation functionality to other classes.
|
3
|
-
module Deprecation # :nodoc:
|
4
|
-
# This sets the output stream for the deprecation messages. Set it to an IO
|
5
|
-
# (or any object that responds to puts) and it will call puts on that
|
6
|
-
# object with the deprecation message. Set to nil to ignore deprecation messages.
|
7
|
-
def self.deprecation_message_stream=(file)
|
8
|
-
@dms = file
|
9
|
-
end
|
10
|
-
|
11
|
-
# Set this to true to print tracebacks with every deprecation message,
|
12
|
-
# so you can see exactly where in your code the deprecated methods are
|
13
|
-
# being called.
|
14
|
-
def self.print_tracebacks=(pt)
|
15
|
-
@pt = pt
|
16
|
-
end
|
17
|
-
|
18
|
-
# Puts the messages unaltered to the deprecation message stream
|
19
|
-
def self.deprecate(message)
|
20
|
-
if @dms
|
21
|
-
@dms.puts(message)
|
22
|
-
caller.each{|c| @dms.puts(c)} if @pt
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
@@ -1,42 +0,0 @@
|
|
1
|
-
module Sequel
|
2
|
-
# Represents an error raised in Sequel code.
|
3
|
-
class Error < ::StandardError
|
4
|
-
|
5
|
-
# Raised when Sequel is unable to load a specified adapter.
|
6
|
-
class AdapterNotFound < Error ; end
|
7
|
-
|
8
|
-
# Raise when an invalid expression is encountered inside a block filter.
|
9
|
-
class InvalidExpression < Error; end
|
10
|
-
|
11
|
-
# Represents an Invalid filter.
|
12
|
-
class InvalidFilter < Error ; end
|
13
|
-
|
14
|
-
# Represents an invalid join type.
|
15
|
-
class InvalidJoinType < Error ; end
|
16
|
-
|
17
|
-
# Raised on an invalid operation.
|
18
|
-
class InvalidOperation < Error; end
|
19
|
-
|
20
|
-
# Error raised when an invalid statement is executed.
|
21
|
-
class InvalidStatement < Error; end
|
22
|
-
|
23
|
-
# Represents an Invalid transform.
|
24
|
-
class InvalidTransform < Error ; end
|
25
|
-
|
26
|
-
# Represents an invalid value stored in the database.
|
27
|
-
class InvalidValue < Error ; end
|
28
|
-
|
29
|
-
# Represents an attempt to performing filter operations when no filter has been specified yet.
|
30
|
-
class NoExistingFilter < Error ; end
|
31
|
-
|
32
|
-
# There was an error while waiting on a connection from the connection pool
|
33
|
-
class PoolTimeoutError < Error ; end
|
34
|
-
|
35
|
-
# Rollback is a special error used to rollback a transactions.
|
36
|
-
# A transaction block will catch this error and won't pass further up the stack.
|
37
|
-
class Rollback < Error ; end
|
38
|
-
|
39
|
-
# Should be raised inside a worker loop to tell it to stop working.
|
40
|
-
class WorkerStop < RuntimeError ; end
|
41
|
-
end
|
42
|
-
end
|
@@ -1,187 +0,0 @@
|
|
1
|
-
module Sequel
|
2
|
-
# The Migration class describes a database migration that can be reversed.
|
3
|
-
# The migration looks very similar to ActiveRecord (Rails) migrations, e.g.:
|
4
|
-
#
|
5
|
-
# class CreateSessions < Sequel::Migration
|
6
|
-
# def up
|
7
|
-
# create_table :sessions do
|
8
|
-
# primary_key :id
|
9
|
-
# varchar :session_id, :size => 32, :unique => true
|
10
|
-
# timestamp :created_at
|
11
|
-
# text :data
|
12
|
-
# end
|
13
|
-
# end
|
14
|
-
#
|
15
|
-
# def down
|
16
|
-
# execute 'DROP TABLE sessions'
|
17
|
-
# end
|
18
|
-
# end
|
19
|
-
#
|
20
|
-
# To apply a migration to a database, you can invoke the #apply with
|
21
|
-
# the target database instance and the direction :up or :down, e.g.:
|
22
|
-
#
|
23
|
-
# DB = Sequel.open ('sqlite://mydb')
|
24
|
-
# CreateSessions.apply(DB, :up)
|
25
|
-
#
|
26
|
-
# See Sequel::Schema::Generator for the syntax to use for creating tables,
|
27
|
-
# and Sequel::Schema::AlterTableGenerator for the syntax to use when
|
28
|
-
# altering existing tables.
|
29
|
-
class Migration
|
30
|
-
# Creates a new instance of the migration and sets the @db attribute.
|
31
|
-
def initialize(db)
|
32
|
-
@db = db
|
33
|
-
end
|
34
|
-
|
35
|
-
# Applies the migration to the supplied database in the specified
|
36
|
-
# direction.
|
37
|
-
def self.apply(db, direction)
|
38
|
-
obj = new(db)
|
39
|
-
case direction
|
40
|
-
when :up
|
41
|
-
obj.up
|
42
|
-
when :down
|
43
|
-
obj.down
|
44
|
-
else
|
45
|
-
raise ArgumentError, "Invalid migration direction specified (#{direction.inspect})"
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
# Returns the list of Migration descendants.
|
50
|
-
def self.descendants
|
51
|
-
@descendants ||= []
|
52
|
-
end
|
53
|
-
|
54
|
-
# Adds the new migration class to the list of Migration descendants.
|
55
|
-
def self.inherited(base)
|
56
|
-
descendants << base
|
57
|
-
end
|
58
|
-
|
59
|
-
# The default down action does nothing
|
60
|
-
def down
|
61
|
-
end
|
62
|
-
|
63
|
-
# Intercepts method calls intended for the database and sends them along.
|
64
|
-
def method_missing(method_sym, *args, &block)
|
65
|
-
@db.send(method_sym, *args, &block)
|
66
|
-
end
|
67
|
-
|
68
|
-
# The default up action does nothing
|
69
|
-
def up
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
# The Migrator module performs migrations based on migration files in a
|
74
|
-
# specified directory. The migration files should be named using the
|
75
|
-
# following pattern (in similar fashion to ActiveRecord migrations):
|
76
|
-
#
|
77
|
-
# <version>_<title>.rb
|
78
|
-
#
|
79
|
-
# For example, the following files are considered migration files:
|
80
|
-
#
|
81
|
-
# 001_create_sessions.rb
|
82
|
-
# 002_add_data_column.rb
|
83
|
-
# ...
|
84
|
-
#
|
85
|
-
# The migration files should contain one or more migration classes based
|
86
|
-
# on Sequel::Migration.
|
87
|
-
#
|
88
|
-
# To apply a migration, the #apply method must be invoked with the database
|
89
|
-
# instance, the directory of migration files and the target version. If
|
90
|
-
# no current version is supplied, it is read from the database. The migrator
|
91
|
-
# automatically creates a schema_info table in the database to keep track
|
92
|
-
# of the current migration version. If no migration version is stored in the
|
93
|
-
# database, the version is considered to be 0. If no target version is
|
94
|
-
# specified, the database is migrated to the latest version available in the
|
95
|
-
# migration directory.
|
96
|
-
#
|
97
|
-
# For example, to migrate the database to the latest version:
|
98
|
-
#
|
99
|
-
# Sequel::Migrator.apply(DB, '.')
|
100
|
-
#
|
101
|
-
# To migrate the database from version 1 to version 5:
|
102
|
-
#
|
103
|
-
# Sequel::Migrator.apply(DB, '.', 5, 1)
|
104
|
-
module Migrator
|
105
|
-
MIGRATION_FILE_PATTERN = /\A\d+_.+\.rb\z/.freeze
|
106
|
-
|
107
|
-
# Migrates the supplied database in the specified directory from the
|
108
|
-
# current version to the target version. If no current version is
|
109
|
-
# supplied, it is extracted from a schema_info table. The schema_info
|
110
|
-
# table is automatically created and maintained by the apply function.
|
111
|
-
def self.apply(db, directory, target = nil, current = nil)
|
112
|
-
# determine current and target version and direction
|
113
|
-
current ||= get_current_migration_version(db)
|
114
|
-
target ||= latest_migration_version(directory)
|
115
|
-
raise Error, "No current version available" if current.nil?
|
116
|
-
raise Error, "No target version available" if target.nil?
|
117
|
-
|
118
|
-
direction = current < target ? :up : :down
|
119
|
-
|
120
|
-
classes = migration_classes(directory, target, current, direction)
|
121
|
-
|
122
|
-
db.transaction do
|
123
|
-
classes.each {|c| c.apply(db, direction)}
|
124
|
-
set_current_migration_version(db, target)
|
125
|
-
end
|
126
|
-
|
127
|
-
target
|
128
|
-
end
|
129
|
-
|
130
|
-
# Gets the current migration version stored in the database. If no version
|
131
|
-
# number is stored, 0 is returned.
|
132
|
-
def self.get_current_migration_version(db)
|
133
|
-
r = schema_info_dataset(db).first
|
134
|
-
r ? r[:version] : 0
|
135
|
-
end
|
136
|
-
|
137
|
-
# Returns the latest version available in the specified directory.
|
138
|
-
def self.latest_migration_version(directory)
|
139
|
-
l = migration_files(directory).last
|
140
|
-
l ? File.basename(l).to_i : nil
|
141
|
-
end
|
142
|
-
|
143
|
-
# Returns a list of migration classes filtered for the migration range and
|
144
|
-
# ordered according to the migration direction.
|
145
|
-
def self.migration_classes(directory, target, current, direction)
|
146
|
-
range = direction == :up ?
|
147
|
-
(current + 1)..target : (target + 1)..current
|
148
|
-
|
149
|
-
# Remove class definitions
|
150
|
-
Migration.descendants.each do |c|
|
151
|
-
Object.send(:remove_const, c.to_s) rescue nil
|
152
|
-
end
|
153
|
-
Migration.descendants.clear # remove any defined migration classes
|
154
|
-
|
155
|
-
# load migration files
|
156
|
-
migration_files(directory, range).each {|fn| load(fn)}
|
157
|
-
|
158
|
-
# get migration classes
|
159
|
-
classes = Migration.descendants
|
160
|
-
classes.reverse! if direction == :down
|
161
|
-
classes
|
162
|
-
end
|
163
|
-
|
164
|
-
# Returns any found migration files in the supplied directory.
|
165
|
-
def self.migration_files(directory, range = nil)
|
166
|
-
files = []
|
167
|
-
Dir.new(directory).each do |file|
|
168
|
-
files[file.to_i] = File.join(directory, file) if MIGRATION_FILE_PATTERN.match(file)
|
169
|
-
end
|
170
|
-
filtered = range ? files[range] : files
|
171
|
-
filtered ? filtered.compact : []
|
172
|
-
end
|
173
|
-
|
174
|
-
# Returns the dataset for the schema_info table. If no such table
|
175
|
-
# exists, it is automatically created.
|
176
|
-
def self.schema_info_dataset(db)
|
177
|
-
db.create_table(:schema_info) {integer :version} unless db.table_exists?(:schema_info)
|
178
|
-
db[:schema_info]
|
179
|
-
end
|
180
|
-
|
181
|
-
# Sets the current migration version stored in the database.
|
182
|
-
def self.set_current_migration_version(db, version)
|
183
|
-
dataset = schema_info_dataset(db)
|
184
|
-
dataset.send(dataset.first ? :update : :<<, :version => version)
|
185
|
-
end
|
186
|
-
end
|
187
|
-
end
|
@@ -1,216 +0,0 @@
|
|
1
|
-
module Sequel
|
2
|
-
class Dataset
|
3
|
-
# Allows you to join multiple datasets/tables and have the result set
|
4
|
-
# split into component tables.
|
5
|
-
#
|
6
|
-
# This differs from the usual usage of join, which returns the result set
|
7
|
-
# as a single hash. For example:
|
8
|
-
#
|
9
|
-
# # CREATE TABLE artists (id INTEGER, name TEXT);
|
10
|
-
# # CREATE TABLE albums (id INTEGER, name TEXT, artist_id INTEGER);
|
11
|
-
# DB[:artists].left_outer_join(:albums, :artist_id=>:id).first
|
12
|
-
# => {:id=>(albums.id||artists.id), :name=>(albums.name||artist.names), :artist_id=>albums.artist_id}
|
13
|
-
# DB[:artists].graph(:albums, :artist_id=>:id).first
|
14
|
-
# => {:artists=>{:id=>artists.id, :name=>artists.name}, :albums=>{:id=>albums.id, :name=>albums.name, :artist_id=>albums.artist_id}}
|
15
|
-
#
|
16
|
-
# Using a join such as left_outer_join, the attribute names that are shared between
|
17
|
-
# the tables are combined in the single return hash. You can get around that by
|
18
|
-
# using .select with correct aliases for all of the columns, but it is simpler to
|
19
|
-
# use graph and have the result set split for you. In addition, graph respects
|
20
|
-
# any row_proc or transform attributes of the current dataset and the datasets
|
21
|
-
# you use with graph.
|
22
|
-
#
|
23
|
-
# If you are graphing a table and all columns for that table are nil, this
|
24
|
-
# indicates that no matching rows existed in the table, so graph will return nil
|
25
|
-
# instead of a hash with all nil values:
|
26
|
-
#
|
27
|
-
# # If the artist doesn't have any albums
|
28
|
-
# DB[:artists].graph(:albums, :artist_id=>:id).first
|
29
|
-
# => {:artists=>{:id=>artists.id, :name=>artists.name}, :albums=>nil}
|
30
|
-
#
|
31
|
-
# Arguments:
|
32
|
-
# * dataset - Can be a symbol (specifying a table), another dataset,
|
33
|
-
# or an object that responds to .dataset and yields a symbol or a dataset
|
34
|
-
# * join_conditions - Any condition(s) allowed by join_table.
|
35
|
-
# * options - A hash of graph options. The following options are currently used:
|
36
|
-
# * :table_alias - The alias to use for the table. If not specified, doesn't
|
37
|
-
# alias the table. You will get an error if the the alias (or table) name is
|
38
|
-
# used more than once.
|
39
|
-
# * :join_type - The type of join to use (passed to join_table). Defaults to
|
40
|
-
# :left_outer.
|
41
|
-
# * :select - An array of columns to select. When not used, selects
|
42
|
-
# all columns in the given dataset. When set to false, selects no
|
43
|
-
# columns and is like simply joining the tables, though graph keeps
|
44
|
-
# some metadata about join that makes it important to use graph instead
|
45
|
-
# of join.
|
46
|
-
# * block - A block that is passed to join_table.
|
47
|
-
def graph(dataset, join_conditions = nil, options = {}, &block)
|
48
|
-
# Allow the use of a model, dataset, or symbol as the first argument
|
49
|
-
# Find the table name/dataset based on the argument
|
50
|
-
dataset = dataset.dataset if dataset.respond_to?(:dataset)
|
51
|
-
case dataset
|
52
|
-
when Symbol
|
53
|
-
table = dataset
|
54
|
-
dataset = @db[dataset]
|
55
|
-
when ::Sequel::Dataset
|
56
|
-
table = dataset.first_source
|
57
|
-
else
|
58
|
-
raise Error, "The dataset argument should be a symbol, dataset, or model"
|
59
|
-
end
|
60
|
-
|
61
|
-
# Raise Sequel::Error with explanation that the table alias has been used
|
62
|
-
raise_alias_error = lambda do
|
63
|
-
raise(Error, "this #{options[:table_alias] ? 'alias' : 'table'} has already been been used, please specify " \
|
64
|
-
"#{options[:table_alias] ? 'a different alias' : 'an alias via the :table_alias option'}")
|
65
|
-
end
|
66
|
-
|
67
|
-
# Only allow table aliases that haven't been used
|
68
|
-
table_alias = options[:table_alias] || table
|
69
|
-
raise_alias_error.call if @opts[:graph] && @opts[:graph][:table_aliases] && @opts[:graph][:table_aliases].include?(table_alias)
|
70
|
-
|
71
|
-
# Join the table early in order to avoid cloning the dataset twice
|
72
|
-
ds = join_table(options[:join_type] || :left_outer, table, join_conditions, table_alias, &block)
|
73
|
-
opts = ds.opts
|
74
|
-
|
75
|
-
# Whether to include the table in the result set
|
76
|
-
add_table = options[:select] == false ? false : true
|
77
|
-
# Whether to add the columns to the list of column aliases
|
78
|
-
add_columns = !ds.opts.include?(:graph_aliases)
|
79
|
-
|
80
|
-
# Setup the initial graph data structure if it doesn't exist
|
81
|
-
unless graph = opts[:graph]
|
82
|
-
master = ds.first_source
|
83
|
-
raise_alias_error.call if master == table_alias
|
84
|
-
# Master hash storing all .graph related information
|
85
|
-
graph = opts[:graph] = {}
|
86
|
-
# Associates column aliases back to tables and columns
|
87
|
-
column_aliases = graph[:column_aliases] = {}
|
88
|
-
# Associates table alias (the master is never aliased)
|
89
|
-
table_aliases = graph[:table_aliases] = {master=>self}
|
90
|
-
# Keep track of the alias numbers used
|
91
|
-
ca_num = graph[:column_alias_num] = Hash.new(0)
|
92
|
-
# All columns in the master table are never
|
93
|
-
# aliased, but are not included if set_graph_aliases
|
94
|
-
# has been used.
|
95
|
-
if add_columns
|
96
|
-
select = opts[:select] = []
|
97
|
-
columns.each do |column|
|
98
|
-
column_aliases[column] = [master, column]
|
99
|
-
select.push(column.qualify(master))
|
100
|
-
end
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
|
-
# Add the table alias to the list of aliases
|
105
|
-
# Even if it isn't been used in the result set,
|
106
|
-
# we add a key for it with a nil value so we can check if it
|
107
|
-
# is used more than once
|
108
|
-
table_aliases = graph[:table_aliases]
|
109
|
-
table_aliases[table_alias] = add_table ? dataset : nil
|
110
|
-
|
111
|
-
# Add the columns to the selection unless we are ignoring them
|
112
|
-
if add_table && add_columns
|
113
|
-
select = opts[:select]
|
114
|
-
column_aliases = graph[:column_aliases]
|
115
|
-
ca_num = graph[:column_alias_num]
|
116
|
-
# Which columns to add to the result set
|
117
|
-
cols = options[:select] || dataset.columns
|
118
|
-
# If the column hasn't been used yet, don't alias it.
|
119
|
-
# If it has been used, try table_column.
|
120
|
-
# If that has been used, try table_column_N
|
121
|
-
# using the next value of N that we know hasn't been
|
122
|
-
# used
|
123
|
-
cols.each do |column|
|
124
|
-
col_alias, identifier = if column_aliases[column]
|
125
|
-
column_alias = :"#{table_alias}_#{column}"
|
126
|
-
if column_aliases[column_alias]
|
127
|
-
column_alias_num = ca_num[column_alias]
|
128
|
-
column_alias = :"#{column_alias}_#{column_alias_num}"
|
129
|
-
ca_num[column_alias] += 1
|
130
|
-
end
|
131
|
-
[column_alias, column.qualify(table_alias).as(column_alias)]
|
132
|
-
else
|
133
|
-
[column, column.qualify(table_alias)]
|
134
|
-
end
|
135
|
-
column_aliases[col_alias] = [table_alias, column]
|
136
|
-
select.push(identifier)
|
137
|
-
end
|
138
|
-
end
|
139
|
-
ds
|
140
|
-
end
|
141
|
-
|
142
|
-
# This allows you to manually specify the graph aliases to use
|
143
|
-
# when using graph. You can use it to only select certain
|
144
|
-
# columns, and have those columns mapped to specific aliases
|
145
|
-
# in the result set. This is the equivalent of .select for a
|
146
|
-
# graphed dataset, and must be used instead of .select whenever
|
147
|
-
# graphing is used. Example:
|
148
|
-
#
|
149
|
-
# DB[:artists].graph(:albums, :artist_id=>:id).set_graph_aliases(:artist_name=>[:artists, :name], :album_name=>[:albums, :name]).first
|
150
|
-
# => {:artists=>{:name=>artists.name}, :albums=>{:name=>albums.name}}
|
151
|
-
#
|
152
|
-
# Arguments:
|
153
|
-
# * graph_aliases - Should be a hash with keys being symbols of
|
154
|
-
# column aliases, and values being arrays with two symbol elements.
|
155
|
-
# The first element of the array should be the table alias,
|
156
|
-
# and the second should be the actual column name.
|
157
|
-
def set_graph_aliases(graph_aliases)
|
158
|
-
cols = graph_aliases.collect do |col_alias, tc|
|
159
|
-
identifier = tc[1].qualify(tc[0])
|
160
|
-
identifier = identifier.as(col_alias) unless tc[1] == col_alias
|
161
|
-
identifier
|
162
|
-
end
|
163
|
-
ds = select(*cols)
|
164
|
-
ds.opts[:graph_aliases] = graph_aliases
|
165
|
-
ds
|
166
|
-
end
|
167
|
-
|
168
|
-
private
|
169
|
-
|
170
|
-
# Fetch the rows, split them into component table parts,
|
171
|
-
# tranform and run the row_proc on each part (if applicable),
|
172
|
-
# and yield a hash of the parts.
|
173
|
-
def graph_each(opts, &block)
|
174
|
-
# Reject tables with nil datasets, as they are excluded from
|
175
|
-
# the result set
|
176
|
-
datasets = @opts[:graph][:table_aliases].to_a.reject{|ta,ds| ds.nil?}
|
177
|
-
# Get just the list of table aliases into a local variable, for speed
|
178
|
-
table_aliases = datasets.collect{|ta,ds| ta}
|
179
|
-
# Get an array of arrays, one for each dataset, with
|
180
|
-
# the necessary information about each dataset, for speed
|
181
|
-
datasets = datasets.collect do |ta, ds|
|
182
|
-
[ta, ds, ds.instance_variable_get(:@transform), ds.row_proc]
|
183
|
-
end
|
184
|
-
# Use the manually set graph aliases, if any, otherwise
|
185
|
-
# use the ones automatically created by .graph
|
186
|
-
column_aliases = @opts[:graph_aliases] || @opts[:graph][:column_aliases]
|
187
|
-
fetch_rows(select_sql(opts)) do |r|
|
188
|
-
graph = {}
|
189
|
-
# Create the sub hashes, one per table
|
190
|
-
table_aliases.each{|ta| graph[ta]={}}
|
191
|
-
# Split the result set based on the column aliases
|
192
|
-
# If there are columns in the result set that are
|
193
|
-
# not in column_aliases, they are ignored
|
194
|
-
column_aliases.each do |col_alias, tc|
|
195
|
-
ta, column = tc
|
196
|
-
graph[ta][column] = r[col_alias]
|
197
|
-
end
|
198
|
-
# For each dataset, transform and run the row
|
199
|
-
# row_proc if applicable
|
200
|
-
datasets.each do |ta,ds,tr,rp|
|
201
|
-
g = graph[ta]
|
202
|
-
graph[ta] = if g.values.any?
|
203
|
-
g = ds.transform_load(g) if tr
|
204
|
-
g = rp[g] if rp
|
205
|
-
g
|
206
|
-
else
|
207
|
-
nil
|
208
|
-
end
|
209
|
-
end
|
210
|
-
|
211
|
-
yield graph
|
212
|
-
end
|
213
|
-
self
|
214
|
-
end
|
215
|
-
end
|
216
|
-
end
|