rails_db_views 0.0.4 → 0.0.5
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 +4 -4
- data/lib/rails_db_views/database_symbol.rb +11 -2
- data/lib/rails_db_views/function.rb +1 -1
- data/lib/rails_db_views/version.rb +1 -1
- data/lib/rails_db_views/view.rb +1 -1
- data/test/dummy/app/models/chat.rb +2 -0
- data/test/dummy/app/models/message.rb +6 -0
- data/test/dummy/app/models/user.rb +18 -0
- data/test/dummy/app/models/user_message.rb +6 -0
- data/test/dummy/config/database.yml +3 -9
- data/test/dummy/db/functions/tuple_sort.sql +10 -0
- data/test/dummy/db/migrate/20160208084226_create_test_tables.rb +18 -0
- data/test/dummy/db/schema.rb +20 -1
- data/test/dummy/db/test.sqlite3 +0 -0
- data/test/dummy/db/views/chats.sql +6 -0
- data/test/dummy/db/views/messages.sql +20 -0
- data/test/dummy/lib/tasks/test.rake +30 -0
- data/test/dummy/log/development.log +241 -0
- data/test/dummy/log/test.log +2635 -0
- metadata +29 -27
- data/test/dummy/db/functions/add.sql +0 -5
- data/test/dummy/db/views/hello_world.sql +0 -2
- data/test/dummy/db/views/required.sql +0 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 377a7268197020fe62a087261f12cd94ead05b30
|
4
|
+
data.tar.gz: 90090417d3607056ba577fa159f6b29366ca870b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a1f7de8e87be5f0de472bcc4a19d11934b69bee78520ed7704c0b33c686e7d942af8755c66a644757c076b073d1e77490aab5f945f219f61046b6efc3ddef446
|
7
|
+
data.tar.gz: 13c1b6a148618a475a9185fcaaba6b41e7905de85eaa0d4a45b7c373fa169b679b51748fe7a319361a6ec3fb860ec8bde007dc6dcbcfd03aedbecf8ed1d5b8cc
|
@@ -48,6 +48,10 @@ class RailsDbViews::DatabaseSymbol
|
|
48
48
|
status == Status::UNLOADED
|
49
49
|
end
|
50
50
|
|
51
|
+
def uncommented_sql_content
|
52
|
+
sql_content.split("\n").reject{|x| x=~ COMMENTS }.join("\n")
|
53
|
+
end
|
54
|
+
|
51
55
|
def create!
|
52
56
|
return if marked_as_deleted? || loaded?
|
53
57
|
|
@@ -82,8 +86,8 @@ class RailsDbViews::DatabaseSymbol
|
|
82
86
|
|
83
87
|
begin
|
84
88
|
ActiveRecord::Base.connection.execute(drop_sql)
|
85
|
-
|
86
|
-
|
89
|
+
rescue ActiveRecord::ActiveRecordError => e #Probably because the symbol doesn't exists yet.
|
90
|
+
handle_error_on_drop
|
87
91
|
end
|
88
92
|
|
89
93
|
self.status = Status::LOADED
|
@@ -107,6 +111,11 @@ protected
|
|
107
111
|
SHARP_CHAR_DIRECTIVE_START = /^#[ \t]*!/
|
108
112
|
DIRECTIVE_START = /#{TWO_DASH_DIRECTIVE_START}|#{SHARP_CHAR_DIRECTIVE_START}/
|
109
113
|
|
114
|
+
#It's not very safe in case we start a line into a string with the characters -- or #.
|
115
|
+
COMMENTS_TWO_DASH = /^--.*$/
|
116
|
+
COMMENTS_SHARP = /^#.*$/
|
117
|
+
COMMENTS = /#{COMMENTS_TWO_DASH}|#{COMMENTS_SHARP}/
|
118
|
+
|
110
119
|
def circular_reference_error
|
111
120
|
raise CircularReferenceError, "Circular file reference! (file: #{path})"
|
112
121
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
class RailsDbViews::Function < RailsDbViews::DatabaseSymbol
|
2
2
|
def create_sql
|
3
3
|
puts "CREATE OR REPLACE FUNCTION #{name}..."
|
4
|
-
"CREATE OR REPLACE FUNCTION #{name} #{
|
4
|
+
"CREATE OR REPLACE FUNCTION #{name} #{uncommented_sql_content}"
|
5
5
|
end
|
6
6
|
|
7
7
|
def drop_sql
|
data/lib/rails_db_views/view.rb
CHANGED
@@ -0,0 +1,18 @@
|
|
1
|
+
class User < ActiveRecord::Base
|
2
|
+
validates :name, presence: true, uniqueness: true
|
3
|
+
|
4
|
+
|
5
|
+
has_many :sended_messages, class_name: "UserMessage", foreign_key: :from
|
6
|
+
has_many :received_messages, class_name: "UserMessage", foreign_key: :to
|
7
|
+
|
8
|
+
has_many :messages
|
9
|
+
|
10
|
+
def message! user, content
|
11
|
+
UserMessage.create! from: self, to: user, content: content
|
12
|
+
end
|
13
|
+
|
14
|
+
# Return all chats of this guy!
|
15
|
+
def chats
|
16
|
+
Chat.where("'{?}' && ids", self.id)
|
17
|
+
end
|
18
|
+
end
|
@@ -5,7 +5,7 @@
|
|
5
5
|
# gem 'sqlite3'
|
6
6
|
development:
|
7
7
|
adapter: postgresql
|
8
|
-
database:
|
8
|
+
database: rails_db_views_development
|
9
9
|
pool: 5
|
10
10
|
timeout: 5000
|
11
11
|
|
@@ -13,13 +13,7 @@ development:
|
|
13
13
|
# re-generated from your development database when you run "rake".
|
14
14
|
# Do not set this db to the same as development or production.
|
15
15
|
test:
|
16
|
-
adapter:
|
17
|
-
database:
|
18
|
-
pool: 5
|
19
|
-
timeout: 5000
|
20
|
-
|
21
|
-
production:
|
22
|
-
adapter: sqlite3
|
23
|
-
database: db/production.sqlite3
|
16
|
+
adapter: postgresql
|
17
|
+
database: rails_db_views_test
|
24
18
|
pool: 5
|
25
19
|
timeout: 5000
|
@@ -0,0 +1,18 @@
|
|
1
|
+
class CreateTestTables < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
create_table :users do |t|
|
4
|
+
t.string :name, index: true
|
5
|
+
|
6
|
+
t.timestamps null: false
|
7
|
+
end
|
8
|
+
|
9
|
+
create_table :user_messages do |t|
|
10
|
+
t.integer :from_id, index: true
|
11
|
+
t.integer :to_id, index: true
|
12
|
+
|
13
|
+
t.text :content
|
14
|
+
|
15
|
+
t.timestamps null: false
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/test/dummy/db/schema.rb
CHANGED
@@ -11,9 +11,28 @@
|
|
11
11
|
#
|
12
12
|
# It's strongly recommended that you check this file into your version control system.
|
13
13
|
|
14
|
-
ActiveRecord::Schema.define(version:
|
14
|
+
ActiveRecord::Schema.define(version: 20160208084226) do
|
15
15
|
|
16
16
|
# These are extensions that must be enabled in order to support this database
|
17
17
|
enable_extension "plpgsql"
|
18
18
|
|
19
|
+
create_table "user_messages", force: :cascade do |t|
|
20
|
+
t.integer "from_id"
|
21
|
+
t.integer "to_id"
|
22
|
+
t.text "content"
|
23
|
+
t.datetime "created_at", null: false
|
24
|
+
t.datetime "updated_at", null: false
|
25
|
+
end
|
26
|
+
|
27
|
+
add_index "user_messages", ["from_id"], name: "index_user_messages_on_from_id", using: :btree
|
28
|
+
add_index "user_messages", ["to_id"], name: "index_user_messages_on_to_id", using: :btree
|
29
|
+
|
30
|
+
create_table "users", force: :cascade do |t|
|
31
|
+
t.string "name"
|
32
|
+
t.datetime "created_at", null: false
|
33
|
+
t.datetime "updated_at", null: false
|
34
|
+
end
|
35
|
+
|
36
|
+
add_index "users", ["name"], name: "index_users_on_name", using: :btree
|
37
|
+
|
19
38
|
end
|
data/test/dummy/db/test.sqlite3
CHANGED
Binary file
|
@@ -0,0 +1,6 @@
|
|
1
|
+
# This is the request for virtual chat object.
|
2
|
+
# !require messages
|
3
|
+
SELECT tuple_sort(ARRAY[sender_id, receiver_id]) AS ids,
|
4
|
+
MIN(created_at) as created_at, MAX(updated_at) as updated_at, COUNT(*) as number_of_messages
|
5
|
+
FROM messages
|
6
|
+
GROUP BY tuple_sort(ARRAY[sender_id, receiver_id])
|
@@ -0,0 +1,20 @@
|
|
1
|
+
-- Sample virtual model to test the gem.
|
2
|
+
-- output:
|
3
|
+
-- receiver_name, receiver_id, sender_name, sender_id, content, updated_at, created_at
|
4
|
+
SELECT DISTINCT _.receiver_name, _.receiver_id, _.sender_name, _.sender_id, _.content, _.updated_at, _.created_at
|
5
|
+
FROM
|
6
|
+
(SELECT u2.name as receiver_name, u2.id as receiver_id,
|
7
|
+
u1.name as sender_name, u1.id as sender_id,
|
8
|
+
um.content as content, um.updated_at as updated_at, um.created_at as created_at
|
9
|
+
FROM users u1
|
10
|
+
INNER JOIN user_messages um ON ( u1.id = um.from_id )
|
11
|
+
INNER JOIN users u2 ON (u2.id = um.to_id)
|
12
|
+
UNION
|
13
|
+
SELECT u1.name as receiver_name, u1.id as receiver_id,
|
14
|
+
u2.name as sender_name, u2.id as sender_id,
|
15
|
+
um.content as content, um.updated_at as updated_at, um.created_at as created_at
|
16
|
+
FROM users u1
|
17
|
+
INNER JOIN user_messages um ON ( u1.id = um.to_id )
|
18
|
+
INNER JOIN users u2 ON ( u2.id = um.from_id )
|
19
|
+
ORDER BY created_at ASC
|
20
|
+
) AS _
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# I've no idea of what I'm doing... haha.
|
2
|
+
# No, really, I don't know what's the best way to test
|
3
|
+
# this gem since it's launched during rake process and not during
|
4
|
+
# application time.
|
5
|
+
task :test do
|
6
|
+
begin
|
7
|
+
Rake::Task["db:drop"].invoke
|
8
|
+
rescue
|
9
|
+
# Case the database is not created, we ignore this error
|
10
|
+
end
|
11
|
+
# But if the database can't be created, we don't ignore.
|
12
|
+
Rake::Task["db:create"].invoke
|
13
|
+
Rake::Task["db:migrate"].invoke
|
14
|
+
|
15
|
+
# Launch RoR
|
16
|
+
Rake::Task["environment"].invoke
|
17
|
+
|
18
|
+
#Create some models
|
19
|
+
jack = User.create! name: "Jack"
|
20
|
+
cindy = User.create! name: "Cindy"
|
21
|
+
henry = User.create! name: "Henry"
|
22
|
+
|
23
|
+
jack.message! cindy, "Hey, how are you?"
|
24
|
+
cindy.message! jack, "I'm fine, and you?"
|
25
|
+
henry.message! cindy, "Me too, I want to chat with you babe!"
|
26
|
+
|
27
|
+
puts henry.chats.inspect
|
28
|
+
puts cindy.chats.inspect
|
29
|
+
puts jack.chats.inspect
|
30
|
+
end
|
@@ -482,3 +482,244 @@ $$ LANGUAGE plpgsql;[0m
|
|
482
482
|
[1m[36m (12.4ms)[0m [1mCREATE VIEW required AS SELECT 1 as id[0m
|
483
483
|
[1m[35m (12.6ms)[0m CREATE VIEW hello_world AS --!require required
|
484
484
|
SELECT 'HelloWorld' WHERE ( SELECT id FROM required ) IN (1)
|
485
|
+
[1m[36m (2.3ms)[0m [1mCREATE OR REPLACE FUNCTION add (x integer, y integer) RETURNS integer AS $$
|
486
|
+
BEGIN
|
487
|
+
RETURN x + y;
|
488
|
+
END;
|
489
|
+
$$ LANGUAGE plpgsql;[0m
|
490
|
+
[1m[35m (7.2ms)[0m DROP VIEW hello_world
|
491
|
+
[1m[36m (6.7ms)[0m [1mDROP VIEW required[0m
|
492
|
+
[1m[35mActiveRecord::SchemaMigration Load (0.7ms)[0m SELECT "schema_migrations".* FROM "schema_migrations"
|
493
|
+
[1m[36m (13.2ms)[0m [1mCREATE VIEW required AS SELECT 1 as id[0m
|
494
|
+
[1m[35m (7.1ms)[0m CREATE VIEW hello_world AS --!require required
|
495
|
+
SELECT 'HelloWorld' WHERE ( SELECT id FROM required ) IN (1)
|
496
|
+
[1m[36mActiveRecord::SchemaMigration Load (0.2ms)[0m [1mSELECT "schema_migrations".* FROM "schema_migrations"[0m
|
497
|
+
[1m[36m (2.0ms)[0m [1mCREATE OR REPLACE FUNCTION add (x integer, y integer) RETURNS integer AS $$
|
498
|
+
BEGIN
|
499
|
+
RETURN x + y;
|
500
|
+
END;
|
501
|
+
$$ LANGUAGE plpgsql;[0m
|
502
|
+
[1m[35m (6.1ms)[0m CREATE OR REPLACE FUNCTION tuple_sort (x int[]) RETURNS int[] AS $$
|
503
|
+
BEGIN
|
504
|
+
IF x[0] > x[1] THEN
|
505
|
+
RETURN ARRAY[x[1], x[0]];
|
506
|
+
ELSE
|
507
|
+
RETURN x;
|
508
|
+
END IF;
|
509
|
+
END;
|
510
|
+
$$ LANGUAGE plpgsql;
|
511
|
+
[1m[36m (0.4ms)[0m [1mDROP VIEW chats[0m
|
512
|
+
PG::UndefinedTable: ERROR: view "chats" does not exist
|
513
|
+
: DROP VIEW chats
|
514
|
+
[1m[35m (0.2ms)[0m DROP VIEW messages
|
515
|
+
PG::UndefinedTable: ERROR: view "messages" does not exist
|
516
|
+
: DROP VIEW messages
|
517
|
+
[1m[36m (7.3ms)[0m [1mCREATE TABLE "schema_migrations" ("version" character varying NOT NULL) [0m
|
518
|
+
[1m[35m (0.9ms)[0m CREATE UNIQUE INDEX "unique_schema_migrations" ON "schema_migrations" ("version")
|
519
|
+
[1m[36mActiveRecord::SchemaMigration Load (0.2ms)[0m [1mSELECT "schema_migrations".* FROM "schema_migrations"[0m
|
520
|
+
Migrating to CreateTestTables (20160208084226)
|
521
|
+
[1m[35m (0.1ms)[0m BEGIN
|
522
|
+
[1m[36m (3.7ms)[0m [1mCREATE TABLE "users" ("id" serial primary key, "name" character varying, "created_at" timestamp NOT NULL, "updated_at" timestamp NOT NULL) [0m
|
523
|
+
[1m[35m (0.8ms)[0m CREATE INDEX "index_users_on_name" ON "users" ("name")
|
524
|
+
[1m[36m (2.4ms)[0m [1mCREATE TABLE "user_messages" ("id" serial primary key, "from_id" integer, "to_id" integer, "content" text, "created_at" timestamp NOT NULL, "updated_at" timestamp NOT NULL) [0m
|
525
|
+
[1m[35m (0.7ms)[0m CREATE INDEX "index_user_messages_on_from_id" ON "user_messages" ("from_id")
|
526
|
+
[1m[36m (0.8ms)[0m [1mCREATE INDEX "index_user_messages_on_to_id" ON "user_messages" ("to_id")[0m
|
527
|
+
[1m[35mSQL (0.2ms)[0m INSERT INTO "schema_migrations" ("version") VALUES ($1) [["version", "20160208084226"]]
|
528
|
+
[1m[36m (0.5ms)[0m [1mCOMMIT[0m
|
529
|
+
[1m[35mActiveRecord::SchemaMigration Load (0.1ms)[0m SELECT "schema_migrations".* FROM "schema_migrations"
|
530
|
+
[1m[36m (1.8ms)[0m [1mSELECT t2.oid::regclass::text AS to_table, a1.attname AS column, a2.attname AS primary_key, c.conname AS name, c.confupdtype AS on_update, c.confdeltype AS on_delete
|
531
|
+
FROM pg_constraint c
|
532
|
+
JOIN pg_class t1 ON c.conrelid = t1.oid
|
533
|
+
JOIN pg_class t2 ON c.confrelid = t2.oid
|
534
|
+
JOIN pg_attribute a1 ON a1.attnum = c.conkey[1] AND a1.attrelid = t1.oid
|
535
|
+
JOIN pg_attribute a2 ON a2.attnum = c.confkey[1] AND a2.attrelid = t2.oid
|
536
|
+
JOIN pg_namespace t3 ON c.connamespace = t3.oid
|
537
|
+
WHERE c.contype = 'f'
|
538
|
+
AND t1.relname = 'user_messages'
|
539
|
+
AND t3.nspname = ANY (current_schemas(false))
|
540
|
+
ORDER BY c.conname
|
541
|
+
[0m
|
542
|
+
[1m[35m (1.5ms)[0m SELECT t2.oid::regclass::text AS to_table, a1.attname AS column, a2.attname AS primary_key, c.conname AS name, c.confupdtype AS on_update, c.confdeltype AS on_delete
|
543
|
+
FROM pg_constraint c
|
544
|
+
JOIN pg_class t1 ON c.conrelid = t1.oid
|
545
|
+
JOIN pg_class t2 ON c.confrelid = t2.oid
|
546
|
+
JOIN pg_attribute a1 ON a1.attnum = c.conkey[1] AND a1.attrelid = t1.oid
|
547
|
+
JOIN pg_attribute a2 ON a2.attnum = c.confkey[1] AND a2.attrelid = t2.oid
|
548
|
+
JOIN pg_namespace t3 ON c.connamespace = t3.oid
|
549
|
+
WHERE c.contype = 'f'
|
550
|
+
AND t1.relname = 'users'
|
551
|
+
AND t3.nspname = ANY (current_schemas(false))
|
552
|
+
ORDER BY c.conname
|
553
|
+
|
554
|
+
[1m[36m (10.5ms)[0m [1mCREATE VIEW messages AS SELECT DISTINCT _.receiver_name, _.receiver_id, _.sender_name, _.sender_id, _.content, _.updated_at, _.created_at
|
555
|
+
FROM
|
556
|
+
(SELECT u2.name as receiver_name, u2.id as receiver_id,
|
557
|
+
u1.name as sender_name, u1.id as sender_id,
|
558
|
+
um.content as content, um.updated_at as updated_at, um.created_at as created_at
|
559
|
+
FROM users u1
|
560
|
+
INNER JOIN user_messages um ON ( u1.id = um.from_id )
|
561
|
+
INNER JOIN users u2 ON (u2.id = um.to_id)
|
562
|
+
UNION
|
563
|
+
SELECT u1.name as receiver_name, u1.id as receiver_id,
|
564
|
+
u2.name as sender_name, u2.id as sender_id,
|
565
|
+
um.content as content, um.updated_at as updated_at, um.created_at as created_at
|
566
|
+
FROM users u1
|
567
|
+
INNER JOIN user_messages um ON ( u1.id = um.to_id )
|
568
|
+
INNER JOIN users u2 ON ( u2.id = um.from_id )
|
569
|
+
ORDER BY created_at ASC
|
570
|
+
) AS _[0m
|
571
|
+
[1m[35m (7.1ms)[0m CREATE VIEW chats AS SELECT tuple_sort(ARRAY[sender_id, receiver_id]) AS ids,
|
572
|
+
MIN(created_at) as created_at, MAX(updated_at) as updated_at, COUNT(*) as number_of_messages
|
573
|
+
FROM messages
|
574
|
+
GROUP BY tuple_sort(ARRAY[sender_id, receiver_id])
|
575
|
+
[1m[36m (1.5ms)[0m [1mCREATE OR REPLACE FUNCTION add (x integer, y integer) RETURNS integer AS $$
|
576
|
+
BEGIN
|
577
|
+
RETURN x + y;
|
578
|
+
END;
|
579
|
+
$$ LANGUAGE plpgsql;[0m
|
580
|
+
[1m[35m (0.7ms)[0m CREATE OR REPLACE FUNCTION tuple_sort (x int[]) RETURNS int[] AS $$
|
581
|
+
BEGIN
|
582
|
+
IF x[0] > x[1] THEN
|
583
|
+
RETURN ARRAY[x[1], x[0]];
|
584
|
+
ELSE
|
585
|
+
RETURN x;
|
586
|
+
END IF;
|
587
|
+
END;
|
588
|
+
$$ LANGUAGE plpgsql;
|
589
|
+
[1m[36m (1.6ms)[0m [1mDROP VIEW chats[0m
|
590
|
+
[1m[35m (0.8ms)[0m DROP VIEW messages
|
591
|
+
[1m[36mActiveRecord::SchemaMigration Load (0.2ms)[0m [1mSELECT "schema_migrations".* FROM "schema_migrations"[0m
|
592
|
+
[1m[35mActiveRecord::SchemaMigration Load (0.1ms)[0m SELECT "schema_migrations".* FROM "schema_migrations"
|
593
|
+
[1m[36m (1.9ms)[0m [1mSELECT t2.oid::regclass::text AS to_table, a1.attname AS column, a2.attname AS primary_key, c.conname AS name, c.confupdtype AS on_update, c.confdeltype AS on_delete
|
594
|
+
FROM pg_constraint c
|
595
|
+
JOIN pg_class t1 ON c.conrelid = t1.oid
|
596
|
+
JOIN pg_class t2 ON c.confrelid = t2.oid
|
597
|
+
JOIN pg_attribute a1 ON a1.attnum = c.conkey[1] AND a1.attrelid = t1.oid
|
598
|
+
JOIN pg_attribute a2 ON a2.attnum = c.confkey[1] AND a2.attrelid = t2.oid
|
599
|
+
JOIN pg_namespace t3 ON c.connamespace = t3.oid
|
600
|
+
WHERE c.contype = 'f'
|
601
|
+
AND t1.relname = 'user_messages'
|
602
|
+
AND t3.nspname = ANY (current_schemas(false))
|
603
|
+
ORDER BY c.conname
|
604
|
+
[0m
|
605
|
+
[1m[35m (1.4ms)[0m SELECT t2.oid::regclass::text AS to_table, a1.attname AS column, a2.attname AS primary_key, c.conname AS name, c.confupdtype AS on_update, c.confdeltype AS on_delete
|
606
|
+
FROM pg_constraint c
|
607
|
+
JOIN pg_class t1 ON c.conrelid = t1.oid
|
608
|
+
JOIN pg_class t2 ON c.confrelid = t2.oid
|
609
|
+
JOIN pg_attribute a1 ON a1.attnum = c.conkey[1] AND a1.attrelid = t1.oid
|
610
|
+
JOIN pg_attribute a2 ON a2.attnum = c.confkey[1] AND a2.attrelid = t2.oid
|
611
|
+
JOIN pg_namespace t3 ON c.connamespace = t3.oid
|
612
|
+
WHERE c.contype = 'f'
|
613
|
+
AND t1.relname = 'users'
|
614
|
+
AND t3.nspname = ANY (current_schemas(false))
|
615
|
+
ORDER BY c.conname
|
616
|
+
|
617
|
+
[1m[36m (8.5ms)[0m [1mCREATE VIEW messages AS SELECT DISTINCT _.receiver_name, _.receiver_id, _.sender_name, _.sender_id, _.content, _.updated_at, _.created_at
|
618
|
+
FROM
|
619
|
+
(SELECT u2.name as receiver_name, u2.id as receiver_id,
|
620
|
+
u1.name as sender_name, u1.id as sender_id,
|
621
|
+
um.content as content, um.updated_at as updated_at, um.created_at as created_at
|
622
|
+
FROM users u1
|
623
|
+
INNER JOIN user_messages um ON ( u1.id = um.from_id )
|
624
|
+
INNER JOIN users u2 ON (u2.id = um.to_id)
|
625
|
+
UNION
|
626
|
+
SELECT u1.name as receiver_name, u1.id as receiver_id,
|
627
|
+
u2.name as sender_name, u2.id as sender_id,
|
628
|
+
um.content as content, um.updated_at as updated_at, um.created_at as created_at
|
629
|
+
FROM users u1
|
630
|
+
INNER JOIN user_messages um ON ( u1.id = um.to_id )
|
631
|
+
INNER JOIN users u2 ON ( u2.id = um.from_id )
|
632
|
+
ORDER BY created_at ASC
|
633
|
+
) AS _[0m
|
634
|
+
[1m[35m (7.6ms)[0m CREATE VIEW chats AS SELECT tuple_sort(ARRAY[sender_id, receiver_id]) AS ids,
|
635
|
+
MIN(created_at) as created_at, MAX(updated_at) as updated_at, COUNT(*) as number_of_messages
|
636
|
+
FROM messages
|
637
|
+
GROUP BY tuple_sort(ARRAY[sender_id, receiver_id])
|
638
|
+
[1m[36m (0.1ms)[0m [1mSELECT 1;[0m
|
639
|
+
[1m[35m (0.3ms)[0m SELECT 1;
|
640
|
+
[1m[36m (0.3ms)[0m [1mSELECT 2;[0m
|
641
|
+
[1m[35m (0.2ms)[0m SELECT 2;
|
642
|
+
[1m[36m (0.3ms)[0m [1mSELECT 2[0m
|
643
|
+
[1m[35m (8.3ms)[0m SELECT tuple_sort(ARRAY[1,3])
|
644
|
+
[1m[36m (0.9ms)[0m [1mSELECT tuple_sort(ARRAY[3,1])[0m
|
645
|
+
[1m[35m (0.9ms)[0m SELECT tuple_sort(ARRAY[3,1])
|
646
|
+
[1m[36m (2.4ms)[0m [1mCREATE OR REPLACE FUNCTION add (x integer, y integer) RETURNS integer AS $$
|
647
|
+
BEGIN
|
648
|
+
RETURN x + y;
|
649
|
+
END;
|
650
|
+
$$ LANGUAGE plpgsql;[0m
|
651
|
+
[1m[35m (0.6ms)[0m CREATE OR REPLACE FUNCTION tuple_sort (x int[]) RETURNS int[] AS $$
|
652
|
+
BEGIN
|
653
|
+
IF x[0]::int > x[1]::int THEN
|
654
|
+
RETURN ARRAY[x[1], x[0]];
|
655
|
+
ELSE
|
656
|
+
RETURN x;
|
657
|
+
END IF;
|
658
|
+
END;
|
659
|
+
$$ LANGUAGE plpgsql;
|
660
|
+
[1m[36m (0.3ms)[0m [1mDROP VIEW chats[0m
|
661
|
+
PG::UndefinedTable: ERROR: view "chats" does not exist
|
662
|
+
: DROP VIEW chats
|
663
|
+
[1m[35m (0.2ms)[0m DROP VIEW messages
|
664
|
+
PG::UndefinedTable: ERROR: view "messages" does not exist
|
665
|
+
: DROP VIEW messages
|
666
|
+
[1m[36m (2.3ms)[0m [1mCREATE TABLE "schema_migrations" ("version" character varying NOT NULL) [0m
|
667
|
+
[1m[35m (1.2ms)[0m CREATE UNIQUE INDEX "unique_schema_migrations" ON "schema_migrations" ("version")
|
668
|
+
[1m[36mActiveRecord::SchemaMigration Load (0.2ms)[0m [1mSELECT "schema_migrations".* FROM "schema_migrations"[0m
|
669
|
+
Migrating to CreateTestTables (20160208084226)
|
670
|
+
[1m[35m (0.1ms)[0m BEGIN
|
671
|
+
[1m[36m (5.8ms)[0m [1mCREATE TABLE "users" ("id" serial primary key, "name" character varying, "created_at" timestamp NOT NULL, "updated_at" timestamp NOT NULL) [0m
|
672
|
+
[1m[35m (0.6ms)[0m CREATE INDEX "index_users_on_name" ON "users" ("name")
|
673
|
+
[1m[36m (2.2ms)[0m [1mCREATE TABLE "user_messages" ("id" serial primary key, "from_id" integer, "to_id" integer, "content" text, "created_at" timestamp NOT NULL, "updated_at" timestamp NOT NULL) [0m
|
674
|
+
[1m[35m (0.6ms)[0m CREATE INDEX "index_user_messages_on_from_id" ON "user_messages" ("from_id")
|
675
|
+
[1m[36m (0.6ms)[0m [1mCREATE INDEX "index_user_messages_on_to_id" ON "user_messages" ("to_id")[0m
|
676
|
+
[1m[35mSQL (0.2ms)[0m INSERT INTO "schema_migrations" ("version") VALUES ($1) [["version", "20160208084226"]]
|
677
|
+
[1m[36m (0.5ms)[0m [1mCOMMIT[0m
|
678
|
+
[1m[35mActiveRecord::SchemaMigration Load (0.1ms)[0m SELECT "schema_migrations".* FROM "schema_migrations"
|
679
|
+
[1m[36m (2.0ms)[0m [1mSELECT t2.oid::regclass::text AS to_table, a1.attname AS column, a2.attname AS primary_key, c.conname AS name, c.confupdtype AS on_update, c.confdeltype AS on_delete
|
680
|
+
FROM pg_constraint c
|
681
|
+
JOIN pg_class t1 ON c.conrelid = t1.oid
|
682
|
+
JOIN pg_class t2 ON c.confrelid = t2.oid
|
683
|
+
JOIN pg_attribute a1 ON a1.attnum = c.conkey[1] AND a1.attrelid = t1.oid
|
684
|
+
JOIN pg_attribute a2 ON a2.attnum = c.confkey[1] AND a2.attrelid = t2.oid
|
685
|
+
JOIN pg_namespace t3 ON c.connamespace = t3.oid
|
686
|
+
WHERE c.contype = 'f'
|
687
|
+
AND t1.relname = 'user_messages'
|
688
|
+
AND t3.nspname = ANY (current_schemas(false))
|
689
|
+
ORDER BY c.conname
|
690
|
+
[0m
|
691
|
+
[1m[35m (1.5ms)[0m SELECT t2.oid::regclass::text AS to_table, a1.attname AS column, a2.attname AS primary_key, c.conname AS name, c.confupdtype AS on_update, c.confdeltype AS on_delete
|
692
|
+
FROM pg_constraint c
|
693
|
+
JOIN pg_class t1 ON c.conrelid = t1.oid
|
694
|
+
JOIN pg_class t2 ON c.confrelid = t2.oid
|
695
|
+
JOIN pg_attribute a1 ON a1.attnum = c.conkey[1] AND a1.attrelid = t1.oid
|
696
|
+
JOIN pg_attribute a2 ON a2.attnum = c.confkey[1] AND a2.attrelid = t2.oid
|
697
|
+
JOIN pg_namespace t3 ON c.connamespace = t3.oid
|
698
|
+
WHERE c.contype = 'f'
|
699
|
+
AND t1.relname = 'users'
|
700
|
+
AND t3.nspname = ANY (current_schemas(false))
|
701
|
+
ORDER BY c.conname
|
702
|
+
|
703
|
+
[1m[36m (7.7ms)[0m [1mCREATE VIEW messages AS SELECT DISTINCT _.receiver_name, _.receiver_id, _.sender_name, _.sender_id, _.content, _.updated_at, _.created_at
|
704
|
+
FROM
|
705
|
+
(SELECT u2.name as receiver_name, u2.id as receiver_id,
|
706
|
+
u1.name as sender_name, u1.id as sender_id,
|
707
|
+
um.content as content, um.updated_at as updated_at, um.created_at as created_at
|
708
|
+
FROM users u1
|
709
|
+
INNER JOIN user_messages um ON ( u1.id = um.from_id )
|
710
|
+
INNER JOIN users u2 ON (u2.id = um.to_id)
|
711
|
+
UNION
|
712
|
+
SELECT u1.name as receiver_name, u1.id as receiver_id,
|
713
|
+
u2.name as sender_name, u2.id as sender_id,
|
714
|
+
um.content as content, um.updated_at as updated_at, um.created_at as created_at
|
715
|
+
FROM users u1
|
716
|
+
INNER JOIN user_messages um ON ( u1.id = um.to_id )
|
717
|
+
INNER JOIN users u2 ON ( u2.id = um.from_id )
|
718
|
+
ORDER BY created_at ASC
|
719
|
+
) AS _[0m
|
720
|
+
[1m[35m (7.7ms)[0m CREATE VIEW chats AS SELECT tuple_sort(ARRAY[sender_id, receiver_id]) AS ids,
|
721
|
+
MIN(created_at) as created_at, MAX(updated_at) as updated_at, COUNT(*) as number_of_messages
|
722
|
+
FROM messages
|
723
|
+
GROUP BY tuple_sort(ARRAY[sender_id, receiver_id])
|
724
|
+
[1m[36m (1.0ms)[0m [1mSELECT tuple_sort(ARRAY[3,1])[0m
|
725
|
+
[1m[35m (2.1ms)[0m SELECT tuple_sort(ARRAY[1,3])
|