rails_db_views 0.0.4 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- 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])
|