Rajout de doctrine/orm
[zf2.biz/galerie.git] / vendor / doctrine / dbal / lib / Doctrine / DBAL / Schema / Schema.php
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\Schema;
21
22 use Doctrine\DBAL\Schema\Visitor\CreateSchemaSqlCollector;
23 use Doctrine\DBAL\Schema\Visitor\DropSchemaSqlCollector;
24 use Doctrine\DBAL\Schema\Visitor\Visitor;
25
26 /**
27  * Object representation of a database schema
28  *
29  * Different vendors have very inconsistent naming with regard to the concept
30  * of a "schema". Doctrine understands a schema as the entity that conceptually
31  * wraps a set of database objects such as tables, sequences, indexes and
32  * foreign keys that belong to each other into a namespace. A Doctrine Schema
33  * has nothing to do with the "SCHEMA" defined as in PostgreSQL, it is more
34  * related to the concept of "DATABASE" that exists in MySQL and PostgreSQL.
35  *
36  * Every asset in the doctrine schema has a name. A name consists of either a
37  * namespace.local name pair or just a local unqualified name.
38  *
39  * The abstraction layer that covers a PostgreSQL schema is the namespace of an
40  * database object (asset). A schema can have a name, which will be used as
41  * default namespace for the unqualified database objects that are created in
42  * the schema.
43  *
44  * In the case of MySQL where cross-database queries are allowed this leads to
45  * databases being "misinterpreted" as namespaces. This is intentional, however
46  * the CREATE/DROP SQL visitors will just filter this queries and do not
47  * execute them. Only the queries for the currently connected database are
48  * executed.
49  *
50  *
51  * @link    www.doctrine-project.org
52  * @since   2.0
53  * @author  Benjamin Eberlei <kontakt@beberlei.de>
54  */
55 class Schema extends AbstractAsset
56 {
57     /**
58      * @var array
59      */
60     protected $_tables = array();
61
62     /**
63      * @var array
64      */
65     protected $_sequences = array();
66
67     /**
68      * @var SchemaConfig
69      */
70     protected $_schemaConfig = false;
71
72     /**
73      * @param array $tables
74      * @param array $sequences
75      * @param array $views
76      * @param array $triggers
77      * @param SchemaConfig $schemaConfig
78      */
79     public function __construct(array $tables=array(), array $sequences=array(), SchemaConfig $schemaConfig=null)
80     {
81         if ($schemaConfig == null) {
82             $schemaConfig = new SchemaConfig();
83         }
84         $this->_schemaConfig = $schemaConfig;
85         $this->_setName($schemaConfig->getName() ?: 'public');
86
87         foreach ($tables as $table) {
88             $this->_addTable($table);
89         }
90
91         foreach ($sequences as $sequence) {
92             $this->_addSequence($sequence);
93         }
94     }
95
96     /**
97      * @return bool
98      */
99     public function hasExplicitForeignKeyIndexes()
100     {
101         return $this->_schemaConfig->hasExplicitForeignKeyIndexes();
102     }
103
104     /**
105      * @param Table $table
106      */
107     protected function _addTable(Table $table)
108     {
109         $tableName = $table->getFullQualifiedName($this->getName());
110         if(isset($this->_tables[$tableName])) {
111             throw SchemaException::tableAlreadyExists($tableName);
112         }
113
114         $this->_tables[$tableName] = $table;
115         $table->setSchemaConfig($this->_schemaConfig);
116     }
117
118     /**
119      * @param Sequence $sequence
120      */
121     protected function _addSequence(Sequence $sequence)
122     {
123         $seqName = $sequence->getFullQualifiedName($this->getName());
124         if (isset($this->_sequences[$seqName])) {
125             throw SchemaException::sequenceAlreadyExists($seqName);
126         }
127         $this->_sequences[$seqName] = $sequence;
128     }
129
130     /**
131      * Get all tables of this schema.
132      *
133      * @return array
134      */
135     public function getTables()
136     {
137         return $this->_tables;
138     }
139
140     /**
141      * @param string $tableName
142      * @return Table
143      */
144     public function getTable($tableName)
145     {
146         $tableName = $this->getFullQualifiedAssetName($tableName);
147         if (!isset($this->_tables[$tableName])) {
148             throw SchemaException::tableDoesNotExist($tableName);
149         }
150
151         return $this->_tables[$tableName];
152     }
153
154     /**
155      * @return string
156      */
157     private function getFullQualifiedAssetName($name)
158     {
159         if ($this->isIdentifierQuoted($name)) {
160             $name = $this->trimQuotes($name);
161         }
162         if (strpos($name, ".") === false) {
163             $name = $this->getName() . "." . $name;
164         }
165         return strtolower($name);
166     }
167
168     /**
169      * Does this schema have a table with the given name?
170      *
171      * @param  string $tableName
172      * @return Schema
173      */
174     public function hasTable($tableName)
175     {
176         $tableName = $this->getFullQualifiedAssetName($tableName);
177         return isset($this->_tables[$tableName]);
178     }
179
180     /**
181      * Get all table names, prefixed with a schema name, even the default one
182      * if present.
183      *
184      * @return array
185      */
186     public function getTableNames()
187     {
188         return array_keys($this->_tables);
189     }
190
191     public function hasSequence($sequenceName)
192     {
193         $sequenceName = $this->getFullQualifiedAssetName($sequenceName);
194         return isset($this->_sequences[$sequenceName]);
195     }
196
197     /**
198      * @throws SchemaException
199      * @param  string $sequenceName
200      * @return \Doctrine\DBAL\Schema\Sequence
201      */
202     public function getSequence($sequenceName)
203     {
204         $sequenceName = $this->getFullQualifiedAssetName($sequenceName);
205         if(!$this->hasSequence($sequenceName)) {
206             throw SchemaException::sequenceDoesNotExist($sequenceName);
207         }
208         return $this->_sequences[$sequenceName];
209     }
210
211     /**
212      * @return \Doctrine\DBAL\Schema\Sequence[]
213      */
214     public function getSequences()
215     {
216         return $this->_sequences;
217     }
218
219     /**
220      * Create a new table
221      *
222      * @param  string $tableName
223      * @return Table
224      */
225     public function createTable($tableName)
226     {
227         $table = new Table($tableName);
228         $this->_addTable($table);
229
230         foreach ($this->_schemaConfig->getDefaultTableOptions() as $name => $value) {
231             $table->addOption($name, $value);
232         }
233
234         return $table;
235     }
236
237     /**
238      * Rename a table
239      *
240      * @param string $oldTableName
241      * @param string $newTableName
242      * @return Schema
243      */
244     public function renameTable($oldTableName, $newTableName)
245     {
246         $table = $this->getTable($oldTableName);
247         $table->_setName($newTableName);
248
249         $this->dropTable($oldTableName);
250         $this->_addTable($table);
251         return $this;
252     }
253
254     /**
255      * Drop a table from the schema.
256      *
257      * @param string $tableName
258      * @return Schema
259      */
260     public function dropTable($tableName)
261     {
262         $tableName = $this->getFullQualifiedAssetName($tableName);
263         $table = $this->getTable($tableName);
264         unset($this->_tables[$tableName]);
265         return $this;
266     }
267
268     /**
269      * Create a new sequence
270      *
271      * @param  string $sequenceName
272      * @param  int $allocationSize
273      * @param  int $initialValue
274      * @return Sequence
275      */
276     public function createSequence($sequenceName, $allocationSize=1, $initialValue=1)
277     {
278         $seq = new Sequence($sequenceName, $allocationSize, $initialValue);
279         $this->_addSequence($seq);
280         return $seq;
281     }
282
283     /**
284      * @param string $sequenceName
285      * @return Schema
286      */
287     public function dropSequence($sequenceName)
288     {
289         $sequenceName = $this->getFullQualifiedAssetName($sequenceName);
290         unset($this->_sequences[$sequenceName]);
291         return $this;
292     }
293
294     /**
295      * Return an array of necessary sql queries to create the schema on the given platform.
296      *
297      * @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform
298      * @return array
299      */
300     public function toSql(\Doctrine\DBAL\Platforms\AbstractPlatform $platform)
301     {
302         $sqlCollector = new CreateSchemaSqlCollector($platform);
303         $this->visit($sqlCollector);
304
305         return $sqlCollector->getQueries();
306     }
307
308     /**
309      * Return an array of necessary sql queries to drop the schema on the given platform.
310      *
311      * @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform
312      * @return array
313      */
314     public function toDropSql(\Doctrine\DBAL\Platforms\AbstractPlatform $platform)
315     {
316         $dropSqlCollector = new DropSchemaSqlCollector($platform);
317         $this->visit($dropSqlCollector);
318
319         return $dropSqlCollector->getQueries();
320     }
321
322     /**
323      * @param Schema $toSchema
324      * @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform
325      */
326     public function getMigrateToSql(Schema $toSchema, \Doctrine\DBAL\Platforms\AbstractPlatform $platform)
327     {
328         $comparator = new Comparator();
329         $schemaDiff = $comparator->compare($this, $toSchema);
330         return $schemaDiff->toSql($platform);
331     }
332
333     /**
334      * @param Schema $fromSchema
335      * @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform
336      */
337     public function getMigrateFromSql(Schema $fromSchema, \Doctrine\DBAL\Platforms\AbstractPlatform $platform)
338     {
339         $comparator = new Comparator();
340         $schemaDiff = $comparator->compare($fromSchema, $this);
341         return $schemaDiff->toSql($platform);
342     }
343
344     /**
345      * @param Visitor $visitor
346      */
347     public function visit(Visitor $visitor)
348     {
349         $visitor->acceptSchema($this);
350
351         foreach ($this->_tables as $table) {
352             $table->visit($visitor);
353         }
354         foreach ($this->_sequences as $sequence) {
355             $sequence->visit($visitor);
356         }
357     }
358
359     /**
360      * Cloning a Schema triggers a deep clone of all related assets.
361      *
362      * @return void
363      */
364     public function __clone()
365     {
366         foreach ($this->_tables as $k => $table) {
367             $this->_tables[$k] = clone $table;
368         }
369         foreach ($this->_sequences as $k => $sequence) {
370             $this->_sequences[$k] = clone $sequence;
371         }
372     }
373 }