Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
D
doctrine-dbal
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Tomáš Trávníček
doctrine-dbal
Commits
75dbc8c8
Commit
75dbc8c8
authored
Jul 21, 2007
by
romanb
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Several bugfixes for the export module (expecially pgsql).
parent
6348e5f7
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
1885 additions
and
1813 deletions
+1885
-1813
Pgsql.php
lib/Doctrine/DataDict/Pgsql.php
+621
-621
Export.php
lib/Doctrine/Export.php
+1094
-1093
Pgsql.php
lib/Doctrine/Export/Pgsql.php
+63
-0
PgsqlTestCase.php
tests/Export/PgsqlTestCase.php
+98
-98
SingleRootTestCase.php
tests/NestedSet/SingleRootTestCase.php
+8
-0
run.php
tests/run.php
+1
-1
No files found.
lib/Doctrine/DataDict/Pgsql.php
View file @
75dbc8c8
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.phpdoctrine.com>.
*/
Doctrine
::
autoload
(
'Doctrine_DataDict'
);
/**
* @package Doctrine
* @subpackage Doctrine_DataDict
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
* @author Paul Cooper <pgc@ucecom.com>
* @author Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
* @version $Revision$
* @category Object Relational Mapping
* @link www.phpdoctrine.com
* @since 1.0
*/
class
Doctrine_DataDict_Pgsql
extends
Doctrine_DataDict
{
/**
* @param array $reservedKeyWords an array of reserved keywords by pgsql
*/
protected
static
$reservedKeyWords
=
array
(
'abort'
,
'absolute'
,
'access'
,
'action'
,
'add'
,
'after'
,
'aggregate'
,
'all'
,
'alter'
,
'analyse'
,
'analyze'
,
'and'
,
'any'
,
'as'
,
'asc'
,
'assertion'
,
'assignment'
,
'at'
,
'authorization'
,
'backward'
,
'before'
,
'begin'
,
'between'
,
'bigint'
,
'binary'
,
'bit'
,
'boolean'
,
'both'
,
'by'
,
'cache'
,
'called'
,
'cascade'
,
'case'
,
'cast'
,
'chain'
,
'char'
,
'character'
,
'characteristics'
,
'check'
,
'checkpoint'
,
'class'
,
'close'
,
'cluster'
,
'coalesce'
,
'collate'
,
'column'
,
'comment'
,
'commit'
,
'committed'
,
'constraint'
,
'constraints'
,
'conversion'
,
'convert'
,
'copy'
,
'create'
,
'createdb'
,
'createuser'
,
'cross'
,
'current_date'
,
'current_time'
,
'current_timestamp'
,
'current_user'
,
'cursor'
,
'cycle'
,
'database'
,
'day'
,
'deallocate'
,
'dec'
,
'decimal'
,
'declare'
,
'default'
,
'deferrable'
,
'deferred'
,
'definer'
,
'delete'
,
'delimiter'
,
'delimiters'
,
'desc'
,
'distinct'
,
'do'
,
'domain'
,
'double'
,
'drop'
,
'each'
,
'else'
,
'encoding'
,
'encrypted'
,
'end'
,
'escape'
,
'except'
,
'exclusive'
,
'execute'
,
'exists'
,
'explain'
,
'external'
,
'extract'
,
'false'
,
'fetch'
,
'float'
,
'for'
,
'force'
,
'foreign'
,
'forward'
,
'freeze'
,
'from'
,
'full'
,
'function'
,
'get'
,
'global'
,
'grant'
,
'group'
,
'handler'
,
'having'
,
'hour'
,
'ilike'
,
'immediate'
,
'immutable'
,
'implicit'
,
'in'
,
'increment'
,
'index'
,
'inherits'
,
'initially'
,
'inner'
,
'inout'
,
'input'
,
'insensitive'
,
'insert'
,
'instead'
,
'int'
,
'integer'
,
'intersect'
,
'interval'
,
'into'
,
'invoker'
,
'is'
,
'isnull'
,
'isolation'
,
'join'
,
'key'
,
'lancompiler'
,
'language'
,
'leading'
,
'left'
,
'level'
,
'like'
,
'limit'
,
'listen'
,
'load'
,
'local'
,
'localtime'
,
'localtimestamp'
,
'location'
,
'lock'
,
'match'
,
'maxvalue'
,
'minute'
,
'minvalue'
,
'mode'
,
'month'
,
'move'
,
'names'
,
'national'
,
'natural'
,
'nchar'
,
'new'
,
'next'
,
'no'
,
'nocreatedb'
,
'nocreateuser'
,
'none'
,
'not'
,
'nothing'
,
'notify'
,
'notnull'
,
'null'
,
'nullif'
,
'numeric'
,
'of'
,
'off'
,
'offset'
,
'oids'
,
'old'
,
'on'
,
'only'
,
'operator'
,
'option'
,
'or'
,
'order'
,
'out'
,
'outer'
,
'overlaps'
,
'overlay'
,
'owner'
,
'partial'
,
'password'
,
'path'
,
'pendant'
,
'placing'
,
'position'
,
'precision'
,
'prepare'
,
'primary'
,
'prior'
,
'privileges'
,
'procedural'
,
'procedure'
,
'read'
,
'real'
,
'recheck'
,
'references'
,
'reindex'
,
'relative'
,
'rename'
,
'replace'
,
'reset'
,
'restrict'
,
'returns'
,
'revoke'
,
'right'
,
'rollback'
,
'row'
,
'rule'
,
'schema'
,
'scroll'
,
'second'
,
'security'
,
'select'
,
'sequence'
,
'serializable'
,
'session'
,
'session_user'
,
'set'
,
'setof'
,
'share'
,
'show'
,
'similar'
,
'simple'
,
'smallint'
,
'some'
,
'stable'
,
'start'
,
'statement'
,
'statistics'
,
'stdin'
,
'stdout'
,
'storage'
,
'strict'
,
'substring'
,
'sysid'
,
'table'
,
'temp'
,
'template'
,
'temporary'
,
'then'
,
'time'
,
'timestamp'
,
'to'
,
'toast'
,
'trailing'
,
'transaction'
,
'treat'
,
'trigger'
,
'trim'
,
'true'
,
'truncate'
,
'trusted'
,
'type'
,
'unencrypted'
,
'union'
,
'unique'
,
'unknown'
,
'unlisten'
,
'until'
,
'update'
,
'usage'
,
'user'
,
'using'
,
'vacuum'
,
'valid'
,
'validator'
,
'values'
,
'varchar'
,
'varying'
,
'verbose'
,
'version'
,
'view'
,
'volatile'
,
'when'
,
'where'
,
'with'
,
'without'
,
'work'
,
'write'
,
'year'
,
'zone'
);
/**
* Obtain DBMS specific SQL code portion needed to declare an text type
* field to be used in statements like CREATE TABLE.
*
* @param array $field associative array with the name of the properties
* of the field being declared as array indexes. Currently, the types
* of supported field properties are as follows:
*
* length
* Integer value that determines the maximum length of the text
* field. If this argument is missing the field should be
* declared to have the longest length allowed by the DBMS.
*
* default
* Text value to be used as default for this field.
*
* notnull
* Boolean flag that indicates whether this field is constrained
* to not be set to null.
*
* @return string DBMS specific SQL code portion that should be used to
* declare the specified field.
*/
public
function
getNativeDeclaration
(
array
$field
)
{
if
(
!
isset
(
$field
[
'type'
]))
{
throw
new
Doctrine_DataDict_Exception
(
'Missing column type.'
);
}
switch
(
$field
[
'type'
])
{
case
'char'
:
case
'string'
:
case
'array'
:
case
'object'
:
case
'varchar'
:
case
'gzip'
:
$length
=
(
isset
(
$field
[
'length'
])
&&
$field
[
'length'
])
?
$field
[
'length'
]
:
null
;
// TODO: $this->conn->options['default_text_field_length'];
$fixed
=
((
isset
(
$field
[
'fixed'
])
&&
$field
[
'fixed'
])
||
$field
[
'type'
]
==
'char'
)
?
true
:
false
;
return
$fixed
?
(
$length
?
'CHAR('
.
$length
.
')'
:
'CHAR('
.
$this
->
conn
->
options
[
'default_text_field_length'
]
.
')'
)
:
(
$length
?
'VARCHAR('
.
$length
.
')'
:
'TEXT'
);
case
'clob'
:
return
'TEXT'
;
case
'blob'
:
return
'BYTEA'
;
case
'enum'
:
case
'integer'
:
case
'int'
:
if
(
!
empty
(
$field
[
'autoincrement'
]))
{
if
(
!
empty
(
$field
[
'length'
]))
{
$length
=
$field
[
'length'
];
if
(
$length
>
4
)
{
return
'BIGSERIAL'
;
}
}
return
'SERIAL'
;
}
if
(
!
empty
(
$field
[
'length'
]))
{
$length
=
$field
[
'length'
];
if
(
$length
<=
2
)
{
return
'SMALLINT'
;
}
elseif
(
$length
==
3
||
$length
==
4
)
{
return
'INT'
;
}
elseif
(
$length
>
4
)
{
return
'BIGINT'
;
}
}
return
'INT'
;
case
'boolean'
:
return
'BOOLEAN'
;
case
'date'
:
return
'DATE'
;
case
'time'
:
return
'TIME without time zone'
;
case
'timestamp'
:
return
'TIMESTAMP without time zone'
;
case
'float'
:
case
'double'
:
return
'FLOAT8'
;
case
'decimal'
:
$length
=
!
empty
(
$field
[
'length'
])
?
$field
[
'length'
]
:
18
;
$scale
=
!
empty
(
$field
[
'scale'
])
?
$field
[
'scale'
]
:
$this
->
conn
->
getAttribute
(
Doctrine
::
ATTR_DECIMAL_PLACES
);
return
'NUMERIC('
.
$length
.
','
.
$scale
.
')'
;
}
throw
new
Doctrine_DataDict_Exception
(
'Unknown field type \''
.
$field
[
'type'
]
.
'\'.'
);
}
/**
* Maps a native array description of a field to a portable Doctrine datatype and length
*
* @param array $field native field description
*
* @return array containing the various possible types, length, sign, fixed
*/
public
function
getPortableDeclaration
(
array
$field
)
{
$length
=
(
isset
(
$field
[
'length'
]))
?
$field
[
'length'
]
:
null
;
if
(
$length
==
'-1'
&&
isset
(
$field
[
'atttypmod'
]))
{
$length
=
$field
[
'atttypmod'
]
-
4
;
}
if
((
int
)
$length
<=
0
)
{
$length
=
null
;
}
$type
=
array
();
$unsigned
=
$fixed
=
null
;
if
(
!
isset
(
$field
[
'name'
]))
{
$field
[
'name'
]
=
''
;
}
$dbType
=
strtolower
(
$field
[
'type'
]);
switch
(
$dbType
)
{
case
'smallint'
:
case
'int2'
:
$type
[]
=
'integer'
;
$unsigned
=
false
;
$length
=
2
;
if
(
$length
==
'2'
)
{
$type
[]
=
'boolean'
;
if
(
preg_match
(
'/^(is|has)/'
,
$field
[
'name'
]))
{
$type
=
array_reverse
(
$type
);
}
}
break
;
case
'int'
:
case
'int4'
:
case
'integer'
:
case
'serial'
:
case
'serial4'
:
$type
[]
=
'integer'
;
$unsigned
=
false
;
$length
=
4
;
break
;
case
'bigint'
:
case
'int8'
:
case
'bigserial'
:
case
'serial8'
:
$type
[]
=
'integer'
;
$unsigned
=
false
;
$length
=
8
;
break
;
case
'bool'
:
case
'boolean'
:
$type
[]
=
'boolean'
;
$length
=
1
;
break
;
case
'text'
:
case
'varchar'
:
$fixed
=
false
;
case
'unknown'
:
case
'char'
:
case
'bpchar'
:
$type
[]
=
'string'
;
if
(
$length
==
'1'
)
{
$type
[]
=
'boolean'
;
if
(
preg_match
(
'/^(is|has)/'
,
$field
[
'name'
]))
{
$type
=
array_reverse
(
$type
);
}
}
elseif
(
strstr
(
$db
_type
,
'text'
))
{
$type
[]
=
'clob'
;
}
if
(
$fixed
!==
false
)
{
$fixed
=
true
;
}
break
;
case
'date'
:
$type
[]
=
'date'
;
$length
=
null
;
break
;
case
'datetime'
:
case
'timestamp'
:
$type
[]
=
'timestamp'
;
$length
=
null
;
break
;
case
'time'
:
$type
[]
=
'time'
;
$length
=
null
;
break
;
case
'float'
:
case
'double'
:
case
'real'
:
$type
[]
=
'float'
;
break
;
case
'decimal'
:
case
'money'
:
case
'numeric'
:
$type
[]
=
'decimal'
;
break
;
case
'tinyblob'
:
case
'mediumblob'
:
case
'longblob'
:
case
'blob'
:
case
'bytea'
:
$type
[]
=
'blob'
;
$length
=
null
;
break
;
case
'oid'
:
$type
[]
=
'blob'
;
$type
[]
=
'clob'
;
$length
=
null
;
break
;
case
'year'
:
$type
[]
=
'integer'
;
$type
[]
=
'date'
;
$length
=
null
;
break
;
default
:
throw
new
Doctrine_DataDict_Exception
(
'unknown database attribute type: '
.
$db
_type
);
}
return
array
(
'type'
=>
$type
,
'length'
=>
$length
,
'unsigned'
=>
$unsigned
,
'fixed'
=>
$fixed
);
}
/**
* Obtain DBMS specific SQL code portion needed to declare an integer type
* field to be used in statements like CREATE TABLE.
*
* @param string $name name the field to be declared.
* @param array $field associative array with the name of the properties
* of the field being declared as array indexes. Currently, the types
* of supported field properties are as follows:
*
* unsigned
* Boolean flag that indicates whether the field should be
* declared as unsigned integer if possible.
*
* default
* Integer value to be used as default for this field.
*
* notnull
* Boolean flag that indicates whether this field is constrained
* to not be set to null.
* @return string DBMS specific SQL code portion that should be used to
* declare the specified field.
*/
public
function
getIntegerDeclaration
(
$name
,
$field
)
{
/**
if (!empty($field['unsigned'])) {
$this->conn->warnings[] = "unsigned integer field \"$name\" is being declared as signed integer";
}
*/
if
(
!
empty
(
$field
[
'autoincrement'
]))
{
$name
=
$this
->
conn
->
quoteIdentifier
(
$name
,
true
);
return
$name
.
' '
.
$this
->
getNativeDeclaration
(
$field
);
}
$default
=
''
;
if
(
array_key_exists
(
'default'
,
$field
))
{
if
(
$field
[
'default'
]
===
''
)
{
$field
[
'default'
]
=
empty
(
$field
[
'notnull'
])
?
null
:
0
;
}
$default
=
' DEFAULT '
.
$this
->
conn
->
quote
(
$field
[
'default'
],
$field
[
'type'
]);
}
/**
TODO: is this needed ?
elseif (empty($field['notnull'])) {
$default = ' DEFAULT NULL';
}
*/
$notnull
=
empty
(
$field
[
'notnull'
])
?
''
:
' NOT NULL'
;
$name
=
$this
->
conn
->
quoteIdentifier
(
$name
,
true
);
return
$name
.
' '
.
$this
->
getNativeDeclaration
(
$field
)
.
$default
.
$notnull
;
}
/**
* parseBoolean
* parses a literal boolean value and returns
* proper sql equivalent
*
* @param string $value boolean value to be parsed
* @return string parsed boolean value
*/
public
function
parseBoolean
(
$value
)
{
return
$value
;
}
}
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.phpdoctrine.com>.
*/
Doctrine
::
autoload
(
'Doctrine_DataDict'
);
/**
* @package Doctrine
* @subpackage Doctrine_DataDict
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
* @author Paul Cooper <pgc@ucecom.com>
* @author Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
* @version $Revision$
* @category Object Relational Mapping
* @link www.phpdoctrine.com
* @since 1.0
*/
class
Doctrine_DataDict_Pgsql
extends
Doctrine_DataDict
{
/**
* @param array $reservedKeyWords an array of reserved keywords by pgsql
*/
protected
static
$reservedKeyWords
=
array
(
'abort'
,
'absolute'
,
'access'
,
'action'
,
'add'
,
'after'
,
'aggregate'
,
'all'
,
'alter'
,
'analyse'
,
'analyze'
,
'and'
,
'any'
,
'as'
,
'asc'
,
'assertion'
,
'assignment'
,
'at'
,
'authorization'
,
'backward'
,
'before'
,
'begin'
,
'between'
,
'bigint'
,
'binary'
,
'bit'
,
'boolean'
,
'both'
,
'by'
,
'cache'
,
'called'
,
'cascade'
,
'case'
,
'cast'
,
'chain'
,
'char'
,
'character'
,
'characteristics'
,
'check'
,
'checkpoint'
,
'class'
,
'close'
,
'cluster'
,
'coalesce'
,
'collate'
,
'column'
,
'comment'
,
'commit'
,
'committed'
,
'constraint'
,
'constraints'
,
'conversion'
,
'convert'
,
'copy'
,
'create'
,
'createdb'
,
'createuser'
,
'cross'
,
'current_date'
,
'current_time'
,
'current_timestamp'
,
'current_user'
,
'cursor'
,
'cycle'
,
'database'
,
'day'
,
'deallocate'
,
'dec'
,
'decimal'
,
'declare'
,
'default'
,
'deferrable'
,
'deferred'
,
'definer'
,
'delete'
,
'delimiter'
,
'delimiters'
,
'desc'
,
'distinct'
,
'do'
,
'domain'
,
'double'
,
'drop'
,
'each'
,
'else'
,
'encoding'
,
'encrypted'
,
'end'
,
'escape'
,
'except'
,
'exclusive'
,
'execute'
,
'exists'
,
'explain'
,
'external'
,
'extract'
,
'false'
,
'fetch'
,
'float'
,
'for'
,
'force'
,
'foreign'
,
'forward'
,
'freeze'
,
'from'
,
'full'
,
'function'
,
'get'
,
'global'
,
'grant'
,
'group'
,
'handler'
,
'having'
,
'hour'
,
'ilike'
,
'immediate'
,
'immutable'
,
'implicit'
,
'in'
,
'increment'
,
'index'
,
'inherits'
,
'initially'
,
'inner'
,
'inout'
,
'input'
,
'insensitive'
,
'insert'
,
'instead'
,
'int'
,
'integer'
,
'intersect'
,
'interval'
,
'into'
,
'invoker'
,
'is'
,
'isnull'
,
'isolation'
,
'join'
,
'key'
,
'lancompiler'
,
'language'
,
'leading'
,
'left'
,
'level'
,
'like'
,
'limit'
,
'listen'
,
'load'
,
'local'
,
'localtime'
,
'localtimestamp'
,
'location'
,
'lock'
,
'match'
,
'maxvalue'
,
'minute'
,
'minvalue'
,
'mode'
,
'month'
,
'move'
,
'names'
,
'national'
,
'natural'
,
'nchar'
,
'new'
,
'next'
,
'no'
,
'nocreatedb'
,
'nocreateuser'
,
'none'
,
'not'
,
'nothing'
,
'notify'
,
'notnull'
,
'null'
,
'nullif'
,
'numeric'
,
'of'
,
'off'
,
'offset'
,
'oids'
,
'old'
,
'on'
,
'only'
,
'operator'
,
'option'
,
'or'
,
'order'
,
'out'
,
'outer'
,
'overlaps'
,
'overlay'
,
'owner'
,
'partial'
,
'password'
,
'path'
,
'pendant'
,
'placing'
,
'position'
,
'precision'
,
'prepare'
,
'primary'
,
'prior'
,
'privileges'
,
'procedural'
,
'procedure'
,
'read'
,
'real'
,
'recheck'
,
'references'
,
'reindex'
,
'relative'
,
'rename'
,
'replace'
,
'reset'
,
'restrict'
,
'returns'
,
'revoke'
,
'right'
,
'rollback'
,
'row'
,
'rule'
,
'schema'
,
'scroll'
,
'second'
,
'security'
,
'select'
,
'sequence'
,
'serializable'
,
'session'
,
'session_user'
,
'set'
,
'setof'
,
'share'
,
'show'
,
'similar'
,
'simple'
,
'smallint'
,
'some'
,
'stable'
,
'start'
,
'statement'
,
'statistics'
,
'stdin'
,
'stdout'
,
'storage'
,
'strict'
,
'substring'
,
'sysid'
,
'table'
,
'temp'
,
'template'
,
'temporary'
,
'then'
,
'time'
,
'timestamp'
,
'to'
,
'toast'
,
'trailing'
,
'transaction'
,
'treat'
,
'trigger'
,
'trim'
,
'true'
,
'truncate'
,
'trusted'
,
'type'
,
'unencrypted'
,
'union'
,
'unique'
,
'unknown'
,
'unlisten'
,
'until'
,
'update'
,
'usage'
,
'user'
,
'using'
,
'vacuum'
,
'valid'
,
'validator'
,
'values'
,
'varchar'
,
'varying'
,
'verbose'
,
'version'
,
'view'
,
'volatile'
,
'when'
,
'where'
,
'with'
,
'without'
,
'work'
,
'write'
,
'year'
,
'zone'
);
/**
* Obtain DBMS specific SQL code portion needed to declare an text type
* field to be used in statements like CREATE TABLE.
*
* @param array $field associative array with the name of the properties
* of the field being declared as array indexes. Currently, the types
* of supported field properties are as follows:
*
* length
* Integer value that determines the maximum length of the text
* field. If this argument is missing the field should be
* declared to have the longest length allowed by the DBMS.
*
* default
* Text value to be used as default for this field.
*
* notnull
* Boolean flag that indicates whether this field is constrained
* to not be set to null.
*
* @return string DBMS specific SQL code portion that should be used to
* declare the specified field.
*/
public
function
getNativeDeclaration
(
array
$field
)
{
if
(
!
isset
(
$field
[
'type'
]))
{
throw
new
Doctrine_DataDict_Exception
(
'Missing column type.'
);
}
switch
(
$field
[
'type'
])
{
case
'char'
:
case
'string'
:
case
'array'
:
case
'object'
:
case
'varchar'
:
case
'gzip'
:
$length
=
(
isset
(
$field
[
'length'
])
&&
$field
[
'length'
])
?
$field
[
'length'
]
:
null
;
// TODO: $this->conn->options['default_text_field_length'];
$fixed
=
((
isset
(
$field
[
'fixed'
])
&&
$field
[
'fixed'
])
||
$field
[
'type'
]
==
'char'
)
?
true
:
false
;
return
$fixed
?
(
$length
?
'CHAR('
.
$length
.
')'
:
'CHAR('
.
$this
->
conn
->
options
[
'default_text_field_length'
]
.
')'
)
:
(
$length
?
'VARCHAR('
.
$length
.
')'
:
'TEXT'
);
case
'clob'
:
return
'TEXT'
;
case
'blob'
:
return
'BYTEA'
;
case
'enum'
:
case
'integer'
:
case
'int'
:
if
(
!
empty
(
$field
[
'autoincrement'
]))
{
if
(
!
empty
(
$field
[
'length'
]))
{
$length
=
$field
[
'length'
];
if
(
$length
>
4
)
{
return
'BIGSERIAL'
;
}
}
return
'SERIAL'
;
}
if
(
!
empty
(
$field
[
'length'
]))
{
$length
=
$field
[
'length'
];
if
(
$length
<=
2
)
{
return
'SMALLINT'
;
}
elseif
(
$length
==
3
||
$length
==
4
)
{
return
'INT'
;
}
elseif
(
$length
>
4
)
{
return
'BIGINT'
;
}
}
return
'INT'
;
case
'boolean'
:
return
'BOOLEAN'
;
case
'date'
:
return
'DATE'
;
case
'time'
:
return
'TIME without time zone'
;
case
'timestamp'
:
return
'TIMESTAMP without time zone'
;
case
'float'
:
case
'double'
:
return
'FLOAT8'
;
case
'decimal'
:
$length
=
!
empty
(
$field
[
'length'
])
?
$field
[
'length'
]
:
18
;
$scale
=
!
empty
(
$field
[
'scale'
])
?
$field
[
'scale'
]
:
$this
->
conn
->
getAttribute
(
Doctrine
::
ATTR_DECIMAL_PLACES
);
return
'NUMERIC('
.
$length
.
','
.
$scale
.
')'
;
}
throw
new
Doctrine_DataDict_Exception
(
'Unknown field type \''
.
$field
[
'type'
]
.
'\'.'
);
}
/**
* Maps a native array description of a field to a portable Doctrine datatype and length
*
* @param array $field native field description
*
* @return array containing the various possible types, length, sign, fixed
*/
public
function
getPortableDeclaration
(
array
$field
)
{
$length
=
(
isset
(
$field
[
'length'
]))
?
$field
[
'length'
]
:
null
;
if
(
$length
==
'-1'
&&
isset
(
$field
[
'atttypmod'
]))
{
$length
=
$field
[
'atttypmod'
]
-
4
;
}
if
((
int
)
$length
<=
0
)
{
$length
=
null
;
}
$type
=
array
();
$unsigned
=
$fixed
=
null
;
if
(
!
isset
(
$field
[
'name'
]))
{
$field
[
'name'
]
=
''
;
}
$dbType
=
strtolower
(
$field
[
'type'
]);
switch
(
$dbType
)
{
case
'smallint'
:
case
'int2'
:
$type
[]
=
'integer'
;
$unsigned
=
false
;
$length
=
2
;
if
(
$length
==
'2'
)
{
$type
[]
=
'boolean'
;
if
(
preg_match
(
'/^(is|has)/'
,
$field
[
'name'
]))
{
$type
=
array_reverse
(
$type
);
}
}
break
;
case
'int'
:
case
'int4'
:
case
'integer'
:
case
'serial'
:
case
'serial4'
:
$type
[]
=
'integer'
;
$unsigned
=
false
;
$length
=
4
;
break
;
case
'bigint'
:
case
'int8'
:
case
'bigserial'
:
case
'serial8'
:
$type
[]
=
'integer'
;
$unsigned
=
false
;
$length
=
8
;
break
;
case
'bool'
:
case
'boolean'
:
$type
[]
=
'boolean'
;
$length
=
1
;
break
;
case
'text'
:
case
'varchar'
:
$fixed
=
false
;
case
'unknown'
:
case
'char'
:
case
'bpchar'
:
$type
[]
=
'string'
;
if
(
$length
==
'1'
)
{
$type
[]
=
'boolean'
;
if
(
preg_match
(
'/^(is|has)/'
,
$field
[
'name'
]))
{
$type
=
array_reverse
(
$type
);
}
}
elseif
(
strstr
(
$db
Type
,
'text'
))
{
$type
[]
=
'clob'
;
}
if
(
$fixed
!==
false
)
{
$fixed
=
true
;
}
break
;
case
'date'
:
$type
[]
=
'date'
;
$length
=
null
;
break
;
case
'datetime'
:
case
'timestamp'
:
$type
[]
=
'timestamp'
;
$length
=
null
;
break
;
case
'time'
:
$type
[]
=
'time'
;
$length
=
null
;
break
;
case
'float'
:
case
'double'
:
case
'real'
:
$type
[]
=
'float'
;
break
;
case
'decimal'
:
case
'money'
:
case
'numeric'
:
$type
[]
=
'decimal'
;
break
;
case
'tinyblob'
:
case
'mediumblob'
:
case
'longblob'
:
case
'blob'
:
case
'bytea'
:
$type
[]
=
'blob'
;
$length
=
null
;
break
;
case
'oid'
:
$type
[]
=
'blob'
;
$type
[]
=
'clob'
;
$length
=
null
;
break
;
case
'year'
:
$type
[]
=
'integer'
;
$type
[]
=
'date'
;
$length
=
null
;
break
;
default
:
throw
new
Doctrine_DataDict_Exception
(
'unknown database attribute type: '
.
$db
Type
);
}
return
array
(
'type'
=>
$type
,
'length'
=>
$length
,
'unsigned'
=>
$unsigned
,
'fixed'
=>
$fixed
);
}
/**
* Obtain DBMS specific SQL code portion needed to declare an integer type
* field to be used in statements like CREATE TABLE.
*
* @param string $name name the field to be declared.
* @param array $field associative array with the name of the properties
* of the field being declared as array indexes. Currently, the types
* of supported field properties are as follows:
*
* unsigned
* Boolean flag that indicates whether the field should be
* declared as unsigned integer if possible.
*
* default
* Integer value to be used as default for this field.
*
* notnull
* Boolean flag that indicates whether this field is constrained
* to not be set to null.
* @return string DBMS specific SQL code portion that should be used to
* declare the specified field.
*/
public
function
getIntegerDeclaration
(
$name
,
$field
)
{
/**
if (!empty($field['unsigned'])) {
$this->conn->warnings[] = "unsigned integer field \"$name\" is being declared as signed integer";
}
*/
if
(
!
empty
(
$field
[
'autoincrement'
]))
{
$name
=
$this
->
conn
->
quoteIdentifier
(
$name
,
true
);
return
$name
.
' '
.
$this
->
getNativeDeclaration
(
$field
);
}
$default
=
''
;
if
(
array_key_exists
(
'default'
,
$field
))
{
if
(
$field
[
'default'
]
===
''
)
{
$field
[
'default'
]
=
empty
(
$field
[
'notnull'
])
?
null
:
0
;
}
$default
=
' DEFAULT '
.
$this
->
conn
->
quote
(
$field
[
'default'
],
$field
[
'type'
]);
}
/**
TODO: is this needed ?
elseif (empty($field['notnull'])) {
$default = ' DEFAULT NULL';
}
*/
$notnull
=
empty
(
$field
[
'notnull'
])
?
''
:
' NOT NULL'
;
$name
=
$this
->
conn
->
quoteIdentifier
(
$name
,
true
);
return
$name
.
' '
.
$this
->
getNativeDeclaration
(
$field
)
.
$default
.
$notnull
;
}
/**
* parseBoolean
* parses a literal boolean value and returns
* proper sql equivalent
*
* @param string $value boolean value to be parsed
* @return string parsed boolean value
*/
public
function
parseBoolean
(
$value
)
{
return
$value
;
}
}
lib/Doctrine/Export.php
View file @
75dbc8c8
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.phpdoctrine.com>.
*/
Doctrine
::
autoload
(
'Doctrine_Connection_Module'
);
/**
* Doctrine_Export
*
* @package Doctrine
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
* @author Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @category Object Relational Mapping
* @link www.phpdoctrine.com
* @since 1.0
* @version $Revision$
*/
class
Doctrine_Export
extends
Doctrine_Connection_Module
{
protected
$valid_default_values
=
array
(
'text'
=>
''
,
'boolean'
=>
true
,
'integer'
=>
0
,
'decimal'
=>
0.0
,
'float'
=>
0.0
,
'timestamp'
=>
'1970-01-01 00:00:00'
,
'time'
=>
'00:00:00'
,
'date'
=>
'1970-01-01'
,
'clob'
=>
''
,
'blob'
=>
''
,
);
/**
* drop an existing database
* (this method is implemented by the drivers)
*
* @param string $name name of the database that should be dropped
* @return void
*/
public
function
dropDatabase
(
$database
)
{
$this
->
conn
->
execute
(
$this
->
dropDatabaseSql
(
$database
));
}
/**
* drop an existing database
* (this method is implemented by the drivers)
*
* @param string $name name of the database that should be dropped
* @return void
*/
public
function
dropDatabaseSql
(
$database
)
{
throw
new
Doctrine_Export_Exception
(
'Drop database not supported by this driver.'
);
}
/**
* dropTableSql
* drop an existing table
*
* @param string $table name of table that should be dropped from the database
* @return string
*/
public
function
dropTableSql
(
$table
)
{
return
'DROP TABLE '
.
$this
->
conn
->
quoteIdentifier
(
$table
);
}
/**
* dropTable
* drop an existing table
*
* @param string $table name of table that should be dropped from the database
* @return void
*/
public
function
dropTable
(
$table
)
{
$this
->
conn
->
execute
(
$this
->
dropTableSql
(
$table
));
}
/**
* drop existing index
*
* @param string $table name of table that should be used in method
* @param string $name name of the index to be dropped
* @return void
*/
public
function
dropIndex
(
$table
,
$name
)
{
return
$this
->
conn
->
exec
(
$this
->
dropIndexSql
(
$table
,
$name
));
}
/**
* dropIndexSql
*
* @param string $table name of table that should be used in method
* @param string $name name of the index to be dropped
* @return string SQL that is used for dropping an index
*/
public
function
dropIndexSql
(
$table
,
$name
)
{
$name
=
$this
->
conn
->
quoteIdentifier
(
$this
->
conn
->
formatter
->
getIndexName
(
$name
));
return
'DROP INDEX '
.
$name
;
}
/**
* drop existing constraint
*
* @param string $table name of table that should be used in method
* @param string $name name of the constraint to be dropped
* @param string $primary hint if the constraint is primary
* @return void
*/
public
function
dropConstraint
(
$table
,
$name
,
$primary
=
false
)
{
$table
=
$this
->
conn
->
quoteIdentifier
(
$table
);
$name
=
$this
->
conn
->
quoteIdentifier
(
$this
->
conn
->
formatter
->
getIndexName
(
$name
));
return
$this
->
conn
->
exec
(
'ALTER TABLE '
.
$table
.
' DROP CONSTRAINT '
.
$name
);
}
/**
* dropSequenceSql
* drop existing sequence
* (this method is implemented by the drivers)
*
* @throws Doctrine_Connection_Exception if something fails at database level
* @param string $sequenceName name of the sequence to be dropped
* @return void
*/
public
function
dropSequence
(
$sequenceName
)
{
$this
->
conn
->
exec
(
$this
->
dropSequenceSql
(
$sequenceName
));
}
/**
* dropSequenceSql
* drop existing sequence
*
* @throws Doctrine_Connection_Exception if something fails at database level
* @param string $sequenceName name of the sequence to be dropped
* @return void
*/
public
function
dropSequenceSql
(
$sequenceName
)
{
throw
new
Doctrine_Export_Exception
(
'Drop sequence not supported by this driver.'
);
}
/**
* create a new database
* (this method is implemented by the drivers)
*
* @param string $name name of the database that should be created
* @return void
*/
public
function
createDatabase
(
$database
)
{
$this
->
conn
->
execute
(
$this
->
createDatabaseSql
(
$database
));
}
/**
* create a new database
* (this method is implemented by the drivers)
*
* @param string $name name of the database that should be created
* @return string
*/
public
function
createDatabaseSql
(
$database
)
{
throw
new
Doctrine_Export_Exception
(
'Create database not supported by this driver.'
);
}
/**
* create a new table
*
* @param string $name Name of the database that should be created
* @param array $fields Associative array that contains the definition of each field of the new table
* The indexes of the array entries are the names of the fields of the table an
* the array entry values are associative arrays like those that are meant to be
* passed with the field definitions to get[Type]Declaration() functions.
* array(
* 'id' => array(
* 'type' => 'integer',
* 'unsigned' => 1
* 'notnull' => 1
* 'default' => 0
* ),
* 'name' => array(
* 'type' => 'text',
* 'length' => 12
* ),
* 'password' => array(
* 'type' => 'text',
* 'length' => 12
* )
* );
* @param array $options An associative array of table options:
*
* @return string
*/
public
function
createTableSql
(
$name
,
array
$fields
,
array
$options
=
array
())
{
if
(
!
$name
)
{
throw
new
Doctrine_Export_Exception
(
'no valid table name specified'
);
}
if
(
empty
(
$fields
))
{
throw
new
Doctrine_Export_Exception
(
'no fields specified for table '
.
$name
);
}
$queryFields
=
$this
->
getFieldDeclarationList
(
$fields
);
if
(
isset
(
$options
[
'primary'
])
&&
!
empty
(
$options
[
'primary'
]))
{
$queryFields
.=
', PRIMARY KEY('
.
implode
(
', '
,
array_values
(
$options
[
'primary'
]))
.
')'
;
}
if
(
isset
(
$options
[
'indexes'
])
&&
!
empty
(
$options
[
'indexes'
]))
{
foreach
(
$options
[
'indexes'
]
as
$index
=>
$definition
)
{
$queryFields
.=
', '
.
$this
->
getIndexDeclaration
(
$index
,
$definition
);
}
}
$name
=
$this
->
conn
->
quoteIdentifier
(
$name
,
true
);
$query
=
'CREATE TABLE '
.
$name
.
' ('
.
$queryFields
.
')'
;
$sql
[]
=
$query
;
if
(
isset
(
$options
[
'foreignKeys'
]))
{
foreach
((
array
)
$options
[
'foreignKeys'
]
as
$k
=>
$definition
)
{
if
(
is_array
(
$definition
))
{
$sql
[]
=
$this
->
createForeignKeySql
(
$name
,
$definition
);
}
}
}
return
$sql
;
}
/**
* create a new table
*
* @param string $name Name of the database that should be created
* @param array $fields Associative array that contains the definition of each field of the new table
* @param array $options An associative array of table options:
* @see Doctrine_Export::createTableSql()
*
* @return void
*/
public
function
createTable
(
$name
,
array
$fields
,
array
$options
=
array
())
{
$sql
=
(
array
)
$this
->
createTableSql
(
$name
,
$fields
,
$options
);
foreach
(
$sql
as
$query
)
{
$this
->
conn
->
execute
(
$query
);
}
}
/**
* create sequence
*
* @throws Doctrine_Connection_Exception if something fails at database level
* @param string $seqName name of the sequence to be created
* @param string $start start value of the sequence; default is 1
* @param array $options An associative array of table options:
* array(
* 'comment' => 'Foo',
* 'charset' => 'utf8',
* 'collate' => 'utf8_unicode_ci',
* );
* @return void
*/
public
function
createSequence
(
$seqName
,
$start
=
1
,
array
$options
=
array
())
{
return
$this
->
conn
->
execute
(
$this
->
createSequenceSql
(
$seqName
,
$start
=
1
,
$options
));
}
/**
* return RDBMS specific create sequence statement
* (this method is implemented by the drivers)
*
* @throws Doctrine_Connection_Exception if something fails at database level
* @param string $seqName name of the sequence to be created
* @param string $start start value of the sequence; default is 1
* @param array $options An associative array of table options:
* array(
* 'comment' => 'Foo',
* 'charset' => 'utf8',
* 'collate' => 'utf8_unicode_ci',
* );
* @return string
*/
public
function
createSequenceSql
(
$seqName
,
$start
=
1
,
array
$options
=
array
())
{
throw
new
Doctrine_Export_Exception
(
'Create sequence not supported by this driver.'
);
}
/**
* create a constraint on a table
*
* @param string $table name of the table on which the constraint is to be created
* @param string $name name of the constraint to be created
* @param array $definition associative array that defines properties of the constraint to be created.
* Currently, only one property named FIELDS is supported. This property
* is also an associative with the names of the constraint fields as array
* constraints. Each entry of this array is set to another type of associative
* array that specifies properties of the constraint that are specific to
* each field.
*
* Example
* array(
* 'fields' => array(
* 'user_name' => array(),
* 'last_login' => array()
* )
* )
* @return void
*/
public
function
createConstraint
(
$table
,
$name
,
$definition
)
{
return
$this
->
conn
->
exec
(
$this
->
createConstraintSql
(
$table
,
$name
,
$definition
));
}
/**
* create a constraint on a table
*
* @param string $table name of the table on which the constraint is to be created
* @param string $name name of the constraint to be created
* @param array $definition associative array that defines properties of the constraint to be created.
* Currently, only one property named FIELDS is supported. This property
* is also an associative with the names of the constraint fields as array
* constraints. Each entry of this array is set to another type of associative
* array that specifies properties of the constraint that are specific to
* each field.
*
* Example
* array(
* 'fields' => array(
* 'user_name' => array(),
* 'last_login' => array()
* )
* )
* @return void
*/
public
function
createConstraintSql
(
$table
,
$name
,
$definition
)
{
$table
=
$this
->
conn
->
quoteIdentifier
(
$table
);
$name
=
$this
->
conn
->
quoteIdentifier
(
$this
->
conn
->
formatter
->
getIndexName
(
$name
));
$query
=
'ALTER TABLE '
.
$table
.
' ADD CONSTRAINT '
.
$name
;
if
(
isset
(
$definition
[
'primary'
])
&&
$definition
[
'primary'
])
{
$query
.=
' PRIMARY KEY'
;
}
elseif
(
isset
(
$definition
[
'unique'
])
&&
$definition
[
'unique'
])
{
$query
.=
' UNIQUE'
;
}
$fields
=
array
();
foreach
(
array_keys
(
$definition
[
'fields'
])
as
$field
)
{
$fields
[]
=
$this
->
conn
->
quoteIdentifier
(
$field
,
true
);
}
$query
.=
' ('
.
implode
(
', '
,
$fields
)
.
')'
;
return
$query
;
}
/**
* Get the stucture of a field into an array
*
* @param string $table name of the table on which the index is to be created
* @param string $name name of the index to be created
* @param array $definition associative array that defines properties of the index to be created.
* Currently, only one property named FIELDS is supported. This property
* is also an associative with the names of the index fields as array
* indexes. Each entry of this array is set to another type of associative
* array that specifies properties of the index that are specific to
* each field.
*
* Currently, only the sorting property is supported. It should be used
* to define the sorting direction of the index. It may be set to either
* ascending or descending.
*
* Not all DBMS support index sorting direction configuration. The DBMS
* drivers of those that do not support it ignore this property. Use the
* function supports() to determine whether the DBMS driver can manage indexes.
*
* Example
* array(
* 'fields' => array(
* 'user_name' => array(
* 'sorting' => 'ascending'
* ),
* 'last_login' => array()
* )
* )
* @return void
*/
public
function
createIndex
(
$table
,
$name
,
array
$definition
)
{
return
$this
->
conn
->
execute
(
$this
->
createIndexSql
(
$table
,
$name
,
$definition
));
}
/**
* Get the stucture of a field into an array
*
* @param string $table name of the table on which the index is to be created
* @param string $name name of the index to be created
* @param array $definition associative array that defines properties of the index to be created.
* @see Doctrine_Export::createIndex()
* @return string
*/
public
function
createIndexSql
(
$table
,
$name
,
array
$definition
)
{
$table
=
$this
->
conn
->
quoteIdentifier
(
$table
);
$name
=
$this
->
conn
->
quoteIdentifier
(
$name
);
$type
=
''
;
if
(
isset
(
$definition
[
'type'
]))
{
switch
(
strtolower
(
$definition
[
'type'
]))
{
case
'unique'
:
$type
=
strtoupper
(
$definition
[
'type'
])
.
' '
;
break
;
default
:
throw
new
Doctrine_Export_Exception
(
'Unknown index type '
.
$definition
[
'type'
]);
}
}
$query
=
'CREATE '
.
$type
.
'INDEX '
.
$name
.
' ON '
.
$table
;
$fields
=
array
();
foreach
(
array_keys
(
$definition
[
'fields'
])
as
$field
)
{
$fields
[]
=
$this
->
conn
->
quoteIdentifier
(
$field
);
}
$query
.=
' ('
.
implode
(
', '
,
$fields
)
.
')'
;
return
$query
;
}
/**
* createForeignKeySql
*
* @param string $table name of the table on which the foreign key is to be created
* @param array $definition associative array that defines properties of the foreign key to be created.
* @return string
*/
public
function
createForeignKeySql
(
$table
,
array
$definition
)
{
$table
=
$this
->
conn
->
quoteIdentifier
(
$table
);
$query
=
'ALTER TABLE '
.
$table
.
' ADD CONSTRAINT '
.
$this
->
getForeignKeyDeclaration
(
$definition
);
return
$query
;
}
/**
* alter an existing table
* (this method is implemented by the drivers)
*
* @param string $name name of the table that is intended to be changed.
* @param array $changes associative array that contains the details of each type
* of change that is intended to be performed. The types of
* changes that are currently supported are defined as follows:
*
* name
*
* New name for the table.
*
* add
*
* Associative array with the names of fields to be added as
* indexes of the array. The value of each entry of the array
* should be set to another associative array with the properties
* of the fields to be added. The properties of the fields should
* be the same as defined by the MDB2 parser.
*
*
* remove
*
* Associative array with the names of fields to be removed as indexes
* of the array. Currently the values assigned to each entry are ignored.
* An empty array should be used for future compatibility.
*
* rename
*
* Associative array with the names of fields to be renamed as indexes
* of the array. The value of each entry of the array should be set to
* another associative array with the entry named name with the new
* field name and the entry named Declaration that is expected to contain
* the portion of the field declaration already in DBMS specific SQL code
* as it is used in the CREATE TABLE statement.
*
* change
*
* Associative array with the names of the fields to be changed as indexes
* of the array. Keep in mind that if it is intended to change either the
* name of a field and any other properties, the change array entries
* should have the new names of the fields as array indexes.
*
* The value of each entry of the array should be set to another associative
* array with the properties of the fields to that are meant to be changed as
* array entries. These entries should be assigned to the new values of the
* respective properties. The properties of the fields should be the same
* as defined by the MDB2 parser.
*
* Example
* array(
* 'name' => 'userlist',
* 'add' => array(
* 'quota' => array(
* 'type' => 'integer',
* 'unsigned' => 1
* )
* ),
* 'remove' => array(
* 'file_limit' => array(),
* 'time_limit' => array()
* ),
* 'change' => array(
* 'name' => array(
* 'length' => '20',
* 'definition' => array(
* 'type' => 'text',
* 'length' => 20,
* ),
* )
* ),
* 'rename' => array(
* 'sex' => array(
* 'name' => 'gender',
* 'definition' => array(
* 'type' => 'text',
* 'length' => 1,
* 'default' => 'M',
* ),
* )
* )
* )
*
* @param boolean $check indicates whether the function should just check if the DBMS driver
* can perform the requested table alterations if the value is true or
* actually perform them otherwise.
* @return void
*/
public
function
alterTable
(
$name
,
array
$changes
,
$check
)
{
$this
->
conn
->
execute
(
$this
->
alterTableSql
(
$name
,
$changes
,
$check
));
}
/**
* generates the sql for altering an existing table
* (this method is implemented by the drivers)
*
* @param string $name name of the table that is intended to be changed.
* @param array $changes associative array that contains the details of each type *
* @param boolean $check indicates whether the function should just check if the DBMS driver
* can perform the requested table alterations if the value is true or
* actually perform them otherwise.
* @see Doctrine_Export::alterTable()
* @return string
*/
public
function
alterTableSql
(
$name
,
array
$changes
,
$check
)
{
throw
new
Doctrine_Export_Exception
(
'Alter table not supported by this driver.'
);
}
/**
* Get declaration of a number of field in bulk
*
* @param array $fields a multidimensional associative array.
* The first dimension determines the field name, while the second
* dimension is keyed with the name of the properties
* of the field being declared as array indexes. Currently, the types
* of supported field properties are as follows:
*
* length
* Integer value that determines the maximum length of the text
* field. If this argument is missing the field should be
* declared to have the longest length allowed by the DBMS.
*
* default
* Text value to be used as default for this field.
*
* notnull
* Boolean flag that indicates whether this field is constrained
* to not be set to null.
* charset
* Text value with the default CHARACTER SET for this field.
* collation
* Text value with the default COLLATION for this field.
* unique
* unique constraint
*
* @return string
*/
public
function
getFieldDeclarationList
(
array
$fields
)
{
foreach
(
$fields
as
$fieldName
=>
$field
)
{
$query
=
$this
->
getDeclaration
(
$fieldName
,
$field
);
$queryFields
[]
=
$query
;
}
return
implode
(
', '
,
$queryFields
);
}
/**
* Obtain DBMS specific SQL code portion needed to declare a generic type
* field to be used in statements like CREATE TABLE.
*
* @param string $name name the field to be declared.
* @param array $field associative array with the name of the properties
* of the field being declared as array indexes. Currently, the types
* of supported field properties are as follows:
*
* length
* Integer value that determines the maximum length of the text
* field. If this argument is missing the field should be
* declared to have the longest length allowed by the DBMS.
*
* default
* Text value to be used as default for this field.
*
* notnull
* Boolean flag that indicates whether this field is constrained
* to not be set to null.
* charset
* Text value with the default CHARACTER SET for this field.
* collation
* Text value with the default COLLATION for this field.
* unique
* unique constraint
* check
* column check constraint
*
* @return string DBMS specific SQL code portion that should be used to
* declare the specified field.
*/
public
function
getDeclaration
(
$name
,
array
$field
)
{
$default
=
$this
->
getDefaultFieldDeclaration
(
$field
);
$charset
=
(
isset
(
$field
[
'charset'
])
&&
$field
[
'charset'
])
?
' '
.
$this
->
getCharsetFieldDeclaration
(
$field
[
'charset'
])
:
''
;
$collation
=
(
isset
(
$field
[
'collation'
])
&&
$field
[
'collation'
])
?
' '
.
$this
->
getCollationFieldDeclaration
(
$field
[
'collation'
])
:
''
;
$notnull
=
(
isset
(
$field
[
'notnull'
])
&&
$field
[
'notnull'
])
?
' NOT NULL'
:
''
;
$unique
=
(
isset
(
$field
[
'unique'
])
&&
$field
[
'unique'
])
?
' '
.
$this
->
getUniqueFieldDeclaration
()
:
''
;
$check
=
(
isset
(
$field
[
'check'
])
&&
$field
[
'check'
])
?
' '
.
$field
[
'check'
]
:
''
;
$method
=
'get'
.
$field
[
'type'
]
.
'Declaration'
;
if
(
method_exists
(
$this
->
conn
->
dataDict
,
$method
))
{
return
$this
->
conn
->
dataDict
->
$method
(
$name
,
$field
);
}
else
{
$dec
=
$this
->
conn
->
dataDict
->
getNativeDeclaration
(
$field
);
}
return
$this
->
conn
->
quoteIdentifier
(
$name
,
true
)
.
' '
.
$dec
.
$charset
.
$default
.
$notnull
.
$unique
.
$check
.
$collation
;
}
/**
* getDefaultDeclaration
* Obtain DBMS specific SQL code portion needed to set a default value
* declaration to be used in statements like CREATE TABLE.
*
* @param array $field field definition array
* @return string DBMS specific SQL code portion needed to set a default value
*/
public
function
getDefaultFieldDeclaration
(
$field
)
{
$default
=
''
;
if
(
isset
(
$field
[
'default'
]))
{
if
(
$field
[
'default'
]
===
''
)
{
$field
[
'default'
]
=
empty
(
$field
[
'notnull'
])
?
null
:
$this
->
valid_default_values
[
$field
[
'type'
]];
if
(
$field
[
'default'
]
===
''
&&
(
$conn
->
getAttribute
(
Doctrine
::
ATTR_PORTABILITY
)
&
Doctrine
::
PORTABILITY_EMPTY_TO_NULL
))
{
$field
[
'default'
]
=
null
;
}
}
if
(
$field
[
'type'
]
===
'boolean'
)
{
$fields
[
'default'
]
=
$this
->
conn
->
convertBooleans
(
$field
[
'default'
]);
}
$default
=
' DEFAULT '
.
$this
->
conn
->
quote
(
$field
[
'default'
],
$field
[
'type'
]);
}
return
$default
;
}
/**
* Obtain DBMS specific SQL code portion needed to set an index
* declaration to be used in statements like CREATE TABLE.
*
* @param string $charset name of the index
* @param array $definition index definition
* @return string DBMS specific SQL code portion needed to set an index
*/
public
function
getIndexDeclaration
(
$name
,
array
$definition
)
{
$name
=
$this
->
conn
->
quoteIdentifier
(
$name
);
$type
=
''
;
if
(
isset
(
$definition
[
'type'
]))
{
if
(
strtolower
(
$definition
[
'type'
])
==
'unique'
)
{
$type
=
strtoupper
(
$definition
[
'type'
])
.
' '
;
}
else
{
throw
new
Doctrine_Export_Exception
(
'Unknown index type '
.
$definition
[
'type'
]);
}
}
if
(
!
isset
(
$definition
[
'fields'
])
||
!
is_array
(
$definition
[
'fields'
]))
{
throw
new
Doctrine_Export_Exception
(
'No index columns given.'
);
}
$query
=
$type
.
'INDEX '
.
$name
;
$query
.=
' ('
.
$this
->
getIndexFieldDeclarationList
(
$definition
[
'fields'
])
.
')'
;
return
$query
;
}
/**
* getIndexFieldDeclarationList
* Obtain DBMS specific SQL code portion needed to set an index
* declaration to be used in statements like CREATE TABLE.
*
* @return string
*/
public
function
getIndexFieldDeclarationList
(
array
$fields
)
{
$ret
=
array
();
foreach
(
$fields
as
$field
=>
$definition
)
{
if
(
is_array
(
$definition
))
{
$ret
[]
=
$this
->
conn
->
quoteIdentifier
(
$field
);
}
else
{
$ret
[]
=
$this
->
conn
->
quoteIdentifier
(
$definition
);
}
}
return
implode
(
', '
,
$ret
);
}
/**
* A method to return the required SQL string that fits between CREATE ... TABLE
* to create the table as a temporary table.
*
* Should be overridden in driver classes to return the correct string for the
* specific database type.
*
* The default is to return the string "TEMPORARY" - this will result in a
* SQL error for any database that does not support temporary tables, or that
* requires a different SQL command from "CREATE TEMPORARY TABLE".
*
* @return string The string required to be placed between "CREATE" and "TABLE"
* to generate a temporary table, if possible.
*/
public
function
getTemporaryTableQuery
()
{
return
'TEMPORARY'
;
}
/**
* getForeignKeyDeclaration
* Obtain DBMS specific SQL code portion needed to set the FOREIGN KEY constraint
* of a field declaration to be used in statements like CREATE TABLE.
*
* @param array $definition an associative array with the following structure:
* name optional constraint name
*
* local the local field(s)
*
* foreign the foreign reference field(s)
*
* foreignTable the name of the foreign table
*
* onDelete referential delete action
*
* onUpdate referential update action
*
* deferred deferred constraint checking
*
* The onDelete and onUpdate keys accept the following values:
*
* CASCADE: Delete or update the row from the parent table and automatically delete or
* update the matching rows in the child table. Both ON DELETE CASCADE and ON UPDATE CASCADE are supported.
* Between two tables, you should not define several ON UPDATE CASCADE clauses that act on the same column
* in the parent table or in the child table.
*
* SET NULL: Delete or update the row from the parent table and set the foreign key column or columns in the
* child table to NULL. This is valid only if the foreign key columns do not have the NOT NULL qualifier
* specified. Both ON DELETE SET NULL and ON UPDATE SET NULL clauses are supported.
*
* NO ACTION: In standard SQL, NO ACTION means no action in the sense that an attempt to delete or update a primary
* key value is not allowed to proceed if there is a related foreign key value in the referenced table.
*
* RESTRICT: Rejects the delete or update operation for the parent table. NO ACTION and RESTRICT are the same as
* omitting the ON DELETE or ON UPDATE clause.
*
* SET DEFAULT
*
* @return string DBMS specific SQL code portion needed to set the FOREIGN KEY constraint
* of a field declaration.
*/
public
function
getForeignKeyDeclaration
(
array
$definition
)
{
$sql
=
$this
->
getForeignKeyBaseDeclaration
(
$definition
);
$sql
.=
$this
->
getAdvancedForeignKeyOptions
(
$definition
);
return
$sql
;
}
/**
* getAdvancedForeignKeyOptions
* Return the FOREIGN KEY query section dealing with non-standard options
* as MATCH, INITIALLY DEFERRED, ON UPDATE, ...
*
* @param array $definition foreign key definition
* @return string
*/
public
function
getAdvancedForeignKeyOptions
(
array
$definition
)
{
$query
=
''
;
if
(
!
empty
(
$definition
[
'onUpdate'
]))
{
$query
.=
' ON UPDATE '
.
$this
->
getForeignKeyRefentialAction
(
$definition
[
'onUpdate'
]);
}
if
(
!
empty
(
$definition
[
'onDelete'
]))
{
$query
.=
' ON DELETE '
.
$this
->
getForeignKeyRefentialAction
(
$definition
[
'onDelete'
]);
}
return
$query
;
}
/**
* getForeignKeyReferentialAction
*
* returns given referential action in uppercase if valid, otherwise throws
* an exception
*
* @throws Doctrine_Exception_Exception if unknown referential action given
* @param string $action foreign key referential action
* @param string foreign key referential action in uppercase
*/
public
function
getForeignKeyReferentialAction
(
$action
)
{
$upper
=
strtoupper
(
$action
);
switch
(
$upper
)
{
case
'CASCADE'
:
case
'SET NULL'
:
case
'NO ACTION'
:
case
'RESTRICT'
:
case
'SET DEFAULT'
:
return
$upper
;
break
;
default
:
throw
new
Doctrine_Export_Exception
(
'Unknown foreign key referential action \''
.
$upper
.
'\' given.'
);
}
}
/**
* getForeignKeyBaseDeclaration
* Obtain DBMS specific SQL code portion needed to set the FOREIGN KEY constraint
* of a field declaration to be used in statements like CREATE TABLE.
*
* @param array $definition
* @return string
*/
public
function
getForeignKeyBaseDeclaration
(
array
$definition
)
{
$sql
=
''
;
if
(
isset
(
$definition
[
'name'
]))
{
$sql
.=
'CONSTRAINT '
.
$this
->
conn
->
quoteIdentifier
(
$definition
[
'name'
])
.
' '
;
}
$sql
.=
'FOREIGN KEY ('
;
if
(
!
isset
(
$definition
[
'local'
]))
{
throw
new
Doctrine_Export_Exception
(
'Local reference field missing from definition.'
);
}
if
(
!
isset
(
$definition
[
'foreign'
]))
{
throw
new
Doctrine_Export_Exception
(
'Foreign reference field missing from definition.'
);
}
if
(
!
isset
(
$definition
[
'foreignTable'
]))
{
throw
new
Doctrine_Export_Exception
(
'Foreign reference table missing from definition.'
);
}
if
(
!
is_array
(
$definition
[
'local'
]))
{
$definition
[
'local'
]
=
array
(
$definition
[
'local'
]);
}
if
(
!
is_array
(
$definition
[
'foreign'
]))
{
$definition
[
'foreign'
]
=
array
(
$definition
[
'foreign'
]);
}
$sql
.=
implode
(
', '
,
array_map
(
array
(
$this
->
conn
,
'quoteIdentifier'
),
$definition
[
'local'
]))
.
') REFERENCES '
.
$definition
[
'foreignTable'
]
.
'('
.
implode
(
', '
,
array_map
(
array
(
$this
->
conn
,
'quoteIdentifier'
),
$definition
[
'foreign'
]))
.
')'
;
return
$sql
;
}
/**
* Obtain DBMS specific SQL code portion needed to set the UNIQUE constraint
* of a field declaration to be used in statements like CREATE TABLE.
*
* @return string DBMS specific SQL code portion needed to set the UNIQUE constraint
* of a field declaration.
*/
public
function
getUniqueFieldDeclaration
()
{
return
'UNIQUE'
;
}
/**
* Obtain DBMS specific SQL code portion needed to set the CHARACTER SET
* of a field declaration to be used in statements like CREATE TABLE.
*
* @param string $charset name of the charset
* @return string DBMS specific SQL code portion needed to set the CHARACTER SET
* of a field declaration.
*/
public
function
getCharsetFieldDeclaration
(
$charset
)
{
return
''
;
}
/**
* Obtain DBMS specific SQL code portion needed to set the COLLATION
* of a field declaration to be used in statements like CREATE TABLE.
*
* @param string $collation name of the collation
* @return string DBMS specific SQL code portion needed to set the COLLATION
* of a field declaration.
*/
public
function
getCollationFieldDeclaration
(
$collation
)
{
return
''
;
}
/**
* export
* method for exporting Doctrine_Record classes to a schema
*
* if the directory parameter is given this method first iterates
* recursively trhough the given directory in order to find any model classes
*
* Then it iterates through all declared classes and creates tables for the ones
* that extend Doctrine_Record and are not abstract classes
*
* @throws Doctrine_Connection_Exception if some error other than Doctrine::ERR_ALREADY_EXISTS
* occurred during the create table operation
* @param string $directory optional directory parameter
* @return void
*/
public
function
export
(
$directory
=
null
)
{
$sql
=
$this
->
exportSql
(
$directory
);
$this
->
conn
->
beginTransaction
();
foreach
(
$sql
as
$query
)
{
try
{
$this
->
conn
->
exec
(
$query
);
}
catch
(
Doctrine_Connection_Exception
$e
)
{
// we only want to silence table already exists errors
if
(
$e
->
getPortableCode
()
!==
Doctrine
::
ERR_ALREADY_EXISTS
)
{
$this
->
conn
->
rollback
();
throw
$e
;
}
}
}
$this
->
conn
->
commit
();
}
/**
* exportClasses
* method for exporting Doctrine_Record classes to a schema
*
* @throws Doctrine_Connection_Exception if some error other than Doctrine::ERR_ALREADY_EXISTS
* occurred during the create table operation
* @param array $classes
* @return void
*/
public
function
exportClasses
(
array
$classes
)
{
$sql
=
$this
->
exportClassesSql
(
$classes
);
$this
->
conn
->
beginTransaction
();
foreach
(
$sql
as
$query
)
{
try
{
$this
->
conn
->
exec
(
$query
);
}
catch
(
Doctrine_Connection_Exception
$e
)
{
// we only want to silence table already exists errors
if
(
$e
->
getPortableCode
()
!==
Doctrine
::
ERR_ALREADY_EXISTS
)
{
$this
->
conn
->
rollback
();
throw
$e
;
}
}
}
$this
->
conn
->
commit
();
}
/**
* exportClassesSql
* method for exporting Doctrine_Record classes to a schema
*
* @throws Doctrine_Connection_Exception if some error other than Doctrine::ERR_ALREADY_EXISTS
* occurred during the create table operation
* @param array $classes
* @return void
*/
public
function
exportClassesSql
(
array
$classes
)
{
$parent
=
new
ReflectionClass
(
'Doctrine_Record'
);
$sql
=
array
();
$fks
=
array
();
// we iterate trhough the diff of previously declared classes
// and currently declared classes
foreach
(
$classes
as
$name
)
{
$class
=
new
ReflectionClass
(
$name
);
$conn
=
Doctrine_Manager
::
getInstance
()
->
getConnectionForComponent
(
$name
);
// check if class is an instance of Doctrine_Record and not abstract
// class must have method setTableDefinition (to avoid non-Record subclasses like symfony's sfDoctrineRecord)
if
(
$class
->
isSubclassOf
(
$parent
)
&&
!
$class
->
isAbstract
()
&&
method_exists
(
$class
->
getName
(),
'setTableDefinition'
))
{
$record
=
new
$name
();
$table
=
$record
->
getTable
();
$data
=
$table
->
getExportableFormat
();
$query
=
$this
->
conn
->
export
->
createTableSql
(
$data
[
'tableName'
],
$data
[
'columns'
],
$data
[
'options'
]);
if
(
is_array
(
$query
))
{
$sql
=
array_merge
(
$sql
,
$query
);
}
else
{
$sql
[]
=
$query
;
}
}
}
$sql
=
array_unique
(
$sql
);
rsort
(
$sql
);
return
$sql
;
}
/**
* exportSql
* returns the sql for exporting Doctrine_Record classes to a schema
*
* if the directory parameter is given this method first iterates
* recursively trhough the given directory in order to find any model classes
*
* Then it iterates through all declared classes and creates tables for the ones
* that extend Doctrine_Record and are not abstract classes
*
* @throws Doctrine_Connection_Exception if some error other than Doctrine::ERR_ALREADY_EXISTS
* occurred during the create table operation
* @param string $directory optional directory parameter
* @return void
*/
public
function
exportSql
(
$directory
=
null
)
{
$declared
=
get_declared_classes
();
if
(
$directory
!==
null
)
{
foreach
((
array
)
$directory
as
$dir
)
{
$it
=
new
RecursiveIteratorIterator
(
new
RecursiveDirectoryIterator
(
$dir
),
RecursiveIteratorIterator
::
LEAVES_ONLY
);
foreach
(
$it
as
$file
)
{
$e
=
explode
(
'.'
,
$file
->
getFileName
());
if
(
end
(
$e
)
===
'php'
&&
strpos
(
$file
->
getFileName
(),
'.inc'
)
===
false
)
{
require_once
$file
->
getPathName
();
}
}
}
$declared
=
array_diff
(
get_declared_classes
(),
$declared
);
}
return
$this
->
exportClassesSql
(
$declared
);
}
/**
* exportTable
* exports given table into database based on column and option definitions
*
* @throws Doctrine_Connection_Exception if some error other than Doctrine::ERR_ALREADY_EXISTS
* occurred during the create table operation
* @return boolean whether or not the export operation was successful
* false if table already existed in the database
*/
public
function
exportTable
(
Doctrine_Table
$table
)
{
/**
TODO: maybe there should be portability option for the following check
if ( ! Doctrine::isValidClassname($table->getOption('declaringClass')->getName())) {
throw new Doctrine_Export_Exception('Class name not valid.');
}
*/
try
{
$data
=
$table
->
getExportableFormat
();
$this
->
conn
->
export
->
createTable
(
$data
[
'tableName'
],
$data
[
'columns'
],
$data
[
'options'
]);
}
catch
(
Doctrine_Connection_Exception
$e
)
{
// we only want to silence table already exists errors
if
(
$e
->
getPortableCode
()
!==
Doctrine
::
ERR_ALREADY_EXISTS
)
{
throw
$e
;
}
}
}
}
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.phpdoctrine.com>.
*/
Doctrine
::
autoload
(
'Doctrine_Connection_Module'
);
/**
* Doctrine_Export
*
* @package Doctrine
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
* @author Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @category Object Relational Mapping
* @link www.phpdoctrine.com
* @since 1.0
* @version $Revision$
*/
class
Doctrine_Export
extends
Doctrine_Connection_Module
{
protected
$valid_default_values
=
array
(
'text'
=>
''
,
'boolean'
=>
true
,
'integer'
=>
0
,
'decimal'
=>
0.0
,
'float'
=>
0.0
,
'timestamp'
=>
'1970-01-01 00:00:00'
,
'time'
=>
'00:00:00'
,
'date'
=>
'1970-01-01'
,
'clob'
=>
''
,
'blob'
=>
''
,
'string'
=>
''
);
/**
* drop an existing database
* (this method is implemented by the drivers)
*
* @param string $name name of the database that should be dropped
* @return void
*/
public
function
dropDatabase
(
$database
)
{
$this
->
conn
->
execute
(
$this
->
dropDatabaseSql
(
$database
));
}
/**
* drop an existing database
* (this method is implemented by the drivers)
*
* @param string $name name of the database that should be dropped
* @return void
*/
public
function
dropDatabaseSql
(
$database
)
{
throw
new
Doctrine_Export_Exception
(
'Drop database not supported by this driver.'
);
}
/**
* dropTableSql
* drop an existing table
*
* @param string $table name of table that should be dropped from the database
* @return string
*/
public
function
dropTableSql
(
$table
)
{
return
'DROP TABLE '
.
$this
->
conn
->
quoteIdentifier
(
$table
);
}
/**
* dropTable
* drop an existing table
*
* @param string $table name of table that should be dropped from the database
* @return void
*/
public
function
dropTable
(
$table
)
{
$this
->
conn
->
execute
(
$this
->
dropTableSql
(
$table
));
}
/**
* drop existing index
*
* @param string $table name of table that should be used in method
* @param string $name name of the index to be dropped
* @return void
*/
public
function
dropIndex
(
$table
,
$name
)
{
return
$this
->
conn
->
exec
(
$this
->
dropIndexSql
(
$table
,
$name
));
}
/**
* dropIndexSql
*
* @param string $table name of table that should be used in method
* @param string $name name of the index to be dropped
* @return string SQL that is used for dropping an index
*/
public
function
dropIndexSql
(
$table
,
$name
)
{
$name
=
$this
->
conn
->
quoteIdentifier
(
$this
->
conn
->
formatter
->
getIndexName
(
$name
));
return
'DROP INDEX '
.
$name
;
}
/**
* drop existing constraint
*
* @param string $table name of table that should be used in method
* @param string $name name of the constraint to be dropped
* @param string $primary hint if the constraint is primary
* @return void
*/
public
function
dropConstraint
(
$table
,
$name
,
$primary
=
false
)
{
$table
=
$this
->
conn
->
quoteIdentifier
(
$table
);
$name
=
$this
->
conn
->
quoteIdentifier
(
$this
->
conn
->
formatter
->
getIndexName
(
$name
));
return
$this
->
conn
->
exec
(
'ALTER TABLE '
.
$table
.
' DROP CONSTRAINT '
.
$name
);
}
/**
* dropSequenceSql
* drop existing sequence
* (this method is implemented by the drivers)
*
* @throws Doctrine_Connection_Exception if something fails at database level
* @param string $sequenceName name of the sequence to be dropped
* @return void
*/
public
function
dropSequence
(
$sequenceName
)
{
$this
->
conn
->
exec
(
$this
->
dropSequenceSql
(
$sequenceName
));
}
/**
* dropSequenceSql
* drop existing sequence
*
* @throws Doctrine_Connection_Exception if something fails at database level
* @param string $sequenceName name of the sequence to be dropped
* @return void
*/
public
function
dropSequenceSql
(
$sequenceName
)
{
throw
new
Doctrine_Export_Exception
(
'Drop sequence not supported by this driver.'
);
}
/**
* create a new database
* (this method is implemented by the drivers)
*
* @param string $name name of the database that should be created
* @return void
*/
public
function
createDatabase
(
$database
)
{
$this
->
conn
->
execute
(
$this
->
createDatabaseSql
(
$database
));
}
/**
* create a new database
* (this method is implemented by the drivers)
*
* @param string $name name of the database that should be created
* @return string
*/
public
function
createDatabaseSql
(
$database
)
{
throw
new
Doctrine_Export_Exception
(
'Create database not supported by this driver.'
);
}
/**
* create a new table
*
* @param string $name Name of the database that should be created
* @param array $fields Associative array that contains the definition of each field of the new table
* The indexes of the array entries are the names of the fields of the table an
* the array entry values are associative arrays like those that are meant to be
* passed with the field definitions to get[Type]Declaration() functions.
* array(
* 'id' => array(
* 'type' => 'integer',
* 'unsigned' => 1
* 'notnull' => 1
* 'default' => 0
* ),
* 'name' => array(
* 'type' => 'text',
* 'length' => 12
* ),
* 'password' => array(
* 'type' => 'text',
* 'length' => 12
* )
* );
* @param array $options An associative array of table options:
*
* @return string
*/
public
function
createTableSql
(
$name
,
array
$fields
,
array
$options
=
array
())
{
if
(
!
$name
)
{
throw
new
Doctrine_Export_Exception
(
'no valid table name specified'
);
}
if
(
empty
(
$fields
))
{
throw
new
Doctrine_Export_Exception
(
'no fields specified for table '
.
$name
);
}
$queryFields
=
$this
->
getFieldDeclarationList
(
$fields
);
if
(
isset
(
$options
[
'primary'
])
&&
!
empty
(
$options
[
'primary'
]))
{
$queryFields
.=
', PRIMARY KEY('
.
implode
(
', '
,
array_values
(
$options
[
'primary'
]))
.
')'
;
}
if
(
isset
(
$options
[
'indexes'
])
&&
!
empty
(
$options
[
'indexes'
]))
{
foreach
(
$options
[
'indexes'
]
as
$index
=>
$definition
)
{
$queryFields
.=
', '
.
$this
->
getIndexDeclaration
(
$index
,
$definition
);
}
}
$name
=
$this
->
conn
->
quoteIdentifier
(
$name
,
true
);
$query
=
'CREATE TABLE '
.
$name
.
' ('
.
$queryFields
.
')'
;
$sql
[]
=
$query
;
if
(
isset
(
$options
[
'foreignKeys'
]))
{
foreach
((
array
)
$options
[
'foreignKeys'
]
as
$k
=>
$definition
)
{
if
(
is_array
(
$definition
))
{
$sql
[]
=
$this
->
createForeignKeySql
(
$name
,
$definition
);
}
}
}
return
$sql
;
}
/**
* create a new table
*
* @param string $name Name of the database that should be created
* @param array $fields Associative array that contains the definition of each field of the new table
* @param array $options An associative array of table options:
* @see Doctrine_Export::createTableSql()
*
* @return void
*/
public
function
createTable
(
$name
,
array
$fields
,
array
$options
=
array
())
{
$sql
=
(
array
)
$this
->
createTableSql
(
$name
,
$fields
,
$options
);
foreach
(
$sql
as
$query
)
{
$this
->
conn
->
execute
(
$query
);
}
}
/**
* create sequence
*
* @throws Doctrine_Connection_Exception if something fails at database level
* @param string $seqName name of the sequence to be created
* @param string $start start value of the sequence; default is 1
* @param array $options An associative array of table options:
* array(
* 'comment' => 'Foo',
* 'charset' => 'utf8',
* 'collate' => 'utf8_unicode_ci',
* );
* @return void
*/
public
function
createSequence
(
$seqName
,
$start
=
1
,
array
$options
=
array
())
{
return
$this
->
conn
->
execute
(
$this
->
createSequenceSql
(
$seqName
,
$start
=
1
,
$options
));
}
/**
* return RDBMS specific create sequence statement
* (this method is implemented by the drivers)
*
* @throws Doctrine_Connection_Exception if something fails at database level
* @param string $seqName name of the sequence to be created
* @param string $start start value of the sequence; default is 1
* @param array $options An associative array of table options:
* array(
* 'comment' => 'Foo',
* 'charset' => 'utf8',
* 'collate' => 'utf8_unicode_ci',
* );
* @return string
*/
public
function
createSequenceSql
(
$seqName
,
$start
=
1
,
array
$options
=
array
())
{
throw
new
Doctrine_Export_Exception
(
'Create sequence not supported by this driver.'
);
}
/**
* create a constraint on a table
*
* @param string $table name of the table on which the constraint is to be created
* @param string $name name of the constraint to be created
* @param array $definition associative array that defines properties of the constraint to be created.
* Currently, only one property named FIELDS is supported. This property
* is also an associative with the names of the constraint fields as array
* constraints. Each entry of this array is set to another type of associative
* array that specifies properties of the constraint that are specific to
* each field.
*
* Example
* array(
* 'fields' => array(
* 'user_name' => array(),
* 'last_login' => array()
* )
* )
* @return void
*/
public
function
createConstraint
(
$table
,
$name
,
$definition
)
{
return
$this
->
conn
->
exec
(
$this
->
createConstraintSql
(
$table
,
$name
,
$definition
));
}
/**
* create a constraint on a table
*
* @param string $table name of the table on which the constraint is to be created
* @param string $name name of the constraint to be created
* @param array $definition associative array that defines properties of the constraint to be created.
* Currently, only one property named FIELDS is supported. This property
* is also an associative with the names of the constraint fields as array
* constraints. Each entry of this array is set to another type of associative
* array that specifies properties of the constraint that are specific to
* each field.
*
* Example
* array(
* 'fields' => array(
* 'user_name' => array(),
* 'last_login' => array()
* )
* )
* @return void
*/
public
function
createConstraintSql
(
$table
,
$name
,
$definition
)
{
$table
=
$this
->
conn
->
quoteIdentifier
(
$table
);
$name
=
$this
->
conn
->
quoteIdentifier
(
$this
->
conn
->
formatter
->
getIndexName
(
$name
));
$query
=
'ALTER TABLE '
.
$table
.
' ADD CONSTRAINT '
.
$name
;
if
(
isset
(
$definition
[
'primary'
])
&&
$definition
[
'primary'
])
{
$query
.=
' PRIMARY KEY'
;
}
elseif
(
isset
(
$definition
[
'unique'
])
&&
$definition
[
'unique'
])
{
$query
.=
' UNIQUE'
;
}
$fields
=
array
();
foreach
(
array_keys
(
$definition
[
'fields'
])
as
$field
)
{
$fields
[]
=
$this
->
conn
->
quoteIdentifier
(
$field
,
true
);
}
$query
.=
' ('
.
implode
(
', '
,
$fields
)
.
')'
;
return
$query
;
}
/**
* Get the stucture of a field into an array
*
* @param string $table name of the table on which the index is to be created
* @param string $name name of the index to be created
* @param array $definition associative array that defines properties of the index to be created.
* Currently, only one property named FIELDS is supported. This property
* is also an associative with the names of the index fields as array
* indexes. Each entry of this array is set to another type of associative
* array that specifies properties of the index that are specific to
* each field.
*
* Currently, only the sorting property is supported. It should be used
* to define the sorting direction of the index. It may be set to either
* ascending or descending.
*
* Not all DBMS support index sorting direction configuration. The DBMS
* drivers of those that do not support it ignore this property. Use the
* function supports() to determine whether the DBMS driver can manage indexes.
*
* Example
* array(
* 'fields' => array(
* 'user_name' => array(
* 'sorting' => 'ascending'
* ),
* 'last_login' => array()
* )
* )
* @return void
*/
public
function
createIndex
(
$table
,
$name
,
array
$definition
)
{
return
$this
->
conn
->
execute
(
$this
->
createIndexSql
(
$table
,
$name
,
$definition
));
}
/**
* Get the stucture of a field into an array
*
* @param string $table name of the table on which the index is to be created
* @param string $name name of the index to be created
* @param array $definition associative array that defines properties of the index to be created.
* @see Doctrine_Export::createIndex()
* @return string
*/
public
function
createIndexSql
(
$table
,
$name
,
array
$definition
)
{
$table
=
$this
->
conn
->
quoteIdentifier
(
$table
);
$name
=
$this
->
conn
->
quoteIdentifier
(
$name
);
$type
=
''
;
if
(
isset
(
$definition
[
'type'
]))
{
switch
(
strtolower
(
$definition
[
'type'
]))
{
case
'unique'
:
$type
=
strtoupper
(
$definition
[
'type'
])
.
' '
;
break
;
default
:
throw
new
Doctrine_Export_Exception
(
'Unknown index type '
.
$definition
[
'type'
]);
}
}
$query
=
'CREATE '
.
$type
.
'INDEX '
.
$name
.
' ON '
.
$table
;
$fields
=
array
();
foreach
(
$definition
[
'fields'
]
as
$field
)
{
$fields
[]
=
$this
->
conn
->
quoteIdentifier
(
$field
);
}
$query
.=
' ('
.
implode
(
', '
,
$fields
)
.
')'
;
return
$query
;
}
/**
* createForeignKeySql
*
* @param string $table name of the table on which the foreign key is to be created
* @param array $definition associative array that defines properties of the foreign key to be created.
* @return string
*/
public
function
createForeignKeySql
(
$table
,
array
$definition
)
{
$table
=
$this
->
conn
->
quoteIdentifier
(
$table
);
$query
=
'ALTER TABLE '
.
$table
.
' ADD CONSTRAINT '
.
$this
->
getForeignKeyDeclaration
(
$definition
);
return
$query
;
}
/**
* alter an existing table
* (this method is implemented by the drivers)
*
* @param string $name name of the table that is intended to be changed.
* @param array $changes associative array that contains the details of each type
* of change that is intended to be performed. The types of
* changes that are currently supported are defined as follows:
*
* name
*
* New name for the table.
*
* add
*
* Associative array with the names of fields to be added as
* indexes of the array. The value of each entry of the array
* should be set to another associative array with the properties
* of the fields to be added. The properties of the fields should
* be the same as defined by the MDB2 parser.
*
*
* remove
*
* Associative array with the names of fields to be removed as indexes
* of the array. Currently the values assigned to each entry are ignored.
* An empty array should be used for future compatibility.
*
* rename
*
* Associative array with the names of fields to be renamed as indexes
* of the array. The value of each entry of the array should be set to
* another associative array with the entry named name with the new
* field name and the entry named Declaration that is expected to contain
* the portion of the field declaration already in DBMS specific SQL code
* as it is used in the CREATE TABLE statement.
*
* change
*
* Associative array with the names of the fields to be changed as indexes
* of the array. Keep in mind that if it is intended to change either the
* name of a field and any other properties, the change array entries
* should have the new names of the fields as array indexes.
*
* The value of each entry of the array should be set to another associative
* array with the properties of the fields to that are meant to be changed as
* array entries. These entries should be assigned to the new values of the
* respective properties. The properties of the fields should be the same
* as defined by the MDB2 parser.
*
* Example
* array(
* 'name' => 'userlist',
* 'add' => array(
* 'quota' => array(
* 'type' => 'integer',
* 'unsigned' => 1
* )
* ),
* 'remove' => array(
* 'file_limit' => array(),
* 'time_limit' => array()
* ),
* 'change' => array(
* 'name' => array(
* 'length' => '20',
* 'definition' => array(
* 'type' => 'text',
* 'length' => 20,
* ),
* )
* ),
* 'rename' => array(
* 'sex' => array(
* 'name' => 'gender',
* 'definition' => array(
* 'type' => 'text',
* 'length' => 1,
* 'default' => 'M',
* ),
* )
* )
* )
*
* @param boolean $check indicates whether the function should just check if the DBMS driver
* can perform the requested table alterations if the value is true or
* actually perform them otherwise.
* @return void
*/
public
function
alterTable
(
$name
,
array
$changes
,
$check
)
{
$this
->
conn
->
execute
(
$this
->
alterTableSql
(
$name
,
$changes
,
$check
));
}
/**
* generates the sql for altering an existing table
* (this method is implemented by the drivers)
*
* @param string $name name of the table that is intended to be changed.
* @param array $changes associative array that contains the details of each type *
* @param boolean $check indicates whether the function should just check if the DBMS driver
* can perform the requested table alterations if the value is true or
* actually perform them otherwise.
* @see Doctrine_Export::alterTable()
* @return string
*/
public
function
alterTableSql
(
$name
,
array
$changes
,
$check
)
{
throw
new
Doctrine_Export_Exception
(
'Alter table not supported by this driver.'
);
}
/**
* Get declaration of a number of field in bulk
*
* @param array $fields a multidimensional associative array.
* The first dimension determines the field name, while the second
* dimension is keyed with the name of the properties
* of the field being declared as array indexes. Currently, the types
* of supported field properties are as follows:
*
* length
* Integer value that determines the maximum length of the text
* field. If this argument is missing the field should be
* declared to have the longest length allowed by the DBMS.
*
* default
* Text value to be used as default for this field.
*
* notnull
* Boolean flag that indicates whether this field is constrained
* to not be set to null.
* charset
* Text value with the default CHARACTER SET for this field.
* collation
* Text value with the default COLLATION for this field.
* unique
* unique constraint
*
* @return string
*/
public
function
getFieldDeclarationList
(
array
$fields
)
{
foreach
(
$fields
as
$fieldName
=>
$field
)
{
$query
=
$this
->
getDeclaration
(
$fieldName
,
$field
);
$queryFields
[]
=
$query
;
}
return
implode
(
', '
,
$queryFields
);
}
/**
* Obtain DBMS specific SQL code portion needed to declare a generic type
* field to be used in statements like CREATE TABLE.
*
* @param string $name name the field to be declared.
* @param array $field associative array with the name of the properties
* of the field being declared as array indexes. Currently, the types
* of supported field properties are as follows:
*
* length
* Integer value that determines the maximum length of the text
* field. If this argument is missing the field should be
* declared to have the longest length allowed by the DBMS.
*
* default
* Text value to be used as default for this field.
*
* notnull
* Boolean flag that indicates whether this field is constrained
* to not be set to null.
* charset
* Text value with the default CHARACTER SET for this field.
* collation
* Text value with the default COLLATION for this field.
* unique
* unique constraint
* check
* column check constraint
*
* @return string DBMS specific SQL code portion that should be used to
* declare the specified field.
*/
public
function
getDeclaration
(
$name
,
array
$field
)
{
$default
=
$this
->
getDefaultFieldDeclaration
(
$field
);
$charset
=
(
isset
(
$field
[
'charset'
])
&&
$field
[
'charset'
])
?
' '
.
$this
->
getCharsetFieldDeclaration
(
$field
[
'charset'
])
:
''
;
$collation
=
(
isset
(
$field
[
'collation'
])
&&
$field
[
'collation'
])
?
' '
.
$this
->
getCollationFieldDeclaration
(
$field
[
'collation'
])
:
''
;
$notnull
=
(
isset
(
$field
[
'notnull'
])
&&
$field
[
'notnull'
])
?
' NOT NULL'
:
''
;
$unique
=
(
isset
(
$field
[
'unique'
])
&&
$field
[
'unique'
])
?
' '
.
$this
->
getUniqueFieldDeclaration
()
:
''
;
$check
=
(
isset
(
$field
[
'check'
])
&&
$field
[
'check'
])
?
' '
.
$field
[
'check'
]
:
''
;
$method
=
'get'
.
$field
[
'type'
]
.
'Declaration'
;
if
(
method_exists
(
$this
->
conn
->
dataDict
,
$method
))
{
return
$this
->
conn
->
dataDict
->
$method
(
$name
,
$field
);
}
else
{
$dec
=
$this
->
conn
->
dataDict
->
getNativeDeclaration
(
$field
);
}
return
$this
->
conn
->
quoteIdentifier
(
$name
,
true
)
.
' '
.
$dec
.
$charset
.
$default
.
$notnull
.
$unique
.
$check
.
$collation
;
}
/**
* getDefaultDeclaration
* Obtain DBMS specific SQL code portion needed to set a default value
* declaration to be used in statements like CREATE TABLE.
*
* @param array $field field definition array
* @return string DBMS specific SQL code portion needed to set a default value
*/
public
function
getDefaultFieldDeclaration
(
$field
)
{
$default
=
''
;
if
(
isset
(
$field
[
'default'
]))
{
if
(
$field
[
'default'
]
===
''
)
{
$field
[
'default'
]
=
empty
(
$field
[
'notnull'
])
?
null
:
$this
->
valid_default_values
[
$field
[
'type'
]];
if
(
$field
[
'default'
]
===
''
&&
(
$this
->
conn
->
getAttribute
(
Doctrine
::
ATTR_PORTABILITY
)
&
Doctrine
::
PORTABILITY_EMPTY_TO_NULL
))
{
$field
[
'default'
]
=
null
;
}
}
if
(
$field
[
'type'
]
===
'boolean'
)
{
$fields
[
'default'
]
=
$this
->
conn
->
convertBooleans
(
$field
[
'default'
]);
}
$default
=
' DEFAULT '
.
$this
->
conn
->
quote
(
$field
[
'default'
],
$field
[
'type'
]);
}
return
$default
;
}
/**
* Obtain DBMS specific SQL code portion needed to set an index
* declaration to be used in statements like CREATE TABLE.
*
* @param string $charset name of the index
* @param array $definition index definition
* @return string DBMS specific SQL code portion needed to set an index
*/
public
function
getIndexDeclaration
(
$name
,
array
$definition
)
{
$name
=
$this
->
conn
->
quoteIdentifier
(
$name
);
$type
=
''
;
if
(
isset
(
$definition
[
'type'
]))
{
if
(
strtolower
(
$definition
[
'type'
])
==
'unique'
)
{
$type
=
strtoupper
(
$definition
[
'type'
])
.
' '
;
}
else
{
throw
new
Doctrine_Export_Exception
(
'Unknown index type '
.
$definition
[
'type'
]);
}
}
if
(
!
isset
(
$definition
[
'fields'
])
||
!
is_array
(
$definition
[
'fields'
]))
{
throw
new
Doctrine_Export_Exception
(
'No index columns given.'
);
}
$query
=
$type
.
'INDEX '
.
$name
;
$query
.=
' ('
.
$this
->
getIndexFieldDeclarationList
(
$definition
[
'fields'
])
.
')'
;
return
$query
;
}
/**
* getIndexFieldDeclarationList
* Obtain DBMS specific SQL code portion needed to set an index
* declaration to be used in statements like CREATE TABLE.
*
* @return string
*/
public
function
getIndexFieldDeclarationList
(
array
$fields
)
{
$ret
=
array
();
foreach
(
$fields
as
$field
=>
$definition
)
{
if
(
is_array
(
$definition
))
{
$ret
[]
=
$this
->
conn
->
quoteIdentifier
(
$field
);
}
else
{
$ret
[]
=
$this
->
conn
->
quoteIdentifier
(
$definition
);
}
}
return
implode
(
', '
,
$ret
);
}
/**
* A method to return the required SQL string that fits between CREATE ... TABLE
* to create the table as a temporary table.
*
* Should be overridden in driver classes to return the correct string for the
* specific database type.
*
* The default is to return the string "TEMPORARY" - this will result in a
* SQL error for any database that does not support temporary tables, or that
* requires a different SQL command from "CREATE TEMPORARY TABLE".
*
* @return string The string required to be placed between "CREATE" and "TABLE"
* to generate a temporary table, if possible.
*/
public
function
getTemporaryTableQuery
()
{
return
'TEMPORARY'
;
}
/**
* getForeignKeyDeclaration
* Obtain DBMS specific SQL code portion needed to set the FOREIGN KEY constraint
* of a field declaration to be used in statements like CREATE TABLE.
*
* @param array $definition an associative array with the following structure:
* name optional constraint name
*
* local the local field(s)
*
* foreign the foreign reference field(s)
*
* foreignTable the name of the foreign table
*
* onDelete referential delete action
*
* onUpdate referential update action
*
* deferred deferred constraint checking
*
* The onDelete and onUpdate keys accept the following values:
*
* CASCADE: Delete or update the row from the parent table and automatically delete or
* update the matching rows in the child table. Both ON DELETE CASCADE and ON UPDATE CASCADE are supported.
* Between two tables, you should not define several ON UPDATE CASCADE clauses that act on the same column
* in the parent table or in the child table.
*
* SET NULL: Delete or update the row from the parent table and set the foreign key column or columns in the
* child table to NULL. This is valid only if the foreign key columns do not have the NOT NULL qualifier
* specified. Both ON DELETE SET NULL and ON UPDATE SET NULL clauses are supported.
*
* NO ACTION: In standard SQL, NO ACTION means no action in the sense that an attempt to delete or update a primary
* key value is not allowed to proceed if there is a related foreign key value in the referenced table.
*
* RESTRICT: Rejects the delete or update operation for the parent table. NO ACTION and RESTRICT are the same as
* omitting the ON DELETE or ON UPDATE clause.
*
* SET DEFAULT
*
* @return string DBMS specific SQL code portion needed to set the FOREIGN KEY constraint
* of a field declaration.
*/
public
function
getForeignKeyDeclaration
(
array
$definition
)
{
$sql
=
$this
->
getForeignKeyBaseDeclaration
(
$definition
);
$sql
.=
$this
->
getAdvancedForeignKeyOptions
(
$definition
);
return
$sql
;
}
/**
* getAdvancedForeignKeyOptions
* Return the FOREIGN KEY query section dealing with non-standard options
* as MATCH, INITIALLY DEFERRED, ON UPDATE, ...
*
* @param array $definition foreign key definition
* @return string
*/
public
function
getAdvancedForeignKeyOptions
(
array
$definition
)
{
$query
=
''
;
if
(
!
empty
(
$definition
[
'onUpdate'
]))
{
$query
.=
' ON UPDATE '
.
$this
->
getForeignKeyRefentialAction
(
$definition
[
'onUpdate'
]);
}
if
(
!
empty
(
$definition
[
'onDelete'
]))
{
$query
.=
' ON DELETE '
.
$this
->
getForeignKeyRefentialAction
(
$definition
[
'onDelete'
]);
}
return
$query
;
}
/**
* getForeignKeyReferentialAction
*
* returns given referential action in uppercase if valid, otherwise throws
* an exception
*
* @throws Doctrine_Exception_Exception if unknown referential action given
* @param string $action foreign key referential action
* @param string foreign key referential action in uppercase
*/
public
function
getForeignKeyReferentialAction
(
$action
)
{
$upper
=
strtoupper
(
$action
);
switch
(
$upper
)
{
case
'CASCADE'
:
case
'SET NULL'
:
case
'NO ACTION'
:
case
'RESTRICT'
:
case
'SET DEFAULT'
:
return
$upper
;
break
;
default
:
throw
new
Doctrine_Export_Exception
(
'Unknown foreign key referential action \''
.
$upper
.
'\' given.'
);
}
}
/**
* getForeignKeyBaseDeclaration
* Obtain DBMS specific SQL code portion needed to set the FOREIGN KEY constraint
* of a field declaration to be used in statements like CREATE TABLE.
*
* @param array $definition
* @return string
*/
public
function
getForeignKeyBaseDeclaration
(
array
$definition
)
{
$sql
=
''
;
if
(
isset
(
$definition
[
'name'
]))
{
$sql
.=
'CONSTRAINT '
.
$this
->
conn
->
quoteIdentifier
(
$definition
[
'name'
])
.
' '
;
}
$sql
.=
'FOREIGN KEY ('
;
if
(
!
isset
(
$definition
[
'local'
]))
{
throw
new
Doctrine_Export_Exception
(
'Local reference field missing from definition.'
);
}
if
(
!
isset
(
$definition
[
'foreign'
]))
{
throw
new
Doctrine_Export_Exception
(
'Foreign reference field missing from definition.'
);
}
if
(
!
isset
(
$definition
[
'foreignTable'
]))
{
throw
new
Doctrine_Export_Exception
(
'Foreign reference table missing from definition.'
);
}
if
(
!
is_array
(
$definition
[
'local'
]))
{
$definition
[
'local'
]
=
array
(
$definition
[
'local'
]);
}
if
(
!
is_array
(
$definition
[
'foreign'
]))
{
$definition
[
'foreign'
]
=
array
(
$definition
[
'foreign'
]);
}
$sql
.=
implode
(
', '
,
array_map
(
array
(
$this
->
conn
,
'quoteIdentifier'
),
$definition
[
'local'
]))
.
') REFERENCES '
.
$definition
[
'foreignTable'
]
.
'('
.
implode
(
', '
,
array_map
(
array
(
$this
->
conn
,
'quoteIdentifier'
),
$definition
[
'foreign'
]))
.
')'
;
return
$sql
;
}
/**
* Obtain DBMS specific SQL code portion needed to set the UNIQUE constraint
* of a field declaration to be used in statements like CREATE TABLE.
*
* @return string DBMS specific SQL code portion needed to set the UNIQUE constraint
* of a field declaration.
*/
public
function
getUniqueFieldDeclaration
()
{
return
'UNIQUE'
;
}
/**
* Obtain DBMS specific SQL code portion needed to set the CHARACTER SET
* of a field declaration to be used in statements like CREATE TABLE.
*
* @param string $charset name of the charset
* @return string DBMS specific SQL code portion needed to set the CHARACTER SET
* of a field declaration.
*/
public
function
getCharsetFieldDeclaration
(
$charset
)
{
return
''
;
}
/**
* Obtain DBMS specific SQL code portion needed to set the COLLATION
* of a field declaration to be used in statements like CREATE TABLE.
*
* @param string $collation name of the collation
* @return string DBMS specific SQL code portion needed to set the COLLATION
* of a field declaration.
*/
public
function
getCollationFieldDeclaration
(
$collation
)
{
return
''
;
}
/**
* export
* method for exporting Doctrine_Record classes to a schema
*
* if the directory parameter is given this method first iterates
* recursively trhough the given directory in order to find any model classes
*
* Then it iterates through all declared classes and creates tables for the ones
* that extend Doctrine_Record and are not abstract classes
*
* @throws Doctrine_Connection_Exception if some error other than Doctrine::ERR_ALREADY_EXISTS
* occurred during the create table operation
* @param string $directory optional directory parameter
* @return void
*/
public
function
export
(
$directory
=
null
)
{
$sql
=
$this
->
exportSql
(
$directory
);
$this
->
conn
->
beginTransaction
();
foreach
(
$sql
as
$query
)
{
try
{
$this
->
conn
->
exec
(
$query
);
}
catch
(
Doctrine_Connection_Exception
$e
)
{
// we only want to silence table already exists errors
if
(
$e
->
getPortableCode
()
!==
Doctrine
::
ERR_ALREADY_EXISTS
)
{
$this
->
conn
->
rollback
();
throw
$e
;
}
}
}
$this
->
conn
->
commit
();
}
/**
* exportClasses
* method for exporting Doctrine_Record classes to a schema
*
* @throws Doctrine_Connection_Exception if some error other than Doctrine::ERR_ALREADY_EXISTS
* occurred during the create table operation
* @param array $classes
* @return void
*/
public
function
exportClasses
(
array
$classes
)
{
$sql
=
$this
->
exportClassesSql
(
$classes
);
$this
->
conn
->
beginTransaction
();
foreach
(
$sql
as
$query
)
{
try
{
$this
->
conn
->
exec
(
$query
);
}
catch
(
Doctrine_Connection_Exception
$e
)
{
// we only want to silence table already exists errors
if
(
$e
->
getPortableCode
()
!==
Doctrine
::
ERR_ALREADY_EXISTS
)
{
$this
->
conn
->
rollback
();
throw
$e
;
}
}
}
$this
->
conn
->
commit
();
}
/**
* exportClassesSql
* method for exporting Doctrine_Record classes to a schema
*
* @throws Doctrine_Connection_Exception if some error other than Doctrine::ERR_ALREADY_EXISTS
* occurred during the create table operation
* @param array $classes
* @return void
*/
public
function
exportClassesSql
(
array
$classes
)
{
$parent
=
new
ReflectionClass
(
'Doctrine_Record'
);
$sql
=
array
();
$fks
=
array
();
// we iterate trhough the diff of previously declared classes
// and currently declared classes
foreach
(
$classes
as
$name
)
{
$class
=
new
ReflectionClass
(
$name
);
$conn
=
Doctrine_Manager
::
getInstance
()
->
getConnectionForComponent
(
$name
);
// check if class is an instance of Doctrine_Record and not abstract
// class must have method setTableDefinition (to avoid non-Record subclasses like symfony's sfDoctrineRecord)
if
(
$class
->
isSubclassOf
(
$parent
)
&&
!
$class
->
isAbstract
()
&&
method_exists
(
$class
->
getName
(),
'setTableDefinition'
))
{
$record
=
new
$name
();
$table
=
$record
->
getTable
();
$data
=
$table
->
getExportableFormat
();
$query
=
$this
->
conn
->
export
->
createTableSql
(
$data
[
'tableName'
],
$data
[
'columns'
],
$data
[
'options'
]);
if
(
is_array
(
$query
))
{
$sql
=
array_merge
(
$sql
,
$query
);
}
else
{
$sql
[]
=
$query
;
}
}
}
$sql
=
array_unique
(
$sql
);
rsort
(
$sql
);
return
$sql
;
}
/**
* exportSql
* returns the sql for exporting Doctrine_Record classes to a schema
*
* if the directory parameter is given this method first iterates
* recursively trhough the given directory in order to find any model classes
*
* Then it iterates through all declared classes and creates tables for the ones
* that extend Doctrine_Record and are not abstract classes
*
* @throws Doctrine_Connection_Exception if some error other than Doctrine::ERR_ALREADY_EXISTS
* occurred during the create table operation
* @param string $directory optional directory parameter
* @return void
*/
public
function
exportSql
(
$directory
=
null
)
{
$declared
=
get_declared_classes
();
if
(
$directory
!==
null
)
{
foreach
((
array
)
$directory
as
$dir
)
{
$it
=
new
RecursiveIteratorIterator
(
new
RecursiveDirectoryIterator
(
$dir
),
RecursiveIteratorIterator
::
LEAVES_ONLY
);
foreach
(
$it
as
$file
)
{
$e
=
explode
(
'.'
,
$file
->
getFileName
());
if
(
end
(
$e
)
===
'php'
&&
strpos
(
$file
->
getFileName
(),
'.inc'
)
===
false
)
{
require_once
$file
->
getPathName
();
}
}
}
$declared
=
array_diff
(
get_declared_classes
(),
$declared
);
}
return
$this
->
exportClassesSql
(
$declared
);
}
/**
* exportTable
* exports given table into database based on column and option definitions
*
* @throws Doctrine_Connection_Exception if some error other than Doctrine::ERR_ALREADY_EXISTS
* occurred during the create table operation
* @return boolean whether or not the export operation was successful
* false if table already existed in the database
*/
public
function
exportTable
(
Doctrine_Table
$table
)
{
/**
TODO: maybe there should be portability option for the following check
if ( ! Doctrine::isValidClassname($table->getOption('declaringClass')->getName())) {
throw new Doctrine_Export_Exception('Class name not valid.');
}
*/
try
{
$data
=
$table
->
getExportableFormat
();
$this
->
conn
->
export
->
createTable
(
$data
[
'tableName'
],
$data
[
'columns'
],
$data
[
'options'
]);
}
catch
(
Doctrine_Connection_Exception
$e
)
{
// we only want to silence table already exists errors
if
(
$e
->
getPortableCode
()
!==
Doctrine
::
ERR_ALREADY_EXISTS
)
{
throw
$e
;
}
}
}
}
lib/Doctrine/Export/Pgsql.php
View file @
75dbc8c8
...
...
@@ -283,5 +283,68 @@ class Doctrine_Export_Pgsql extends Doctrine_Export
return
'DROP SEQUENCE '
.
$sequenceName
;
}
/**
* Creates a table.
*
* @param unknown_type $name
* @param array $fields
* @param array $options
* @return unknown
*/
public
function
createTableSql
(
$name
,
array
$fields
,
array
$options
=
array
())
{
if
(
!
$name
)
{
throw
new
Doctrine_Export_Exception
(
'no valid table name specified'
);
}
if
(
empty
(
$fields
))
{
throw
new
Doctrine_Export_Exception
(
'no fields specified for table '
.
$name
);
}
$queryFields
=
$this
->
getFieldDeclarationList
(
$fields
);
if
(
isset
(
$options
[
'primary'
])
&&
!
empty
(
$options
[
'primary'
]))
{
$queryFields
.=
', PRIMARY KEY('
.
implode
(
', '
,
array_values
(
$options
[
'primary'
]))
.
')'
;
}
$name
=
$this
->
conn
->
quoteIdentifier
(
$name
,
true
);
$query
=
'CREATE TABLE '
.
$name
.
' ('
.
$queryFields
.
')'
;
$sql
[]
=
$query
;
if
(
isset
(
$options
[
'indexes'
])
&&
!
empty
(
$options
[
'indexes'
]))
{
foreach
(
$options
[
'indexes'
]
as
$index
=>
$definition
)
{
$sql
[]
=
$this
->
createIndexSql
(
$name
,
$index
,
$definition
);
}
}
if
(
isset
(
$options
[
'foreignKeys'
]))
{
foreach
((
array
)
$options
[
'foreignKeys'
]
as
$k
=>
$definition
)
{
if
(
is_array
(
$definition
))
{
$sql
[]
=
$this
->
createForeignKeySql
(
$name
,
$definition
);
}
}
}
return
$sql
;
}
/**
* createForeignKeySql
*
* @param string $table name of the table on which the foreign key is to be created
* @param array $definition associative array that defines properties of the foreign key to be created.
* @return string
*/
public
function
createForeignKeySql
(
$table
,
array
$definition
)
{
$table
=
$this
->
conn
->
quoteIdentifier
(
$table
);
$query
=
'ALTER TABLE '
.
$table
.
' ADD '
.
$this
->
getForeignKeyDeclaration
(
$definition
);
return
$query
;
}
}
tests/Export/PgsqlTestCase.php
View file @
75dbc8c8
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.phpdoctrine.com>.
*/
/**
* Doctrine_Export_Mysql_TestCase
*
* @package Doctrine
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @category Object Relational Mapping
* @link www.phpdoctrine.com
* @since 1.0
* @version $Revision$
*/
class
Doctrine_Export_Pgsql_TestCase
extends
Doctrine_UnitTestCase
{
public
function
testCreateDatabaseExecutesSql
()
{
$this
->
export
->
createDatabase
(
'db'
);
$this
->
assertEqual
(
$this
->
adapter
->
pop
(),
'CREATE DATABASE db'
);
}
public
function
testDropDatabaseExecutesSql
()
{
$this
->
export
->
dropDatabase
(
'db'
);
$this
->
assertEqual
(
$this
->
adapter
->
pop
(),
'DROP DATABASE db'
);
}
public
function
testCreateTableSupportsAutoincPks
()
{
$name
=
'mytable'
;
$fields
=
array
(
'id'
=>
array
(
'type'
=>
'integer'
,
'unsigned'
=>
1
,
'autoincrement'
=>
true
));
$options
=
array
(
'primary'
=>
array
(
'id'
));
$this
->
export
->
createTable
(
$name
,
$fields
,
$options
);
$this
->
assertEqual
(
$this
->
adapter
->
pop
(),
'CREATE TABLE mytable (id SERIAL, PRIMARY KEY(id))'
);
}
public
function
testCreateTableSupportsDefaultAttribute
()
{
$name
=
'mytable'
;
$fields
=
array
(
'name'
=>
array
(
'type'
=>
'char'
,
'length'
=>
10
,
'default'
=>
'def'
),
'type'
=>
array
(
'type'
=>
'integer'
,
'length'
=>
3
,
'default'
=>
12
)
);
$options
=
array
(
'primary'
=>
array
(
'name'
,
'type'
));
$this
->
export
->
createTable
(
$name
,
$fields
,
$options
);
$this
->
assertEqual
(
$this
->
adapter
->
pop
(),
'CREATE TABLE mytable (name CHAR(10) DEFAULT \'def\', type INT DEFAULT 12, PRIMARY KEY(name, type))'
);
}
public
function
testCreateTableSupportsMultiplePks
()
{
$name
=
'mytable'
;
$fields
=
array
(
'name'
=>
array
(
'type'
=>
'char'
,
'length'
=>
10
),
'type'
=>
array
(
'type'
=>
'integer'
,
'length'
=>
3
));
$options
=
array
(
'primary'
=>
array
(
'name'
,
'type'
));
$this
->
export
->
createTable
(
$name
,
$fields
,
$options
);
$this
->
assertEqual
(
$this
->
adapter
->
pop
(),
'CREATE TABLE mytable (name CHAR(10), type INT, PRIMARY KEY(name, type))'
);
}
public
function
testExportSql
()
{
$sql
=
$this
->
export
->
exportSql
(
dirname
(
__FILE__
)
.
DIRECTORY_SEPARATOR
.
'_files'
);
$this
->
assertEqual
(
$sql
,
array
(
0
=>
'CREATE TABLE foo_reference (foo1 BIGINT, foo2 BIGINT, PRIMARY KEY(foo1, foo2))'
,
1
=>
'CREATE TABLE foo_locally_owned (id BIGSERIAL, name VARCHAR(200), PRIMARY KEY(id))'
,
2
=>
'CREATE TABLE foo_foreignly_owned_with_pk (id BIGSERIAL, name VARCHAR(200), PRIMARY KEY(id))'
,
3
=>
'CREATE TABLE foo_foreignly_owned (id BIGSERIAL, name VARCHAR(200), fooid BIGINT, PRIMARY KEY(id))'
,
4
=>
'CREATE TABLE foo_bar_record (fooid BIGINT, barid BIGINT, PRIMARY KEY(fooid, barid))'
,
5
=>
'CREATE TABLE foo (id BIGSERIAL, name VARCHAR(200) NOT NULL, parent_id BIGINT, local_foo BIGINT, PRIMARY KEY(id))'
,
6
=>
'CREATE TABLE bar (id BIGSERIAL, name VARCHAR(200), PRIMARY KEY(id))'
,
7
=>
'ALTER TABLE foo_reference ADD
CONSTRAINT FOREIGN KEY (foo1) REFERENCES foo(foo1, foo2) NOT DEFERRABLE INITIALLY IMMEDIATE'
,
8
=>
'ALTER TABLE foo_bar_record ADD
CONSTRAINT FOREIGN KEY (fooId) REFERENCES foo(fooid, barid) NOT DEFERRABLE INITIALLY IMMEDIATE'
,
9
=>
'ALTER TABLE foo ADD
CONSTRAINT FOREIGN KEY (parent_id) REFERENCES foo(id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE'
,
10
=>
'ALTER TABLE foo ADD
CONSTRAINT FOREIGN KEY (local_foo) REFERENCES foo_locally_owned(id) ON DELETE RESTRICT NOT DEFERRABLE INITIALLY IMMEDIATE'
,
));
}
}
?>
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.phpdoctrine.com>.
*/
/**
* Doctrine_Export_Mysql_TestCase
*
* @package Doctrine
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @category Object Relational Mapping
* @link www.phpdoctrine.com
* @since 1.0
* @version $Revision$
*/
class
Doctrine_Export_Pgsql_TestCase
extends
Doctrine_UnitTestCase
{
public
function
testCreateDatabaseExecutesSql
()
{
$this
->
export
->
createDatabase
(
'db'
);
$this
->
assertEqual
(
$this
->
adapter
->
pop
(),
'CREATE DATABASE db'
);
}
public
function
testDropDatabaseExecutesSql
()
{
$this
->
export
->
dropDatabase
(
'db'
);
$this
->
assertEqual
(
$this
->
adapter
->
pop
(),
'DROP DATABASE db'
);
}
public
function
testCreateTableSupportsAutoincPks
()
{
$name
=
'mytable'
;
$fields
=
array
(
'id'
=>
array
(
'type'
=>
'integer'
,
'unsigned'
=>
1
,
'autoincrement'
=>
true
));
$options
=
array
(
'primary'
=>
array
(
'id'
));
$this
->
export
->
createTable
(
$name
,
$fields
,
$options
);
$this
->
assertEqual
(
$this
->
adapter
->
pop
(),
'CREATE TABLE mytable (id SERIAL, PRIMARY KEY(id))'
);
}
public
function
testCreateTableSupportsDefaultAttribute
()
{
$name
=
'mytable'
;
$fields
=
array
(
'name'
=>
array
(
'type'
=>
'char'
,
'length'
=>
10
,
'default'
=>
'def'
),
'type'
=>
array
(
'type'
=>
'integer'
,
'length'
=>
3
,
'default'
=>
12
)
);
$options
=
array
(
'primary'
=>
array
(
'name'
,
'type'
));
$this
->
export
->
createTable
(
$name
,
$fields
,
$options
);
$this
->
assertEqual
(
$this
->
adapter
->
pop
(),
'CREATE TABLE mytable (name CHAR(10) DEFAULT \'def\', type INT DEFAULT 12, PRIMARY KEY(name, type))'
);
}
public
function
testCreateTableSupportsMultiplePks
()
{
$name
=
'mytable'
;
$fields
=
array
(
'name'
=>
array
(
'type'
=>
'char'
,
'length'
=>
10
),
'type'
=>
array
(
'type'
=>
'integer'
,
'length'
=>
3
));
$options
=
array
(
'primary'
=>
array
(
'name'
,
'type'
));
$this
->
export
->
createTable
(
$name
,
$fields
,
$options
);
$this
->
assertEqual
(
$this
->
adapter
->
pop
(),
'CREATE TABLE mytable (name CHAR(10), type INT, PRIMARY KEY(name, type))'
);
}
public
function
testExportSql
()
{
$sql
=
$this
->
export
->
exportSql
(
dirname
(
__FILE__
)
.
DIRECTORY_SEPARATOR
.
'_files'
);
$this
->
assertEqual
(
$sql
,
array
(
0
=>
'CREATE TABLE foo_reference (foo1 BIGINT, foo2 BIGINT, PRIMARY KEY(foo1, foo2))'
,
1
=>
'CREATE TABLE foo_locally_owned (id BIGSERIAL, name VARCHAR(200), PRIMARY KEY(id))'
,
2
=>
'CREATE TABLE foo_foreignly_owned_with_pk (id BIGSERIAL, name VARCHAR(200), PRIMARY KEY(id))'
,
3
=>
'CREATE TABLE foo_foreignly_owned (id BIGSERIAL, name VARCHAR(200), fooid BIGINT, PRIMARY KEY(id))'
,
4
=>
'CREATE TABLE foo_bar_record (fooid BIGINT, barid BIGINT, PRIMARY KEY(fooid, barid))'
,
5
=>
'CREATE TABLE foo (id BIGSERIAL, name VARCHAR(200) NOT NULL, parent_id BIGINT, local_foo BIGINT, PRIMARY KEY(id))'
,
6
=>
'CREATE TABLE bar (id BIGSERIAL, name VARCHAR(200), PRIMARY KEY(id))'
,
7
=>
'ALTER TABLE foo_reference ADD
FOREIGN KEY (foo1) REFERENCES foo(id) NOT DEFERRABLE INITIALLY IMMEDIATE'
,
8
=>
'ALTER TABLE foo_bar_record ADD
FOREIGN KEY (fooId) REFERENCES foo(id) NOT DEFERRABLE INITIALLY IMMEDIATE'
,
9
=>
'ALTER TABLE foo ADD
FOREIGN KEY (parent_id) REFERENCES foo(id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE'
,
10
=>
'ALTER TABLE foo ADD
FOREIGN KEY (local_foo) REFERENCES foo_locally_owned(id) ON DELETE RESTRICT NOT DEFERRABLE INITIALLY IMMEDIATE'
,
));
}
}
?>
tests/NestedSet/SingleRootTestCase.php
View file @
75dbc8c8
...
...
@@ -49,6 +49,14 @@ class Doctrine_NestedSet_SingleRoot_TestCase extends Doctrine_UnitTestCase
$node2
->
name
=
'node2'
;
$node2
->
getNode
()
->
insertAsLastChildOf
(
$node
);
}
public
function
testLftRgtValues
()
{
$treeMngr
=
$this
->
conn
->
getTable
(
'NestedSetTest_SingleRootNode'
)
->
getTree
();
$root
=
$treeMngr
->
fetchRoot
();
$this
->
assertEqual
(
1
,
$root
[
'lft'
]);
$this
->
assertEqual
(
4
,
$root
[
'rgt'
]);
}
public
function
testGetDescendants
()
{
...
...
tests/run.php
View file @
75dbc8c8
...
...
@@ -336,7 +336,7 @@ $test->addTestCase(new Doctrine_Search_TestCase());
//$test->addTestCase(new Doctrine_AuditLog_TestCase());
//
$test->addTestCase(new Doctrine_NestedSet_SingleRoot_TestCase());
$test
->
addTestCase
(
new
Doctrine_NestedSet_SingleRoot_TestCase
());
// Cache tests
//$test->addTestCase(new Doctrine_Cache_Query_SqliteTestCase());
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment