dbee-active_record 1.0.0.pre.alpha
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.
- 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
|