Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
D
doctrine-dbal
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Tomáš Trávníček
doctrine-dbal
Commits
6a7bd7d9
Commit
6a7bd7d9
authored
Oct 12, 2010
by
beberlei
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fix Positional to Named Parameters parser to take literals into account.
parent
84770cd5
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
162 additions
and
23 deletions
+162
-23
OCI8Connection.php
lib/Doctrine/DBAL/Driver/OCI8/OCI8Connection.php
+54
-11
OCI8Statement.php
lib/Doctrine/DBAL/Driver/OCI8/OCI8Statement.php
+30
-12
UtilTest.php
tests/Doctrine/Tests/DBAL/UtilTest.php
+78
-0
No files found.
lib/Doctrine/DBAL/Driver/OCI8/OCI8Connection.php
View file @
6a7bd7d9
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
...
...
@@ -30,6 +28,13 @@ class OCI8Connection implements \Doctrine\DBAL\Driver\Connection
{
private
$_dbh
;
/**
* Create a Connection to an Oracle Database using oci8 extension.
*
* @param string $username
* @param string $password
* @param string $db
*/
public
function
__construct
(
$username
,
$password
,
$db
)
{
$this
->
_dbh
=
@
oci_connect
(
$username
,
$password
,
$db
);
...
...
@@ -38,11 +43,21 @@ class OCI8Connection implements \Doctrine\DBAL\Driver\Connection
}
}
/**
* Create a non-executed prepared statement.
*
* @param string $prepareString
* @return OCI8Statement
*/
public
function
prepare
(
$prepareString
)
{
return
new
OCI8Statement
(
$this
->
_dbh
,
$prepareString
);
}
/**
* @param string $sql
* @return OCI8Statement
*/
public
function
query
()
{
$args
=
func_get_args
();
...
...
@@ -53,11 +68,23 @@ class OCI8Connection implements \Doctrine\DBAL\Driver\Connection
return
$stmt
;
}
/**
* Quote input value.
*
* @param mixed $input
* @param int $type PDO::PARAM*
* @return mixed
*/
public
function
quote
(
$input
,
$type
=
\PDO
::
PARAM_STR
)
{
return
is_numeric
(
$input
)
?
$input
:
"'
$input
'"
;
}
/**
*
* @param string $statement
* @return int
*/
public
function
exec
(
$statement
)
{
$stmt
=
$this
->
prepare
(
$statement
);
...
...
@@ -70,11 +97,24 @@ class OCI8Connection implements \Doctrine\DBAL\Driver\Connection
//TODO: throw exception or support sequences?
}
/**
* Start a transactiom
*
* Oracle has to explicitly set the autocommit mode off. That means
* after connection, a commit or rollback there is always automatically
* opened a new transaction.
*
* @return bool
*/
public
function
beginTransaction
()
{
return
true
;
}
/**
* @throws OCI8Exception
* @return bool
*/
public
function
commit
()
{
if
(
!
oci_commit
(
$this
->
_dbh
))
{
...
...
@@ -83,6 +123,10 @@ class OCI8Connection implements \Doctrine\DBAL\Driver\Connection
return
true
;
}
/**
* @throws OCI8Exception
* @return bool
*/
public
function
rollBack
()
{
if
(
!
oci_rollback
(
$this
->
_dbh
))
{
...
...
@@ -104,5 +148,4 @@ class OCI8Connection implements \Doctrine\DBAL\Driver\Connection
{
return
oci_error
(
$this
->
_dbh
);
}
}
\ No newline at end of file
lib/Doctrine/DBAL/Driver/OCI8/OCI8Statement.php
View file @
6a7bd7d9
<?php
/*
* $Id: Interface.php 3882 2008-02-22 18:11:35Z jwage $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
...
...
@@ -33,7 +31,6 @@ class OCI8Statement implements \Doctrine\DBAL\Driver\Statement
{
/** Statement handle. */
private
$_sth
;
private
$_paramCounter
=
0
;
private
static
$_PARAM
=
':param'
;
private
static
$fetchStyleMap
=
array
(
PDO
::
FETCH_BOTH
=>
OCI_BOTH
,
...
...
@@ -50,28 +47,49 @@ class OCI8Statement implements \Doctrine\DBAL\Driver\Statement
*/
public
function
__construct
(
$dbh
,
$statement
)
{
$this
->
_sth
=
oci_parse
(
$dbh
,
$this
->
_convertPositionalToNamedPlaceholders
(
$statement
));
list
(
$statement
,
$paramMap
)
=
self
::
convertPositionalToNamedPlaceholders
(
$statement
);
$this
->
_sth
=
oci_parse
(
$dbh
,
$statement
);
$this
->
_paramMap
=
$paramMap
;
}
/**
* Convert positional (?) into named placeholders (:param<num>)
*
* Oracle does not support positional parameters, hence this method converts all
* positional parameters into artificially named parameters. Note that this conversion
* is not perfect. All question marks (?) in the original statement are treated as
* placeholders and converted to a named parameter.
*
* @param string $statement The SQL statement to convert.
* The algorithm uses a state machine with two possible states: InLiteral and NotInLiteral.
* Question marks inside literal strings are therefore handled correctly by this method.
* This comes at a cost, the whole sql statement has to be looped over.
*
* @todo extract into utility class in Doctrine\DBAL\Util namespace
* @todo review and test for lost spaces. we experienced missing spaces with oci8 in some sql statements.
* @param string $statement The SQL statement to convert.
* @return string
*/
private
function
_
convertPositionalToNamedPlaceholders
(
$statement
)
static
public
function
convertPositionalToNamedPlaceholders
(
$statement
)
{
$count
=
1
;
while
((
$pos
=
strpos
(
$statement
,
'?'
))
!==
false
)
{
$this
->
_paramMap
[
$count
]
=
":param
$count
"
;
$statement
=
substr_replace
(
$statement
,
":param
$count
"
,
$pos
,
1
);
$inLiteral
=
false
;
// a valid query never starts with quotes
$stmtLen
=
strlen
(
$statement
);
$paramMap
=
array
();
for
(
$i
=
0
;
$i
<
$stmtLen
;
$i
++
)
{
if
(
$statement
[
$i
]
==
'?'
&&
!
$inLiteral
)
{
// real positional parameter detected
$paramMap
[
$count
]
=
":param
$count
"
;
$len
=
strlen
(
$paramMap
[
$count
]);
$statement
=
substr_replace
(
$statement
,
":param
$count
"
,
$i
,
1
);
$i
+=
$len
-
1
;
// jump ahead
$stmtLen
=
strlen
(
$statement
);
// adjust statement length
++
$count
;
}
else
if
(
$statement
[
$i
]
==
"'"
||
$statement
[
$i
]
==
'"'
)
{
$inLiteral
=
!
$inLiteral
;
// switch state!
}
}
return
$statement
;
return
array
(
$statement
,
$paramMap
)
;
}
/**
...
...
tests/Doctrine/Tests/DBAL/UtilTest.php
0 → 100644
View file @
6a7bd7d9
<?php
namespace
Doctrine\Tests\DBAL
;
require_once
__DIR__
.
'/../TestInit.php'
;
class
UtilTest
extends
\Doctrine\Tests\DbalTestCase
{
static
public
function
dataConvertPositionalToNamedParameters
()
{
return
array
(
array
(
'SELECT name FROM users WHERE id = ?'
,
'SELECT name FROM users WHERE id = :param1'
,
array
(
1
=>
':param1'
)
),
array
(
'SELECT name FROM users WHERE id = ? AND status = ?'
,
'SELECT name FROM users WHERE id = :param1 AND status = :param2'
,
array
(
1
=>
':param1'
,
2
=>
':param2'
),
),
array
(
"UPDATE users SET name = '???', status = ?"
,
"UPDATE users SET name = '???', status = :param1"
,
array
(
1
=>
':param1'
),
),
array
(
"UPDATE users SET status = ?, name = '???'"
,
"UPDATE users SET status = :param1, name = '???'"
,
array
(
1
=>
':param1'
),
),
array
(
"UPDATE users SET foo = ?, name = '???', status = ?"
,
"UPDATE users SET foo = :param1, name = '???', status = :param2"
,
array
(
1
=>
':param1'
,
2
=>
':param2'
),
),
array
(
'UPDATE users SET name = "???", status = ?'
,
'UPDATE users SET name = "???", status = :param1'
,
array
(
1
=>
':param1'
),
),
array
(
'UPDATE users SET status = ?, name = "???"'
,
'UPDATE users SET status = :param1, name = "???"'
,
array
(
1
=>
':param1'
),
),
array
(
'UPDATE users SET foo = ?, name = "???", status = ?'
,
'UPDATE users SET foo = :param1, name = "???", status = :param2'
,
array
(
1
=>
':param1'
,
2
=>
':param2'
),
),
array
(
'SELECT * FROM users WHERE id = ? AND name = "" AND status = ?'
,
'SELECT * FROM users WHERE id = :param1 AND name = "" AND status = :param2'
,
array
(
1
=>
':param1'
,
2
=>
':param2'
),
),
array
(
"SELECT * FROM users WHERE id = ? AND name = '' AND status = ?"
,
"SELECT * FROM users WHERE id = :param1 AND name = '' AND status = :param2"
,
array
(
1
=>
':param1'
,
2
=>
':param2'
),
)
);
}
/**
* @dataProvider dataConvertPositionalToNamedParameters
* @param string $inputSQL
* @param string $expectedOutputSQL
* @param array $expectedOutputParamsMap
*/
public
function
testConvertPositionalToNamedParameters
(
$inputSQL
,
$expectedOutputSQL
,
$expectedOutputParamsMap
)
{
list
(
$statement
,
$params
)
=
\Doctrine\DBAL\Driver\OCI8\OCI8Statement
::
convertPositionalToNamedPlaceholders
(
$inputSQL
);
$this
->
assertEquals
(
$expectedOutputSQL
,
$statement
);
$this
->
assertEquals
(
$expectedOutputParamsMap
,
$params
);
}
}
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment