SlideShare a Scribd company logo
1 of 40
Postgres Rules
Heresy
CREATE RULE
Esoteric
Y u no use trigger?
View
View
CREATE TABLE users (
    id     integer,
    name    varchar(40),
    PRIMARY KEY(did)
);

CREATE VIEW myview AS SELECT * FROM users;
View
CREATE TABLE users (
    id     integer,
    name    varchar(40),
    PRIMARY KEY(did)
);

CREATE VIEW myview AS SELECT * FROM users;

                           ==
CREATE RULE "_RETURN" AS ON SELECT TO myview DO INSTEAD
    SELECT * FROM mytab;
Speed
Warning
Warning
Qualification given and INSTEAD
the query tree from the rule action with the rule qualification and the original query tree's
qualification; and the original query tree with the negated rule qualification added
Qualification given and INSTEAD
the query tree from the rule action with the rule qualification and the original query tree's
qualification; and the original query tree with the negated rule qualification added
CREATE TABLE counts (
    id    INT4 PRIMARY KEY,
    count INT4 NOT NULL
);
CREATE TABLE counts (
    id    INT4 PRIMARY KEY,
    count INT4 NOT NULL
);

CREATE RULE upsert_counts AS ON INSERT TO counts
    WHERE exists ( SELECT * FROM counts WHERE id = NEW.id )
        DO INSTEAD UPDATE counts SET count = count + 1 WHERE id = NEW.id;
Qualification given and INSTEAD
the query tree from the rule action with the rule qualification and the original query tree's
qualification; and the original query tree with the negated rule qualification added



          CREATE TABLE counts (
              id    INT4 PRIMARY KEY,
              count INT4 NOT NULL
          );
          CREATE RULE upsert_counts AS ON INSERT TO counts
              WHERE exists ( SELECT * FROM counts WHERE id = NEW.id )
                  DO INSTEAD UPDATE counts SET count = count + 1 WHERE id = NEW.id;
Qualification given and INSTEAD
the query tree from the rule action with the rule qualification and the original query tree's
qualification; and the original query tree with the negated rule qualification added

CREATE TABLE counts (
    id    INT4 PRIMARY KEY,
    count INT4 NOT NULL
);
CREATE RULE upsert_counts AS ON INSERT TO counts
    WHERE exists ( SELECT * FROM counts WHERE id = NEW.id )
        DO INSTEAD UPDATE counts SET count = count + 1 WHERE id = NEW.id;
Qualification given and INSTEAD
the query tree from the rule action with the rule qualification and the original query tree's
qualification; and the original query tree with the negated rule qualification added

CREATE TABLE counts (
    id    INT4 PRIMARY KEY,
    count INT4 NOT NULL
);
CREATE RULE upsert_counts AS ON INSERT TO counts
    WHERE exists ( SELECT * FROM counts WHERE id = NEW.id )
        DO INSTEAD UPDATE counts SET count = count + 1 WHERE id = NEW.id;




INSERT INTO counts (id, count) VALUES (1, 1);
Qualification given and INSTEAD
the query tree from the rule action with the rule qualification and the original query tree's
qualification; and the original query tree with the negated rule qualification added

CREATE TABLE counts (
    id    INT4 PRIMARY KEY,
    count INT4 NOT NULL
);
CREATE RULE upsert_counts AS ON INSERT TO counts
    WHERE exists ( SELECT * FROM counts WHERE id = NEW.id )
        DO INSTEAD UPDATE counts SET count = count + 1 WHERE id = NEW.id;




INSERT INTO counts (id, count) VALUES (1, 1);                                   # SELECT * FROM counts;
                                                                                 id | count
                                                                                ----+----------
                                                                                  1 |        2
                                                                                (1 row)
Qualification given and INSTEAD
the query tree from the rule action with the rule qualification and the original query tree's
qualification; and the original query tree with the negated rule qualification added

CREATE TABLE counts (
    id    INT4 PRIMARY KEY,
    count INT4 NOT NULL
);
CREATE RULE upsert_counts AS ON INSERT TO counts
    WHERE exists ( SELECT * FROM counts WHERE id = NEW.id )
        DO INSTEAD UPDATE counts SET count = count + 1 WHERE id = NEW.id;


INSERT INTO counts (id, count) VALUES (1, 1);



                                                                                # SELECT * FROM counts;
                                                                                 id | count
                                                                                ----+----------
                                                                                  1 |        2
                                                                                (1 row)
Qualification given and INSTEAD
the query tree from the rule action with the rule qualification and the original query tree's
qualification; and the original query tree with the negated rule qualification added

CREATE TABLE counts (
    id    INT4 PRIMARY KEY,
    count INT4 NOT NULL
);
CREATE RULE upsert_counts AS ON INSERT TO counts
    WHERE exists ( SELECT * FROM counts WHERE id = NEW.id )
        DO INSTEAD UPDATE counts SET count = count + 1 WHERE id = NEW.id;


INSERT INTO counts (id, count) VALUES (1, 1);



                                                                                # SELECT * FROM counts;
                                                                                 id | count
BECOMES:
                                                                                ----+----------
INSERT INTO test (id, some_val)                                                   1 |        2
    SELECT 1, 1 WHERE NOT (                                                     (1 row)
        EXISTS ( SELECT * FROM test WHERE id = 1)
    );
UPDATE test
SET some_val = some_val + 1
WHERE id = 1 AND ( EXISTS ( SELECT * FROM test WHERE id = 1 ) );
CREATE TABLE test (
    id!
      ! INT4 PRIMARY KEY,
    val! INT4 NOT NULL
);
CREATE TABLE test (
    id!
      ! INT4 PRIMARY KEY,
    val! INT4 NOT NULL
);

CREATE TABLE test_log (
   id       !! ! INT4 PRIMARY KEY,
   creation_date! TIMESTAMP NOT NULL,
   val ! ! ! ! INT4 NOT NULL,
! CONSTRAINT test_log_pk PRIMARY KEY(id, creation_date)
);
CREATE TABLE test (
    id!
      ! INT4 PRIMARY KEY,
    val! INT4 NOT NULL
);

CREATE TABLE test_log (
   id       !! ! INT4 PRIMARY KEY,
   creation_date! TIMESTAMP NOT NULL,
   val ! ! ! ! INT4 NOT NULL,
! CONSTRAINT test_log_pk PRIMARY KEY(id, creation_date)
);

CREATE RULE test_logging AS ON INSERT TO test
! DO ALSO INSERT INTO test_log(id, creation_date, val) VALUES(NEW.id, NOW(), NEW.val);
CREATE TABLE test (
    id!
      ! INT4 PRIMARY KEY,
    val! INT4 NOT NULL
);

CREATE TABLE test_log (
   id       !! ! INT4 PRIMARY KEY,
   creation_date! TIMESTAMP NOT NULL,
   val ! ! ! ! INT4 NOT NULL,
! CONSTRAINT test_log_pk PRIMARY KEY(id, creation_date)
);

CREATE RULE test_logging AS ON INSERT TO test
! DO ALSO INSERT INTO test_log(id, creation_date, val) VALUES(NEW.id, NOW(), NEW.val);

INSERT INTO test(id, count) VALUES (1, RANDOM());
CREATE TABLE test (
    id!
      ! INT4 PRIMARY KEY,
    val! INT4 NOT NULL
);

CREATE TABLE test_log (
   id       !! ! INT4 PRIMARY KEY,
   creation_date! TIMESTAMP NOT NULL,
   val ! ! ! ! INT4 NOT NULL,
! CONSTRAINT test_log_pk PRIMARY KEY(id, creation_date)
);

CREATE RULE test_logging AS ON INSERT TO test
! DO ALSO INSERT INTO test_log(id, creation_date, val) VALUES(NEW.id, NOW(), NEW.val);

INSERT INTO test(id, count) VALUES (1, RANDOM());




# SELECT * FROM test;
 id | val
----+------
  1 | 46228
(1 row)
CREATE TABLE test (
    id!
      ! INT4 PRIMARY KEY,
    val! INT4 NOT NULL
);

CREATE TABLE test_log (
   id       !! ! INT4 PRIMARY KEY,
   creation_date! TIMESTAMP NOT NULL,
   val ! ! ! ! INT4 NOT NULL,
! CONSTRAINT test_log_pk PRIMARY KEY(id, creation_date)
);

CREATE RULE test_logging AS ON INSERT TO test
! DO ALSO INSERT INTO test_log(id, creation_date, val) VALUES(NEW.id, NOW(), NEW.val);

INSERT INTO test(id, count) VALUES (1, RANDOM());




# SELECT * FROM test;          # SELECT * FROM test_log;
 id | val                       id |      creation_date! !    | val
----+------                    ----+--------------------------+-----
  1 | 46228                      1 | 2012-05-03 07:02:16.43841 15375
(1 row)                        (1 row)
Use Case
reconciliations_data
financial_operations
                       id
id
                       bank_num
amount
                       start_count
card_number
                       end_count
cashier_id
                       deposit_slip_number
reconciliation_id
                       cashier_id
reconciliations_data
financial_operations
                       id
id
                       bank_num
amount
                       start_count
card_number
                       end_count
cashier_id
                       deposit_slip_number
reconciliation_id
                       cashier_id
CREATE OR REPLACE VIEW reconciliations AS
  SELECT
  ! rec.*,
  ! fin1.id AS start_id,
  ! fin1.upload_date AS start_date,
  ! fin2.id AS end_id,
  ! fin2.upload_date AS end_date
  FROM
  ! reconciliations_data rec
  LEFT OUTER JOIN
  ! (SELECT
    DISTINCT
       first_value(id) OVER (partition BY reconciliation_id ORDER BY upload_date ASC) AS id,
       first_value(upload_date) OVER (partition BY reconciliation_id ORDER BY upload_date ASC) AS upload_date,
       reconciliation_id
    FROM
       financial_operations) AS fin1 ON (fin1.reconciliation_id = rec.id)
    LEFT OUTER JOIN
  ! (SELECT
       DISTINCT
         first_value(id) OVER (partition BY reconciliation_id ORDER BY upload_date DESC) AS id,
         first_value(upload_date) OVER (partition BY reconciliation_id ORDER BY upload_date DESC) AS upload_date,
         reconciliation_id
       FROM
         financial_operations) AS fin2 ON (fin2.reconciliation_id = rec.id)
reconciliations_data
financial_operations
                       id
id
                       bank_num
amount
                       start_count
card_number
                       end_count
cashier_id
                       deposit_slip_number
reconciliation_id
                       cashier_id
reconciliations_data
 financial_operations
                                                   id
 id
                                                   bank_num
 amount
                                                   start_count
 card_number
                                                   end_count
 cashier_id
                                                   deposit_slip_number
 reconciliation_id
                                                   cashier_id


CREATE OR REPLACE RULE fin_ops_from_recons AS
    ON INSERT TO reconciliations DO INSTEAD
    ( INSERT INTO reconciliations_data (cashier_id, lot_id, lane_id, start_count, end_count, cash_deposited, bank_amount,
bank_returned, deposit_slip_number, created_at, updated_at)
      VALUES (new.cashier_id, new.lot_id, new.lane_id, new.start_count, new.end_count, new.cash_deposited, new.bank_amount,
new.bank_returned, new.deposit_slip_number, new.created_at, new.updated_at)
        RETURNING
!   !  !   currval('reconciliations_id_seq')::integer,
!   !  !   cashier_id,
!   !  !   lot_id,
!   !  !   lane_id,
!   !  !   start_count,
!   !  !   end_count,
!   !  !   cash_deposited,
!   !  !   bank_amount,
!   !  !   bank_returned,
!   !  !   deposit_slip_number,
!   !  !   created_at,
!   !  !   updated_at,
!   !  !   null::varchar,
!   !  !   null::varchar,
!   !  !   null::timestamp,
!   !  !   null::varchar,
!   !  !   null::timestamp;
    ;
reconciliations_data
financial_operations
                       id
id
                       bank_num
amount
                       start_count
card_number
                       end_count
cashier_id
                       deposit_slip_number
reconciliation_id
                       cashier_id
reconciliations_data
         financial_operations
                                                           id
         id
                                                           bank_num
         amount
                                                           start_count
         card_number
                                                           end_count
         cashier_id
                                                           deposit_slip_number
         reconciliation_id
                                                           cashier_id




     UPDATE financial_operations SET reconciliation_id = lastval()
       WHERE financial_operations.remote_creation_date >= (( SELECT financial_operations.remote_creation_date
                FROM financial_operations
               WHERE financial_operations.id::text = new.start_id::text)) AND financial_operations.remote_creation_date <=
(( SELECT financial_operations.remote_creation_date
                FROM financial_operations
               WHERE financial_operations.id::text = new.end_id::text)) AND financial_operations.order_transaction_id IS NOT NULL
AND
             CASE
                  WHEN new.lot_id IS NULL THEN new.cashier_id::text = (SELECT order_transactions.user_id
                     FROM order_transactions
                    WHERE order_transactions.id::text = financial_operations.order_transaction_id::text)::text
                  ELSE ((new.cashier_id::text, new.lot_id) = ( SELECT order_transactions.user_id, order_transactions.lot_id
                     FROM order_transactions
                    WHERE order_transactions.id::text = financial_operations.order_transaction_id::text))
             END;
    );
FIN




      guyren@relevantlogic.com

More Related Content

What's hot

PostgreSQL: Advanced features in practice
PostgreSQL: Advanced features in practicePostgreSQL: Advanced features in practice
PostgreSQL: Advanced features in practiceJano Suchal
 
The Ring programming language version 1.5.1 book - Part 34 of 180
The Ring programming language version 1.5.1 book - Part 34 of 180The Ring programming language version 1.5.1 book - Part 34 of 180
The Ring programming language version 1.5.1 book - Part 34 of 180Mahmoud Samir Fayed
 
PHP webboard
PHP webboardPHP webboard
PHP webboardtumetr1
 
PHP cart
PHP cartPHP cart
PHP carttumetr1
 
Hadoop Summit EU 2014
Hadoop Summit EU   2014Hadoop Summit EU   2014
Hadoop Summit EU 2014cwensel
 
BGOUG15: JSON support in MySQL 5.7
BGOUG15: JSON support in MySQL 5.7BGOUG15: JSON support in MySQL 5.7
BGOUG15: JSON support in MySQL 5.7Georgi Kodinov
 
Web осень 2012 лекция 6
Web осень 2012 лекция 6Web осень 2012 лекция 6
Web осень 2012 лекция 6Technopark
 
Web весна 2013 лекция 6
Web весна 2013 лекция 6Web весна 2013 лекция 6
Web весна 2013 лекция 6Technopark
 
JSON Support in MariaDB: News, non-news and the bigger picture
JSON Support in MariaDB: News, non-news and the bigger pictureJSON Support in MariaDB: News, non-news and the bigger picture
JSON Support in MariaDB: News, non-news and the bigger pictureSergey Petrunya
 
PHP and MySQL Tips and tricks, DC 2007
PHP and MySQL Tips and tricks, DC 2007PHP and MySQL Tips and tricks, DC 2007
PHP and MySQL Tips and tricks, DC 2007Damien Seguy
 
Introduction to type classes in 30 min
Introduction to type classes in 30 minIntroduction to type classes in 30 min
Introduction to type classes in 30 minPawel Szulc
 
Introduction to type classes
Introduction to type classesIntroduction to type classes
Introduction to type classesPawel Szulc
 
WorkingWithSlick2.1.0
WorkingWithSlick2.1.0WorkingWithSlick2.1.0
WorkingWithSlick2.1.0Knoldus Inc.
 
Apache Solr Search Mastery
Apache Solr Search MasteryApache Solr Search Mastery
Apache Solr Search MasteryAcquia
 
Obtain better data accuracy using reference tables
Obtain better data accuracy using reference tablesObtain better data accuracy using reference tables
Obtain better data accuracy using reference tablesKiran Venna
 
DConf 2016 std.database (a proposed interface & implementation)
DConf 2016 std.database (a proposed interface & implementation)DConf 2016 std.database (a proposed interface & implementation)
DConf 2016 std.database (a proposed interface & implementation)cruisercoder
 

What's hot (20)

PostgreSQL: Advanced features in practice
PostgreSQL: Advanced features in practicePostgreSQL: Advanced features in practice
PostgreSQL: Advanced features in practice
 
The Ring programming language version 1.5.1 book - Part 34 of 180
The Ring programming language version 1.5.1 book - Part 34 of 180The Ring programming language version 1.5.1 book - Part 34 of 180
The Ring programming language version 1.5.1 book - Part 34 of 180
 
PHP webboard
PHP webboardPHP webboard
PHP webboard
 
Php forum2015 tomas_final
Php forum2015 tomas_finalPhp forum2015 tomas_final
Php forum2015 tomas_final
 
PHP cart
PHP cartPHP cart
PHP cart
 
Hadoop Summit EU 2014
Hadoop Summit EU   2014Hadoop Summit EU   2014
Hadoop Summit EU 2014
 
BGOUG15: JSON support in MySQL 5.7
BGOUG15: JSON support in MySQL 5.7BGOUG15: JSON support in MySQL 5.7
BGOUG15: JSON support in MySQL 5.7
 
Web осень 2012 лекция 6
Web осень 2012 лекция 6Web осень 2012 лекция 6
Web осень 2012 лекция 6
 
Web весна 2013 лекция 6
Web весна 2013 лекция 6Web весна 2013 лекция 6
Web весна 2013 лекция 6
 
JSON Support in MariaDB: News, non-news and the bigger picture
JSON Support in MariaDB: News, non-news and the bigger pictureJSON Support in MariaDB: News, non-news and the bigger picture
JSON Support in MariaDB: News, non-news and the bigger picture
 
PHP and MySQL Tips and tricks, DC 2007
PHP and MySQL Tips and tricks, DC 2007PHP and MySQL Tips and tricks, DC 2007
PHP and MySQL Tips and tricks, DC 2007
 
dbms lab manual
dbms lab manualdbms lab manual
dbms lab manual
 
Introduction to type classes in 30 min
Introduction to type classes in 30 minIntroduction to type classes in 30 min
Introduction to type classes in 30 min
 
Introduction to type classes
Introduction to type classesIntroduction to type classes
Introduction to type classes
 
WorkingWithSlick2.1.0
WorkingWithSlick2.1.0WorkingWithSlick2.1.0
WorkingWithSlick2.1.0
 
Apache Solr Search Mastery
Apache Solr Search MasteryApache Solr Search Mastery
Apache Solr Search Mastery
 
Pytables
PytablesPytables
Pytables
 
Obtain better data accuracy using reference tables
Obtain better data accuracy using reference tablesObtain better data accuracy using reference tables
Obtain better data accuracy using reference tables
 
DConf 2016 std.database (a proposed interface & implementation)
DConf 2016 std.database (a proposed interface & implementation)DConf 2016 std.database (a proposed interface & implementation)
DConf 2016 std.database (a proposed interface & implementation)
 
Spl Not A Bridge Too Far phpNW09
Spl Not A Bridge Too Far phpNW09Spl Not A Bridge Too Far phpNW09
Spl Not A Bridge Too Far phpNW09
 

Similar to Postgres rules

2 BytesC++ course_2014_c4_ arrays
2 BytesC++ course_2014_c4_ arrays2 BytesC++ course_2014_c4_ arrays
2 BytesC++ course_2014_c4_ arrayskinan keshkeh
 
MySQL 8.0 NF : Common Table Expressions (CTE)
MySQL 8.0 NF : Common Table Expressions (CTE)MySQL 8.0 NF : Common Table Expressions (CTE)
MySQL 8.0 NF : Common Table Expressions (CTE)I Goo Lee
 
Bootcamp sql fundamental
Bootcamp sql fundamentalBootcamp sql fundamental
Bootcamp sql fundamentalvarunbhatt23
 
Index and types of Index used in Oracle.pptx
Index and types of Index used in Oracle.pptxIndex and types of Index used in Oracle.pptx
Index and types of Index used in Oracle.pptxGSCWU
 
Using ddl statements to create and manage tables
Using ddl statements to create and manage tablesUsing ddl statements to create and manage tables
Using ddl statements to create and manage tablesSyed Zaid Irshad
 
T sql denali code Day of .Net
T sql denali code Day of .NetT sql denali code Day of .Net
T sql denali code Day of .NetKathiK58
 
Evolving with Java - How to remain Relevant and Effective
Evolving with Java - How to remain Relevant and EffectiveEvolving with Java - How to remain Relevant and Effective
Evolving with Java - How to remain Relevant and EffectiveNaresha K
 
Property-Based Testing
Property-Based TestingProperty-Based Testing
Property-Based TestingShai Geva
 
[Pgday.Seoul 2017] 6. GIN vs GiST 인덱스 이야기 - 박진우
[Pgday.Seoul 2017] 6. GIN vs GiST 인덱스 이야기 - 박진우[Pgday.Seoul 2017] 6. GIN vs GiST 인덱스 이야기 - 박진우
[Pgday.Seoul 2017] 6. GIN vs GiST 인덱스 이야기 - 박진우PgDay.Seoul
 
Writeable ct es_pgcon_may_2011
Writeable ct es_pgcon_may_2011Writeable ct es_pgcon_may_2011
Writeable ct es_pgcon_may_2011David Fetter
 
Les09 (using ddl statements to create and manage tables)
Les09 (using ddl statements to create and manage tables)Les09 (using ddl statements to create and manage tables)
Les09 (using ddl statements to create and manage tables)Achmad Solichin
 
Cassandra Community Webinar | Become a Super Modeler
Cassandra Community Webinar | Become a Super ModelerCassandra Community Webinar | Become a Super Modeler
Cassandra Community Webinar | Become a Super ModelerDataStax
 
Chapter 7.1
Chapter 7.1Chapter 7.1
Chapter 7.1sotlsoc
 

Similar to Postgres rules (20)

Postgre sql index
Postgre sql indexPostgre sql index
Postgre sql index
 
How to Use JSON in MySQL Wrong
How to Use JSON in MySQL WrongHow to Use JSON in MySQL Wrong
How to Use JSON in MySQL Wrong
 
2 BytesC++ course_2014_c4_ arrays
2 BytesC++ course_2014_c4_ arrays2 BytesC++ course_2014_c4_ arrays
2 BytesC++ course_2014_c4_ arrays
 
MySQL 8.0 NF : Common Table Expressions (CTE)
MySQL 8.0 NF : Common Table Expressions (CTE)MySQL 8.0 NF : Common Table Expressions (CTE)
MySQL 8.0 NF : Common Table Expressions (CTE)
 
Bootcamp sql fundamental
Bootcamp sql fundamentalBootcamp sql fundamental
Bootcamp sql fundamental
 
Arrays in Java
Arrays in JavaArrays in Java
Arrays in Java
 
Sql commands
Sql commandsSql commands
Sql commands
 
Index and types of Index used in Oracle.pptx
Index and types of Index used in Oracle.pptxIndex and types of Index used in Oracle.pptx
Index and types of Index used in Oracle.pptx
 
Using ddl statements to create and manage tables
Using ddl statements to create and manage tablesUsing ddl statements to create and manage tables
Using ddl statements to create and manage tables
 
T sql denali code Day of .Net
T sql denali code Day of .NetT sql denali code Day of .Net
T sql denali code Day of .Net
 
Les20
Les20Les20
Les20
 
Evolving with Java - How to remain Relevant and Effective
Evolving with Java - How to remain Relevant and EffectiveEvolving with Java - How to remain Relevant and Effective
Evolving with Java - How to remain Relevant and Effective
 
Property-Based Testing
Property-Based TestingProperty-Based Testing
Property-Based Testing
 
DOODB_LAB.pptx
DOODB_LAB.pptxDOODB_LAB.pptx
DOODB_LAB.pptx
 
[Pgday.Seoul 2017] 6. GIN vs GiST 인덱스 이야기 - 박진우
[Pgday.Seoul 2017] 6. GIN vs GiST 인덱스 이야기 - 박진우[Pgday.Seoul 2017] 6. GIN vs GiST 인덱스 이야기 - 박진우
[Pgday.Seoul 2017] 6. GIN vs GiST 인덱스 이야기 - 박진우
 
Les09
Les09Les09
Les09
 
Writeable ct es_pgcon_may_2011
Writeable ct es_pgcon_may_2011Writeable ct es_pgcon_may_2011
Writeable ct es_pgcon_may_2011
 
Les09 (using ddl statements to create and manage tables)
Les09 (using ddl statements to create and manage tables)Les09 (using ddl statements to create and manage tables)
Les09 (using ddl statements to create and manage tables)
 
Cassandra Community Webinar | Become a Super Modeler
Cassandra Community Webinar | Become a Super ModelerCassandra Community Webinar | Become a Super Modeler
Cassandra Community Webinar | Become a Super Modeler
 
Chapter 7.1
Chapter 7.1Chapter 7.1
Chapter 7.1
 

More from gisborne

Love Your Database Railsconf 2017
Love Your Database Railsconf 2017Love Your Database Railsconf 2017
Love Your Database Railsconf 2017gisborne
 
Indexes: The Second Pillar of Database Wisdom
Indexes: The Second Pillar of Database WisdomIndexes: The Second Pillar of Database Wisdom
Indexes: The Second Pillar of Database Wisdomgisborne
 
Postgres is easier
Postgres is easierPostgres is easier
Postgres is easiergisborne
 
Cyc Presentation
Cyc PresentationCyc Presentation
Cyc Presentationgisborne
 
Break up the Net
Break up the NetBreak up the Net
Break up the Netgisborne
 
Postgres Presentation
Postgres PresentationPostgres Presentation
Postgres Presentationgisborne
 

More from gisborne (6)

Love Your Database Railsconf 2017
Love Your Database Railsconf 2017Love Your Database Railsconf 2017
Love Your Database Railsconf 2017
 
Indexes: The Second Pillar of Database Wisdom
Indexes: The Second Pillar of Database WisdomIndexes: The Second Pillar of Database Wisdom
Indexes: The Second Pillar of Database Wisdom
 
Postgres is easier
Postgres is easierPostgres is easier
Postgres is easier
 
Cyc Presentation
Cyc PresentationCyc Presentation
Cyc Presentation
 
Break up the Net
Break up the NetBreak up the Net
Break up the Net
 
Postgres Presentation
Postgres PresentationPostgres Presentation
Postgres Presentation
 

Recently uploaded

Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationBeyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationSafe Software
 
Hyderabad Call Girls Khairatabad ✨ 7001305949 ✨ Cheap Price Your Budget
Hyderabad Call Girls Khairatabad ✨ 7001305949 ✨ Cheap Price Your BudgetHyderabad Call Girls Khairatabad ✨ 7001305949 ✨ Cheap Price Your Budget
Hyderabad Call Girls Khairatabad ✨ 7001305949 ✨ Cheap Price Your BudgetEnjoy Anytime
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Patryk Bandurski
 
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | DelhiFULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhisoniya singh
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitecturePixlogix Infotech
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationMichael W. Hawkins
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Scott Keck-Warren
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountPuma Security, LLC
 
Pigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticscarlostorres15106
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machinePadma Pradeep
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slidespraypatel2
 
Pigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking MenDelhi Call girls
 
Azure Monitor & Application Insight to monitor Infrastructure & Application
Azure Monitor & Application Insight to monitor Infrastructure & ApplicationAzure Monitor & Application Insight to monitor Infrastructure & Application
Azure Monitor & Application Insight to monitor Infrastructure & ApplicationAndikSusilo4
 
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...HostedbyConfluent
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking MenDelhi Call girls
 
Next-generation AAM aircraft unveiled by Supernal, S-A2
Next-generation AAM aircraft unveiled by Supernal, S-A2Next-generation AAM aircraft unveiled by Supernal, S-A2
Next-generation AAM aircraft unveiled by Supernal, S-A2Hyundai Motor Group
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesSinan KOZAK
 
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024BookNet Canada
 

Recently uploaded (20)

Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationBeyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
 
Hyderabad Call Girls Khairatabad ✨ 7001305949 ✨ Cheap Price Your Budget
Hyderabad Call Girls Khairatabad ✨ 7001305949 ✨ Cheap Price Your BudgetHyderabad Call Girls Khairatabad ✨ 7001305949 ✨ Cheap Price Your Budget
Hyderabad Call Girls Khairatabad ✨ 7001305949 ✨ Cheap Price Your Budget
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
 
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | DelhiFULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC Architecture
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path Mount
 
Pigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food Manufacturing
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machine
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slides
 
Pigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping Elbows
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men
 
Azure Monitor & Application Insight to monitor Infrastructure & Application
Azure Monitor & Application Insight to monitor Infrastructure & ApplicationAzure Monitor & Application Insight to monitor Infrastructure & Application
Azure Monitor & Application Insight to monitor Infrastructure & Application
 
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
Next-generation AAM aircraft unveiled by Supernal, S-A2
Next-generation AAM aircraft unveiled by Supernal, S-A2Next-generation AAM aircraft unveiled by Supernal, S-A2
Next-generation AAM aircraft unveiled by Supernal, S-A2
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen Frames
 
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
 

Postgres rules

  • 5. Y u no use trigger?
  • 7. View CREATE TABLE users ( id integer, name varchar(40), PRIMARY KEY(did) ); CREATE VIEW myview AS SELECT * FROM users;
  • 8. View CREATE TABLE users ( id integer, name varchar(40), PRIMARY KEY(did) ); CREATE VIEW myview AS SELECT * FROM users; == CREATE RULE "_RETURN" AS ON SELECT TO myview DO INSTEAD SELECT * FROM mytab;
  • 12.
  • 13. Qualification given and INSTEAD the query tree from the rule action with the rule qualification and the original query tree's qualification; and the original query tree with the negated rule qualification added
  • 14. Qualification given and INSTEAD the query tree from the rule action with the rule qualification and the original query tree's qualification; and the original query tree with the negated rule qualification added
  • 15.
  • 16. CREATE TABLE counts ( id INT4 PRIMARY KEY, count INT4 NOT NULL );
  • 17. CREATE TABLE counts ( id INT4 PRIMARY KEY, count INT4 NOT NULL ); CREATE RULE upsert_counts AS ON INSERT TO counts WHERE exists ( SELECT * FROM counts WHERE id = NEW.id ) DO INSTEAD UPDATE counts SET count = count + 1 WHERE id = NEW.id;
  • 18. Qualification given and INSTEAD the query tree from the rule action with the rule qualification and the original query tree's qualification; and the original query tree with the negated rule qualification added CREATE TABLE counts ( id INT4 PRIMARY KEY, count INT4 NOT NULL ); CREATE RULE upsert_counts AS ON INSERT TO counts WHERE exists ( SELECT * FROM counts WHERE id = NEW.id ) DO INSTEAD UPDATE counts SET count = count + 1 WHERE id = NEW.id;
  • 19. Qualification given and INSTEAD the query tree from the rule action with the rule qualification and the original query tree's qualification; and the original query tree with the negated rule qualification added CREATE TABLE counts ( id INT4 PRIMARY KEY, count INT4 NOT NULL ); CREATE RULE upsert_counts AS ON INSERT TO counts WHERE exists ( SELECT * FROM counts WHERE id = NEW.id ) DO INSTEAD UPDATE counts SET count = count + 1 WHERE id = NEW.id;
  • 20. Qualification given and INSTEAD the query tree from the rule action with the rule qualification and the original query tree's qualification; and the original query tree with the negated rule qualification added CREATE TABLE counts ( id INT4 PRIMARY KEY, count INT4 NOT NULL ); CREATE RULE upsert_counts AS ON INSERT TO counts WHERE exists ( SELECT * FROM counts WHERE id = NEW.id ) DO INSTEAD UPDATE counts SET count = count + 1 WHERE id = NEW.id; INSERT INTO counts (id, count) VALUES (1, 1);
  • 21. Qualification given and INSTEAD the query tree from the rule action with the rule qualification and the original query tree's qualification; and the original query tree with the negated rule qualification added CREATE TABLE counts ( id INT4 PRIMARY KEY, count INT4 NOT NULL ); CREATE RULE upsert_counts AS ON INSERT TO counts WHERE exists ( SELECT * FROM counts WHERE id = NEW.id ) DO INSTEAD UPDATE counts SET count = count + 1 WHERE id = NEW.id; INSERT INTO counts (id, count) VALUES (1, 1); # SELECT * FROM counts; id | count ----+---------- 1 | 2 (1 row)
  • 22. Qualification given and INSTEAD the query tree from the rule action with the rule qualification and the original query tree's qualification; and the original query tree with the negated rule qualification added CREATE TABLE counts ( id INT4 PRIMARY KEY, count INT4 NOT NULL ); CREATE RULE upsert_counts AS ON INSERT TO counts WHERE exists ( SELECT * FROM counts WHERE id = NEW.id ) DO INSTEAD UPDATE counts SET count = count + 1 WHERE id = NEW.id; INSERT INTO counts (id, count) VALUES (1, 1); # SELECT * FROM counts; id | count ----+---------- 1 | 2 (1 row)
  • 23. Qualification given and INSTEAD the query tree from the rule action with the rule qualification and the original query tree's qualification; and the original query tree with the negated rule qualification added CREATE TABLE counts ( id INT4 PRIMARY KEY, count INT4 NOT NULL ); CREATE RULE upsert_counts AS ON INSERT TO counts WHERE exists ( SELECT * FROM counts WHERE id = NEW.id ) DO INSTEAD UPDATE counts SET count = count + 1 WHERE id = NEW.id; INSERT INTO counts (id, count) VALUES (1, 1); # SELECT * FROM counts; id | count BECOMES: ----+---------- INSERT INTO test (id, some_val) 1 | 2 SELECT 1, 1 WHERE NOT ( (1 row) EXISTS ( SELECT * FROM test WHERE id = 1) ); UPDATE test SET some_val = some_val + 1 WHERE id = 1 AND ( EXISTS ( SELECT * FROM test WHERE id = 1 ) );
  • 24.
  • 25. CREATE TABLE test ( id! ! INT4 PRIMARY KEY, val! INT4 NOT NULL );
  • 26. CREATE TABLE test ( id! ! INT4 PRIMARY KEY, val! INT4 NOT NULL ); CREATE TABLE test_log ( id !! ! INT4 PRIMARY KEY, creation_date! TIMESTAMP NOT NULL, val ! ! ! ! INT4 NOT NULL, ! CONSTRAINT test_log_pk PRIMARY KEY(id, creation_date) );
  • 27. CREATE TABLE test ( id! ! INT4 PRIMARY KEY, val! INT4 NOT NULL ); CREATE TABLE test_log ( id !! ! INT4 PRIMARY KEY, creation_date! TIMESTAMP NOT NULL, val ! ! ! ! INT4 NOT NULL, ! CONSTRAINT test_log_pk PRIMARY KEY(id, creation_date) ); CREATE RULE test_logging AS ON INSERT TO test ! DO ALSO INSERT INTO test_log(id, creation_date, val) VALUES(NEW.id, NOW(), NEW.val);
  • 28. CREATE TABLE test ( id! ! INT4 PRIMARY KEY, val! INT4 NOT NULL ); CREATE TABLE test_log ( id !! ! INT4 PRIMARY KEY, creation_date! TIMESTAMP NOT NULL, val ! ! ! ! INT4 NOT NULL, ! CONSTRAINT test_log_pk PRIMARY KEY(id, creation_date) ); CREATE RULE test_logging AS ON INSERT TO test ! DO ALSO INSERT INTO test_log(id, creation_date, val) VALUES(NEW.id, NOW(), NEW.val); INSERT INTO test(id, count) VALUES (1, RANDOM());
  • 29. CREATE TABLE test ( id! ! INT4 PRIMARY KEY, val! INT4 NOT NULL ); CREATE TABLE test_log ( id !! ! INT4 PRIMARY KEY, creation_date! TIMESTAMP NOT NULL, val ! ! ! ! INT4 NOT NULL, ! CONSTRAINT test_log_pk PRIMARY KEY(id, creation_date) ); CREATE RULE test_logging AS ON INSERT TO test ! DO ALSO INSERT INTO test_log(id, creation_date, val) VALUES(NEW.id, NOW(), NEW.val); INSERT INTO test(id, count) VALUES (1, RANDOM()); # SELECT * FROM test; id | val ----+------ 1 | 46228 (1 row)
  • 30. CREATE TABLE test ( id! ! INT4 PRIMARY KEY, val! INT4 NOT NULL ); CREATE TABLE test_log ( id !! ! INT4 PRIMARY KEY, creation_date! TIMESTAMP NOT NULL, val ! ! ! ! INT4 NOT NULL, ! CONSTRAINT test_log_pk PRIMARY KEY(id, creation_date) ); CREATE RULE test_logging AS ON INSERT TO test ! DO ALSO INSERT INTO test_log(id, creation_date, val) VALUES(NEW.id, NOW(), NEW.val); INSERT INTO test(id, count) VALUES (1, RANDOM()); # SELECT * FROM test; # SELECT * FROM test_log; id | val id | creation_date! ! | val ----+------ ----+--------------------------+----- 1 | 46228 1 | 2012-05-03 07:02:16.43841 15375 (1 row) (1 row)
  • 32. reconciliations_data financial_operations id id bank_num amount start_count card_number end_count cashier_id deposit_slip_number reconciliation_id cashier_id
  • 33. reconciliations_data financial_operations id id bank_num amount start_count card_number end_count cashier_id deposit_slip_number reconciliation_id cashier_id
  • 34.
  • 35. CREATE OR REPLACE VIEW reconciliations AS SELECT ! rec.*, ! fin1.id AS start_id, ! fin1.upload_date AS start_date, ! fin2.id AS end_id, ! fin2.upload_date AS end_date FROM ! reconciliations_data rec LEFT OUTER JOIN ! (SELECT DISTINCT first_value(id) OVER (partition BY reconciliation_id ORDER BY upload_date ASC) AS id, first_value(upload_date) OVER (partition BY reconciliation_id ORDER BY upload_date ASC) AS upload_date, reconciliation_id FROM financial_operations) AS fin1 ON (fin1.reconciliation_id = rec.id) LEFT OUTER JOIN ! (SELECT DISTINCT first_value(id) OVER (partition BY reconciliation_id ORDER BY upload_date DESC) AS id, first_value(upload_date) OVER (partition BY reconciliation_id ORDER BY upload_date DESC) AS upload_date, reconciliation_id FROM financial_operations) AS fin2 ON (fin2.reconciliation_id = rec.id)
  • 36. reconciliations_data financial_operations id id bank_num amount start_count card_number end_count cashier_id deposit_slip_number reconciliation_id cashier_id
  • 37. reconciliations_data financial_operations id id bank_num amount start_count card_number end_count cashier_id deposit_slip_number reconciliation_id cashier_id CREATE OR REPLACE RULE fin_ops_from_recons AS ON INSERT TO reconciliations DO INSTEAD ( INSERT INTO reconciliations_data (cashier_id, lot_id, lane_id, start_count, end_count, cash_deposited, bank_amount, bank_returned, deposit_slip_number, created_at, updated_at) VALUES (new.cashier_id, new.lot_id, new.lane_id, new.start_count, new.end_count, new.cash_deposited, new.bank_amount, new.bank_returned, new.deposit_slip_number, new.created_at, new.updated_at) RETURNING ! ! ! currval('reconciliations_id_seq')::integer, ! ! ! cashier_id, ! ! ! lot_id, ! ! ! lane_id, ! ! ! start_count, ! ! ! end_count, ! ! ! cash_deposited, ! ! ! bank_amount, ! ! ! bank_returned, ! ! ! deposit_slip_number, ! ! ! created_at, ! ! ! updated_at, ! ! ! null::varchar, ! ! ! null::varchar, ! ! ! null::timestamp, ! ! ! null::varchar, ! ! ! null::timestamp; ;
  • 38. reconciliations_data financial_operations id id bank_num amount start_count card_number end_count cashier_id deposit_slip_number reconciliation_id cashier_id
  • 39. reconciliations_data financial_operations id id bank_num amount start_count card_number end_count cashier_id deposit_slip_number reconciliation_id cashier_id UPDATE financial_operations SET reconciliation_id = lastval() WHERE financial_operations.remote_creation_date >= (( SELECT financial_operations.remote_creation_date FROM financial_operations WHERE financial_operations.id::text = new.start_id::text)) AND financial_operations.remote_creation_date <= (( SELECT financial_operations.remote_creation_date FROM financial_operations WHERE financial_operations.id::text = new.end_id::text)) AND financial_operations.order_transaction_id IS NOT NULL AND CASE WHEN new.lot_id IS NULL THEN new.cashier_id::text = (SELECT order_transactions.user_id FROM order_transactions WHERE order_transactions.id::text = financial_operations.order_transaction_id::text)::text ELSE ((new.cashier_id::text, new.lot_id) = ( SELECT order_transactions.user_id, order_transactions.lot_id FROM order_transactions WHERE order_transactions.id::text = financial_operations.order_transaction_id::text)) END; );
  • 40. FIN guyren@relevantlogic.com

Editor's Notes

  1. This is a presentation about the Rules feature of Postgres.\n\nIn brief, Rules are a sometimes more efficient alternative to triggers, which function by rewriting incoming SQL.\n\nThey can be massively faster than triggers, and they give you great flexibility in creating writable views, but the expectation that they should work like triggers when they don&amp;#x2019;t can induce some subtle and dangerous errors.\n
  2. To speak of code in the server to a Rails using audience is of course to engage in heresy. Nevertheless, I believe that for performance, reliability and security reasons, code in the database can be just the thing.\n
  3. Here is how we create a Rule\n
  4. I should emphasize that Rules are esoteric. Meaning that for most purposes, you don&amp;#x2019;t need Rules. If triggers will work for you and are fast enough, use triggers.\n\nRules are for two specific uses:\n1. Writable views; and\n2. Code that runs on insert, update or delete that runs fast when you are doing a *bulk* insert, update or delete.\n
  5. Why not just use a trigger?\n\nIf you do a bulk insert, update or delete, your trigger will run at least once for each affected row. This can be deadly slow. Many developers avoid triggers for this specific reason.\n
  6. Worth pointing out that you&amp;#x2019;re probably already employing Rules: Postgres implements views using Rules.\n
  7. A Postgres view is just a dummy table with a Rule that runs on SELECT that instead runs the query underlying the view\n
  8. So speed is one of the reason to use Rules. A rule will only run once, no matter how man rows you&amp;#x2019;re affecting, so a Rule won&amp;#x2019;t be affected at all by the problem affecting triggers.\n
  9. If you&amp;#x2019;re contemplating using Rules, please head a serious warning. You can really do things wrong if you don&amp;#x2019;t really understand how Rules work, or if you don&amp;#x2019;t test carefully.\n
  10. Here is the page you have to read, *carefully* if you&amp;#x2019;re contemplating using Rules.\n\nIt&amp;#x2019;s dry as dust. I&amp;#x2019;ve encountered more readable EULAs. But there is information in there you *must* understand. Because your intuitions *will* grievously mislead you otherwise.\n
  11. Here, for example, is the crucial point about an INSTEAD rule.\n\nYou *must* remember that a Rule doesn&amp;#x2019;t run its condition and *then* rewrite the query. Instead, it modifies the query and runs that, to similar but by no means identical effect.\n
  12. One of the first things many ask about when they discover Rules is how to do an upsert (insert if not present; update if it is).\n\nSo they do something like this&amp;#x2026;\n
  13. One of the first things many ask about when they discover Rules is how to do an upsert (insert if not present; update if it is).\n\nSo they do something like this&amp;#x2026;\n
  14. One of the first things many ask about when they discover Rules is how to do an upsert (insert if not present; update if it is).\n\nSo they do something like this&amp;#x2026;\n
  15. If you really stare at the conversion, you can see why the rule turns an insert of (1, 1) into a result of (1, 2). But it sure isn&amp;#x2019;t obvious from the Rule that this is what will happen.\n
  16. If you really stare at the conversion, you can see why the rule turns an insert of (1, 1) into a result of (1, 2). But it sure isn&amp;#x2019;t obvious from the Rule that this is what will happen.\n
  17. If you really stare at the conversion, you can see why the rule turns an insert of (1, 1) into a result of (1, 2). But it sure isn&amp;#x2019;t obvious from the Rule that this is what will happen.\n
  18. If you really stare at the conversion, you can see why the rule turns an insert of (1, 1) into a result of (1, 2). But it sure isn&amp;#x2019;t obvious from the Rule that this is what will happen.\n
  19. If you really stare at the conversion, you can see why the rule turns an insert of (1, 1) into a result of (1, 2). But it sure isn&amp;#x2019;t obvious from the Rule that this is what will happen.\n
  20. Here is another example. Because the insert has a dynamic function in it, the query rewrite gives you different results in the log table than what was inserted into the original table.\n
  21. Here is another example. Because the insert has a dynamic function in it, the query rewrite gives you different results in the log table than what was inserted into the original table.\n
  22. Here is another example. Because the insert has a dynamic function in it, the query rewrite gives you different results in the log table than what was inserted into the original table.\n
  23. Here is another example. Because the insert has a dynamic function in it, the query rewrite gives you different results in the log table than what was inserted into the original table.\n
  24. Here is another example. Because the insert has a dynamic function in it, the query rewrite gives you different results in the log table than what was inserted into the original table.\n
  25. Here is another example. Because the insert has a dynamic function in it, the query rewrite gives you different results in the log table than what was inserted into the original table.\n
  26. Let&amp;#x2019;s see a real-world example.\n
  27. I&amp;#x2019;ve a set of financial operations (credit card and cash receipts). These are &amp;#x201C;covered&amp;#x201D; by reconciliations. All the operations between a start and end time stamp by a particular operator are covered by the single reconciliation.\n\nThe question becomes how to maintain the relationship? We could include the start and end timestamps in the reconciliations table, but then to determine the reconciliation for a financial operation is a bit of a hassle.\n\nOr we could point a financial operation at its reconciliation, but we need to enforce that the financial operations in a block are all covered by the same reconciliation.\n
  28. We put the foreign key on financial_operations because that&amp;#x2019;s reasonably easy to work with from either end of the relationship.\n\nThen we create a reconciliations view that pulls in the results of that relationship.\n
  29. We put the foreign key on financial_operations because that&amp;#x2019;s reasonably easy to work with from either end of the relationship.\n\nThen we create a reconciliations view that pulls in the results of that relationship.\n
  30. We create a rule in two parts:\n\nThe first updates the reconciliations_data table.\n\nNote the &amp;#x201C;returning&amp;#x201D; clause can go just fine on the first query. You can only have one &amp;#x201C;returning&amp;#x201D;, but it doesn&amp;#x2019;t have to be on the last statement.\n
  31. The second part updates the matching financial_operations records.\n\nThe results are simple and effective, and we can update many thousands of financial_operations records with a single insert to the view.\n
  32. \n