Subversion-Projekte lars-tiefland.ci

Revision

Revision 2257 | Details | Vergleich mit vorheriger | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
68 lars 1
<?php
2
/**
3
 * CodeIgniter
4
 *
5
 * An open source application development framework for PHP
6
 *
7
 * This content is released under the MIT License (MIT)
8
 *
2414 lars 9
 * Copyright (c) 2014 - 2019, British Columbia Institute of Technology
68 lars 10
 *
11
 * Permission is hereby granted, free of charge, to any person obtaining a copy
12
 * of this software and associated documentation files (the "Software"), to deal
13
 * in the Software without restriction, including without limitation the rights
14
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15
 * copies of the Software, and to permit persons to whom the Software is
16
 * furnished to do so, subject to the following conditions:
17
 *
18
 * The above copyright notice and this permission notice shall be included in
19
 * all copies or substantial portions of the Software.
20
 *
21
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27
 * THE SOFTWARE.
28
 *
29
 * @package	CodeIgniter
30
 * @author	EllisLab Dev Team
31
 * @copyright	Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
2414 lars 32
 * @copyright	Copyright (c) 2014 - 2019, British Columbia Institute of Technology (https://bcit.ca/)
33
 * @license	https://opensource.org/licenses/MIT	MIT License
68 lars 34
 * @link	https://codeigniter.com
35
 * @since	Version 3.0.0
36
 * @filesource
37
 */
38
defined('BASEPATH') OR exit('No direct script access allowed');
39
 
40
/**
41
 * PDO Oracle Database Adapter Class
42
 *
43
 * Note: _DB is an extender class that the app controller
44
 * creates dynamically based on whether the query builder
45
 * class is being used or not.
46
 *
47
 * @package		CodeIgniter
48
 * @subpackage	Drivers
49
 * @category	Database
50
 * @author		EllisLab Dev Team
51
 * @link		https://codeigniter.com/user_guide/database/
52
 */
53
class CI_DB_pdo_oci_driver extends CI_DB_pdo_driver {
54
 
55
	/**
56
	 * Sub-driver
57
	 *
58
	 * @var	string
59
	 */
60
	public $subdriver = 'oci';
61
 
62
	// --------------------------------------------------------------------
63
 
64
	/**
65
	 * List of reserved identifiers
66
	 *
67
	 * Identifiers that must NOT be escaped.
68
	 *
69
	 * @var	string[]
70
	 */
71
	protected $_reserved_identifiers = array('*', 'rownum');
72
 
73
	/**
74
	 * ORDER BY random keyword
75
	 *
76
	 * @var	array
77
	 */
78
	protected $_random_keyword = array('ASC', 'ASC'); // Currently not supported
79
 
80
	/**
81
	 * COUNT string
82
	 *
83
	 * @used-by	CI_DB_driver::count_all()
84
	 * @used-by	CI_DB_query_builder::count_all_results()
85
	 *
86
	 * @var	string
87
	 */
88
	protected $_count_string = 'SELECT COUNT(1) AS ';
89
 
90
	// --------------------------------------------------------------------
91
 
92
	/**
93
	 * Class constructor
94
	 *
95
	 * Builds the DSN if not already set.
96
	 *
97
	 * @param	array	$params
98
	 * @return	void
99
	 */
100
	public function __construct($params)
101
	{
102
		parent::__construct($params);
103
 
104
		if (empty($this->dsn))
105
		{
106
			$this->dsn = 'oci:dbname=';
107
 
108
			// Oracle has a slightly different PDO DSN format (Easy Connect),
109
			// which also supports pre-defined DSNs.
110
			if (empty($this->hostname) && empty($this->port))
111
			{
112
				$this->dsn .= $this->database;
113
			}
114
			else
115
			{
116
				$this->dsn .= '//'.(empty($this->hostname) ? '127.0.0.1' : $this->hostname)
117
					.(empty($this->port) ? '' : ':'.$this->port).'/';
118
 
119
				empty($this->database) OR $this->dsn .= $this->database;
120
			}
121
 
122
			empty($this->char_set) OR $this->dsn .= ';charset='.$this->char_set;
123
		}
124
		elseif ( ! empty($this->char_set) && strpos($this->dsn, 'charset=', 4) === FALSE)
125
		{
126
			$this->dsn .= ';charset='.$this->char_set;
127
		}
128
	}
129
 
130
	// --------------------------------------------------------------------
131
 
132
	/**
133
	 * Database version number
134
	 *
135
	 * @return	string
136
	 */
137
	public function version()
138
	{
139
		if (isset($this->data_cache['version']))
140
		{
141
			return $this->data_cache['version'];
142
		}
143
 
144
		$version_string = parent::version();
145
		if (preg_match('#Release\s(?<version>\d+(?:\.\d+)+)#', $version_string, $match))
146
		{
147
			return $this->data_cache['version'] = $match[1];
148
		}
149
 
150
		return FALSE;
151
	}
152
 
153
	// --------------------------------------------------------------------
154
 
155
	/**
156
	 * Show table query
157
	 *
158
	 * Generates a platform-specific query string so that the table names can be fetched
159
	 *
160
	 * @param	bool	$prefix_limit
161
	 * @return	string
162
	 */
163
	protected function _list_tables($prefix_limit = FALSE)
164
	{
165
		$sql = 'SELECT "TABLE_NAME" FROM "ALL_TABLES"';
166
 
167
		if ($prefix_limit === TRUE && $this->dbprefix !== '')
168
		{
169
			return $sql.' WHERE "TABLE_NAME" LIKE \''.$this->escape_like_str($this->dbprefix)."%' "
170
				.sprintf($this->_like_escape_str, $this->_like_escape_chr);
171
		}
172
 
173
		return $sql;
174
	}
175
 
176
	// --------------------------------------------------------------------
177
 
178
	/**
179
	 * Show column query
180
	 *
181
	 * Generates a platform-specific query string so that the column names can be fetched
182
	 *
183
	 * @param	string	$table
184
	 * @return	string
185
	 */
186
	protected function _list_columns($table = '')
187
	{
188
		if (strpos($table, '.') !== FALSE)
189
		{
190
			sscanf($table, '%[^.].%s', $owner, $table);
191
		}
192
		else
193
		{
194
			$owner = $this->username;
195
		}
196
 
197
		return 'SELECT COLUMN_NAME FROM ALL_TAB_COLUMNS
198
			WHERE UPPER(OWNER) = '.$this->escape(strtoupper($owner)).'
199
				AND UPPER(TABLE_NAME) = '.$this->escape(strtoupper($table));
200
	}
201
 
202
	// --------------------------------------------------------------------
203
 
204
	/**
205
	 * Returns an object with field data
206
	 *
207
	 * @param	string	$table
208
	 * @return	array
209
	 */
210
	public function field_data($table)
211
	{
212
		if (strpos($table, '.') !== FALSE)
213
		{
214
			sscanf($table, '%[^.].%s', $owner, $table);
215
		}
216
		else
217
		{
218
			$owner = $this->username;
219
		}
220
 
221
		$sql = 'SELECT COLUMN_NAME, DATA_TYPE, CHAR_LENGTH, DATA_PRECISION, DATA_LENGTH, DATA_DEFAULT, NULLABLE
222
			FROM ALL_TAB_COLUMNS
223
			WHERE UPPER(OWNER) = '.$this->escape(strtoupper($owner)).'
224
				AND UPPER(TABLE_NAME) = '.$this->escape(strtoupper($table));
225
 
226
		if (($query = $this->query($sql)) === FALSE)
227
		{
228
			return FALSE;
229
		}
230
		$query = $query->result_object();
231
 
232
		$retval = array();
233
		for ($i = 0, $c = count($query); $i < $c; $i++)
234
		{
235
			$retval[$i]			= new stdClass();
236
			$retval[$i]->name		= $query[$i]->COLUMN_NAME;
237
			$retval[$i]->type		= $query[$i]->DATA_TYPE;
238
 
239
			$length = ($query[$i]->CHAR_LENGTH > 0)
240
				? $query[$i]->CHAR_LENGTH : $query[$i]->DATA_PRECISION;
241
			if ($length === NULL)
242
			{
243
				$length = $query[$i]->DATA_LENGTH;
244
			}
245
			$retval[$i]->max_length		= $length;
246
 
247
			$default = $query[$i]->DATA_DEFAULT;
248
			if ($default === NULL && $query[$i]->NULLABLE === 'N')
249
			{
250
				$default = '';
251
			}
252
			$retval[$i]->default		= $query[$i]->COLUMN_DEFAULT;
253
		}
254
 
255
		return $retval;
256
	}
257
 
258
	// --------------------------------------------------------------------
259
 
260
	/**
261
	 * Insert batch statement
262
	 *
263
	 * @param	string	$table	Table name
264
	 * @param	array	$keys	INSERT keys
265
	 * @param	array	$values	INSERT values
266
	 * @return 	string
267
	 */
268
	protected function _insert_batch($table, $keys, $values)
269
	{
270
		$keys = implode(', ', $keys);
271
		$sql = "INSERT ALL\n";
272
 
273
		for ($i = 0, $c = count($values); $i < $c; $i++)
274
		{
275
			$sql .= '	INTO '.$table.' ('.$keys.') VALUES '.$values[$i]."\n";
276
		}
277
 
278
		return $sql.'SELECT * FROM dual';
279
	}
280
 
281
	// --------------------------------------------------------------------
282
 
283
	/**
284
	 * Delete statement
285
	 *
286
	 * Generates a platform-specific delete string from the supplied data
287
	 *
288
	 * @param	string	$table
289
	 * @return	string
290
	 */
291
	protected function _delete($table)
292
	{
293
		if ($this->qb_limit)
294
		{
295
			$this->where('rownum <= ',$this->qb_limit, FALSE);
296
			$this->qb_limit = FALSE;
297
		}
298
 
299
		return parent::_delete($table);
300
	}
301
 
302
	// --------------------------------------------------------------------
303
 
304
	/**
305
	 * LIMIT
306
	 *
307
	 * Generates a platform-specific LIMIT clause
308
	 *
309
	 * @param	string	$sql	SQL Query
310
	 * @return	string
311
	 */
312
	protected function _limit($sql)
313
	{
314
		if (version_compare($this->version(), '12.1', '>='))
315
		{
316
			// OFFSET-FETCH can be used only with the ORDER BY clause
317
			empty($this->qb_orderby) && $sql .= ' ORDER BY 1';
318
 
319
			return $sql.' OFFSET '.(int) $this->qb_offset.' ROWS FETCH NEXT '.$this->qb_limit.' ROWS ONLY';
320
		}
321
 
322
		return 'SELECT * FROM (SELECT inner_query.*, rownum rnum FROM ('.$sql.') inner_query WHERE rownum < '.($this->qb_offset + $this->qb_limit + 1).')'
323
			.($this->qb_offset ? ' WHERE rnum >= '.($this->qb_offset + 1): '');
324
	}
325
 
326
}