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
c1c33531
Commit
c1c33531
authored
Aug 19, 2014
by
Steve Müller
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #600 from PowerKiKi/feature-partial-indexes
Support for Partial Indexes for PostgreSql and Sqlite
parents
f61840a6
8feb89be
Changes
11
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
208 additions
and
21 deletions
+208
-21
UPGRADE.md
UPGRADE.md
+6
-0
AbstractPlatform.php
lib/Doctrine/DBAL/Platforms/AbstractPlatform.php
+31
-5
PostgreSqlPlatform.php
lib/Doctrine/DBAL/Platforms/PostgreSqlPlatform.php
+10
-1
AbstractSchemaManager.php
lib/Doctrine/DBAL/Schema/AbstractSchemaManager.php
+2
-1
Index.php
lib/Doctrine/DBAL/Schema/Index.php
+71
-5
PostgreSqlSchemaManager.php
lib/Doctrine/DBAL/Schema/PostgreSqlSchemaManager.php
+2
-1
Table.php
lib/Doctrine/DBAL/Schema/Table.php
+9
-6
AbstractPlatformTestCase.php
...octrine/Tests/DBAL/Platforms/AbstractPlatformTestCase.php
+21
-0
PostgreSqlPlatformTest.php
.../Doctrine/Tests/DBAL/Platforms/PostgreSqlPlatformTest.php
+5
-0
SQLAnywherePlatformTest.php
...Doctrine/Tests/DBAL/Platforms/SQLAnywherePlatformTest.php
+5
-0
IndexTest.php
tests/Doctrine/Tests/DBAL/Schema/IndexTest.php
+46
-2
No files found.
UPGRADE.md
View file @
c1c33531
# Upgrade to 2.5
## BC BREAK: Doctrine\DBAL\Schema\Table
The methods
``addIndex()``
and
``addUniqueIndex()``
in
``Doctrine\DBAL\Schema\Table``
hav an additional, optional parameter. If you override these methods, you should
add this new parameter to the declaration of your overridden methods.
## BC BREAK: Doctrine\DBAL\Connection
The visibility of the property
``$_platform``
in
``Doctrine\DBAL\Connection``
...
...
lib/Doctrine/DBAL/Platforms/AbstractPlatform.php
View file @
c1c33531
...
...
@@ -1745,11 +1745,27 @@ abstract class AbstractPlatform
}
$query
=
'CREATE '
.
$this
->
getCreateIndexSQLFlags
(
$index
)
.
'INDEX '
.
$name
.
' ON '
.
$table
;
$query
.=
' ('
.
$this
->
getIndexFieldDeclarationListSQL
(
$columns
)
.
')'
;
$query
.=
' ('
.
$this
->
getIndexFieldDeclarationListSQL
(
$columns
)
.
')'
.
$this
->
getPartialIndexSQL
(
$index
)
;
return
$query
;
}
/**
* Adds condition for partial index.
*
* @param \Doctrine\DBAL\Schema\Index $index
*
* @return string
*/
protected
function
getPartialIndexSQL
(
Index
$index
)
{
if
(
$this
->
supportsPartialIndexes
()
&&
$index
->
hasOption
(
'where'
))
{
return
' WHERE '
.
$index
->
getOption
(
'where'
);
}
return
''
;
}
/**
* Adds additional flags for index generation.
*
...
...
@@ -2289,7 +2305,7 @@ abstract class AbstractPlatform
return
'CONSTRAINT '
.
$name
.
' UNIQUE ('
.
$this
->
getIndexFieldDeclarationListSQL
(
$columns
)
.
')'
;
.
')'
.
$this
->
getPartialIndexSQL
(
$index
)
;
}
/**
...
...
@@ -2312,8 +2328,8 @@ abstract class AbstractPlatform
}
return
$this
->
getCreateIndexSQLFlags
(
$index
)
.
'INDEX '
.
$name
.
' ('
.
$this
->
getIndexFieldDeclarationListSQL
(
$columns
)
.
')'
;
.
$this
->
getIndexFieldDeclarationListSQL
(
$columns
)
.
')'
.
$this
->
getPartialIndexSQL
(
$index
)
;
}
/**
...
...
@@ -2571,7 +2587,7 @@ abstract class AbstractPlatform
return
$item
;
}
/**
* Some platforms have boolean literals that needs to be correctly converted
*
...
...
@@ -3007,6 +3023,16 @@ abstract class AbstractPlatform
return
true
;
}
/**
* Whether the platform supports partial indexes.
*
* @return boolean
*/
public
function
supportsPartialIndexes
()
{
return
false
;
}
/**
* Whether the platform supports altering tables.
*
...
...
lib/Doctrine/DBAL/Platforms/PostgreSqlPlatform.php
View file @
c1c33531
...
...
@@ -174,6 +174,14 @@ class PostgreSqlPlatform extends AbstractPlatform
return
true
;
}
/**
* {@inheritdoc}
*/
public
function
supportsPartialIndexes
()
{
return
true
;
}
/**
* {@inheritdoc}
*/
...
...
@@ -322,7 +330,8 @@ class PostgreSqlPlatform extends AbstractPlatform
public
function
getListTableIndexesSQL
(
$table
,
$currentDatabase
=
null
)
{
return
"SELECT quote_ident(relname) as relname, pg_index.indisunique, pg_index.indisprimary,
pg_index.indkey, pg_index.indrelid
pg_index.indkey, pg_index.indrelid,
TRIM(BOTH '()' FROM pg_get_expr(indpred, indrelid)) AS where
FROM pg_class, pg_index
WHERE oid IN (
SELECT indexrelid
...
...
lib/Doctrine/DBAL/Schema/AbstractSchemaManager.php
View file @
c1c33531
...
...
@@ -863,6 +863,7 @@ abstract class AbstractSchemaManager
'unique'
=>
$tableIndex
[
'non_unique'
]
?
false
:
true
,
'primary'
=>
$tableIndex
[
'primary'
],
'flags'
=>
isset
(
$tableIndex
[
'flags'
])
?
$tableIndex
[
'flags'
]
:
array
(),
'options'
=>
isset
(
$tableIndex
[
'where'
])
?
array
(
'where'
=>
$tableIndex
[
'where'
])
:
array
(),
);
}
else
{
$result
[
$keyName
][
'columns'
][]
=
$tableIndex
[
'column_name'
];
...
...
@@ -885,7 +886,7 @@ abstract class AbstractSchemaManager
}
if
(
!
$defaultPrevented
)
{
$index
=
new
Index
(
$data
[
'name'
],
$data
[
'columns'
],
$data
[
'unique'
],
$data
[
'primary'
],
$data
[
'flags'
]);
$index
=
new
Index
(
$data
[
'name'
],
$data
[
'columns'
],
$data
[
'unique'
],
$data
[
'primary'
],
$data
[
'flags'
]
,
$data
[
'options'
]
);
}
if
(
$index
)
{
...
...
lib/Doctrine/DBAL/Schema/Index.php
View file @
c1c33531
...
...
@@ -49,20 +49,31 @@ class Index extends AbstractAsset implements Constraint
*/
protected
$_flags
=
array
();
/**
* Platform specific options
*
* @todo $_flags should eventually be refactored into options
*
* @var array
*/
private
$options
=
array
();
/**
* @param string $indexName
* @param string[] $columns
* @param boolean $isUnique
* @param boolean $isPrimary
* @param string[] $flags
* @param array $options
*/
public
function
__construct
(
$indexName
,
array
$columns
,
$isUnique
=
false
,
$isPrimary
=
false
,
array
$flags
=
array
())
public
function
__construct
(
$indexName
,
array
$columns
,
$isUnique
=
false
,
$isPrimary
=
false
,
array
$flags
=
array
()
,
array
$options
=
array
()
)
{
$isUnique
=
$isUnique
||
$isPrimary
;
$this
->
_setName
(
$indexName
);
$this
->
_isUnique
=
$isUnique
;
$this
->
_isPrimary
=
$isPrimary
;
$this
->
options
=
$options
;
foreach
(
$columns
as
$column
)
{
$this
->
_addColumn
(
$column
);
...
...
@@ -199,15 +210,23 @@ class Index extends AbstractAsset implements Constraint
$sameColumns
=
$this
->
spansColumns
(
$other
->
getColumns
());
if
(
$sameColumns
)
{
if
(
!
$this
->
isUnique
()
&&
!
$this
->
isPrimary
())
{
if
(
!
$this
->
samePartialIndex
(
$other
))
{
return
false
;
}
if
(
!
$this
->
isUnique
()
&&
!
$this
->
isPrimary
())
{
// this is a special case: If the current key is neither primary or unique, any uniqe or
// primary key will always have the same effect for the index and there cannot be any constraint
// overlaps. This means a primary or unique index can always fulfill the requirements of just an
// index that has no constraints.
return
true
;
}
elseif
(
$other
->
isPrimary
()
!=
$this
->
isPrimary
())
{
}
if
(
$other
->
isPrimary
()
!=
$this
->
isPrimary
())
{
return
false
;
}
elseif
(
$other
->
isUnique
()
!=
$this
->
isUnique
())
{
}
if
(
$other
->
isUnique
()
!=
$this
->
isUnique
())
{
return
false
;
}
...
...
@@ -232,7 +251,7 @@ class Index extends AbstractAsset implements Constraint
return
false
;
}
if
(
$this
->
spansColumns
(
$other
->
getColumns
())
&&
(
$this
->
isPrimary
()
||
$this
->
isUnique
()))
{
if
(
$this
->
spansColumns
(
$other
->
getColumns
())
&&
(
$this
->
isPrimary
()
||
$this
->
isUnique
())
&&
$this
->
samePartialIndex
(
$other
)
)
{
return
true
;
}
...
...
@@ -288,4 +307,51 @@ class Index extends AbstractAsset implements Constraint
{
unset
(
$this
->
_flags
[
strtolower
(
$flag
)]);
}
/**
* @param string $name
*
* @return boolean
*/
public
function
hasOption
(
$name
)
{
return
isset
(
$this
->
options
[
strtolower
(
$name
)]);
}
/**
* @param string $name
*
* @return mixed
*/
public
function
getOption
(
$name
)
{
return
$this
->
options
[
strtolower
(
$name
)];
}
/**
* @return array
*/
public
function
getOptions
()
{
return
$this
->
options
;
}
/**
* Return whether the two indexes have the same partial index
* @param \Doctrine\DBAL\Schema\Index $other
* @return boolean
*/
private
function
samePartialIndex
(
Index
$other
)
{
if
(
$this
->
hasOption
(
'where'
)
&&
$other
->
hasOption
(
'where'
)
&&
$this
->
getOption
(
'where'
)
==
$other
->
getOption
(
'where'
))
{
return
true
;
}
if
(
!
$this
->
hasOption
(
'where'
)
&&
!
$other
->
hasOption
(
'where'
))
{
return
true
;
}
return
false
;
}
}
lib/Doctrine/DBAL/Schema/PostgreSqlSchemaManager.php
View file @
c1c33531
...
...
@@ -239,7 +239,8 @@ class PostgreSqlSchemaManager extends AbstractSchemaManager
'key_name'
=>
$row
[
'relname'
],
'column_name'
=>
trim
(
$colRow
[
'attname'
]),
'non_unique'
=>
!
$row
[
'indisunique'
],
'primary'
=>
$row
[
'indisprimary'
]
'primary'
=>
$row
[
'indisprimary'
],
'where'
=>
$row
[
'where'
],
);
}
}
...
...
lib/Doctrine/DBAL/Schema/Table.php
View file @
c1c33531
...
...
@@ -146,10 +146,11 @@ class Table extends AbstractAsset
* @param array $columnNames
* @param string|null $indexName
* @param array $flags
* @param array $options
*
* @return self
*/
public
function
addIndex
(
array
$columnNames
,
$indexName
=
null
,
array
$flags
=
array
())
public
function
addIndex
(
array
$columnNames
,
$indexName
=
null
,
array
$flags
=
array
()
,
array
$options
=
array
()
)
{
if
(
$indexName
==
null
)
{
$indexName
=
$this
->
_generateIdentifierName
(
...
...
@@ -157,7 +158,7 @@ class Table extends AbstractAsset
);
}
return
$this
->
_addIndex
(
$this
->
_createIndex
(
$columnNames
,
$indexName
,
false
,
false
,
$flags
));
return
$this
->
_addIndex
(
$this
->
_createIndex
(
$columnNames
,
$indexName
,
false
,
false
,
$flags
,
$options
));
}
/**
...
...
@@ -192,10 +193,11 @@ class Table extends AbstractAsset
/**
* @param array $columnNames
* @param string|null $indexName
* @param array $options
*
* @return self
*/
public
function
addUniqueIndex
(
array
$columnNames
,
$indexName
=
null
)
public
function
addUniqueIndex
(
array
$columnNames
,
$indexName
=
null
,
array
$options
=
array
()
)
{
if
(
$indexName
===
null
)
{
$indexName
=
$this
->
_generateIdentifierName
(
...
...
@@ -203,7 +205,7 @@ class Table extends AbstractAsset
);
}
return
$this
->
_addIndex
(
$this
->
_createIndex
(
$columnNames
,
$indexName
,
true
,
false
));
return
$this
->
_addIndex
(
$this
->
_createIndex
(
$columnNames
,
$indexName
,
true
,
false
,
array
(),
$options
));
}
/**
...
...
@@ -277,12 +279,13 @@ class Table extends AbstractAsset
* @param boolean $isUnique
* @param boolean $isPrimary
* @param array $flags
* @param array $options
*
* @return Index
*
* @throws SchemaException
*/
private
function
_createIndex
(
array
$columnNames
,
$indexName
,
$isUnique
,
$isPrimary
,
array
$flags
=
array
())
private
function
_createIndex
(
array
$columnNames
,
$indexName
,
$isUnique
,
$isPrimary
,
array
$flags
=
array
()
,
array
$options
=
array
()
)
{
if
(
preg_match
(
'(([^a-zA-Z0-9_]+))'
,
$indexName
))
{
throw
SchemaException
::
indexNameInvalid
(
$indexName
);
...
...
@@ -298,7 +301,7 @@ class Table extends AbstractAsset
}
}
return
new
Index
(
$indexName
,
$columnNames
,
$isUnique
,
$isPrimary
,
$flags
);
return
new
Index
(
$indexName
,
$columnNames
,
$isUnique
,
$isPrimary
,
$flags
,
$options
);
}
/**
...
...
tests/Doctrine/Tests/DBAL/Platforms/AbstractPlatformTestCase.php
View file @
c1c33531
...
...
@@ -136,6 +136,27 @@ abstract class AbstractPlatformTestCase extends \Doctrine\Tests\DbalTestCase
abstract
public
function
getGenerateUniqueIndexSql
();
public
function
testGeneratesPartialIndexesSqlOnlyWhenSupportingPartialIndexes
()
{
$where
=
'test IS NULL AND test2 IS NOT NULL'
;
$indexDef
=
new
\Doctrine\DBAL\Schema\Index
(
'name'
,
array
(
'test'
,
'test2'
),
false
,
false
,
array
(),
array
(
'where'
=>
$where
));
$expected
=
' WHERE '
.
$where
;
$actuals
=
array
();
$actuals
[]
=
$this
->
_platform
->
getIndexDeclarationSQL
(
'name'
,
$indexDef
);
$actuals
[]
=
$this
->
_platform
->
getUniqueConstraintDeclarationSQL
(
'name'
,
$indexDef
);
$actuals
[]
=
$this
->
_platform
->
getCreateIndexSQL
(
$indexDef
,
'table'
);
foreach
(
$actuals
as
$actual
)
{
if
(
$this
->
_platform
->
supportsPartialIndexes
())
{
$this
->
assertStringEndsWith
(
$expected
,
$actual
,
'WHERE clause should be present'
);
}
else
{
$this
->
assertStringEndsNotWith
(
$expected
,
$actual
,
'WHERE clause should NOT be present'
);
}
}
}
public
function
testGeneratesForeignKeyCreationSql
()
{
$fk
=
new
\Doctrine\DBAL\Schema\ForeignKeyConstraint
(
array
(
'fk_name_id'
),
'other_table'
,
array
(
'id'
),
''
);
...
...
tests/Doctrine/Tests/DBAL/Platforms/PostgreSqlPlatformTest.php
View file @
c1c33531
...
...
@@ -10,4 +10,9 @@ class PostgreSqlPlatformTest extends AbstractPostgreSqlPlatformTestCase
{
return
new
PostgreSqlPlatform
;
}
public
function
testSupportsPartialIndexes
()
{
$this
->
assertTrue
(
$this
->
_platform
->
supportsPartialIndexes
());
}
}
tests/Doctrine/Tests/DBAL/Platforms/SQLAnywherePlatformTest.php
View file @
c1c33531
...
...
@@ -822,6 +822,11 @@ class SQLAnywherePlatformTest extends AbstractPlatformTestCase
);
}
public
function
testGeneratesPartialIndexesSqlOnlyWhenSupportingPartialIndexes
()
{
$this
->
markTestSkipped
(
'Index declaration in statements like CREATE TABLE is not supported.'
);
}
/**
* {@inheritdoc}
*/
...
...
tests/Doctrine/Tests/DBAL/Schema/IndexTest.php
View file @
c1c33531
...
...
@@ -8,9 +8,9 @@ use Doctrine\DBAL\Schema\Index;
class
IndexTest
extends
\PHPUnit_Framework_TestCase
{
public
function
createIndex
(
$unique
=
false
,
$primary
=
false
)
public
function
createIndex
(
$unique
=
false
,
$primary
=
false
,
$options
=
array
()
)
{
return
new
Index
(
"foo"
,
array
(
"bar"
,
"baz"
),
$unique
,
$primary
);
return
new
Index
(
"foo"
,
array
(
"bar"
,
"baz"
),
$unique
,
$primary
,
array
(),
$options
);
}
public
function
testCreateIndex
()
...
...
@@ -79,6 +79,36 @@ class IndexTest extends \PHPUnit_Framework_TestCase
$this
->
assertTrue
(
$idx1
->
isFullfilledBy
(
$uniq
));
}
public
function
testFullfilledWithPartial
()
{
$without
=
new
Index
(
'without'
,
array
(
'col1'
,
'col2'
),
true
,
false
,
array
(),
array
());
$partial
=
new
Index
(
'partial'
,
array
(
'col1'
,
'col2'
),
true
,
false
,
array
(),
array
(
'where'
=>
'col1 IS NULL'
));
$another
=
new
Index
(
'another'
,
array
(
'col1'
,
'col2'
),
true
,
false
,
array
(),
array
(
'where'
=>
'col1 IS NULL'
));
$this
->
assertFalse
(
$partial
->
isFullfilledBy
(
$without
));
$this
->
assertFalse
(
$without
->
isFullfilledBy
(
$partial
));
$this
->
assertTrue
(
$partial
->
isFullfilledBy
(
$partial
));
$this
->
assertTrue
(
$partial
->
isFullfilledBy
(
$another
));
$this
->
assertTrue
(
$another
->
isFullfilledBy
(
$partial
));
}
public
function
testOverrulesWithPartial
()
{
$without
=
new
Index
(
'without'
,
array
(
'col1'
,
'col2'
),
true
,
false
,
array
(),
array
());
$partial
=
new
Index
(
'partial'
,
array
(
'col1'
,
'col2'
),
true
,
false
,
array
(),
array
(
'where'
=>
'col1 IS NULL'
));
$another
=
new
Index
(
'another'
,
array
(
'col1'
,
'col2'
),
true
,
false
,
array
(),
array
(
'where'
=>
'col1 IS NULL'
));
$this
->
assertFalse
(
$partial
->
overrules
(
$without
));
$this
->
assertFalse
(
$without
->
overrules
(
$partial
));
$this
->
assertTrue
(
$partial
->
overrules
(
$partial
));
$this
->
assertTrue
(
$partial
->
overrules
(
$another
));
$this
->
assertTrue
(
$another
->
overrules
(
$partial
));
}
/**
* @group DBAL-220
*/
...
...
@@ -112,4 +142,18 @@ class IndexTest extends \PHPUnit_Framework_TestCase
$this
->
assertFalse
(
$index
->
hasColumnAtPosition
(
"bar"
,
1
));
$this
->
assertFalse
(
$index
->
hasColumnAtPosition
(
"baz"
,
0
));
}
public
function
testOptions
()
{
$idx1
=
$this
->
createIndex
();
$this
->
assertFalse
(
$idx1
->
hasOption
(
'where'
));
$this
->
assertEmpty
(
$idx1
->
getOptions
());
$idx2
=
$this
->
createIndex
(
false
,
false
,
array
(
'where'
=>
'name IS NULL'
));
$this
->
assertTrue
(
$idx2
->
hasOption
(
'where'
));
$this
->
assertTrue
(
$idx2
->
hasOption
(
'WHERE'
));
$this
->
assertSame
(
'name IS NULL'
,
$idx2
->
getOption
(
'where'
));
$this
->
assertSame
(
'name IS NULL'
,
$idx2
->
getOption
(
'WHERE'
));
$this
->
assertSame
(
array
(
'where'
=>
'name IS NULL'
),
$idx2
->
getOptions
());
}
}
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