php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Request #44007 oci8: Ability to externally set a default $mode value for oci_execute()
Submitted: 2008-01-31 20:11 UTC Modified: 2011-12-20 22:51 UTC
Votes:2
Avg. Score:4.5 ± 0.5
Reproduced:1 of 1 (100.0%)
Same Version:1 (100.0%)
Same OS:1 (100.0%)
From: crescentfreshpot at yahoo dot com Assigned:
Status: Open Package: OCI8 related
PHP Version: 5.2.5 OS: Any
Private report: No CVE-ID: None
Have you experienced this issue?
Rate the importance of this bug to you:

 [2008-01-31 20:11 UTC] crescentfreshpot at yahoo dot com
Description:
------------
The php oci8 extension has the following transaction model:
1) a new session (connection) implicitly starts a local transaction (AUTOCOMMIT=OFF)
2) oci_execute() implicitly autocommits unless OCI_DEFAULT is passed
3) when the session exits (connection is closed) all pending changes are rolled back

Re point 2), php has hardcoded OCI_COMMIT_ON_SUCCESS as the default autocommit value in oci_execute(). This means that all calls to oci_execute() will by default turn autocommit ON (including SELECT queries for example). This makes it awkward to write generic database application code that is decoupled from transaction awareness. 

An example:
There is a class User that interfaces to a USERS table. It has some getters and setters and a insert() method that constructs and executes an INSERT statement. Separately, there is a [similar] class Address that performs an INSERT into a ADDRESS table. Now we want to create a USER record, and then create a ADDRESS record. Sounds easy enough, as these are discreet blocks of code that can be simply called in order ($user->insert(); $address->insert();). Further, we would like to wrap these both in a transaction so that if either insert() fails we can roll back. Here is where php's transaction implementation bites our 'generic insert' application code. Both calls to insert() must know the caller's desires for a transaction in order to pass the correct mode to oci_execute().

http://www.oracle.com/technology/pub/articles/oracle_php_cookbook/fuecks_transactions.html includes another example of php oci8's transaction 'gotcha' (namely, forgetting to pass OCI_DEFAULT).

Now to the feature request: 
Could we have an oci_set_auto_commit([$auto_commit=true|false]) userspace function that internally toggles the default value oci_execute() uses if not passed a $mode? 

An example usage:

<?php

// ...
$connection = oci_connect(...);

// passing false tells oci8 that calls to oci_execute() should
// NOT use OCI_COMMIT_ON_SUCCESS as the default if no $mode given
oci_set_auto_commit($connection, false);

// ...
oci_execute($stmt1); // does not commit
// ...
oci_execute($stmt2); // does not commit
// ...
oci_execute($stmt3); // does not commit

oci_rollback($connection);

?>

With an oci_set_auto_commit() function, forgetting to pass OCI_DEFAULT to oci_execute(), or wrapping each oci_execute() in some generic code that doesn't know what to pass to oci_execute() become non-issues. 

Obviously there are workarounds. An oci8 OO wrapper or a global flag can solve the "what do I pass to oci_execute() here?" problem. I just thought it would be a nice to have that could help make oci8 code a little more readable in this particular instance.

I would be happy to try my hand at a patch for this if there are no objections. I've been digging around php's C internals for years now but haven't written any C since university.

Thoughts?



Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2011-12-20 22:51 UTC] sixd@php.net
-Package: Feature/Change Request +Package: OCI8 related
 
PHP Copyright © 2001-2019 The PHP Group
All rights reserved.
Last updated: Sat Aug 24 09:01:26 2019 UTC