GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

CI_DB_forge::_process_fields()   F
last analyzed

Complexity

Conditions 23
Paths 4483

Size

Total Lines 94
Code Lines 51

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 23
eloc 51
nc 4483
nop 1
dl 0
loc 94
rs 2
c 1
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
0 ignored issues
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 47 and the first side effect is on line 38.

The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.

The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.

To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.

Loading history...
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
 *
9
 * Copyright (c) 2014 - 2015, British Columbia Institute of Technology
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. (http://ellislab.com/)
32
 * @copyright	Copyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/)
33
 * @license	http://opensource.org/licenses/MIT	MIT License
34
 * @link	http://codeigniter.com
35
 * @since	Version 1.0.0
36
 * @filesource
37
 */
38
defined('BASEPATH') OR exit('No direct script access allowed');
39
40
/**
41
 * Database Forge Class
42
 *
43
 * @category	Database
44
 * @author		EllisLab Dev Team
45
 * @link		http://codeigniter.com/user_guide/database/
46
 */
47
abstract class CI_DB_forge {
48
49
	/**
50
	 * Database object
51
	 *
52
	 * @var	object
53
	 */
54
	protected $db;
55
56
	/**
57
	 * Fields data
58
	 *
59
	 * @var	array
60
	 */
61
	public $fields		= array();
62
63
	/**
64
	 * Keys data
65
	 *
66
	 * @var	array
67
	 */
68
	public $keys		= array();
69
70
	/**
71
	 * Primary Keys data
72
	 *
73
	 * @var	array
74
	 */
75
	public $primary_keys	= array();
76
77
	/**
78
	 * Database character set
79
	 *
80
	 * @var	string
81
	 */
82
	public $db_char_set	= '';
83
84
	// --------------------------------------------------------------------
85
86
	/**
87
	 * CREATE DATABASE statement
88
	 *
89
	 * @var	string
90
	 */
91
	protected $_create_database	= 'CREATE DATABASE %s';
92
93
	/**
94
	 * DROP DATABASE statement
95
	 *
96
	 * @var	string
97
	 */
98
	protected $_drop_database	= 'DROP DATABASE %s';
99
100
	/**
101
	 * CREATE TABLE statement
102
	 *
103
	 * @var	string
104
	 */
105
	protected $_create_table	= "%s %s (%s\n)";
106
107
	/**
108
	 * CREATE TABLE IF statement
109
	 *
110
	 * @var	string
111
	 */
112
	protected $_create_table_if	= 'CREATE TABLE IF NOT EXISTS';
113
114
	/**
115
	 * CREATE TABLE keys flag
116
	 *
117
	 * Whether table keys are created from within the
118
	 * CREATE TABLE statement.
119
	 *
120
	 * @var	bool
121
	 */
122
	protected $_create_table_keys	= FALSE;
123
124
	/**
125
	 * DROP TABLE IF EXISTS statement
126
	 *
127
	 * @var	string
128
	 */
129
	protected $_drop_table_if	= 'DROP TABLE IF EXISTS';
130
131
	/**
132
	 * RENAME TABLE statement
133
	 *
134
	 * @var	string
135
	 */
136
	protected $_rename_table	= 'ALTER TABLE %s RENAME TO %s;';
137
138
	/**
139
	 * UNSIGNED support
140
	 *
141
	 * @var	bool|array
142
	 */
143
	protected $_unsigned		= TRUE;
144
145
	/**
146
	 * NULL value representation in CREATE/ALTER TABLE statements
147
	 *
148
	 * @var	string
149
	 */
150
	protected $_null		= '';
151
152
	/**
153
	 * DEFAULT value representation in CREATE/ALTER TABLE statements
154
	 *
155
	 * @var	string
156
	 */
157
	protected $_default		= ' DEFAULT ';
158
159
	// --------------------------------------------------------------------
160
161
	/**
162
	 * Class constructor
163
	 *
164
	 * @param	object	&$db	Database object
165
	 * @return	void
166
	 */
167
	public function __construct(&$db)
168
	{
169
		$this->db =& $db;
170
		log_message('info', 'Database Forge Class Initialized');
171
	}
172
173
	// --------------------------------------------------------------------
174
175
	/**
176
	 * Create database
177
	 *
178
	 * @param	string	$db_name
179
	 * @return	bool
180
	 */
181
	public function create_database($db_name)
182
	{
183
		if ($this->_create_database === FALSE)
184
		{
185
			return ($this->db->db_debug) ? $this->db->display_error('db_unsupported_feature') : FALSE;
186
		}
187
		elseif ( ! $this->db->query(sprintf($this->_create_database, $db_name, $this->db->char_set, $this->db->dbcollat)))
188
		{
189
			return ($this->db->db_debug) ? $this->db->display_error('db_unable_to_drop') : FALSE;
190
		}
191
192
		if ( ! empty($this->db->data_cache['db_names']))
193
		{
194
			$this->db->data_cache['db_names'][] = $db_name;
195
		}
196
197
		return TRUE;
198
	}
199
200
	// --------------------------------------------------------------------
201
202
	/**
203
	 * Drop database
204
	 *
205
	 * @param	string	$db_name
206
	 * @return	bool
207
	 */
208
	public function drop_database($db_name)
209
	{
210
		if ($this->_drop_database === FALSE)
211
		{
212
			return ($this->db->db_debug) ? $this->db->display_error('db_unsupported_feature') : FALSE;
213
		}
214
		elseif ( ! $this->db->query(sprintf($this->_drop_database, $db_name)))
215
		{
216
			return ($this->db->db_debug) ? $this->db->display_error('db_unable_to_drop') : FALSE;
217
		}
218
219
		if ( ! empty($this->db->data_cache['db_names']))
220
		{
221
			$key = array_search(strtolower($db_name), array_map('strtolower', $this->db->data_cache['db_names']), TRUE);
222
			if ($key !== FALSE)
223
			{
224
				unset($this->db->data_cache['db_names'][$key]);
225
			}
226
		}
227
228
		return TRUE;
229
	}
230
231
	// --------------------------------------------------------------------
232
233
	/**
234
	 * Add Key
235
	 *
236
	 * @param	string	$key
237
	 * @param	bool	$primary
238
	 * @return	CI_DB_forge
239
	 */
240
	public function add_key($key, $primary = FALSE)
241
	{
242
		// DO NOT change this! This condition is only applicable
243
		// for PRIMARY keys because you can only have one such,
244
		// and therefore all fields you add to it will be included
245
		// in the same, composite PRIMARY KEY.
246
		//
247
		// It's not the same for regular indexes.
248
		if ($primary === TRUE && is_array($key))
249
		{
250
			foreach ($key as $one)
251
			{
252
				$this->add_key($one, $primary);
253
			}
254
255
			return $this;
256
		}
257
258
		if ($primary === TRUE)
259
		{
260
			$this->primary_keys[] = $key;
261
		}
262
		else
263
		{
264
			$this->keys[] = $key;
265
		}
266
267
		return $this;
268
	}
269
270
	// --------------------------------------------------------------------
271
272
	/**
273
	 * Add Field
274
	 *
275
	 * @param	array	$field
276
	 * @return	CI_DB_forge
277
	 */
278
	public function add_field($field)
279
	{
280
		if (is_string($field))
281
		{
282
			if ($field === 'id')
283
			{
284
				$this->add_field(array(
285
					'id' => array(
286
						'type' => 'INT',
287
						'constraint' => 9,
288
						'auto_increment' => TRUE
289
					)
290
				));
291
				$this->add_key('id', TRUE);
292
			}
293
			else
294
			{
295
				if (strpos($field, ' ') === FALSE)
296
				{
297
					show_error('Field information is required for that operation.');
298
				}
299
300
				$this->fields[] = $field;
301
			}
302
		}
303
304
		if (is_array($field))
305
		{
306
			$this->fields = array_merge($this->fields, $field);
307
		}
308
309
		return $this;
310
	}
311
312
	// --------------------------------------------------------------------
313
314
	/**
315
	 * Create Table
316
	 *
317
	 * @param	string	$table		Table name
318
	 * @param	bool	$if_not_exists	Whether to add IF NOT EXISTS condition
319
	 * @param	array	$attributes	Associative array of table attributes
320
	 * @return	bool
321
	 */
322
	public function create_table($table, $if_not_exists = FALSE, array $attributes = array())
323
	{
324
		if ($table === '')
325
		{
326
			show_error('A table name is required for that operation.');
327
		}
328
		else
329
		{
330
			$table = $this->db->dbprefix.$table;
331
		}
332
333
		if (count($this->fields) === 0)
334
		{
335
			show_error('Field information is required.');
336
		}
337
338
		$sql = $this->_create_table($table, $if_not_exists, $attributes);
339
340
		if (is_bool($sql))
341
		{
342
			$this->_reset();
343
			if ($sql === FALSE)
344
			{
345
				return ($this->db->db_debug) ? $this->db->display_error('db_unsupported_feature') : FALSE;
346
			}
347
		}
348
349
		if (($result = $this->db->query($sql)) !== FALSE)
350
		{
351
			empty($this->db->data_cache['table_names']) OR $this->db->data_cache['table_names'][] = $table;
352
353
			// Most databases don't support creating indexes from within the CREATE TABLE statement
354
			if ( ! empty($this->keys))
355
			{
356
				for ($i = 0, $sqls = $this->_process_indexes($table), $c = count($sqls); $i < $c; $i++)
357
				{
358
					$this->db->query($sqls[$i]);
359
				}
360
			}
361
		}
362
363
		$this->_reset();
364
		return $result;
365
	}
366
367
	// --------------------------------------------------------------------
368
369
	/**
370
	 * Create Table
371
	 *
372
	 * @param	string	$table		Table name
373
	 * @param	bool	$if_not_exists	Whether to add 'IF NOT EXISTS' condition
374
	 * @param	array	$attributes	Associative array of table attributes
375
	 * @return	mixed
376
	 */
377
	protected function _create_table($table, $if_not_exists, $attributes)
378
	{
379
		if ($if_not_exists === TRUE && $this->_create_table_if === FALSE)
380
		{
381
			if ($this->db->table_exists($table))
382
			{
383
				return TRUE;
384
			}
385
			else
386
			{
387
				$if_not_exists = FALSE;
388
			}
389
		}
390
391
		$sql = ($if_not_exists)
392
			? sprintf($this->_create_table_if, $this->db->escape_identifiers($table))
393
			: 'CREATE TABLE';
394
395
		$columns = $this->_process_fields(TRUE);
396
		for ($i = 0, $c = count($columns); $i < $c; $i++)
397
		{
398
			$columns[$i] = ($columns[$i]['_literal'] !== FALSE)
399
					? "\n\t".$columns[$i]['_literal']
400
					: "\n\t".$this->_process_column($columns[$i]);
401
		}
402
403
		$columns = implode(',', $columns)
404
				.$this->_process_primary_keys($table);
405
406
		// Are indexes created from within the CREATE TABLE statement? (e.g. in MySQL)
407
		if ($this->_create_table_keys === TRUE)
408
		{
409
			$columns .= $this->_process_indexes($table);
410
		}
411
412
		// _create_table will usually have the following format: "%s %s (%s\n)"
413
		$sql = sprintf($this->_create_table.'%s',
414
			$sql,
415
			$this->db->escape_identifiers($table),
416
			$columns,
417
			$this->_create_table_attr($attributes)
418
		);
419
420
		return $sql;
421
	}
422
423
	// --------------------------------------------------------------------
424
425
	/**
426
	 * CREATE TABLE attributes
427
	 *
428
	 * @param	array	$attributes	Associative array of table attributes
429
	 * @return	string
430
	 */
431
	protected function _create_table_attr($attributes)
432
	{
433
		$sql = '';
434
435
		foreach (array_keys($attributes) as $key)
436
		{
437
			if (is_string($key))
438
			{
439
				$sql .= ' '.strtoupper($key).' '.$attributes[$key];
440
			}
441
		}
442
443
		return $sql;
444
	}
445
446
	// --------------------------------------------------------------------
447
448
	/**
449
	 * Drop Table
450
	 *
451
	 * @param	string	$table_name	Table name
452
	 * @param	bool	$if_exists	Whether to add an IF EXISTS condition
453
	 * @return	bool
454
	 */
455
	public function drop_table($table_name, $if_exists = FALSE)
456
	{
457
		if ($table_name === '')
458
		{
459
			return ($this->db->db_debug) ? $this->db->display_error('db_table_name_required') : FALSE;
460
		}
461
462
		if (($query = $this->_drop_table($this->db->dbprefix.$table_name, $if_exists)) === TRUE)
463
		{
464
			return TRUE;
465
		}
466
467
		$query = $this->db->query($query);
468
469
		// Update table list cache
470 View Code Duplication
		if ($query && ! empty($this->db->data_cache['table_names']))
471
		{
472
			$key = array_search(strtolower($this->db->dbprefix.$table_name), array_map('strtolower', $this->db->data_cache['table_names']), TRUE);
473
			if ($key !== FALSE)
474
			{
475
				unset($this->db->data_cache['table_names'][$key]);
476
			}
477
		}
478
479
		return $query;
480
	}
481
482
	// --------------------------------------------------------------------
483
484
	/**
485
	 * Drop Table
486
	 *
487
	 * Generates a platform-specific DROP TABLE string
488
	 *
489
	 * @param	string	$table		Table name
490
	 * @param	bool	$if_exists	Whether to add an IF EXISTS condition
491
	 * @return	string
492
	 */
493
	protected function _drop_table($table, $if_exists)
494
	{
495
		$sql = 'DROP TABLE';
496
497
		if ($if_exists)
498
		{
499
			if ($this->_drop_table_if === FALSE)
500
			{
501
				if ( ! $this->db->table_exists($table))
502
				{
503
					return TRUE;
504
				}
505
			}
506
			else
507
			{
508
				$sql = sprintf($this->_drop_table_if, $this->db->escape_identifiers($table));
509
			}
510
		}
511
512
		return $sql.' '.$this->db->escape_identifiers($table);
513
	}
514
515
	// --------------------------------------------------------------------
516
517
	/**
518
	 * Rename Table
519
	 *
520
	 * @param	string	$table_name	Old table name
521
	 * @param	string	$new_table_name	New table name
522
	 * @return	bool
523
	 */
524
	public function rename_table($table_name, $new_table_name)
525
	{
526
		if ($table_name === '' OR $new_table_name === '')
527
		{
528
			show_error('A table name is required for that operation.');
529
			return FALSE;
530
		}
531
		elseif ($this->_rename_table === FALSE)
532
		{
533
			return ($this->db->db_debug) ? $this->db->display_error('db_unsupported_feature') : FALSE;
534
		}
535
536
		$result = $this->db->query(sprintf($this->_rename_table,
537
						$this->db->escape_identifiers($this->db->dbprefix.$table_name),
538
						$this->db->escape_identifiers($this->db->dbprefix.$new_table_name))
539
					);
540
541 View Code Duplication
		if ($result && ! empty($this->db->data_cache['table_names']))
542
		{
543
			$key = array_search(strtolower($this->db->dbprefix.$table_name), array_map('strtolower', $this->db->data_cache['table_names']), TRUE);
544
			if ($key !== FALSE)
545
			{
546
				$this->db->data_cache['table_names'][$key] = $this->db->dbprefix.$new_table_name;
547
			}
548
		}
549
550
		return $result;
551
	}
552
553
	// --------------------------------------------------------------------
554
555
	/**
556
	 * Column Add
557
	 *
558
	 * @todo	Remove deprecated $_after option in 3.1+
559
	 * @param	string	$table	Table name
560
	 * @param	array	$field	Column definition
561
	 * @param	string	$_after	Column for AFTER clause (deprecated)
562
	 * @return	bool
563
	 */
564
	public function add_column($table, $field, $_after = NULL)
565
	{
566
		// Work-around for literal column definitions
567
		is_array($field) OR $field = array($field);
568
569
		foreach (array_keys($field) as $k)
570
		{
571
			// Backwards-compatibility work-around for MySQL/CUBRID AFTER clause (remove in 3.1+)
572
			if ($_after !== NULL && is_array($field[$k]) && ! isset($field[$k]['after']))
573
			{
574
				$field[$k]['after'] = $_after;
575
			}
576
577
			$this->add_field(array($k => $field[$k]));
578
		}
579
580
		$sqls = $this->_alter_table('ADD', $this->db->dbprefix.$table, $this->_process_fields());
581
		$this->_reset();
582
		if ($sqls === FALSE)
583
		{
584
			return ($this->db->db_debug) ? $this->db->display_error('db_unsupported_feature') : FALSE;
585
		}
586
587 View Code Duplication
		for ($i = 0, $c = count($sqls); $i < $c; $i++)
588
		{
589
			if ($this->db->query($sqls[$i]) === FALSE)
590
			{
591
				return FALSE;
592
			}
593
		}
594
595
		return TRUE;
596
	}
597
598
	// --------------------------------------------------------------------
599
600
	/**
601
	 * Column Drop
602
	 *
603
	 * @param	string	$table		Table name
604
	 * @param	string	$column_name	Column name
605
	 * @return	bool
606
	 */
607
	public function drop_column($table, $column_name)
608
	{
609
		$sql = $this->_alter_table('DROP', $this->db->dbprefix.$table, $column_name);
610
		if ($sql === FALSE)
611
		{
612
			return ($this->db->db_debug) ? $this->db->display_error('db_unsupported_feature') : FALSE;
613
		}
614
615
		return $this->db->query($sql);
616
	}
617
618
	// --------------------------------------------------------------------
619
620
	/**
621
	 * Column Modify
622
	 *
623
	 * @param	string	$table	Table name
624
	 * @param	string	$field	Column definition
625
	 * @return	bool
626
	 */
627
	public function modify_column($table, $field)
628
	{
629
		// Work-around for literal column definitions
630
		is_array($field) OR $field = array($field);
631
632
		foreach (array_keys($field) as $k)
633
		{
634
			$this->add_field(array($k => $field[$k]));
635
		}
636
637
		if (count($this->fields) === 0)
638
		{
639
			show_error('Field information is required.');
640
		}
641
642
		$sqls = $this->_alter_table('CHANGE', $this->db->dbprefix.$table, $this->_process_fields());
643
		$this->_reset();
644
		if ($sqls === FALSE)
645
		{
646
			return ($this->db->db_debug) ? $this->db->display_error('db_unsupported_feature') : FALSE;
647
		}
648
649 View Code Duplication
		for ($i = 0, $c = count($sqls); $i < $c; $i++)
650
		{
651
			if ($this->db->query($sqls[$i]) === FALSE)
652
			{
653
				return FALSE;
654
			}
655
		}
656
657
		return TRUE;
658
	}
659
660
	// --------------------------------------------------------------------
661
662
	/**
663
	 * ALTER TABLE
664
	 *
665
	 * @param	string	$alter_type	ALTER type
666
	 * @param	string	$table		Table name
667
	 * @param	mixed	$field		Column definition
668
	 * @return	string|string[]
669
	 */
670
	protected function _alter_table($alter_type, $table, $field)
671
	{
672
		$sql = 'ALTER TABLE '.$this->db->escape_identifiers($table).' ';
673
674
		// DROP has everything it needs now.
675
		if ($alter_type === 'DROP')
676
		{
677
			return $sql.'DROP COLUMN '.$this->db->escape_identifiers($field);
678
		}
679
680
		$sql .= ($alter_type === 'ADD')
681
			? 'ADD '
682
			: $alter_type.' COLUMN ';
683
684
		$sqls = array();
685
		for ($i = 0, $c = count($field); $i < $c; $i++)
686
		{
687
			$sqls[] = $sql
688
				.($field[$i]['_literal'] !== FALSE ? $field[$i]['_literal'] : $this->_process_column($field[$i]));
689
		}
690
691
		return $sqls;
692
	}
693
694
	// --------------------------------------------------------------------
695
696
	/**
697
	 * Process fields
698
	 *
699
	 * @param	bool	$create_table
700
	 * @return	array
701
	 */
702
	protected function _process_fields($create_table = FALSE)
703
	{
704
		$fields = array();
705
706
		foreach ($this->fields as $key => $attributes)
707
		{
708
			if (is_int($key) && ! is_array($attributes))
709
			{
710
				$fields[] = array('_literal' => $attributes);
711
				continue;
712
			}
713
714
			$attributes = array_change_key_case($attributes, CASE_UPPER);
715
716
			if ($create_table === TRUE && empty($attributes['TYPE']))
717
			{
718
				continue;
719
			}
720
721
			isset($attributes['TYPE']) && $this->_attr_type($attributes);
722
723
			$field = array(
724
				'name'			=> $key,
725
				'new_name'		=> isset($attributes['NAME']) ? $attributes['NAME'] : NULL,
726
				'type'			=> isset($attributes['TYPE']) ? $attributes['TYPE'] : NULL,
727
				'length'		=> '',
728
				'unsigned'		=> '',
729
				'null'			=> '',
730
				'unique'		=> '',
731
				'default'		=> '',
732
				'auto_increment'	=> '',
733
				'_literal'		=> FALSE
734
			);
735
736
			isset($attributes['TYPE']) && $this->_attr_unsigned($attributes, $field);
737
738
			if ($create_table === FALSE)
739
			{
740
				if (isset($attributes['AFTER']))
741
				{
742
					$field['after'] = $attributes['AFTER'];
743
				}
744
				elseif (isset($attributes['FIRST']))
745
				{
746
					$field['first'] = (bool) $attributes['FIRST'];
747
				}
748
			}
749
750
			$this->_attr_default($attributes, $field);
751
752
			if (isset($attributes['NULL']))
753
			{
754
				if ($attributes['NULL'] === TRUE)
755
				{
756
					$field['null'] = empty($this->_null) ? '' : ' '.$this->_null;
757
				}
758
				else
759
				{
760
					$field['null'] = ' NOT NULL';
761
				}
762
			}
763
			elseif ($create_table === TRUE)
764
			{
765
				$field['null'] = ' NOT NULL';
766
			}
767
768
			$this->_attr_auto_increment($attributes, $field);
769
			$this->_attr_unique($attributes, $field);
770
771
			if (isset($attributes['COMMENT']))
772
			{
773
				$field['comment'] = $this->db->escape($attributes['COMMENT']);
774
			}
775
776
			if (isset($attributes['TYPE']) && ! empty($attributes['CONSTRAINT']))
777
			{
778
				switch (strtoupper($attributes['TYPE']))
779
				{
780
					case 'ENUM':
781
					case 'SET':
782
						$attributes['CONSTRAINT'] = $this->db->escape($attributes['CONSTRAINT']);
783
					default:
784
						$field['length'] = is_array($attributes['CONSTRAINT'])
785
							? '('.implode(',', $attributes['CONSTRAINT']).')'
786
							: '('.$attributes['CONSTRAINT'].')';
787
						break;
788
				}
789
			}
790
791
			$fields[] = $field;
792
		}
793
794
		return $fields;
795
	}
796
797
	// --------------------------------------------------------------------
798
799
	/**
800
	 * Process column
801
	 *
802
	 * @param	array	$field
803
	 * @return	string
804
	 */
805
	protected function _process_column($field)
806
	{
807
		return $this->db->escape_identifiers($field['name'])
808
			.' '.$field['type'].$field['length']
809
			.$field['unsigned']
810
			.$field['default']
811
			.$field['null']
812
			.$field['auto_increment']
813
			.$field['unique'];
814
	}
815
816
	// --------------------------------------------------------------------
817
818
	/**
819
	 * Field attribute TYPE
820
	 *
821
	 * Performs a data type mapping between different databases.
822
	 *
823
	 * @param	array	&$attributes
824
	 * @return	void
825
	 */
826
	protected function _attr_type(&$attributes)
827
	{
828
		// Usually overridden by drivers
829
	}
830
831
	// --------------------------------------------------------------------
832
833
	/**
834
	 * Field attribute UNSIGNED
835
	 *
836
	 * Depending on the _unsigned property value:
837
	 *
838
	 *	- TRUE will always set $field['unsigned'] to 'UNSIGNED'
839
	 *	- FALSE will always set $field['unsigned'] to ''
840
	 *	- array(TYPE) will set $field['unsigned'] to 'UNSIGNED',
841
	 *		if $attributes['TYPE'] is found in the array
842
	 *	- array(TYPE => UTYPE) will change $field['type'],
843
	 *		from TYPE to UTYPE in case of a match
844
	 *
845
	 * @param	array	&$attributes
846
	 * @param	array	&$field
847
	 * @return	void
848
	 */
849
	protected function _attr_unsigned(&$attributes, &$field)
850
	{
851
		if (empty($attributes['UNSIGNED']) OR $attributes['UNSIGNED'] !== TRUE)
852
		{
853
			return;
854
		}
855
856
		// Reset the attribute in order to avoid issues if we do type conversion
857
		$attributes['UNSIGNED'] = FALSE;
858
859
		if (is_array($this->_unsigned))
860
		{
861
			foreach (array_keys($this->_unsigned) as $key)
862
			{
863
				if (is_int($key) && strcasecmp($attributes['TYPE'], $this->_unsigned[$key]) === 0)
864
				{
865
					$field['unsigned'] = ' UNSIGNED';
866
					return;
867
				}
868
				elseif (is_string($key) && strcasecmp($attributes['TYPE'], $key) === 0)
869
				{
870
					$field['type'] = $key;
871
					return;
872
				}
873
			}
874
875
			return;
876
		}
877
878
		$field['unsigned'] = ($this->_unsigned === TRUE) ? ' UNSIGNED' : '';
879
	}
880
881
	// --------------------------------------------------------------------
882
883
	/**
884
	 * Field attribute DEFAULT
885
	 *
886
	 * @param	array	&$attributes
887
	 * @param	array	&$field
888
	 * @return	void
889
	 */
890
	protected function _attr_default(&$attributes, &$field)
891
	{
892
		if ($this->_default === FALSE)
893
		{
894
			return;
895
		}
896
897
		if (array_key_exists('DEFAULT', $attributes))
898
		{
899
			if ($attributes['DEFAULT'] === NULL)
900
			{
901
				$field['default'] = empty($this->_null) ? '' : $this->_default.$this->_null;
902
903
				// Override the NULL attribute if that's our default
904
				$attributes['NULL'] = TRUE;
905
				$field['null'] = empty($this->_null) ? '' : ' '.$this->_null;
906
			}
907
			else
908
			{
909
				$field['default'] = $this->_default.$this->db->escape($attributes['DEFAULT']);
910
			}
911
		}
912
	}
913
914
	// --------------------------------------------------------------------
915
916
	/**
917
	 * Field attribute UNIQUE
918
	 *
919
	 * @param	array	&$attributes
920
	 * @param	array	&$field
921
	 * @return	void
922
	 */
923
	protected function _attr_unique(&$attributes, &$field)
924
	{
925
		if ( ! empty($attributes['UNIQUE']) && $attributes['UNIQUE'] === TRUE)
926
		{
927
			$field['unique'] = ' UNIQUE';
928
		}
929
	}
930
931
	// --------------------------------------------------------------------
932
933
	/**
934
	 * Field attribute AUTO_INCREMENT
935
	 *
936
	 * @param	array	&$attributes
937
	 * @param	array	&$field
938
	 * @return	void
939
	 */
940
	protected function _attr_auto_increment(&$attributes, &$field)
941
	{
942
		if ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE && stripos($field['type'], 'int') !== FALSE)
943
		{
944
			$field['auto_increment'] = ' AUTO_INCREMENT';
945
		}
946
	}
947
948
	// --------------------------------------------------------------------
949
950
	/**
951
	 * Process primary keys
952
	 *
953
	 * @param	string	$table	Table name
954
	 * @return	string
955
	 */
956
	protected function _process_primary_keys($table)
957
	{
958
		$sql = '';
959
960
		for ($i = 0, $c = count($this->primary_keys); $i < $c; $i++)
961
		{
962
			if ( ! isset($this->fields[$this->primary_keys[$i]]))
963
			{
964
				unset($this->primary_keys[$i]);
965
			}
966
		}
967
968
		if (count($this->primary_keys) > 0)
969
		{
970
			$sql .= ",\n\tCONSTRAINT ".$this->db->escape_identifiers('pk_'.$table)
971
				.' PRIMARY KEY('.implode(', ', $this->db->escape_identifiers($this->primary_keys)).')';
972
		}
973
974
		return $sql;
975
	}
976
977
	// --------------------------------------------------------------------
978
979
	/**
980
	 * Process indexes
981
	 *
982
	 * @param	string	$table
983
	 * @return	string
984
	 */
985
	protected function _process_indexes($table)
986
	{
987
		$sqls = array();
988
989
		for ($i = 0, $c = count($this->keys); $i < $c; $i++)
990
		{
991
			if (is_array($this->keys[$i]))
992
			{
993
				for ($i2 = 0, $c2 = count($this->keys[$i]); $i2 < $c2; $i2++)
994
				{
995
					if ( ! isset($this->fields[$this->keys[$i][$i2]]))
996
					{
997
						unset($this->keys[$i][$i2]);
998
						continue;
999
					}
1000
				}
1001
			}
1002
			elseif ( ! isset($this->fields[$this->keys[$i]]))
1003
			{
1004
				unset($this->keys[$i]);
1005
				continue;
1006
			}
1007
1008
			is_array($this->keys[$i]) OR $this->keys[$i] = array($this->keys[$i]);
1009
1010
			$sqls[] = 'CREATE INDEX '.$this->db->escape_identifiers($table.'_'.implode('_', $this->keys[$i]))
1011
				.' ON '.$this->db->escape_identifiers($table)
1012
				.' ('.implode(', ', $this->db->escape_identifiers($this->keys[$i])).');';
1013
		}
1014
1015
		return $sqls;
1016
	}
1017
1018
	// --------------------------------------------------------------------
1019
1020
	/**
1021
	 * Reset
1022
	 *
1023
	 * Resets table creation vars
1024
	 *
1025
	 * @return	void
1026
	 */
1027
	protected function _reset()
1028
	{
1029
		$this->fields = $this->keys = $this->primary_keys = array();
1030
	}
1031
1032
}
1033