Skip to content

Commit d0c9ef8

Browse files
committed
add SAP SQL Anywhere database vendor
1 parent 6ea864d commit d0c9ef8

21 files changed

+3891
-22
lines changed

docs/en/reference/portability.rst

+4-4
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ Portability
44
There are often cases when you need to write an application or library that is portable
55
across multiple different database vendors. The Doctrine ORM is one example of such
66
a library. It is an abstraction layer over all the currently supported vendors (MySQL, Oracle,
7-
PostgreSQL, SQLite and Microsoft SQL Server). If you want to use the DBAL to write a portable application
8-
or library you have to follow lots of rules to make all the different vendors work the
9-
same.
7+
PostgreSQL, SQLite, SAP SQL Anywhere and Microsoft SQL Server). If you want to use the DBAL
8+
to write a portable application or library you have to follow lots of rules to make
9+
all the different vendors work the same.
1010

1111
There are many different layers that you need to take care of, here is a quick list:
1212

@@ -39,7 +39,7 @@ Connection Wrapper
3939
This functionality is only implemented with Doctrine 2.1 upwards.
4040

4141
To handle all the points 1-3 you have to use a special wrapper around the database
42-
connection. The handling and differences to tackle are all taken from the great
42+
connection. The handling and differences to tackle are all taken from the great
4343
`PEAR MDB2 library <http://pear.php.net/package/MDB2/redirected>`_.
4444

4545
Using the following code block in your initialization will:
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
<?php
2+
/*
3+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
4+
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
5+
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
6+
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
7+
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
8+
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
9+
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
10+
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
11+
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
12+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
13+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
14+
*
15+
* This software consists of voluntary contributions made by many individuals
16+
* and is licensed under the MIT license. For more information, see
17+
* <http://www.doctrine-project.org>.
18+
*/
19+
20+
namespace Doctrine\DBAL\Driver\SQLAnywhere;
21+
22+
use Doctrine\DBAL\Connection;
23+
use Doctrine\DBAL\Platforms\SQLAnywhere12Platform;
24+
use Doctrine\DBAL\Schema\SQLAnywhereSchemaManager;
25+
26+
/**
27+
* A Doctrine DBAL driver for the SAP Sybase SQL Anywhere PHP extension.
28+
*
29+
* @author Steve Müller <[email protected]>
30+
* @link www.doctrine-project.org
31+
* @since 2.5
32+
*/
33+
class Driver implements \Doctrine\DBAL\Driver
34+
{
35+
/**
36+
* Build the connection string for given connection parameters and driver options.
37+
*
38+
* @param string $host Host address to connect to.
39+
* @param integer $port Port to use for the connection (default to SQL Anywhere standard port 2683).
40+
* @param string $server Database server name on the host to connect to.
41+
* SQL Anywhere allows multiple database server instances on the same host,
42+
* therefore specifying the server instance name to use is mandatory.
43+
* @param string $dbname Name of the database on the server instance to connect to.
44+
* @param string $username User name to use for connection authentication.
45+
* @param string $password Password to use for connection authentication.
46+
* @param array $driverOptions Additional parameters to use for the connection.
47+
*
48+
* @return string
49+
*/
50+
public function buildDsn($host, $port, $server, $dbname, $username = null, $password = null, array $driverOptions = array())
51+
{
52+
$port = $port ?: 2683;
53+
54+
return
55+
'LINKS=tcpip(HOST=' . $host . ';PORT=' . $port . ';DoBroadcast=Direct)' .
56+
';SERVER=' . $server .
57+
';DBN=' . $dbname .
58+
';UID=' . $username .
59+
';PWD=' . $password .
60+
';' . implode(
61+
';',
62+
array_map(function ($key, $value) {
63+
return $key . '=' . $value;
64+
}, array_keys($driverOptions), $driverOptions)
65+
);
66+
}
67+
68+
/**
69+
* {@inheritdoc}
70+
*
71+
* @throws SQLAnywhereException
72+
*/
73+
public function connect(array $params, $username = null, $password = null, array $driverOptions = array())
74+
{
75+
if ( ! isset($params['host'])) {
76+
throw new SQLAnywhereException("Missing 'host' in configuration for sqlanywhere driver.");
77+
}
78+
79+
if ( ! isset($params['server'])) {
80+
throw new SQLAnywhereException("Missing 'server' in configuration for sqlanywhere driver.");
81+
}
82+
83+
if ( ! isset($params['dbname'])) {
84+
throw new SQLAnywhereException("Missing 'dbname' in configuration for sqlanywhere driver.");
85+
}
86+
87+
return new SQLAnywhereConnection(
88+
$this->buildDsn(
89+
$params['host'],
90+
isset($params['port']) ? $params['port'] : null,
91+
$params['server'],
92+
$params['dbname'],
93+
$username,
94+
$password,
95+
$driverOptions
96+
),
97+
isset($params['persistent']) ? $params['persistent'] : false
98+
);
99+
}
100+
101+
/**
102+
* {@inheritdoc}
103+
*/
104+
public function getDatabase(Connection $conn)
105+
{
106+
$params = $conn->getParams();
107+
108+
return $params['dbname'];
109+
}
110+
111+
/**
112+
* {@inheritdoc}
113+
*/
114+
public function getDatabasePlatform()
115+
{
116+
return new SQLAnywhere12Platform();
117+
}
118+
119+
/**
120+
* {@inheritdoc}
121+
*/
122+
public function getName()
123+
{
124+
return 'sqlanywhere';
125+
}
126+
127+
/**
128+
* {@inheritdoc}
129+
*/
130+
public function getSchemaManager(Connection $conn)
131+
{
132+
return new SQLAnywhereSchemaManager($conn);
133+
}
134+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,210 @@
1+
<?php
2+
/*
3+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
4+
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
5+
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
6+
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
7+
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
8+
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
9+
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
10+
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
11+
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
12+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
13+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
14+
*
15+
* This software consists of voluntary contributions made by many individuals
16+
* and is licensed under the MIT license. For more information, see
17+
* <http://www.doctrine-project.org>.
18+
*/
19+
20+
namespace Doctrine\DBAL\Driver\SQLAnywhere;
21+
22+
use Doctrine\DBAL\Driver\Connection;
23+
24+
/**
25+
* SAP Sybase SQL Anywhere implementation of the Connection interface.
26+
*
27+
* @author Steve Müller <[email protected]>
28+
* @link www.doctrine-project.org
29+
* @since 2.5
30+
*/
31+
class SQLAnywhereConnection implements Connection
32+
{
33+
/**
34+
* @var resource The SQL Anywhere connection resource.
35+
*/
36+
private $conn;
37+
38+
/**
39+
* Constructor.
40+
*
41+
* Connects to database with given connection string.
42+
*
43+
* @param string $dsn The connection string.
44+
* @param boolean $persistent Whether or not to establish a persistent connection.
45+
*
46+
* @throws SQLAnywhereException
47+
*/
48+
public function __construct($dsn, $persistent = false)
49+
{
50+
$this->conn = $persistent ? @sasql_pconnect($dsn) : @sasql_connect($dsn);
51+
52+
if ( ! is_resource($this->conn) || get_resource_type($this->conn) != 'SQLAnywhere connection') {
53+
throw SQLAnywhereException::fromSQLAnywhereError();
54+
}
55+
56+
/**
57+
* Disable PHP warnings on error
58+
*/
59+
if ( ! sasql_set_option($this->conn, 'verbose_errors', false)) {
60+
throw SQLAnywhereException::fromSQLAnywhereError($this->conn);
61+
}
62+
63+
/**
64+
* Enable auto committing by default
65+
*/
66+
if ( ! sasql_set_option($this->conn, 'auto_commit', 'on')) {
67+
throw SQLAnywhereException::fromSQLAnywhereError($this->conn);
68+
}
69+
70+
/**
71+
* Enable exact, non-approximated row count retrieval
72+
*/
73+
if ( ! sasql_set_option($this->conn, 'row_counts', true)) {
74+
throw SQLAnywhereException::fromSQLAnywhereError($this->conn);
75+
}
76+
}
77+
78+
/**
79+
* {@inheritdoc}
80+
*
81+
* @throws SQLAnywhereException
82+
*/
83+
public function beginTransaction()
84+
{
85+
if ( ! sasql_set_option($this->conn, 'auto_commit', 'off')) {
86+
throw SQLAnywhereException::fromSQLAnywhereError($this->conn);
87+
}
88+
89+
return true;
90+
}
91+
92+
/**
93+
* {@inheritdoc}
94+
*
95+
* @throws SQLAnywhereException
96+
*/
97+
public function commit()
98+
{
99+
if ( ! sasql_commit($this->conn)) {
100+
throw SQLAnywhereException::fromSQLAnywhereError($this->conn);
101+
}
102+
103+
$this->endTransaction();
104+
105+
return true;
106+
}
107+
108+
/**
109+
* {@inheritdoc}
110+
*/
111+
public function errorCode()
112+
{
113+
return sasql_errorcode($this->conn);
114+
}
115+
116+
/**
117+
* {@inheritdoc}
118+
*/
119+
public function errorInfo()
120+
{
121+
return sasql_error($this->conn);
122+
}
123+
124+
/**
125+
* {@inheritdoc}
126+
*/
127+
public function exec($statement)
128+
{
129+
$stmt = $this->prepare($statement);
130+
$stmt->execute();
131+
132+
return $stmt->rowCount();
133+
}
134+
135+
/**
136+
* {@inheritdoc}
137+
*/
138+
public function lastInsertId($name = null)
139+
{
140+
if ($name === null) {
141+
return sasql_insert_id($this->conn);
142+
}
143+
144+
return $this->query('SELECT ' . $name . '.CURRVAL')->fetchColumn();
145+
}
146+
147+
/**
148+
* {@inheritdoc}
149+
*/
150+
public function prepare($prepareString)
151+
{
152+
return new SQLAnywhereStatement($this->conn, $prepareString);
153+
}
154+
155+
/**
156+
* {@inheritdoc}
157+
*/
158+
public function query()
159+
{
160+
$args = func_get_args();
161+
$stmt = $this->prepare($args[0]);
162+
$stmt->execute();
163+
164+
return $stmt;
165+
}
166+
167+
/**
168+
* {@inheritdoc}
169+
*/
170+
public function quote($input, $type = \PDO::PARAM_STR)
171+
{
172+
if (is_int($input) || is_float($input)) {
173+
return $input;
174+
}
175+
176+
return "'" . sasql_escape_string($this->conn, $input) . "'";
177+
}
178+
179+
/**
180+
* {@inheritdoc}
181+
*
182+
* @throws SQLAnywhereException
183+
*/
184+
public function rollBack()
185+
{
186+
if ( ! sasql_rollback($this->conn)) {
187+
throw SQLAnywhereException::fromSQLAnywhereError($this->conn);
188+
}
189+
190+
$this->endTransaction();
191+
192+
return true;
193+
}
194+
195+
/**
196+
* Ends transactional mode and enables auto commit again.
197+
*
198+
* @throws SQLAnywhereException
199+
*
200+
* @return boolean Whether or not ending transactional mode succeeded.
201+
*/
202+
private function endTransaction()
203+
{
204+
if ( ! sasql_set_option($this->conn, 'auto_commit', 'on')) {
205+
throw SQLAnywhereException::fromSQLAnywhereError($this->conn);
206+
}
207+
208+
return true;
209+
}
210+
}

0 commit comments

Comments
 (0)