Version: 1.2
Type: Full Script
Category: Databases
License: BSD License
Description: If you want to store you sessions in the oracle DB and speed it up with Packages and stored procedures. Also locking is handaled correctly, not like other implimintations. Emulates file locking and implise correct session bihavier.
/*
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");
?>
