Skip to content
Newer
Older
100644 923 lines (845 sloc) 32.8 KB
e704cd0 Continued refactorings. Started to refactor the DBAL layer.
romanb authored
1 <?php
d8b76a5 continued refactorings.
romanb authored
2 /*
3 * $Id$
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
705199e [2.0] Parser work. Added support for functions in SelectExpressions.
romanb authored
19 * <http://www.doctrine-project.org>.
d8b76a5 continued refactorings.
romanb authored
20 */
e704cd0 Continued refactorings. Started to refactor the DBAL layer.
romanb authored
21
22e94ac Enabling namespaces. Final restructurings.
romanb authored
22 namespace Doctrine\DBAL\Platforms;
4d7b883 Intermediate checkin. Refactoring towards namespaced structure.
romanb authored
23
7479a0c [2.0] Starting to improve functional tests. First basic functional qu…
romanb authored
24 use Doctrine\Common\DoctrineException;
25
e704cd0 Continued refactorings. Started to refactor the DBAL layer.
romanb authored
26 /**
27 * The MySqlPlatform provides the behavior, features and SQL dialect of the
28 * MySQL database platform.
29 *
30 * @since 2.0
31 * @author Roman Borschel <roman@code-factory.org>
32 */
22e94ac Enabling namespaces. Final restructurings.
romanb authored
33 class MySqlPlatform extends AbstractPlatform
7479a0c [2.0] Starting to improve functional tests. First basic functional qu…
romanb authored
34 {
e704cd0 Continued refactorings. Started to refactor the DBAL layer.
romanb authored
35 /**
3cd4fc5 Intermediate checkin.
romanb authored
36 * Creates a new MySqlPlatform instance.
e704cd0 Continued refactorings. Started to refactor the DBAL layer.
romanb authored
37 */
38 public function __construct()
39 {
3cd4fc5 Intermediate checkin.
romanb authored
40 parent::__construct();
41 }
42
43 /**
44 * Gets the character used for identifier quoting.
45 *
46 * @return string
47 * @override
48 */
49 public function getIdentifierQuoteCharacter()
50 {
51 return '`';
e704cd0 Continued refactorings. Started to refactor the DBAL layer.
romanb authored
52 }
53
54 /**
3cd4fc5 Intermediate checkin.
romanb authored
55 * Returns the regular expression operator.
e704cd0 Continued refactorings. Started to refactor the DBAL layer.
romanb authored
56 *
57 * @return string
58 * @override
59 */
60 public function getRegexpExpression()
61 {
62 return 'RLIKE';
63 }
64
65 /**
66 * return string to call a function to get random value inside an SQL statement
67 *
68 * @return string to generate float between 0 and 1
69 */
70 public function getRandomExpression()
71 {
72 return 'RAND()';
73 }
74
75 /**
76 * Builds a pattern matching string.
77 *
78 * EXPERIMENTAL
79 *
80 * WARNING: this function is experimental and may change signature at
81 * any time until labelled as non-experimental.
82 *
83 * @param array $pattern even keys are strings, odd are patterns (% and _)
84 * @param string $operator optional pattern operator (LIKE, ILIKE and maybe others in the future)
85 * @param string $field optional field name that is being matched against
86 * (might be required when emulating ILIKE)
87 *
88 * @return string SQL pattern
89 * @override
90 */
91 public function getMatchPatternExpression($pattern, $operator = null, $field = null)
92 {
93 $match = '';
94 if ( ! is_null($operator)) {
95 $field = is_null($field) ? '' : $field.' ';
96 $operator = strtoupper($operator);
97 switch ($operator) {
98 // case insensitive
99 case 'ILIKE':
100 $match = $field.'LIKE ';
101 break;
102 // case sensitive
103 case 'LIKE':
104 $match = $field.'LIKE BINARY ';
105 break;
106 default:
705199e [2.0] Parser work. Added support for functions in SelectExpressions.
romanb authored
107 throw DoctrineException::updateMe('not a supported operator type:'. $operator);
e704cd0 Continued refactorings. Started to refactor the DBAL layer.
romanb authored
108 }
109 }
110 $match.= "'";
111 foreach ($pattern as $key => $value) {
112 if ($key % 2) {
113 $match .= $value;
114 } else {
115 $match .= $this->conn->escapePattern($this->conn->escape($value));
116 }
117 }
118 $match.= "'";
119 $match.= $this->patternEscapeString();
3cd4fc5 Intermediate checkin.
romanb authored
120
e704cd0 Continued refactorings. Started to refactor the DBAL layer.
romanb authored
121 return $match;
122 }
123
124 /**
125 * Returns global unique identifier
126 *
127 * @return string to get global unique identifier
128 * @override
129 */
130 public function getGuidExpression()
131 {
132 return 'UUID()';
133 }
134
135 /**
136 * Returns a series of strings concatinated
137 *
138 * concat() accepts an arbitrary number of parameters. Each parameter
139 * must contain an expression or an array with expressions.
140 *
141 * @param string|array(string) strings that will be concatinated.
142 * @override
143 */
144 public function getConcatExpression()
145 {
146 $args = func_get_args();
147 return 'CONCAT(' . join(', ', (array) $args) . ')';
148 }
75e0c1e [2.0] More general work on the SchemaManager and Platform classes. Ma…
jwage authored
149
150 public function getListDatabasesSql()
151 {
152 return 'SHOW DATABASES';
153 }
154
155 public function getListSequencesSql($database)
156 {
157 $query = 'SHOW TABLES';
158 if ( ! is_null($database)) {
159 $query .= ' FROM ' . $this->quoteIdentifier($database);
160 }
161 return $query;
162 }
163
164 public function getListTableConstraintsSql($table)
165 {
166 return 'SHOW INDEX FROM ' . $this->quoteIdentifier($table);
167 }
168
169 public function getListTableIndexesSql($table)
170 {
171 return 'SHOW INDEX FROM ' . $this->quoteIdentifier($table);
172 }
173
174 public function getListUsersSql()
175 {
176 return "SELECT * FROM mysql.user WHERE user != '' GROUP BY user";
177 }
178
179 public function getListViewsSql($database = null)
180 {
181 if (is_null($database)) {
182 return 'SELECT * FROM information_schema.VIEWS';
183 } else {
184 return "SHOW FULL TABLES FROM " . $database . " WHERE Table_type = 'VIEW'";
185 }
186 }
187
188 public function getCreateViewSql($name, $sql)
189 {
190 return 'CREATE VIEW ' . $name . ' AS ' . $sql;
191 }
192
193 public function getDropViewSql($name)
194 {
195 return 'DROP VIEW '. $name;
196 }
197
e704cd0 Continued refactorings. Started to refactor the DBAL layer.
romanb authored
198 /**
d973363 Finally first, very basic, running CRUD tests for Doctrine 2
romanb authored
199 * Gets the SQL snippet used to declare a VARCHAR column on the MySql platform.
200 *
201 * @params array $field
0f8e9e0 refactorings. made basic one-one, one-many joins work.
romanb authored
202 */
16c4efc [2.0] DBAL streamlining and starting to increase test coverage.
romanb authored
203 public function getVarcharTypeDeclarationSql(array $field)
0f8e9e0 refactorings. made basic one-one, one-many joins work.
romanb authored
204 {
205 if ( ! isset($field['length'])) {
206 if (array_key_exists('default', $field)) {
207 $field['length'] = $this->getVarcharMaxLength();
208 } else {
209 $field['length'] = false;
210 }
211 }
212
213 $length = ($field['length'] <= $this->getVarcharMaxLength()) ? $field['length'] : false;
d973363 Finally first, very basic, running CRUD tests for Doctrine 2
romanb authored
214 $fixed = (isset($field['fixed'])) ? $field['fixed'] : false;
0f8e9e0 refactorings. made basic one-one, one-many joins work.
romanb authored
215
216 return $fixed ? ($length ? 'CHAR(' . $length . ')' : 'CHAR(255)')
217 : ($length ? 'VARCHAR(' . $length . ')' : 'TEXT');
218 }
219
220 /**
b5401ee checkin of occasional work from the past weeks.
romanb authored
221 * Enter description here...
222 *
223 * @param array $field
224 */
225 public function getClobDeclarationSql(array $field)
226 {
227 if ( ! empty($field['length'])) {
228 $length = $field['length'];
229 if ($length <= 255) {
230 return 'TINYTEXT';
231 } else if ($length <= 65532) {
232 return 'TEXT';
233 } else if ($length <= 16777215) {
234 return 'MEDIUMTEXT';
235 }
236 }
237 return 'LONGTEXT';
238 }
e704cd0 Continued refactorings. Started to refactor the DBAL layer.
romanb authored
239
240 /**
241 * Obtain DBMS specific SQL code portion needed to set the CHARACTER SET
242 * of a field declaration to be used in statements like CREATE TABLE.
243 *
244 * @param string $charset name of the charset
245 * @return string DBMS specific SQL code portion needed to set the CHARACTER SET
246 * of a field declaration.
247 */
248 public function getCharsetFieldDeclaration($charset)
249 {
250 return 'CHARACTER SET ' . $charset;
251 }
252
253 /**
254 * Obtain DBMS specific SQL code portion needed to set the COLLATION
255 * of a field declaration to be used in statements like CREATE TABLE.
256 *
257 * @param string $collation name of the collation
258 * @return string DBMS specific SQL code portion needed to set the COLLATION
259 * of a field declaration.
260 */
261 public function getCollationFieldDeclaration($collation)
262 {
263 return 'COLLATE ' . $collation;
264 }
265
266 /**
267 * Whether the platform prefers identity columns for ID generation.
268 * MySql prefers "autoincrement" identity columns since sequences can only
269 * be emulated with a table.
270 *
271 * @return boolean
272 * @override
273 */
274 public function prefersIdentityColumns()
275 {
276 return true;
277 }
3cd4fc5 Intermediate checkin.
romanb authored
278
279 /**
280 * Whether the platform supports identity columns.
281 * MySql supports this through AUTO_INCREMENT columns.
282 *
283 * @return boolean
284 * @override
285 */
286 public function supportsIdentityColumns()
287 {
288 return true;
289 }
290
291 /**
292 * Whether the platform supports savepoints. MySql does not.
293 *
294 * @return boolean
295 * @override
296 */
297 public function supportsSavepoints()
298 {
299 return false;
300 }
b5401ee checkin of occasional work from the past weeks.
romanb authored
301
302 /**
303 * Enter description here...
304 *
305 * @return unknown
306 * @override
307 */
308 public function getShowDatabasesSql()
309 {
310 return 'SHOW DATABASES';
311 }
312
313 /**
314 * Enter description here...
315 *
316 * @todo Throw exception by default?
317 * @override
318 */
319 public function getListTablesSql()
320 {
321 return 'SHOW TABLES';
322 }
746d9bc [2.0] Adding listTableColumns() support for mysql.
jwage authored
323
324 public function getListTableColumnsSql($table)
325 {
326 return 'DESCRIBE ' . $this->quoteIdentifier($table);
327 }
328
b5401ee checkin of occasional work from the past weeks.
romanb authored
329 /**
330 * create a new database
331 *
332 * @param string $name name of the database that should be created
333 * @return string
334 * @override
335 */
336 public function getCreateDatabaseSql($name)
337 {
338 return 'CREATE DATABASE ' . $this->quoteIdentifier($name);
339 }
340
341 /**
342 * drop an existing database
343 *
344 * @param string $name name of the database that should be dropped
345 * @return string
346 * @override
347 */
348 public function getDropDatabaseSql($name)
349 {
350 return 'DROP DATABASE ' . $this->quoteIdentifier($name);
351 }
352
353 /**
354 * create a new table
355 *
356 * @param string $name Name of the database that should be created
357 * @param array $fields Associative array that contains the definition of each field of the new table
358 * The indexes of the array entries are the names of the fields of the table an
359 * the array entry values are associative arrays like those that are meant to be
360 * passed with the field definitions to get[Type]Declaration() functions.
361 * array(
362 * 'id' => array(
363 * 'type' => 'integer',
364 * 'unsigned' => 1
365 * 'notnull' => 1
366 * 'default' => 0
367 * ),
368 * 'name' => array(
369 * 'type' => 'text',
370 * 'length' => 12
371 * ),
372 * 'password' => array(
373 * 'type' => 'text',
374 * 'length' => 12
375 * )
376 * );
377 * @param array $options An associative array of table options:
378 * array(
379 * 'comment' => 'Foo',
380 * 'charset' => 'utf8',
381 * 'collate' => 'utf8_unicode_ci',
382 * 'type' => 'innodb',
383 * );
384 *
385 * @return void
386 * @override
387 */
388 public function getCreateTableSql($name, array $fields, array $options = array())
389 {
390 if ( ! $name) {
705199e [2.0] Parser work. Added support for functions in SelectExpressions.
romanb authored
391 throw DoctrineException::updateMe('no valid table name specified');
b5401ee checkin of occasional work from the past weeks.
romanb authored
392 }
393 if (empty($fields)) {
705199e [2.0] Parser work. Added support for functions in SelectExpressions.
romanb authored
394 throw DoctrineException::updateMe('no fields specified for table "'.$name.'"');
b5401ee checkin of occasional work from the past weeks.
romanb authored
395 }
16c4efc [2.0] DBAL streamlining and starting to increase test coverage.
romanb authored
396 $queryFields = $this->getColumnDeclarationListSql($fields);
b5401ee checkin of occasional work from the past weeks.
romanb authored
397
398 // build indexes for all foreign key fields (needed in MySQL!!)
399 if (isset($options['foreignKeys'])) {
400 foreach ($options['foreignKeys'] as $fk) {
401 $local = $fk['local'];
402 $found = false;
403 if (isset($options['indexes'])) {
404 foreach ($options['indexes'] as $definition) {
405 if (is_string($definition['fields'])) {
406 // Check if index already exists on the column
407 $found = ($local == $definition['fields']);
408 } else if (in_array($local, $definition['fields']) && count($definition['fields']) === 1) {
409 // Index already exists on the column
410 $found = true;
411 }
412 }
413 }
414 if (isset($options['primary']) && !empty($options['primary']) &&
415 in_array($local, $options['primary'])) {
416 // field is part of the PK and therefore already indexed
417 $found = true;
418 }
419
420 if ( ! $found) {
421 $options['indexes'][$local] = array('fields' => array($local => array()));
422 }
423 }
424 }
425
426 // add all indexes
427 if (isset($options['indexes']) && ! empty($options['indexes'])) {
428 foreach($options['indexes'] as $index => $definition) {
429 $queryFields .= ', ' . $this->getIndexDeclarationSql($index, $definition);
430 }
431 }
432
433 // attach all primary keys
434 if (isset($options['primary']) && ! empty($options['primary'])) {
ae7be28 [2.0] Work on single table inheritance with more functional tests.
romanb authored
435 $keyColumns = array_unique(array_values($options['primary']));
34f4ee7 First tests for basic collection implementation. First experimental u…
romanb authored
436 $keyColumns = array_map(array($this, 'quoteIdentifier'), $keyColumns);
b5401ee checkin of occasional work from the past weeks.
romanb authored
437 $queryFields .= ', PRIMARY KEY(' . implode(', ', $keyColumns) . ')';
438 }
439
440 $query = 'CREATE ';
441 if (!empty($options['temporary'])) {
442 $query .= 'TEMPORARY ';
443 }
444 $query.= 'TABLE ' . $this->quoteIdentifier($name, true) . ' (' . $queryFields . ')';
445
446 $optionStrings = array();
447
448 if (isset($options['comment'])) {
449 $optionStrings['comment'] = 'COMMENT = ' . $this->quote($options['comment'], 'text');
450 }
451 if (isset($options['charset'])) {
452 $optionStrings['charset'] = 'DEFAULT CHARACTER SET ' . $options['charset'];
453 if (isset($options['collate'])) {
454 $optionStrings['charset'] .= ' COLLATE ' . $options['collate'];
455 }
456 }
457
458 $type = false;
459
460 // get the type of the table
461 if (isset($options['type'])) {
462 $type = $options['type'];
34f4ee7 First tests for basic collection implementation. First experimental u…
romanb authored
463 }/* else {
b5401ee checkin of occasional work from the past weeks.
romanb authored
464 $type = $this->getAttribute(Doctrine::ATTR_DEFAULT_TABLE_TYPE);
34f4ee7 First tests for basic collection implementation. First experimental u…
romanb authored
465 }*/
b5401ee checkin of occasional work from the past weeks.
romanb authored
466
467 if ($type) {
468 $optionStrings[] = 'ENGINE = ' . $type;
469 }
470
471 if ( ! empty($optionStrings)) {
472 $query.= ' '.implode(' ', $optionStrings);
473 }
474 $sql[] = $query;
475
476 if (isset($options['foreignKeys'])) {
477 foreach ((array) $options['foreignKeys'] as $k => $definition) {
478 if (is_array($definition)) {
479 $sql[] = $this->getCreateForeignKeySql($name, $definition);
480 }
481 }
482 }
483
484 return $sql;
485 }
486
487 /**
16c4efc [2.0] DBAL streamlining and starting to increase test coverage.
romanb authored
488 * Gets the SQL to alter an existing table.
b5401ee checkin of occasional work from the past weeks.
romanb authored
489 *
16c4efc [2.0] DBAL streamlining and starting to increase test coverage.
romanb authored
490 * @param string $name The name of the table that is intended to be changed.
491 * @param array $changes Associative array that contains the details of each type
b5401ee checkin of occasional work from the past weeks.
romanb authored
492 * of change that is intended to be performed. The types of
493 * changes that are currently supported are defined as follows:
494 *
495 * name
496 *
497 * New name for the table.
498 *
499 * add
500 *
501 * Associative array with the names of fields to be added as
502 * indexes of the array. The value of each entry of the array
503 * should be set to another associative array with the properties
504 * of the fields to be added. The properties of the fields should
505 * be the same as defined by the Metabase parser.
506 *
507 *
508 * remove
509 *
510 * Associative array with the names of fields to be removed as indexes
511 * of the array. Currently the values assigned to each entry are ignored.
512 * An empty array should be used for future compatibility.
513 *
514 * rename
515 *
516 * Associative array with the names of fields to be renamed as indexes
517 * of the array. The value of each entry of the array should be set to
518 * another associative array with the entry named name with the new
519 * field name and the entry named Declaration that is expected to contain
520 * the portion of the field declaration already in DBMS specific SQL code
521 * as it is used in the CREATE TABLE statement.
522 *
523 * change
524 *
525 * Associative array with the names of the fields to be changed as indexes
526 * of the array. Keep in mind that if it is intended to change either the
527 * name of a field and any other properties, the change array entries
528 * should have the new names of the fields as array indexes.
529 *
530 * The value of each entry of the array should be set to another associative
531 * array with the properties of the fields to that are meant to be changed as
532 * array entries. These entries should be assigned to the new values of the
533 * respective properties. The properties of the fields should be the same
534 * as defined by the Metabase parser.
535 *
536 * Example
537 * array(
538 * 'name' => 'userlist',
539 * 'add' => array(
540 * 'quota' => array(
541 * 'type' => 'integer',
542 * 'unsigned' => 1
543 * )
544 * ),
545 * 'remove' => array(
546 * 'file_limit' => array(),
547 * 'time_limit' => array()
548 * ),
549 * 'change' => array(
550 * 'name' => array(
551 * 'length' => '20',
552 * 'definition' => array(
553 * 'type' => 'text',
554 * 'length' => 20,
555 * ),
556 * )
557 * ),
558 * 'rename' => array(
559 * 'sex' => array(
560 * 'name' => 'gender',
561 * 'definition' => array(
562 * 'type' => 'text',
563 * 'length' => 1,
564 * 'default' => 'M',
565 * ),
566 * )
567 * )
568 * )
569 *
570 * @param boolean $check indicates whether the function should just check if the DBMS driver
571 * can perform the requested table alterations if the value is true or
572 * actually perform them otherwise.
573 * @return boolean
574 * @override
575 */
576 public function getAlterTableSql($name, array $changes, $check = false)
577 {
578 if ( ! $name) {
705199e [2.0] Parser work. Added support for functions in SelectExpressions.
romanb authored
579 throw DoctrineException::updateMe('no valid table name specified');
b5401ee checkin of occasional work from the past weeks.
romanb authored
580 }
581 foreach ($changes as $changeName => $change) {
582 switch ($changeName) {
583 case 'add':
584 case 'remove':
585 case 'change':
586 case 'rename':
587 case 'name':
588 break;
589 default:
705199e [2.0] Parser work. Added support for functions in SelectExpressions.
romanb authored
590 throw DoctrineException::updateMe('change type "' . $changeName . '" not yet supported');
b5401ee checkin of occasional work from the past weeks.
romanb authored
591 }
592 }
593
594 if ($check) {
595 return true;
596 }
597
598 $query = '';
599 if ( ! empty($changes['name'])) {
600 $change_name = $this->quoteIdentifier($changes['name']);
601 $query .= 'RENAME TO ' . $change_name;
602 }
603
604 if ( ! empty($changes['add']) && is_array($changes['add'])) {
605 foreach ($changes['add'] as $fieldName => $field) {
606 if ($query) {
607 $query.= ', ';
608 }
16c4efc [2.0] DBAL streamlining and starting to increase test coverage.
romanb authored
609 $query.= 'ADD ' . $this->getColumnDeclarationSql($fieldName, $field);
b5401ee checkin of occasional work from the past weeks.
romanb authored
610 }
611 }
612
613 if ( ! empty($changes['remove']) && is_array($changes['remove'])) {
614 foreach ($changes['remove'] as $fieldName => $field) {
615 if ($query) {
616 $query .= ', ';
617 }
618 $fieldName = $this->quoteIdentifier($fieldName);
619 $query .= 'DROP ' . $fieldName;
620 }
621 }
622
623 $rename = array();
624 if ( ! empty($changes['rename']) && is_array($changes['rename'])) {
625 foreach ($changes['rename'] as $fieldName => $field) {
626 $rename[$field['name']] = $fieldName;
627 }
628 }
629
630 if ( ! empty($changes['change']) && is_array($changes['change'])) {
631 foreach ($changes['change'] as $fieldName => $field) {
632 if ($query) {
633 $query.= ', ';
634 }
635 if (isset($rename[$fieldName])) {
636 $oldFieldName = $rename[$fieldName];
637 unset($rename[$fieldName]);
638 } else {
639 $oldFieldName = $fieldName;
640 }
641 $oldFieldName = $this->quoteIdentifier($oldFieldName, true);
642 $query .= 'CHANGE ' . $oldFieldName . ' '
16c4efc [2.0] DBAL streamlining and starting to increase test coverage.
romanb authored
643 . $this->getColumnDeclarationSql($fieldName, $field['definition']);
b5401ee checkin of occasional work from the past weeks.
romanb authored
644 }
645 }
646
647 if ( ! empty($rename) && is_array($rename)) {
648 foreach ($rename as $renameName => $renamedField) {
649 if ($query) {
650 $query.= ', ';
651 }
652 $field = $changes['rename'][$renamedField];
653 $renamedField = $this->quoteIdentifier($renamedField, true);
654 $query .= 'CHANGE ' . $renamedField . ' '
16c4efc [2.0] DBAL streamlining and starting to increase test coverage.
romanb authored
655 . $this->getColumnDeclarationSql($field['name'], $field['definition']);
b5401ee checkin of occasional work from the past weeks.
romanb authored
656 }
657 }
658
659 if ( ! $query) {
660 return false;
661 }
662
663 $name = $this->quoteIdentifier($name, true);
664
665 return 'ALTER TABLE ' . $name . ' ' . $query;
666 }
667
668 /**
669 * Get the stucture of a field into an array
670 *
671 * @author Leoncx
672 * @param string $table name of the table on which the index is to be created
673 * @param string $name name of the index to be created
674 * @param array $definition associative array that defines properties of the index to be created.
675 * Currently, only one property named FIELDS is supported. This property
676 * is also an associative with the names of the index fields as array
677 * indexes. Each entry of this array is set to another type of associative
678 * array that specifies properties of the index that are specific to
679 * each field.
680 *
681 * Currently, only the sorting property is supported. It should be used
682 * to define the sorting direction of the index. It may be set to either
683 * ascending or descending.
684 *
685 * Not all DBMS support index sorting direction configuration. The DBMS
686 * drivers of those that do not support it ignore this property. Use the
687 * function supports() to determine whether the DBMS driver can manage indexes.
688 *
689 * Example
690 * array(
691 * 'fields' => array(
692 * 'user_name' => array(
693 * 'sorting' => 'ASC'
694 * 'length' => 10
695 * ),
696 * 'last_login' => array()
697 * )
698 * )
699 * @throws PDOException
700 * @return void
701 * @override
702 */
703 public function getCreateIndexSql($table, $name, array $definition)
704 {
705 $table = $table;
706 $name = $this->quoteIdentifier($name);
707 $type = '';
708 if (isset($definition['type'])) {
709 switch (strtolower($definition['type'])) {
710 case 'fulltext':
711 case 'unique':
712 $type = strtoupper($definition['type']) . ' ';
713 break;
714 default:
705199e [2.0] Parser work. Added support for functions in SelectExpressions.
romanb authored
715 throw DoctrineException::updateMe('Unknown index type ' . $definition['type']);
b5401ee checkin of occasional work from the past weeks.
romanb authored
716 }
717 }
718 $query = 'CREATE ' . $type . 'INDEX ' . $name . ' ON ' . $table;
719 $query .= ' (' . $this->getIndexFieldDeclarationListSql($definition['fields']) . ')';
720
721 return $query;
722 }
723
724 /**
725 * Obtain DBMS specific SQL code portion needed to declare an integer type
726 * field to be used in statements like CREATE TABLE.
727 *
728 * @param string $name name the field to be declared.
729 * @param string $field associative array with the name of the properties
730 * of the field being declared as array indexes.
731 * Currently, the types of supported field
732 * properties are as follows:
733 *
734 * unsigned
735 * Boolean flag that indicates whether the field
736 * should be declared as unsigned integer if
737 * possible.
738 *
739 * default
740 * Integer value to be used as default for this
741 * field.
742 *
743 * notnull
744 * Boolean flag that indicates whether this field is
745 * constrained to not be set to null.
746 * @return string DBMS specific SQL code portion that should be used to
747 * declare the specified field.
748 * @override
749 */
d973363 Finally first, very basic, running CRUD tests for Doctrine 2
romanb authored
750 public function getIntegerTypeDeclarationSql(array $field)
751 {
87fd08e [2.0] Some fixes for ClassExporterTest.
romanb authored
752 return 'INT' . $this->_getCommonIntegerTypeDeclarationSql($field);
d973363 Finally first, very basic, running CRUD tests for Doctrine 2
romanb authored
753 }
754
755 /** @override */
756 public function getBigIntTypeDeclarationSql(array $field)
757 {
87fd08e [2.0] Some fixes for ClassExporterTest.
romanb authored
758 return 'BIGINT' . $this->_getCommonIntegerTypeDeclarationSql($field);
d973363 Finally first, very basic, running CRUD tests for Doctrine 2
romanb authored
759 }
760
761 /** @override */
34f4ee7 First tests for basic collection implementation. First experimental u…
romanb authored
762 public function getSmallIntTypeDeclarationSql(array $field)
d973363 Finally first, very basic, running CRUD tests for Doctrine 2
romanb authored
763 {
87fd08e [2.0] Some fixes for ClassExporterTest.
romanb authored
764 return 'SMALLINT' . $this->_getCommonIntegerTypeDeclarationSql($field);
d973363 Finally first, very basic, running CRUD tests for Doctrine 2
romanb authored
765 }
766
767 /** @override */
768 protected function _getCommonIntegerTypeDeclarationSql(array $columnDef)
b5401ee checkin of occasional work from the past weeks.
romanb authored
769 {
87fd08e [2.0] Some fixes for ClassExporterTest.
romanb authored
770 $autoinc = '';
34f4ee7 First tests for basic collection implementation. First experimental u…
romanb authored
771 if ( ! empty($columnDef['autoincrement'])) {
b5401ee checkin of occasional work from the past weeks.
romanb authored
772 $autoinc = ' AUTO_INCREMENT';
773 }
34f4ee7 First tests for basic collection implementation. First experimental u…
romanb authored
774 $unsigned = (isset($columnDef['unsigned']) && $columnDef['unsigned']) ? ' UNSIGNED' : '';
b5401ee checkin of occasional work from the past weeks.
romanb authored
775
87fd08e [2.0] Some fixes for ClassExporterTest.
romanb authored
776 return $unsigned . $autoinc;
b5401ee checkin of occasional work from the past weeks.
romanb authored
777 }
778
779 /**
780 * Obtain DBMS specific SQL code portion needed to set an index
781 * declaration to be used in statements like CREATE TABLE.
782 *
783 * @param string $charset name of the index
784 * @param array $definition index definition
785 * @return string DBMS specific SQL code portion needed to set an index
786 * @override
787 */
788 public function getIndexDeclarationSql($name, array $definition)
789 {
790 $type = '';
791 if (isset($definition['type'])) {
792 switch (strtolower($definition['type'])) {
793 case 'fulltext':
794 case 'unique':
795 $type = strtoupper($definition['type']) . ' ';
796 break;
797 default:
7479a0c [2.0] Starting to improve functional tests. First basic functional qu…
romanb authored
798 throw DoctrineException::updateMe('Unknown index type ' . $definition['type']);
b5401ee checkin of occasional work from the past weeks.
romanb authored
799 }
800 }
801
802 if ( ! isset($definition['fields'])) {
7479a0c [2.0] Starting to improve functional tests. First basic functional qu…
romanb authored
803 throw DoctrineException::updateMe('No index columns given.');
b5401ee checkin of occasional work from the past weeks.
romanb authored
804 }
805 if ( ! is_array($definition['fields'])) {
806 $definition['fields'] = array($definition['fields']);
807 }
808
809 $query = $type . 'INDEX ' . $this->quoteIdentifier($name);
810
811 $query .= ' (' . $this->getIndexFieldDeclarationListSql($definition['fields']) . ')';
812
813 return $query;
814 }
815
816 /**
817 * getIndexFieldDeclarationList
818 * Obtain DBMS specific SQL code portion needed to set an index
819 * declaration to be used in statements like CREATE TABLE.
820 *
821 * @return string
822 * @override
823 */
824 public function getIndexFieldDeclarationListSql(array $fields)
825 {
826 $declFields = array();
827
828 foreach ($fields as $fieldName => $field) {
829 $fieldString = $this->quoteIdentifier($fieldName);
830
831 if (is_array($field)) {
832 if (isset($field['length'])) {
833 $fieldString .= '(' . $field['length'] . ')';
834 }
835
836 if (isset($field['sorting'])) {
837 $sort = strtoupper($field['sorting']);
838 switch ($sort) {
839 case 'ASC':
840 case 'DESC':
841 $fieldString .= ' ' . $sort;
842 break;
843 default:
7479a0c [2.0] Starting to improve functional tests. First basic functional qu…
romanb authored
844 throw DoctrineException::updateMe('Unknown index sorting option given.');
b5401ee checkin of occasional work from the past weeks.
romanb authored
845 }
846 }
847 } else {
848 $fieldString = $this->quoteIdentifier($field);
849 }
850 $declFields[] = $fieldString;
851 }
852 return implode(', ', $declFields);
853 }
854
855 /**
856 * Return the FOREIGN KEY query section dealing with non-standard options
857 * as MATCH, INITIALLY DEFERRED, ON UPDATE, ...
858 *
859 * @param array $definition
860 * @return string
861 * @override
862 */
863 public function getAdvancedForeignKeyOptionsSql(array $definition)
864 {
865 $query = '';
866 if ( ! empty($definition['match'])) {
867 $query .= ' MATCH ' . $definition['match'];
868 }
869 if ( ! empty($definition['onUpdate'])) {
870 $query .= ' ON UPDATE ' . $this->getForeignKeyReferentialActionSql($definition['onUpdate']);
871 }
872 if ( ! empty($definition['onDelete'])) {
873 $query .= ' ON DELETE ' . $this->getForeignKeyReferentialActionSql($definition['onDelete']);
874 }
875 return $query;
876 }
877
878 /**
16c4efc [2.0] DBAL streamlining and starting to increase test coverage.
romanb authored
879 * Gets the SQL to drop an index of a table.
b5401ee checkin of occasional work from the past weeks.
romanb authored
880 *
881 * @param string $table name of table that should be used in method
882 * @param string $name name of the index to be dropped
883 * @override
884 */
885 public function getDropIndexSql($table, $name)
886 {
16c4efc [2.0] DBAL streamlining and starting to increase test coverage.
romanb authored
887 $table = $this->quoteIdentifier($table);
888 $name = $this->quoteIdentifier($name);
b5401ee checkin of occasional work from the past weeks.
romanb authored
889 return 'DROP INDEX ' . $name . ' ON ' . $table;
890 }
891
892 /**
16c4efc [2.0] DBAL streamlining and starting to increase test coverage.
romanb authored
893 * Gets the SQL to drop a table.
b5401ee checkin of occasional work from the past weeks.
romanb authored
894 *
16c4efc [2.0] DBAL streamlining and starting to increase test coverage.
romanb authored
895 * @param string $table The name of table to drop.
b5401ee checkin of occasional work from the past weeks.
romanb authored
896 * @override
897 */
898 public function getDropTableSql($table)
899 {
16c4efc [2.0] DBAL streamlining and starting to increase test coverage.
romanb authored
900 return 'DROP TABLE ' . $this->quoteIdentifier($table);
b5401ee checkin of occasional work from the past weeks.
romanb authored
901 }
c3ad955 further cleanups
romanb authored
902
903 /**
904 * Enter description here...
905 *
906 * @param unknown_type $level
907 * @override
908 */
909 public function getSetTransactionIsolationSql($level)
910 {
911 return 'SET SESSION TRANSACTION ISOLATION LEVEL ' . $this->_getTransactionIsolationLevelSql($level);
912 }
7426baf [2.0] General work on Platform and SchemaManager classes
jwage authored
913
914 /**
915 * Get the platform name for this instance
916 *
917 * @return string
918 */
919 public function getName()
920 {
921 return 'mysql';
922 }
d458197 [2.0] Another step towards finishing namespace refactoring
jwage authored
923 }
Something went wrong with that request. Please try again.