# Source for file Oracle.php

Documentation is available at Oracle.php

1. <?php
2. /*
3. * $Id: Mock.php 1080 2007-02-10 18:17:08Z romanb $
4. *
5. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
6. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
7. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
8. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
9. * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
10. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
11. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
12. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
13. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
14. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
15. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
16. *
17. * This software consists of voluntary contributions made by many individuals
18. * and is licensed under the LGPL. For more information, see
19. * <http://www.phpdoctrine.com>.
20. */
21. Doctrine::autoload('Doctrine_Adapter');
22. /**
23. * Doctrine_Adapter_Oracle
24. * [BORROWED FROM ZEND FRAMEWORK]
25. *
26. * @package Doctrine
27. * @subpackage Doctrine_Adapter
28. * @author Konsta Vesterinen <kvesteri@cc.hut.fi>
29. * @license http://www.opensource.org/licenses/lgpl-license.php LGPL
30. * @category Object Relational Mapping
31. * @link www.phpdoctrine.com
32. * @since 1.0
33. * @version $Revision: 1080 $
34. */
35. class Doctrine_Adapter_Oracle extends Doctrine_Adapter
36. {
37. /**
38. * User-provided configuration.
39. *
40. * Basic keys are:
41. *
42. * username => (string) Connect to the database as this username.
43. * password => (string) Password associated with the username.
44. * dbname => Either the name of the local Oracle instance, or the
45. * name of the entry in tnsnames.ora to which you want to connect.
46. *
47. * @var array
48. */
49. protected $_config = array(
50. 'dbname' => null,
51. 'username' => null,
52. 'password' => null,
53. );
55. /**
56. * @var integer
57. */
58. protected $_execute_mode = OCI_COMMIT_ON_SUCCESS;
60. /**
61. * Constructor.
62. *
63. * $config is an array of key/value pairs containing configuration
64. * options. These options are common to most adapters:
65. *
66. * username => (string) Connect to the database as this username.
67. * password => (string) Password associated with the username.
68. * dbname => Either the name of the local Oracle instance, or the
69. * name of the entry in tnsnames.ora to which you want to connect.
70. *
71. * @param array $config An array of configuration keys.
72. * @throws Doctrine_Adapter_Exception
73. */
74. public function __construct(array $config)
75. {
76. if ( ! isset($config['password']) || ! isset($config['username'])) {
77. throw new Doctrine_Adapter_Exception('config array must have at least a username and a password');
78. }
80. // @todo Let this protect backward-compatibility for one release, then remove
81. if ( ! isset($config['database']) || ! isset($config['dbname'])) {
82. $config['dbname'] = $config['database'];
83. unset($config['database']);
84. trigger_error("Deprecated config key 'database', use 'dbname' instead.", E_USER_NOTICE);
85. }
87. // keep the config
88. $this->_config = array_merge($this->_config, (array) $config);
90. // create a profiler object
91. $enabled = false;
92. if (array_key_exists('profiler', $this->_config)) {
93. $enabled = (bool) $this->_config['profiler'];
94. unset($this->_config['profiler']);
95. }
97. $this->_profiler = new Doctrine_Profiler($enabled);
98. }
100. /**
101. * Creates a connection resource.
102. *
103. * @return void
104. * @throws Doctrine_Adapter_Oracle_Exception
105. */
106. protected function _connect()
107. {
108. if (is_resource($this->_connection)) {
109. // connection already exists
110. return;
111. }
113. if (!extension_loaded('oci8')) {
114. throw new Doctrine_Adapter_Oracle_Exception('The OCI8 extension is required for this adapter but not loaded');
115. }
117. if (isset($this->_config['dbname'])) {
118. $this->_connection = @oci_connect(
119. $this->_config['username'],
120. $this->_config['password'],
121. $this->_config['dbname']);
122. } else {
123. $this->_connection = oci_connect(
124. $this->_config['username'],
125. $this->_config['password']);
126. }
128. // check the connection
129. if (!$this->_connection) {
130. throw new Doctrine_Adapter_Oracle_Exception(oci_error());
131. }
132. }
134. /**
135. * Force the connection to close.
136. *
137. * @return void
138. */
139. public function closeConnection()
140. {
141. if (is_resource($this->_connection)) {
142. oci_close($this->_connection);
143. }
144. $this->_connection = null;
145. }
147. /**
148. * Returns an SQL statement for preparation.
149. *
150. * @param string $sql The SQL statement with placeholders.
151. * @return Doctrine_Statement_Oracle
152. */
153. public function prepare($sql)
154. {
155. $this->_connect();
156. $stmt = new Doctrine_Statement_Oracle($this, $sql);
157. $stmt->setFetchMode($this->_fetchMode);
158. return $stmt;
159. }
161. /**
162. * Quote a raw string.
163. *
164. * @param string $value Raw string
165. * @return string Quoted string
166. */
167. protected function _quote($value)
168. {
169. $value = str_replace("'", "''", $value);
170. return "'" . addcslashes($value, "\000\n\r\\\032") . "'";
171. }
173. /**
174. * Quote a table identifier and alias.
175. *
176. * @param string|array|Doctrine_Expr$ident The identifier or expression.
177. * @param string $alias An alias for the table.
178. * @return string The quoted identifier and alias.
179. */
180. public function quoteTableAs($ident, $alias)
181. {
182. // Oracle doesn't allow the 'AS' keyword between the table identifier/expression and alias.
183. return $this->_quoteIdentifierAs($ident, $alias, ' ');
184. }
185. /**
186. * Leave autocommit mode and begin a transaction.
187. *
188. * @return void
189. */
190. protected function _beginTransaction()
191. {
192. $this->_setExecuteMode(OCI_DEFAULT);
193. }
194. /**
195. * Commit a transaction and return to autocommit mode.
196. *
197. * @return void
198. * @throws Doctrine_Adapter_Oracle_Exception
199. */
200. protected function _commit()
201. {
202. if (!oci_commit($this->_connection)) {
203. throw new Doctrine_Adapter_Oracle_Exception(oci_error($this->_connection));
204. }
205. $this->_setExecuteMode(OCI_COMMIT_ON_SUCCESS);
206. }
207. /**
208. * Roll back a transaction and return to autocommit mode.
209. *
210. * @return void
211. * @throws Doctrine_Adapter_Oracle_Exception
212. */
213. protected function _rollBack()
214. {
215. if (!oci_rollback($this->_connection)) {
216. throw new Doctrine_Adapter_Oracle_Exception(oci_error($this->_connection));
217. }
218. $this->_setExecuteMode(OCI_COMMIT_ON_SUCCESS);
219. }
221. /**
222. * Set the fetch mode.
223. *
224. * @todo Support FETCH_CLASS and FETCH_INTO.
225. *
226. * @param integer $mode A fetch mode.
227. * @return void
228. * @throws Doctrine_Adapter_Exception
229. */
230. public function setFetchMode($mode)
231. {
232. switch ($mode) {
233. case Doctrine::FETCH_NUM: // seq array
234. case Doctrine::FETCH_ASSOC: // assoc array
235. case Doctrine::FETCH_BOTH: // seq+assoc array
236. case Doctrine::FETCH_OBJ: // object
237. $this->_fetchMode = $mode;
238. break;
239. default:
240. throw new Doctrine_Adapter_Exception('Invalid fetch mode specified');
241. break;
242. }
243. }
244. /**
245. * @param integer $mode
246. * @throws Doctrine_Adapter_Exception
247. */
248. private function _setExecuteMode($mode)
249. {
250. switch($mode) {
251. case OCI_COMMIT_ON_SUCCESS:
252. case OCI_DEFAULT:
253. case OCI_DESCRIBE_ONLY:
254. $this->_execute_mode = $mode;
255. break;
256. default:
257. throw new Doctrine_Adapter_Exception('wrong execution mode specified');
258. break;
259. }
260. }
261. /**
262. * @return
263. */
264. public function _getExecuteMode()
265. {
266. return $this->_execute_mode;
267. }
268. }