PHP
  Home arrow PHP arrow Page 2 - Moving Logic Into the Database
Dev Articles Forums 
ADO.NET  
Apache  
ASP  
ASP.NET  
C#  
C++  
ColdFusion  
COM/COM+  
Delphi-Kylix  
Design Usability  
Development Cycles  
DHTML  
Embedded Tools  
Flash  
Graphic Design  
HTML  
IIS  
Interviews  
Java  
JavaScript  
MySQL  
Oracle  
Photoshop  
PHP  
Reviews  
Ruby-on-Rails  
SQL  
SQL Server  
Style Sheets  
VB.Net  
Visual Basic  
Web Authoring  
Web Services  
Web Standards  
XML  
Mobile Linux 
App Generation ROI 
IBM® developerWorks 
Sun Developer Network 
Weekly Newsletter
 
Developer Updates  
Free Website Content 
 RSS  Articles
 RSS  Forums
 RSS  All Feeds
Write For Us Get Paid 
Request Media Kit
Contact Us 
Site Map 
Privacy Policy 
Support 
 USERNAME
 
 PASSWORD
 
 
  >>> SIGN UP!  
  Lost Password? 
PHP

Moving Logic Into the Database
By: Tim Perdue
  • Search For More Articles!
  • Disclaimer
  • Author Terms
  • Rating:  stars stars stars stars stars / 0
    2003-01-16

    Table of Contents:
  • Moving Logic Into the Database
  • Triggers and PostgreSQL
  • Triggers and PostgreSQL (cont'd)
  • Conclusion

  • Rate this Article: Poor Best 
      ADD THIS ARTICLE TO:
      Del.ici.ous Digg
      Blink Simpy
      Google Spurl
      Y! MyWeb Furl
    Email Me Similar Content When Posted
    Add Developer Shed Article Feed To Your Site
    Email Article To Friend
    Print Version Of Article
    PDF Version Of Article
     
     
    ADVERTISEMENT


    Moving Logic Into the Database - Triggers and PostgreSQL


    (Page 2 of 4 )

    The alternative approach is to move these constraints into triggers in the database. I have messed with triggers that update counters and create rows in related tables, but this is the most I have done with PL/pgsql, the PostgreSQL programming language of choice.

    There are two kinds of triggers in pl/pgsql programming, the "before" trigger and the after trigger. You use the "before" triggers if you want to modify a row of data before it is inserted into the database. That sounds like how we want to handle our start/end dates for tasks. If a user attempts to insert Task B with a start date earlier than the end date of Task A, we need to override him and push his dates back.

    The other kind of trigger is the "after" trigger, which you use if you want to perform actions after your row is inserted into the database. That's how we will push back Tasks B and C if Task A is delayed.
    What's really neat is that we are essentially getting recursion for "free".

    If Task A is updated, the trigger fires and updates Task B. The trigger for Task B is set off as well, which causes Task C to update, and so on down the line until everything is validated.

    We can start by looking at the "before" trigger, which validates the start/end dates.

    CREATE OR REPLACE FUNCTION projtask_insert_depend () RETURNS OPAQUE AS '
    DECLARE
        dependon RECORD;
        delta INTEGER;
    BEGIN
        --
        -- ENFORCE START/END DATE logic
        --
        IF NEW.start_date >= NEW.end_date THEN
            RAISE EXCEPTION ''START DATE CANNOT BE AFTER END DATE'';
        END IF;
        --
        --    First make sure we start on or after end_date of tasks
        --    that we depend on
        --
        FOR dependon IN SELECT * FROM project_dependon_vw
                    WHERE project_task_id=NEW.project_task_id LOOP
            --
            --    See if the task we are dependon on
            --    ends after we are supposed to start
            --
            IF dependon.end_date > NEW.start_date THEN
                delta := dependon.end_date-NEW.start_date;
                RAISE NOTICE ''Bumping Back: % Delta: % '',
                  NEW.project_task_id,delta;
                NEW.start_date := NEW.start_date+delta;
                NEW.end_date := NEW.end_date+delta;
            END IF;

        END LOOP;
        RETURN NEW;
    END;
    ' LANGUAGE 'plpgsql';


    As you can see, we have logic to raise an exception if a (dimwitted) user tries to make his start date after his end date.
    We also have a FOR ... IN loop which queries the tasks we are dependent on, and adjusts our start/end dates if we attempt to start before our predecessor is completed.

    NEW is a reference to the row that this trigger is acting on. If this were on an UDPATE event, we would also have access to the OLD row as well. As you can see, we can reference all the fields in NEW, such as NEW.start_date, and reference all of the rows we are querying as "dependon".

    Those few lines of very simple code will now guarantee that our data is always correct. If we had put this logic into PHP, it would be possible for someone to issue commands on the psql command line that could mess up our system.

    Now for the trigger which will activate this function:

    CREATE TRIGGER projtask_insert_depend_trig
        BEFORE INSERT OR UPDATE ON project_task
        FOR EACH ROW EXECUTE PROCEDURE projtask_insert_depend();

    More PHP Articles
    More By Tim Perdue


     

    PHP ARTICLES

    - Making Usage Statistics in PHP
    - Installing PHP under Windows: Further Config...
    - File Version Management in PHP
    - Statistical View of Data in a Clustered Bar ...
    - Creating a Multi-File Upload Script in PHP
    - Executing Microsoft SQL Server Stored Proced...
    - Code 10x More Efficiently Using Data Access ...
    - A Few Tips for Speeding Up PHP Code
    - The Modular Web Page
    - Quick E-Commerce with PHP and PayPal
    - Regression Testing With JMeter
    - Building an Iterator with PHP
    - PHP Frontend to ImageMagick
    - Using PEAR's mimeDecode Module
    - Incoming Mail and PHP






    © 2003-2008 by Developer Shed. All rights reserved. DS Cluster 6 hosted by Hostway
    Stay green...Green IT