Discussion:
Patch: Basic Oracle stored procedures
Remy Wetzels
2008-05-28 14:31:09 UTC
Permalink
Any interest in a patch for a OCI8CallableStatement class to support
(stored) procedures in Oracle?

It's not fully tested yet for all field types (clobs, blobs, etc), but
it should work on the basic fields like varchar2, integer, date and
stuff... No support for cursors yet. (We do not need it at the moment
and there is I believe no CreoleType for cursors (SQLT_RSET))

There is a small variation in the prepareCall as opposed to the MSSQL
(see also
http://creole.phpdb.org/trac/wiki/Documentation/CreoleGuide#StoredProced
ures). You only need to give the procedure name for MSSQL. For Oracle
you need to create the complete 'BEGIN ... END' SQL string. Also the
setXXX and registerOutParameter have a different behavior due to the
differences in procedure calling between MSSQL and Oracle.

We use a slightly modified version of Creole 1.1.0 (non-locale float
patch and our NLS_DATE_FORMAT has time in it).

My base test was procedure:

==== snip ====
create or replace PROCEDURE
sayHello (name IN VARCHAR2, datum IN DATE, greeting OUT
VARCHAR2)
AS
BEGIN
greeting := 'Hello ' || name || ' on ' || datum;
END;
==== snip ====

The test PHP code ($con is the propel connection):

==== snip ====
$sqlString = 'BEGIN sayHello(:name,:datum,:greeting); END;';
echo '<br>['.$sqlString.']';

$statement = $con->prepareCall($sqlString);
/* setString($paramIndex, $value, $maxLength = -1) */
$statement->setString(':name', 'PutYourNameHere');
/* setTimestamp($paramIndex, $value, $maxLength = -1) */
$statement->setDate(':datum', time());
/* registerOutParameter($paramIndex, $sqlType, $maxLength = -1) */
$statement->registerOutParameter(':greeting', CreoleTypes::VARCHAR,
255);

$result = $statement->executeQuery(ResultSet::FETCHMODE_NUM);
echo '<br>';
var_dump($result);
echo '<br>';
echo '<br><b>result:</b> '.$statement->getString(':greeting');
// the statement below gives an error:
// ORA-24374: define not done before fetch or execute and fetch
// while ($result->next())
// {
// echo '<br><b>Result</b>';
// echo '<br>['.$result->get(1).']';
// }
$statement->close();
==== snip ====

Which will result in the following output:

==== snip ====
[BEGIN sayHello(:name,:datum,:greeting); END;]
object(OCI8ResultSet)#329 (7) { ["fetchmode:protected"]=> int(2)
["conn:protected"]=> object(OCI8Connection)#41 (7) {
["lastStmt:protected"]=> NULL ["execMode:protected"]=> int(32)
["transactionOpcount:protected"]=> int(0) ["dblink:protected"]=>
resource(74) of type (oci8 connection) ["dsn:protected"]=> array(5) {
["database"]=> NULL ["hostspec"]=> string(13) "HOSTSPEC" ["password"]=>
string(7) "PASSWORD" ["phptype"]=> string(6) "oracle" ["username"]=>
string(7) "USERNAME" } ["flags:protected"]=> int(0) ["lastQuery"]=>
string(62) "ALTER SESSION SET NLS_TIMESTAMP_FORMAT='YYYY-MM-DD
HH24:MI:SS'" } ["result:protected"]=> resource(299) of type (oci8
statement) ["cursorPos:protected"]=> int(0) ["fields:protected"]=> NULL
["lowerAssocCase:protected"]=> bool(false) ["rtrimString:protected"]=>
bool(false) }

result: Hello PutYourNameHere on 2008-05-28 00:00:00
==== snip ====

If anyone is interested I will sent it to Hans so that he can check it
into SVN...

Regards,

- Remy Wetzels.
Randy Syring
2008-05-28 14:36:24 UTC
Permalink
Remy,

I wouldn't mind putting it into Creole eventually, but my current
experience with Oracle is virtually non-existent and I have yet to be
able to figure out how to get a free Oracle server setup to test stuff
against. I tried downloading the free server from their website and got
it running but couldn't get the unit tests running on it. Until I can
run unit tests against new code, I am very hesitant to do any work on
the Oracle driver.

That being said, if you know of a tutorial that would help get me up and
running with an Oracle server I could test these changes against, it
will be much more likely that Oracle development in Creole will
continue. Even better would be an explanation of how to run Creol's
unit tests against Oracle.

Thanks.

--------------------------------------
Randy Syring
RCS Computers & Web Solutions
502-644-4776
http://www.rcs-comp.com

"Whether, then, you eat or drink or
whatever you do, do all to the glory
of God." 1 Cor 10:31
Post by Remy Wetzels
Any interest in a patch for a OCI8CallableStatement class to support
(stored) procedures in Oracle?
It's not fully tested yet for all field types (clobs, blobs, etc), but
it should work on the basic fields like varchar2, integer, date and
stuff... No support for cursors yet. (We do not need it at the moment
and there is I believe no CreoleType for cursors (SQLT_RSET))
There is a small variation in the prepareCall as opposed to the MSSQL
(see also
http://creole.phpdb.org/trac/wiki/Documentation/CreoleGuide#StoredProced
ures). You only need to give the procedure name for MSSQL. For Oracle
you need to create the complete 'BEGIN ... END' SQL string. Also the
setXXX and registerOutParameter have a different behavior due to the
differences in procedure calling between MSSQL and Oracle.
We use a slightly modified version of Creole 1.1.0 (non-locale float
patch and our NLS_DATE_FORMAT has time in it).
==== snip ====
create or replace PROCEDURE
sayHello (name IN VARCHAR2, datum IN DATE, greeting OUT
VARCHAR2)
AS
BEGIN
greeting := 'Hello ' || name || ' on ' || datum;
END;
==== snip ====
==== snip ====
$sqlString = 'BEGIN sayHello(:name,:datum,:greeting); END;';
echo '<br>['.$sqlString.']';
$statement = $con->prepareCall($sqlString);
/* setString($paramIndex, $value, $maxLength = -1) */
$statement->setString(':name', 'PutYourNameHere');
/* setTimestamp($paramIndex, $value, $maxLength = -1) */
$statement->setDate(':datum', time());
/* registerOutParameter($paramIndex, $sqlType, $maxLength = -1) */
$statement->registerOutParameter(':greeting', CreoleTypes::VARCHAR,
255);
$result = $statement->executeQuery(ResultSet::FETCHMODE_NUM);
echo '<br>';
var_dump($result);
echo '<br>';
echo '<br><b>result:</b> '.$statement->getString(':greeting');
// ORA-24374: define not done before fetch or execute and fetch
// while ($result->next())
// {
// echo '<br><b>Result</b>';
// echo '<br>['.$result->get(1).']';
// }
$statement->close();
==== snip ====
==== snip ====
[BEGIN sayHello(:name,:datum,:greeting); END;]
object(OCI8ResultSet)#329 (7) { ["fetchmode:protected"]=> int(2)
["conn:protected"]=> object(OCI8Connection)#41 (7) {
["lastStmt:protected"]=> NULL ["execMode:protected"]=> int(32)
["transactionOpcount:protected"]=> int(0) ["dblink:protected"]=>
resource(74) of type (oci8 connection) ["dsn:protected"]=> array(5) {
["database"]=> NULL ["hostspec"]=> string(13) "HOSTSPEC" ["password"]=>
string(7) "PASSWORD" ["phptype"]=> string(6) "oracle" ["username"]=>
string(7) "USERNAME" } ["flags:protected"]=> int(0) ["lastQuery"]=>
string(62) "ALTER SESSION SET NLS_TIMESTAMP_FORMAT='YYYY-MM-DD
HH24:MI:SS'" } ["result:protected"]=> resource(299) of type (oci8
statement) ["cursorPos:protected"]=> int(0) ["fields:protected"]=> NULL
["lowerAssocCase:protected"]=> bool(false) ["rtrimString:protected"]=>
bool(false) }
result: Hello PutYourNameHere on 2008-05-28 00:00:00
==== snip ====
If anyone is interested I will sent it to Hans so that he can check it
into SVN...
Regards,
- Remy Wetzels.
---------------------------------------------------------------------
Remy Wetzels
2008-05-28 15:37:06 UTC
Permalink
Hi Randy,

I know of some trouble with the old oci8 stuff in old releases of PHP.
We had to recompile with a more recent version of ext/oci8 to make it
run correctly on at least 5.1.6.
Recent versions of PHP5 do not have that problem.

When running the unit tests on creole 1.1.0 I get a big bunch of
warnings and stuff...
But it seems to create some tables and do all kinds stuff...

I run the tests on linux:

php -f run-tests.php oracle://username:***@xe.host.domain/

Best it is to have instantclient installed
(http://www.oracle.com/technology/tech/oci/instantclient/index.html )

And in file /etc/profile.d/oracle.sh:

#
# Add profile for Oracle instanclient
#
export ORACLE_SID=XE
export ORACLE_HOME=/opt/oracle/instantclient
export NLS_LANG=AMERICAN_AMERICA.UTF8
export SQLPATH=$ORACLE_HOME
export PATH=$ORACLE_HOME:$PATH
export LD_LIBRARY_PATH=$ORACLE_HOME:$LD_LIBRARY_PATH
export TNS_ADMIN=$ORACLE_HOME

And in file /opt/oracle/instantclient/tnsnames.ora:

XE.HOST.DOMAIN =
(DESCRIPTION =
(ADDRESS = (PROTOCOL= TCP)(HOST=
youroracleserver.yourdomain.com)(PORT= 1521))
(CONNECT_DATA = (SERVICE_NAME = XE))
)

You can test your connection with sqlplus:

/opt/oracle/instantclient/sqlplus username/***@xe.host.domain

You should get a prompt like:

==== snip ====
SQL*Plus: Release 10.2.0.2.0 - Production on Wed May 28 17:34:37 2008

Copyright (c) 1982, 2005, Oracle. All Rights Reserved.

Connected to:
Oracle Database 10g Express Edition Release 10.2.0.1.0 - Production

SQL>
==== snip ====

Hope this helps you a bit...

Regards,

- Remy.
-----Original Message-----
Sent: Wednesday, May 28, 2008 4:36 PM
Subject: Re: [creole-dev] Patch: Basic Oracle stored procedures
Remy,
I wouldn't mind putting it into Creole eventually, but my current
experience with Oracle is virtually non-existent and I have yet to be
able to figure out how to get a free Oracle server setup to test stuff
against. I tried downloading the free server from their website and got
it running but couldn't get the unit tests running on it. Until I can
run unit tests against new code, I am very hesitant to do any work on
the Oracle driver.
That being said, if you know of a tutorial that would help get me up and
running with an Oracle server I could test these changes against, it
will be much more likely that Oracle development in Creole will
continue. Even better would be an explanation of how to run Creol's
unit tests against Oracle.
Thanks.
--------------------------------------
Randy Syring
RCS Computers & Web Solutions
502-644-4776
http://www.rcs-comp.com
"Whether, then, you eat or drink or
whatever you do, do all to the glory
of God." 1 Cor 10:31
Post by Remy Wetzels
Any interest in a patch for a OCI8CallableStatement class to support
(stored) procedures in Oracle?
It's not fully tested yet for all field types (clobs, blobs, etc),
but
Post by Remy Wetzels
it should work on the basic fields like varchar2, integer, date and
stuff... No support for cursors yet. (We do not need it at the moment
and there is I believe no CreoleType for cursors (SQLT_RSET))
There is a small variation in the prepareCall as opposed to the MSSQL
(see also
http://creole.phpdb.org/trac/wiki/Documentation/CreoleGuide#StoredProce
d
Post by Remy Wetzels
ures). You only need to give the procedure name for MSSQL. For Oracle
you need to create the complete 'BEGIN ... END' SQL string. Also the
setXXX and registerOutParameter have a different behavior due to the
differences in procedure calling between MSSQL and Oracle.
We use a slightly modified version of Creole 1.1.0 (non-locale float
patch and our NLS_DATE_FORMAT has time in it).
==== snip ====
create or replace PROCEDURE
sayHello (name IN VARCHAR2, datum IN DATE, greeting OUT
VARCHAR2)
AS
BEGIN
greeting := 'Hello ' || name || ' on ' || datum;
END;
==== snip ====
==== snip ====
$sqlString = 'BEGIN sayHello(:name,:datum,:greeting); END;';
echo '<br>['.$sqlString.']';
$statement = $con->prepareCall($sqlString);
/* setString($paramIndex, $value, $maxLength = -1) */
$statement->setString(':name', 'PutYourNameHere');
/* setTimestamp($paramIndex, $value, $maxLength = -1) */
$statement->setDate(':datum', time());
/* registerOutParameter($paramIndex, $sqlType, $maxLength = -1) */
$statement->registerOutParameter(':greeting', CreoleTypes::VARCHAR,
255);
$result = $statement->executeQuery(ResultSet::FETCHMODE_NUM);
echo '<br>';
var_dump($result);
echo '<br>';
echo '<br><b>result:</b> '.$statement->getString(':greeting');
// ORA-24374: define not done before fetch or execute and fetch
// while ($result->next())
// {
// echo '<br><b>Result</b>';
// echo '<br>['.$result->get(1).']';
// }
$statement->close();
==== snip ====
==== snip ====
[BEGIN sayHello(:name,:datum,:greeting); END;]
object(OCI8ResultSet)#329 (7) { ["fetchmode:protected"]=> int(2)
["conn:protected"]=> object(OCI8Connection)#41 (7) {
["lastStmt:protected"]=> NULL ["execMode:protected"]=> int(32)
["transactionOpcount:protected"]=> int(0) ["dblink:protected"]=>
resource(74) of type (oci8 connection) ["dsn:protected"]=> array(5) {
["database"]=> NULL ["hostspec"]=> string(13) "HOSTSPEC"
["password"]=>
Post by Remy Wetzels
string(7) "PASSWORD" ["phptype"]=> string(6) "oracle" ["username"]=>
string(7) "USERNAME" } ["flags:protected"]=> int(0) ["lastQuery"]=>
string(62) "ALTER SESSION SET NLS_TIMESTAMP_FORMAT='YYYY-MM-DD
HH24:MI:SS'" } ["result:protected"]=> resource(299) of type (oci8
statement) ["cursorPos:protected"]=> int(0) ["fields:protected"]=>
NULL
Post by Remy Wetzels
["lowerAssocCase:protected"]=> bool(false)
["rtrimString:protected"]=>
Post by Remy Wetzels
bool(false) }
result: Hello PutYourNameHere on 2008-05-28 00:00:00
==== snip ====
If anyone is interested I will sent it to Hans so that he can check
it
Post by Remy Wetzels
into SVN...
Regards,
- Remy Wetzels.
---------------------------------------------------------------------
---------------------------------------------------------------------
Loading...