Version: 1.2
Type: Full Script
Category: Databases
License: BSD License
Description: This is a small package to handle sessions in oracle. Strong usage of PL/SQL, so php does not do much. Very quick and scalable. Enjoy!
/* Author: Ian Matyssik. 2003/01/19 */ /* Oracle script you will need to handle Sessions in ORACLE DB. */ DROP INDEX oci_sess_expires_idx; DROP TABLE oci_sess; CREATE TABLE oci_sess ( session_id char(32) PRIMARY KEY NOT NULL, expires NUMBER, data CLOB ); CREATE INDEX oci_sess_expires_idx ON oci_sess (expires); CREATE OR REPLACE PACKAGE php_sess AS procedure sess_open ( sess_id IN CHAR, ro_trans IN BOOLEAN, sess_exp IN NUMBER ); procedure sess_close ( ro_trans IN BOOLEAN ); procedure sess_read ( sess_id IN CHAR, sess_data OUT CLOB ); procedure sess_write ( sess_id IN CHAR, sess_data IN CLOB , sess_exp IN NUMBER ); procedure sess_destroy ( sess_id IN CHAR ); procedure sess_gc ( sess_exp IN NUMBER ); END php_sess; / show errors; CREATE OR REPLACE PACKAGE BODY php_sess AS /* Private Variables */ l_rowid ROWID := NULL; /* Private DATA vars */ l_sid OCI_SESS.session_id%TYPE; l_exp OCI_SESS.expires%TYPE; l_dtd OCI_SESS.data%TYPE; l_ro_trans BOOLEAN := FALSE; l_sess_open BOOLEAN := FALSE; /* Public Procedures. */ -- Procedure to open "SESSION" session. procedure sess_open ( sess_id IN CHAR, ro_trans IN BOOLEAN, sess_exp IN NUMBER ) IS BEGIN l_sess_open := TRUE; l_ro_trans := ro_trans; IF ro_trans THEN SELECT session_id,expires,data,rowid INTO l_sid,l_exp,l_dtd,l_rowid FROM OCI_SESS WHERE session_id = sess_id AND expires > sess_exp AND ROWNUM <= 1; ELSE SELECT session_id,expires,data,rowid INTO l_sid,l_exp,l_dtd,l_rowid FROM OCI_SESS WHERE session_id = sess_id AND expires > sess_exp AND ROWNUM <= 1 FOR UPDATE; END IF; EXCEPTION WHEN NO_DATA_FOUND THEN -- We found no data, so guess to make new one. Just to be safe -- we will delete first and then insert. DELETE FROM OCI_SESS WHERE session_id = sess_id; INSERT INTO OCI_SESS (session_id, expires, data) VALUES ( sess_id, (sess_exp + 1440), EMPTY_CLOB() ) RETURNING rowid INTO l_rowid; IF ro_trans THEN SELECT session_id,expires,data INTO l_sid,l_exp,l_dtd FROM OCI_SESS WHERE rowid = l_rowid; COMMIT; -- No matter if we are in a read only session we will commit to reduce -- risk later on. ELSE SELECT session_id,expires,data INTO l_sid,l_exp,l_dtd FROM OCI_SESS WHERE rowid = l_rowid FOR UPDATE; END IF; WHEN OTHERS THEN RAISE; RETURN; END sess_open; -- Procedure to close "SESSION" session. procedure sess_close ( ro_trans IN BOOLEAN ) IS BEGIN IF l_sess_open THEN IF l_ro_trans THEN RETURN; ELSE COMMIT; END IF; RETURN; ELSE RETURN; END IF; END sess_close; -- Procedure to read "SESSION" data. procedure sess_read ( sess_id IN CHAR, sess_data OUT CLOB ) IS BEGIN IF l_sess_open THEN IF sess_id = l_sid THEN sess_data := l_dtd; ELSE IF l_ro_trans THEN SELECT data INTO sess_data FROM OCI_SESS WHERE session_id = sess_id; ELSE SELECT data INTO sess_data FROM OCI_SESS WHERE session_id = sess_id FOR UPDATE; END IF; END IF; RETURN; ELSE RETURN; END IF; END sess_read; -- Procedure to write "SESSION" data. procedure sess_write ( sess_id IN CHAR, sess_data IN CLOB , sess_exp IN NUMBER ) IS BEGIN IF l_sess_open THEN IF l_ro_trans THEN RETURN; ELSE UPDATE OCI_SESS SET expires = sess_exp, data = sess_data WHERE rowid = l_rowid; END IF; RETURN; ELSE RETURN; END IF; END sess_write; -- Procedure to destroy "SESSION" data. procedure sess_destroy ( sess_id IN CHAR ) IS /*PRAGMA*/ -- PRAGMA AUTONOMOUS_TRANSACTION; BEGIN IF l_ro_trans THEN RETURN; ELSE DELETE FROM OCI_SESS WHERE session_id = sess_id; COMMIT; l_ro_trans := TRUE; END IF; RETURN; END sess_destroy; -- Procedure to cleanup expired "SESSION" data. -- Some times it can take long time so that is why we background it. procedure sess_gc ( sess_exp IN NUMBER ) IS /*PRAGMA*/ PRAGMA AUTONOMOUS_TRANSACTION; l_job_n NUMBER; l_job VARCHAR2(2000); BEGIN l_job := 'BEGIN DELETE FROM OCI_SESS WHERE expires <= '||sess_exp||'; COMMIT; END;'; DBMS_JOB.SUBMIT(l_job_n, l_job); COMMIT; RETURN; END sess_gc; END php_sess; / show errors; //------------------------------------------------ CUT -------------------------------------------- <? // Set this settings corectly. define("___OCI_SESS_DBUSER", 'php'); define("___OCI_SESS_DBPASS", 'php'); define("___OCI_SESS_DBNAME", 'oradb'); function ___oci_session_open($save_path, $name) { global $___oci_session_db, $___oci_session_ro_trans; $expires = time(); if(!$___oci_session_db = @OCIPLogon(___OCI_SESS_DBUSER,___OCI_SESS_DBPASS,___OCI_SESS_DBNAME)) { return False; } if($___oci_session_ro_trans) { $stmt = @OCIParse($___oci_session_db, "BEGIN PHP_SESS.SESS_OPEN(:SESS_ID, TRUE, :SESS_EXP); END;"); } else { $stmt = @OCIParse($___oci_session_db, "BEGIN PHP_SESS.SESS_OPEN(:SESS_ID, FALSE, :SESS_EXP); END;"); } $sess_id = session_id(); @OCIBindByName($stmt,":SESS_ID",$sess_id,-1); @OCIBindByName($stmt,":SESS_EXP",$expires,-1); if(@OCIExecute($stmt, OCI_DEFAULT)) { @OCIFreeStatement($stmt); return True; } else { @OCIRollback($stmt); @OCIFreeStatement($stmt); return False; } } function ___oci_session_close() { global $___oci_session_db, $___oci_session_ro_trans; if($___oci_session_ro_trans) { $stmt = @OCIParse($___oci_session_db, "BEGIN PHP_SESS.SESS_CLOSE(TRUE); END;"); } else { $stmt = @OCIParse($___oci_session_db, "BEGIN PHP_SESS.SESS_CLOSE(FALSE); END;"); } if(@OCIExecute($stmt, OCI_DEFAULT)) { @OCIFreeStatement($stmt); return True; } else { @OCIRollback($stmt); @OCIFreeStatement($stmt); return False; } } function ___oci_session_read($session_id) { global $___oci_session_db; $d_data = @OCINewDescriptor($___oci_session_db,OCI_D_LOB); $stmt = @OCIParse($___oci_session_db, "BEGIN PHP_SESS.SESS_READ(:SESS_ID,:SESS_DATA); END;"); @OCIBindByName($stmt,":SESS_ID",$session_id,-1); @OCIBindByName($stmt,":SESS_DATA",$d_data,-1, @OCI_B_CLOB); if(@OCIExecute($stmt, OCI_DEFAULT)) { $data = @$d_data->load(); @$d_data->free(); @OCIFreeStatement($stmt); return (string)$data; } else { @$d_data->free(); @OCIRollback($stmt); @OCIFreeStatement($stmt); return False; } } function ___oci_session_write($session_id, $data) { global $___oci_session_db; $expires = time() + get_cfg_var("session.gc_maxlifetime"); //Prepare Statement. $stmt = @OCIParse($___oci_session_db, "BEGIN PHP_SESS.SESS_WRITE(:SESS_ID,:SESS_DATA,:SESS_EXP); END;"); //Bind @OCIBindByName($stmt,":SESS_ID",$session_id,-1); @OCIBindByName($stmt,":SESS_DATA",$data,-1); @OCIBindByName($stmt,":SESS_EXP",$expires,-1); if(@OCIExecute($stmt, OCI_DEFAULT)) { @OCIFreeStatement($stmt); return True; } else { @OCIRollback($stmt); @OCIFreeStatement($stmt); return False; } } function ___oci_session_destroy($session_id) { global $___oci_session_db; //Prepare Statement. $stmt = @OCIParse($___oci_session_db, "BEGIN PHP_SESS.SESS_DESTROY(:SESS_ID); END;"); //Bind @OCIBindByName($stmt,":SESS_ID",$session_id,-1); if(@OCIExecute($stmt, OCI_DEFAULT)) { @OCIFreeStatement($stmt); return True; } else { @OCIRollback($stmt); @OCIFreeStatement($stmt); return False; } } function ___oci_session_gc($gc_maxlifetime) { global $___oci_session_db; $ex_time = time(); //Prepare Statement. $stmt = @OCIParse($___oci_session_db, "BEGIN PHP_SESS.SESS_GC(:SESS_EXP); END;" ); //Bind @OCIBindByName($stmt,":SESS_EXP",$ex_time,-1); if(@OCIExecute($stmt, OCI_DEFAULT)) { @OCIFreeStatement($stmt); return True; } else { @OCIRollback($stmt); @OCIFreeStatement($stmt); return False; } } /* * Register callback functions with PHP. * * Note that session.save_handler must be 'user' for this to succeed. */ session_set_save_handler( "___oci_session_open", "___oci_session_close", "___oci_session_read", "___oci_session_write", "___oci_session_destroy", "___oci_session_gc"); ?>