dbee-active_record 1.0.0.pre.alpha
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.editorconfig +8 -0
- data/.gitignore +7 -0
- data/.rubocop.yml +27 -0
- data/.ruby-version +1 -0
- data/.travis.yml +30 -0
- data/CHANGELOG.md +7 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +5 -0
- data/Guardfile +16 -0
- data/LICENSE +7 -0
- data/README.md +75 -0
- data/Rakefile +15 -0
- data/bin/console +18 -0
- data/dbee-active_record.gemspec +36 -0
- data/lib/dbee/providers/active_record_provider/expression_builder/constraint_maker.rb +50 -0
- data/lib/dbee/providers/active_record_provider/expression_builder/order_maker.rb +23 -0
- data/lib/dbee/providers/active_record_provider/expression_builder/select_maker.rb +31 -0
- data/lib/dbee/providers/active_record_provider/expression_builder/where_maker.rb +54 -0
- data/lib/dbee/providers/active_record_provider/expression_builder.rb +169 -0
- data/lib/dbee/providers/active_record_provider/obfuscated_alias_maker.rb +40 -0
- data/lib/dbee/providers/active_record_provider/safe_alias_maker.rb +21 -0
- data/lib/dbee/providers/active_record_provider/version.rb +16 -0
- data/lib/dbee/providers/active_record_provider.rb +51 -0
- data/spec/config/database.yaml.ci +9 -0
- data/spec/db_helper.rb +56 -0
- data/spec/dbee/providers/active_record_provider_spec.rb +79 -0
- data/spec/fixtures/active_record_snapshots/five_table_query.yaml +77 -0
- data/spec/fixtures/active_record_snapshots/multiple_same_table_query_with_static_constraints.yaml +104 -0
- data/spec/fixtures/active_record_snapshots/one_table_query.yaml +26 -0
- data/spec/fixtures/active_record_snapshots/one_table_query_with_ascending_sort.yaml +31 -0
- data/spec/fixtures/active_record_snapshots/one_table_query_with_descending_sort.yaml +32 -0
- data/spec/fixtures/active_record_snapshots/one_table_query_with_filters.yaml +170 -0
- data/spec/fixtures/active_record_snapshots/one_table_query_with_limit.yaml +30 -0
- data/spec/fixtures/active_record_snapshots/one_table_query_with_multiple_sorts.yaml +33 -0
- data/spec/fixtures/active_record_snapshots/two_table_query.yaml +44 -0
- data/spec/fixtures/models.yaml +66 -0
- data/spec/spec_helper.rb +52 -0
- metadata +256 -0
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
# Copyright (c) 2019-present, Blue Marble Payroll, LLC
|
5
|
+
#
|
6
|
+
# This source code is licensed under the MIT license found in the
|
7
|
+
# LICENSE file in the root directory of this source tree.
|
8
|
+
#
|
9
|
+
|
10
|
+
module Dbee
|
11
|
+
module Providers
|
12
|
+
class ActiveRecordProvider
|
13
|
+
# Derives new alias names and keeps count of ones already generated in order to avoid
|
14
|
+
# collision.
|
15
|
+
class ObfuscatedAliasMaker
|
16
|
+
attr_reader :prefix
|
17
|
+
|
18
|
+
def initialize(prefix = '')
|
19
|
+
@counter = -1
|
20
|
+
@prefix = prefix
|
21
|
+
end
|
22
|
+
|
23
|
+
def make(_name)
|
24
|
+
increment
|
25
|
+
current
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def current
|
31
|
+
"#{prefix}#{@counter}"
|
32
|
+
end
|
33
|
+
|
34
|
+
def increment
|
35
|
+
@counter += 1
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
# Copyright (c) 2019-present, Blue Marble Payroll, LLC
|
5
|
+
#
|
6
|
+
# This source code is licensed under the MIT license found in the
|
7
|
+
# LICENSE file in the root directory of this source tree.
|
8
|
+
#
|
9
|
+
|
10
|
+
module Dbee
|
11
|
+
module Providers
|
12
|
+
class ActiveRecordProvider
|
13
|
+
# This class can be used when readable alias names are expected.
|
14
|
+
class SafeAliasMaker
|
15
|
+
def make(name)
|
16
|
+
name.to_s.tr('.', '_')
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
# Copyright (c) 2019-present, Blue Marble Payroll, LLC
|
5
|
+
#
|
6
|
+
# This source code is licensed under the MIT license found in the
|
7
|
+
# LICENSE file in the root directory of this source tree.
|
8
|
+
#
|
9
|
+
|
10
|
+
module Dbee
|
11
|
+
module Providers
|
12
|
+
class ActiveRecordProvider
|
13
|
+
VERSION = '1.0.0-alpha'
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
# Copyright (c) 2019-present, Blue Marble Payroll, LLC
|
5
|
+
#
|
6
|
+
# This source code is licensed under the MIT license found in the
|
7
|
+
# LICENSE file in the root directory of this source tree.
|
8
|
+
#
|
9
|
+
|
10
|
+
require 'dbee'
|
11
|
+
require 'active_record'
|
12
|
+
|
13
|
+
require_relative 'active_record_provider/expression_builder'
|
14
|
+
require_relative 'active_record_provider/obfuscated_alias_maker'
|
15
|
+
require_relative 'active_record_provider/safe_alias_maker'
|
16
|
+
|
17
|
+
module Dbee
|
18
|
+
module Providers
|
19
|
+
# Provider which leverages ActiveRecord and Arel for generating SQL.
|
20
|
+
class ActiveRecordProvider
|
21
|
+
DEFAULT_TABLE_PREFIX = 't'
|
22
|
+
DEFAULT_COLUMN_PREFIX = 'c'
|
23
|
+
|
24
|
+
attr_reader :readable, :table_alias_maker, :column_alias_maker
|
25
|
+
|
26
|
+
def initialize(
|
27
|
+
readable: true,
|
28
|
+
table_prefix: DEFAULT_TABLE_PREFIX,
|
29
|
+
column_prefix: DEFAULT_COLUMN_PREFIX
|
30
|
+
)
|
31
|
+
@readable = readable
|
32
|
+
@table_alias_maker = alias_maker(table_prefix)
|
33
|
+
@column_alias_maker = alias_maker(column_prefix)
|
34
|
+
end
|
35
|
+
|
36
|
+
def sql(model, query)
|
37
|
+
ExpressionBuilder.new(
|
38
|
+
model,
|
39
|
+
table_alias_maker,
|
40
|
+
column_alias_maker
|
41
|
+
).add(query).to_sql
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def alias_maker(prefix)
|
47
|
+
readable ? SafeAliasMaker.new : ObfuscatedAliasMaker.new(prefix)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
data/spec/db_helper.rb
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
# Copyright (c) 2018-present, Blue Marble Payroll, LLC
|
5
|
+
#
|
6
|
+
# This source code is licensed under the MIT license found in the
|
7
|
+
# LICENSE file in the root directory of this source tree.
|
8
|
+
#
|
9
|
+
|
10
|
+
# Enable logging using something like:
|
11
|
+
# ActiveRecord::Base.logger = Logger.new(STDERR)
|
12
|
+
|
13
|
+
def connect_to_db(name)
|
14
|
+
config = yaml_file_read('spec', 'config', 'database.yaml')[name.to_s]
|
15
|
+
ActiveRecord::Base.establish_connection(config)
|
16
|
+
end
|
17
|
+
|
18
|
+
def load_schema
|
19
|
+
ActiveRecord::Schema.define do
|
20
|
+
create_table :theaters do |t|
|
21
|
+
t.column :name, :string
|
22
|
+
t.column :partition, :string
|
23
|
+
t.column :active, :boolean
|
24
|
+
t.column :inspected, :boolean
|
25
|
+
t.timestamps
|
26
|
+
end
|
27
|
+
|
28
|
+
create_table :members do |t|
|
29
|
+
t.column :tid, :integer
|
30
|
+
t.column :account_number, :string
|
31
|
+
t.column :partition, :string
|
32
|
+
t.timestamps
|
33
|
+
end
|
34
|
+
|
35
|
+
create_table :demographics do |t|
|
36
|
+
t.column :member_id, :integer
|
37
|
+
t.column :name, :string
|
38
|
+
t.timestamps
|
39
|
+
end
|
40
|
+
|
41
|
+
create_table :phone_numbers do |t|
|
42
|
+
t.column :demographic_id, :integer
|
43
|
+
t.column :phone_type, :string
|
44
|
+
t.column :phone_number, :string
|
45
|
+
t.timestamps
|
46
|
+
end
|
47
|
+
|
48
|
+
create_table :movies do |t|
|
49
|
+
t.column :member_id, :integer
|
50
|
+
t.column :name, :string
|
51
|
+
t.column :genre, :string
|
52
|
+
t.column :favorite, :boolean, default: false, null: false
|
53
|
+
t.timestamps
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
# Copyright (c) 2019-present, Blue Marble Payroll, LLC
|
5
|
+
#
|
6
|
+
# This source code is licensed under the MIT license found in the
|
7
|
+
# LICENSE file in the root directory of this source tree.
|
8
|
+
#
|
9
|
+
|
10
|
+
require 'spec_helper'
|
11
|
+
require 'db_helper'
|
12
|
+
|
13
|
+
describe Dbee::Providers::ActiveRecordProvider do
|
14
|
+
let(:models) { yaml_fixture('models.yaml') }
|
15
|
+
|
16
|
+
describe 'Snapshot' do
|
17
|
+
context 'Generating SQL' do
|
18
|
+
%w[sqlite mysql].each do |dbms|
|
19
|
+
context dbms do
|
20
|
+
before(:all) do
|
21
|
+
connect_to_db(dbms)
|
22
|
+
end
|
23
|
+
|
24
|
+
{ readable: true, not_readable: false }.each_pair do |type, readable|
|
25
|
+
context type.to_s do
|
26
|
+
let(:key) { "#{dbms}_#{type}" }
|
27
|
+
|
28
|
+
yaml_fixture_files('active_record_snapshots').each_pair do |filename, snapshot|
|
29
|
+
specify File.basename(filename) do
|
30
|
+
model_name = snapshot['model_name']
|
31
|
+
query = Dbee::Query.make(snapshot['query'])
|
32
|
+
model = Dbee::Model.make(models[model_name])
|
33
|
+
expected_sql = snapshot[key].to_s.chomp.tr("\n", ' ')
|
34
|
+
actual_sql = described_class.new(readable: readable).sql(model, query)
|
35
|
+
|
36
|
+
error_msg = <<~ERROR_MSG
|
37
|
+
Expected: #{expected_sql}
|
38
|
+
Actual: #{actual_sql}
|
39
|
+
ERROR_MSG
|
40
|
+
|
41
|
+
expect(actual_sql).to eq(expected_sql), error_msg
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
context 'Executing SQL' do
|
51
|
+
%w[sqlite].each do |dbms|
|
52
|
+
context dbms do
|
53
|
+
before(:all) do
|
54
|
+
connect_to_db(dbms)
|
55
|
+
load_schema
|
56
|
+
end
|
57
|
+
|
58
|
+
{ readable: true, not_readable: false }.each_pair do |type, readable|
|
59
|
+
context type.to_s do
|
60
|
+
let(:key) { "#{dbms}_#{type}" }
|
61
|
+
|
62
|
+
yaml_fixture_files('active_record_snapshots').each_pair do |filename, snapshot|
|
63
|
+
specify File.basename(filename) do
|
64
|
+
model_name = snapshot['model_name']
|
65
|
+
query = Dbee::Query.make(snapshot['query'])
|
66
|
+
model = Dbee::Model.make(models[model_name])
|
67
|
+
|
68
|
+
sql = described_class.new(readable: readable).sql(model, query)
|
69
|
+
|
70
|
+
expect { ActiveRecord::Base.connection.execute(sql) }.to_not raise_error
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
model_name: Theaters, Members, and Movies
|
2
|
+
query:
|
3
|
+
fields:
|
4
|
+
- key_path: members.demos.phone_numbers.phone_number
|
5
|
+
display: PHONE NUMBER
|
6
|
+
- key_path: members.demos.name
|
7
|
+
- key_path: id
|
8
|
+
- key_path: name
|
9
|
+
- key_path: members.movies.id
|
10
|
+
- key_path: members.id
|
11
|
+
- key_path: members.account_number
|
12
|
+
- key_path: members.demos.phone_numbers.phone_type
|
13
|
+
- key_path: members.movies.name
|
14
|
+
sqlite_readable: |+
|
15
|
+
SELECT
|
16
|
+
"members_demos_phone_numbers"."phone_number" AS 'PHONE NUMBER',
|
17
|
+
"members_demos"."name" AS 'members_demos_name',
|
18
|
+
"theaters"."id" AS 'id',
|
19
|
+
"theaters"."name" AS 'name',
|
20
|
+
"members_movies"."id" AS 'members_movies_id',
|
21
|
+
"members"."id" AS 'members_id',
|
22
|
+
"members"."account_number" AS 'members_account_number',
|
23
|
+
"members_demos_phone_numbers"."phone_type" AS 'members_demos_phone_numbers_phone_type',
|
24
|
+
"members_movies"."name" AS 'members_movies_name'
|
25
|
+
FROM "theaters" "theaters"
|
26
|
+
LEFT OUTER JOIN "members" "members" ON "members"."tid" = "theaters"."id" AND "members"."partition" = "theaters"."partition"
|
27
|
+
LEFT OUTER JOIN "demographics" "members_demos" ON "members_demos"."member_id" = "members"."id"
|
28
|
+
LEFT OUTER JOIN "phone_numbers" "members_demos_phone_numbers" ON "members_demos_phone_numbers"."demographic_id" = "members_demos"."id"
|
29
|
+
LEFT OUTER JOIN "movies" "members_movies" ON "members_movies"."member_id" = "members"."id"
|
30
|
+
sqlite_not_readable: |+
|
31
|
+
SELECT
|
32
|
+
"t3"."phone_number" AS 'c0',
|
33
|
+
"t2"."name" AS 'c1',
|
34
|
+
"t0"."id" AS 'c2',
|
35
|
+
"t0"."name" AS 'c3',
|
36
|
+
"t4"."id" AS 'c4',
|
37
|
+
"t1"."id" AS 'c5',
|
38
|
+
"t1"."account_number" AS 'c6',
|
39
|
+
"t3"."phone_type" AS 'c7',
|
40
|
+
"t4"."name" AS 'c8'
|
41
|
+
FROM "theaters" "t0"
|
42
|
+
LEFT OUTER JOIN "members" "t1" ON "t1"."tid" = "t0"."id" AND "t1"."partition" = "t0"."partition"
|
43
|
+
LEFT OUTER JOIN "demographics" "t2" ON "t2"."member_id" = "t1"."id"
|
44
|
+
LEFT OUTER JOIN "phone_numbers" "t3" ON "t3"."demographic_id" = "t2"."id"
|
45
|
+
LEFT OUTER JOIN "movies" "t4" ON "t4"."member_id" = "t1"."id"
|
46
|
+
mysql_readable: |+
|
47
|
+
SELECT
|
48
|
+
`members_demos_phone_numbers`.`phone_number` AS 'PHONE NUMBER',
|
49
|
+
`members_demos`.`name` AS 'members_demos_name',
|
50
|
+
`theaters`.`id` AS 'id',
|
51
|
+
`theaters`.`name` AS 'name',
|
52
|
+
`members_movies`.`id` AS 'members_movies_id',
|
53
|
+
`members`.`id` AS 'members_id',
|
54
|
+
`members`.`account_number` AS 'members_account_number',
|
55
|
+
`members_demos_phone_numbers`.`phone_type` AS 'members_demos_phone_numbers_phone_type',
|
56
|
+
`members_movies`.`name` AS 'members_movies_name'
|
57
|
+
FROM `theaters` `theaters`
|
58
|
+
LEFT OUTER JOIN `members` `members` ON `members`.`tid` = `theaters`.`id` AND `members`.`partition` = `theaters`.`partition`
|
59
|
+
LEFT OUTER JOIN `demographics` `members_demos` ON `members_demos`.`member_id` = `members`.`id`
|
60
|
+
LEFT OUTER JOIN `phone_numbers` `members_demos_phone_numbers` ON `members_demos_phone_numbers`.`demographic_id` = `members_demos`.`id`
|
61
|
+
LEFT OUTER JOIN `movies` `members_movies` ON `members_movies`.`member_id` = `members`.`id`
|
62
|
+
mysql_not_readable: |+
|
63
|
+
SELECT
|
64
|
+
`t3`.`phone_number` AS 'c0',
|
65
|
+
`t2`.`name` AS 'c1',
|
66
|
+
`t0`.`id` AS 'c2',
|
67
|
+
`t0`.`name` AS 'c3',
|
68
|
+
`t4`.`id` AS 'c4',
|
69
|
+
`t1`.`id` AS 'c5',
|
70
|
+
`t1`.`account_number` AS 'c6',
|
71
|
+
`t3`.`phone_type` AS 'c7',
|
72
|
+
`t4`.`name` AS 'c8'
|
73
|
+
FROM `theaters` `t0`
|
74
|
+
LEFT OUTER JOIN `members` `t1` ON `t1`.`tid` = `t0`.`id` AND `t1`.`partition` = `t0`.`partition`
|
75
|
+
LEFT OUTER JOIN `demographics` `t2` ON `t2`.`member_id` = `t1`.`id`
|
76
|
+
LEFT OUTER JOIN `phone_numbers` `t3` ON `t3`.`demographic_id` = `t2`.`id`
|
77
|
+
LEFT OUTER JOIN `movies` `t4` ON `t4`.`member_id` = `t1`.`id`
|
data/spec/fixtures/active_record_snapshots/multiple_same_table_query_with_static_constraints.yaml
ADDED
@@ -0,0 +1,104 @@
|
|
1
|
+
model_name: Theaters, Members, and Movies
|
2
|
+
query:
|
3
|
+
fields:
|
4
|
+
- key_path: id
|
5
|
+
- key_path: name
|
6
|
+
- key_path: members.id
|
7
|
+
- key_path: members.account_number
|
8
|
+
- key_path: members.movies.id
|
9
|
+
- key_path: members.movies.name
|
10
|
+
display: 'Movie Name'
|
11
|
+
- key_path: members.movies.genre
|
12
|
+
- key_path: members.favorite_comic_movies.id
|
13
|
+
- key_path: members.favorite_comic_movies.name
|
14
|
+
display: 'Favorite Comic Movie Name'
|
15
|
+
- key_path: members.favorite_comic_movies.genre
|
16
|
+
- key_path: members.favorite_mystery_movies.id
|
17
|
+
- key_path: members.favorite_mystery_movies.name
|
18
|
+
display: 'Favorite Mystery Movie Name'
|
19
|
+
- key_path: members.favorite_mystery_movies.genre
|
20
|
+
limit: 12
|
21
|
+
sqlite_readable: |+
|
22
|
+
SELECT
|
23
|
+
"theaters"."id" AS 'id',
|
24
|
+
"theaters"."name" AS 'name',
|
25
|
+
"members"."id" AS 'members_id',
|
26
|
+
"members"."account_number" AS 'members_account_number',
|
27
|
+
"members_movies"."id" AS 'members_movies_id',
|
28
|
+
"members_movies"."name" AS 'Movie Name',
|
29
|
+
"members_movies"."genre" AS 'members_movies_genre',
|
30
|
+
"members_favorite_comic_movies"."id" AS 'members_favorite_comic_movies_id',
|
31
|
+
"members_favorite_comic_movies"."name" AS 'Favorite Comic Movie Name',
|
32
|
+
"members_favorite_comic_movies"."genre" AS 'members_favorite_comic_movies_genre',
|
33
|
+
"members_favorite_mystery_movies"."id" AS 'members_favorite_mystery_movies_id',
|
34
|
+
"members_favorite_mystery_movies"."name" AS 'Favorite Mystery Movie Name',
|
35
|
+
"members_favorite_mystery_movies"."genre" AS 'members_favorite_mystery_movies_genre'
|
36
|
+
FROM "theaters" "theaters"
|
37
|
+
LEFT OUTER JOIN "members" "members" ON "members"."tid" = "theaters"."id" AND "members"."partition" = "theaters"."partition"
|
38
|
+
LEFT OUTER JOIN "movies" "members_movies" ON "members_movies"."member_id" = "members"."id"
|
39
|
+
LEFT OUTER JOIN "movies" "members_favorite_comic_movies" ON "members_favorite_comic_movies"."member_id" = "members"."id" AND "members_favorite_comic_movies"."genre" = 'comic'
|
40
|
+
LEFT OUTER JOIN "movies" "members_favorite_mystery_movies" ON "members_favorite_mystery_movies"."member_id" = "members"."id" AND "members_favorite_mystery_movies"."genre" = 'mystery'
|
41
|
+
LIMIT 12
|
42
|
+
sqlite_not_readable: |+
|
43
|
+
SELECT
|
44
|
+
"t0"."id" AS 'c0',
|
45
|
+
"t0"."name" AS 'c1',
|
46
|
+
"t1"."id" AS 'c2',
|
47
|
+
"t1"."account_number" AS 'c3',
|
48
|
+
"t2"."id" AS 'c4',
|
49
|
+
"t2"."name" AS 'c5',
|
50
|
+
"t2"."genre" AS 'c6',
|
51
|
+
"t3"."id" AS 'c7',
|
52
|
+
"t3"."name" AS 'c8',
|
53
|
+
"t3"."genre" AS 'c9',
|
54
|
+
"t4"."id" AS 'c10',
|
55
|
+
"t4"."name" AS 'c11',
|
56
|
+
"t4"."genre" AS 'c12'
|
57
|
+
FROM "theaters" "t0"
|
58
|
+
LEFT OUTER JOIN "members" "t1" ON "t1"."tid" = "t0"."id" AND "t1"."partition" = "t0"."partition"
|
59
|
+
LEFT OUTER JOIN "movies" "t2" ON "t2"."member_id" = "t1"."id"
|
60
|
+
LEFT OUTER JOIN "movies" "t3" ON "t3"."member_id" = "t1"."id" AND "t3"."genre" = 'comic'
|
61
|
+
LEFT OUTER JOIN "movies" "t4" ON "t4"."member_id" = "t1"."id" AND "t4"."genre" = 'mystery'
|
62
|
+
LIMIT 12
|
63
|
+
mysql_readable: |+
|
64
|
+
SELECT
|
65
|
+
`theaters`.`id` AS 'id',
|
66
|
+
`theaters`.`name` AS 'name',
|
67
|
+
`members`.`id` AS 'members_id',
|
68
|
+
`members`.`account_number` AS 'members_account_number',
|
69
|
+
`members_movies`.`id` AS 'members_movies_id',
|
70
|
+
`members_movies`.`name` AS 'Movie Name',
|
71
|
+
`members_movies`.`genre` AS 'members_movies_genre',
|
72
|
+
`members_favorite_comic_movies`.`id` AS 'members_favorite_comic_movies_id',
|
73
|
+
`members_favorite_comic_movies`.`name` AS 'Favorite Comic Movie Name',
|
74
|
+
`members_favorite_comic_movies`.`genre` AS 'members_favorite_comic_movies_genre',
|
75
|
+
`members_favorite_mystery_movies`.`id` AS 'members_favorite_mystery_movies_id',
|
76
|
+
`members_favorite_mystery_movies`.`name` AS 'Favorite Mystery Movie Name',
|
77
|
+
`members_favorite_mystery_movies`.`genre` AS 'members_favorite_mystery_movies_genre'
|
78
|
+
FROM `theaters` `theaters`
|
79
|
+
LEFT OUTER JOIN `members` `members` ON `members`.`tid` = `theaters`.`id` AND `members`.`partition` = `theaters`.`partition`
|
80
|
+
LEFT OUTER JOIN `movies` `members_movies` ON `members_movies`.`member_id` = `members`.`id`
|
81
|
+
LEFT OUTER JOIN `movies` `members_favorite_comic_movies` ON `members_favorite_comic_movies`.`member_id` = `members`.`id` AND `members_favorite_comic_movies`.`genre` = 'comic'
|
82
|
+
LEFT OUTER JOIN `movies` `members_favorite_mystery_movies` ON `members_favorite_mystery_movies`.`member_id` = `members`.`id` AND `members_favorite_mystery_movies`.`genre` = 'mystery'
|
83
|
+
LIMIT 12
|
84
|
+
mysql_not_readable: |+
|
85
|
+
SELECT
|
86
|
+
`t0`.`id` AS 'c0',
|
87
|
+
`t0`.`name` AS 'c1',
|
88
|
+
`t1`.`id` AS 'c2',
|
89
|
+
`t1`.`account_number` AS 'c3',
|
90
|
+
`t2`.`id` AS 'c4',
|
91
|
+
`t2`.`name` AS 'c5',
|
92
|
+
`t2`.`genre` AS 'c6',
|
93
|
+
`t3`.`id` AS 'c7',
|
94
|
+
`t3`.`name` AS 'c8',
|
95
|
+
`t3`.`genre` AS 'c9',
|
96
|
+
`t4`.`id` AS 'c10',
|
97
|
+
`t4`.`name` AS 'c11',
|
98
|
+
`t4`.`genre` AS 'c12'
|
99
|
+
FROM `theaters` `t0`
|
100
|
+
LEFT OUTER JOIN `members` `t1` ON `t1`.`tid` = `t0`.`id` AND `t1`.`partition` = `t0`.`partition`
|
101
|
+
LEFT OUTER JOIN `movies` `t2` ON `t2`.`member_id` = `t1`.`id`
|
102
|
+
LEFT OUTER JOIN `movies` `t3` ON `t3`.`member_id` = `t1`.`id` AND `t3`.`genre` = 'comic'
|
103
|
+
LEFT OUTER JOIN `movies` `t4` ON `t4`.`member_id` = `t1`.`id` AND `t4`.`genre` = 'mystery'
|
104
|
+
LIMIT 12
|
@@ -0,0 +1,26 @@
|
|
1
|
+
model_name: Theaters, Members, and Movies
|
2
|
+
query:
|
3
|
+
fields:
|
4
|
+
- key_path: id
|
5
|
+
display: 'ID #'
|
6
|
+
- key_path: name
|
7
|
+
sqlite_not_readable: |+
|
8
|
+
SELECT
|
9
|
+
"t0"."id" AS 'c0',
|
10
|
+
"t0"."name" AS 'c1'
|
11
|
+
FROM "theaters" "t0"
|
12
|
+
sqlite_readable: |+
|
13
|
+
SELECT
|
14
|
+
"theaters"."id" AS 'ID #',
|
15
|
+
"theaters"."name" AS 'name'
|
16
|
+
FROM "theaters" "theaters"
|
17
|
+
mysql_not_readable: |+
|
18
|
+
SELECT
|
19
|
+
`t0`.`id` AS 'c0',
|
20
|
+
`t0`.`name` AS 'c1'
|
21
|
+
FROM `theaters` `t0`
|
22
|
+
mysql_readable: |+
|
23
|
+
SELECT
|
24
|
+
`theaters`.`id` AS 'ID #',
|
25
|
+
`theaters`.`name` AS 'name'
|
26
|
+
FROM `theaters` `theaters`
|
@@ -0,0 +1,31 @@
|
|
1
|
+
model_name: Theaters, Members, and Movies
|
2
|
+
query:
|
3
|
+
fields:
|
4
|
+
- key_path: id
|
5
|
+
- key_path: name
|
6
|
+
sorters:
|
7
|
+
- key_path: created_at
|
8
|
+
sqlite_readable: |+
|
9
|
+
SELECT
|
10
|
+
"theaters"."id" AS 'id',
|
11
|
+
"theaters"."name" AS 'name'
|
12
|
+
FROM "theaters" "theaters"
|
13
|
+
ORDER BY "theaters"."created_at"
|
14
|
+
sqlite_not_readable: |+
|
15
|
+
SELECT
|
16
|
+
"t0"."id" AS 'c0',
|
17
|
+
"t0"."name" AS 'c1'
|
18
|
+
FROM "theaters" "t0"
|
19
|
+
ORDER BY "t0"."created_at"
|
20
|
+
mysql_readable: |+
|
21
|
+
SELECT
|
22
|
+
`theaters`.`id` AS 'id',
|
23
|
+
`theaters`.`name` AS 'name'
|
24
|
+
FROM `theaters` `theaters`
|
25
|
+
ORDER BY `theaters`.`created_at`
|
26
|
+
mysql_not_readable: |+
|
27
|
+
SELECT
|
28
|
+
`t0`.`id` AS 'c0',
|
29
|
+
`t0`.`name` AS 'c1'
|
30
|
+
FROM `theaters` `t0`
|
31
|
+
ORDER BY `t0`.`created_at`
|
@@ -0,0 +1,32 @@
|
|
1
|
+
model_name: Theaters, Members, and Movies
|
2
|
+
query:
|
3
|
+
fields:
|
4
|
+
- key_path: id
|
5
|
+
- key_path: name
|
6
|
+
sorters:
|
7
|
+
- key_path: created_at
|
8
|
+
direction: descending
|
9
|
+
sqlite_readable: |+
|
10
|
+
SELECT
|
11
|
+
"theaters"."id" AS 'id',
|
12
|
+
"theaters"."name" AS 'name'
|
13
|
+
FROM "theaters" "theaters"
|
14
|
+
ORDER BY "theaters"."created_at" DESC
|
15
|
+
sqlite_not_readable: |+
|
16
|
+
SELECT
|
17
|
+
"t0"."id" AS 'c0',
|
18
|
+
"t0"."name" AS 'c1'
|
19
|
+
FROM "theaters" "t0"
|
20
|
+
ORDER BY "t0"."created_at" DESC
|
21
|
+
mysql_readable: |+
|
22
|
+
SELECT
|
23
|
+
`theaters`.`id` AS 'id',
|
24
|
+
`theaters`.`name` AS 'name'
|
25
|
+
FROM `theaters` `theaters`
|
26
|
+
ORDER BY `theaters`.`created_at` DESC
|
27
|
+
mysql_not_readable: |+
|
28
|
+
SELECT
|
29
|
+
`t0`.`id` AS 'c0',
|
30
|
+
`t0`.`name` AS 'c1'
|
31
|
+
FROM `theaters` `t0`
|
32
|
+
ORDER BY `t0`.`created_at` DESC
|