Skip to content

Commit

Permalink
sql replacement of the query part where empty group placeholder is pr…
Browse files Browse the repository at this point in the history
…esent

outdated installation check
documentation (init command)
example config file
empty group dbchange sample
  • Loading branch information
Jan Kapciar committed Oct 30, 2018
1 parent 3d48bdb commit d3a9c5d
Show file tree
Hide file tree
Showing 14 changed files with 201 additions and 61 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,13 +101,13 @@ Usage

========================================

2] Initialize the environment (e.g. DEV) with
2] Initialize the DbChange with
```
php bin/console.php dbchanger:init DEV
php bin/console.php dbchanger:init
```

This command will load environment data specified in configuration file into internal
DbChanger database. Now, environment is ready for dbChange deployments.
DbChanger database. Now, DbChanger is aligned with your configuration and ready to serve.

========================================

Expand Down
8 changes: 8 additions & 0 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
0.5.9 - 2018/10/30
=================
* Fixed sql replacement of the query part where empty group placeholder is present
* Fixed outdated installation check
* Fixed documentation (init command)
* Added example config file
* Added empty group dbchange sample

0.5.8 - 2018/10/12
=================
* Fixed the wrong order of loaded fragments into installation that could occur on some platforms.
Expand Down
11 changes: 1 addition & 10 deletions config/config.neon
Original file line number Diff line number Diff line change
@@ -1,22 +1,13 @@
parameters:
dbchanger:
database:
driver: oci8
host: localhost
user: DBCHANGER_USER
password: ''
servicename: DBCHANGER_SERVICE
dbname: DBCHANGER_USER
port: 1521
inputDirectory: 'misc\sampledata\'
outputDirectory: 'output'
logDirectory: 'log'
filePrefix: ''
datamodel: []


services:
- Doctrine\ORM\EntityManager::create(%dbchanger.database%, Doctrine\ORM\Tools\Setup::createAnnotationMetadataConfiguration(["/src/Entity"], true, null, null, false))
- Doctrine\ORM\EntityManager::create(%database%, Doctrine\ORM\Tools\Setup::createAnnotationMetadataConfiguration(["/src/Entity"], true, null, null, false))
- Kapcus\DbChanger\Model\Manager(%dbchanger.outputDirectory%)
- Kapcus\DbChanger\Model\Loader(%dbchanger.inputDirectory%, %dbchanger.filePrefix%)
- Kapcus\DbChanger\Model\Generator(%dbchanger.outputDirectory%)
Expand Down
22 changes: 12 additions & 10 deletions misc/config.local.neon.example
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
parameters:
# database connection data for dbchanger running instance, mandatory (individual database parameters by driver spec)
database:
driver: oci8
host: localhost
user: DBCHANGERUSER
password: ''
servicename: DBCHANGERDBINSTANCE
dbname: DBCHANGESCHEMA
port: 1521
dbchanger:
# database connection data for dbchanger running instance, mandatory (individual database parameters by driver spec)
database:
driver: oci8
host: localhost
user: DBCHANGERUSER
password: ''
servicename: DBCHANGERDBINSTANCE
dbname: DBCHANGESCHEMA
port: 1521

# folder where dbchange files are located
inputDirectory: 'misc\sampledata\'
Expand Down Expand Up @@ -63,12 +63,14 @@ parameters:
# database user names (mandatory in case of option 2, omit in case of option 1)
usernames: ['MAINUSER', 'SLAVEUSER1', 'SLAVEUSER2']
# database user passwords (mandatory in case of option 2, omit in case of option 1)
passwords: ['', '', '']
passwords: ['', '', '']

# database groups with assigned users, see this example, mandatory
groups:
all: [MAINUSER, SLAVEUSER1, SLAVEUSER2]
central: [MAINUSER]
region: [SLAVEUSER1, SLAVEUSER2]
empty: []

# placeholders used in dbchange fragment sql content, see this example, optional
placeholders:
Expand Down
71 changes: 71 additions & 0 deletions misc/config.local.neon.example-filled
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
parameters:
database:
driver: oci8
host: localhost
user: ABC_GLOBAL
password: ABC123ABC
servicename: ABC
dbname: ABC
port: 1521
dbchanger:
# database connection data for dbchanger running instance, mandatory (individual database parameters by driver spec)

# folder where dbchange files are located
inputDirectory: 'misc\sampledata\'

# folder into which dbchange content should be generated into
outputDirectory: 'output'

# folder for logs and exceptions
logDirectory: 'log'

# in case dbchange files have some prefix, e.g. when dbchange_01_group.sql = you need to define prefix dbchange_
filePrefix: ''

# in this section environments are defined
datamodel:

# list of all defined groups, mandatory and must be filled
groups: [central, region, home, operations, all]

# which groups should be treated as manual ones (sql content in such fragments is not executed during installation and require manual interaction), optional
manualGroups: [operations]

# environment definitions, mandatory
environments:

# each environment must have 3-letter code, mandatory
LOC:

# environment name, mandatory
name: Local Development

# environment description, optional
description: Local Development Environment

# hostname where database is running, mandatory
hostname: %database.host%

# database name (instance name, service name), mandatory
dbname: %database.dbname%

# database port, mandatory
port: 1521

# or OPTION 2 = define usernames and passwords (order of values is important, length of arrays must equal)
# database user names (mandatory in case of option 2, omit in case of option 1)
usernames: ['%database.dbname%', '%database.dbname%au', '%database.dbname%us']
# database user passwords (mandatory in case of option 2, omit in case of option 1)
passwords: ['%database.password%', '%database.password%au', '%database.password%us']

# database groups with assigned users, see this example, mandatory
groups:
all: ['%database.dbname%', '%database.dbname%au', '%database.dbname%us']
central: ['%database.dbname%']
region: ['%database.dbname%au', '%database.dbname%us']

# placeholders used in dbchange fragment sql content, see this example, optional
placeholders:
'<central>': %database.dbname%
'<user>': ABCUSER
'<systemuser>': ABCSYS
1 change: 1 addition & 0 deletions misc/sampledata/EMPTY_GROUP/01_central.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
GRANT SELECT, INSERT, UPDATE, DELETE ON TESTTABLE to <region> with grant option;
1 change: 1 addition & 0 deletions misc/sampledata/EMPTY_GROUP/02_central.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
GRANT SELECT, INSERT, UPDATE, DELETE ON TESTTABLE to <empty> with grant option;
5 changes: 5 additions & 0 deletions misc/sampledata/EMPTY_GROUP/03_empty.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
CREATE TABLE DUMMYTABLE
(
VALUE1 INT,
VALUE2 VARCHAR2(20)
);
13 changes: 13 additions & 0 deletions misc/sampledata/EMPTY_GROUP/04_central.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
CREATE OR REPLACE VIEW TESTEMPTYGLOBALVIEW AS
SELECT
v.VALUE11 as ONEVALUE1, v.VALUE12 as ONEVALUE2, v.VALUE21 as TWOVALUE1, v.VALUE22 as TWOVALUE2, v.REGION as REGION FROM (
/*START*/ SELECT
tone.VALUE1 as VALUE11, tone.VALUE2 as VALUE12, ttwo.VALUE1 as VALUE21, ttwo.VALUE2 as VALUE22, '<empty>' as REGION
FROM
<empty>.DUMMYTABLE tone, <empty>.DUMMYTABLE ttwo
WHERE
tone.VALUE1 = 1 AND
ttwo.VALUE1 = 2
/*END*/
/*GLUE_START UNION ALL GLUE_END*/
) v;
1 change: 1 addition & 0 deletions misc/sampledata/EMPTY_GROUP/_requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
CENTRAL_TABLE
2 changes: 1 addition & 1 deletion src/Command/InstallCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
try {
$environment = $this->manager->getEnvironmentByCode($environmentCode);
$dbChange = $this->manager->getActiveDbChangeByCode($dbChangeCode);
$this->manager->installDbChange($environment, $this->configurator->getEnvironmentConnectionConfigurations($environment->getCode()), $dbChange, $input->getOption('force'), $input->getOption('stop'));
$this->manager->installDbChange($this->configurator->getGroups(), $environment, $this->configurator->getEnvironmentConnectionConfigurations($environment->getCode()), $dbChange, $input->getOption('force'), $input->getOption('stop'));
$output->writeln('OK - DbChange installed successfully.');
exit(0);
} catch (DbChangeException $e) {
Expand Down
50 changes: 33 additions & 17 deletions src/Model/Generator.php
Original file line number Diff line number Diff line change
Expand Up @@ -160,26 +160,28 @@ private function prepareDbChangeOutputDirectory(Environment $environment, $dbCha
}

/**
* @param \Kapcus\DbChanger\Entity\Group[] $groups
* @param \Kapcus\DbChanger\Entity\Environment $environment
* @param \Kapcus\DbChanger\Entity\Fragment $dbChangeFragment
* @param \Kapcus\DbChanger\Entity\UserGroup $userGroup
*
* @return string
*/
public function getFragmentContent(Environment $environment, Fragment $dbChangeFragment, UserGroup $userGroup)
public function getFragmentContent(array $groups, Environment $environment, Fragment $dbChangeFragment, UserGroup $userGroup)
{
return $this->doGenerateFragmentContent($environment, $dbChangeFragment, $userGroup, false);
return $this->doGenerateFragmentContent($groups, $environment, $dbChangeFragment, $userGroup, false);
}

/**
* @param \Kapcus\DbChanger\Entity\Group[] $groups
* @param \Kapcus\DbChanger\Entity\Environment $environment
* @param \Kapcus\DbChanger\Entity\Fragment $dbChangeFragment
* @param \Kapcus\DbChanger\Entity\UserGroup $userGroup
* @param bool $loadFromFile
*
* @return string
*/
public function doGenerateFragmentContent(Environment $environment, Fragment $dbChangeFragment, UserGroup $userGroup, $loadFromFile = false)
public function doGenerateFragmentContent(array $groups, Environment $environment, Fragment $dbChangeFragment, UserGroup $userGroup, $loadFromFile = false)
{

$contentTemplate = $loadFromFile ? $dbChangeFragment->getTemplateContentFromFile() : $dbChangeFragment->getTemplateContent();
Expand All @@ -201,11 +203,12 @@ public function doGenerateFragmentContent(Environment $environment, Fragment $db
$statements = $this->parser->parseContent($contentTemplate);

foreach ($statements as $statement) {
$newChunks = $this->replaceGroupPlaceholder($environment, $statement->getContent());
$newChunks = $this->replaceGroupPlaceholder($groups, $environment, $statement->getContent());
foreach ($newChunks as $newChunk) {
$chunks[] = sprintf('%s%s', $newChunk, $statement->getDelimiter());
}
}

$chunks[] = 'COMMIT' . $this->parser->getDelimiter();
$chunks[] = '';

Expand All @@ -231,33 +234,40 @@ private function replacePlaceholders(Environment $environment, $content)
}

/**
* @param \Kapcus\DbChanger\Entity\Group[] $groups
* @param \Kapcus\DbChanger\Entity\Environment $environment
* @param string $statementContent
*
* @return string[]
*/
private function replaceGroupPlaceholder(Environment $environment, $statementContent)
private function replaceGroupPlaceholder(array $groups, Environment $environment, $statementContent)
{
if (strpos($statementContent, self::PLACEHOLDER_START) !== false) {
return $this->replaceGroupPlaceholderInSubstring($environment, $statementContent);
return $this->replaceGroupPlaceholderInSubstring($groups, $environment, $statementContent);
} else {
return $this->replaceGroupPlaceholderGlobally($environment, $statementContent);
return $this->replaceGroupPlaceholderGlobally($groups, $environment, $statementContent);
}
}

/**
* @param \Kapcus\DbChanger\Entity\Group[] $groups
* @param \Kapcus\DbChanger\Entity\Environment $environment
* @param $statementContent
*
* @return string[]
*/
private function replaceGroupPlaceholderGlobally(Environment $environment, $statementContent) {
private function replaceGroupPlaceholderGlobally(array $groups, Environment $environment, $statementContent) {
$newStatements = [];
foreach ($environment->getGroupNames() as $groupName) {
if (strpos($statementContent, $this->getGroupPlaceholder($groupName)) !== false) {
foreach (Util::getUserGroupUsersByGroupName($environment->getUserGroups(), $groupName) as $user) {
foreach ($groups as $group) {
if (strpos($statementContent, $this->getGroupPlaceholder($group->getName())) !== false) {
$users = Util::getUserGroupUsersByGroupName($environment->getUserGroups(), $group->getName());
// empty group -> no sql is produced where group placeholder is present
if (empty($users)) {
return [];
}
foreach ($users as $user) {
$newStatements[] = str_replace(
$this->getGroupPlaceholder($groupName),
$this->getGroupPlaceholder($group->getName()),
$user->getName(),
$statementContent
);
Expand All @@ -269,12 +279,13 @@ private function replaceGroupPlaceholderGlobally(Environment $environment, $stat
}

/**
* @param \Kapcus\DbChanger\Entity\Group[] $groups
* @param \Kapcus\DbChanger\Entity\Environment $environment
* @param $statementContent
*
* @return string[]
*/
private function replaceGroupPlaceholderInSubstring(Environment $environment, $statementContent) {
private function replaceGroupPlaceholderInSubstring(array $groups, Environment $environment, $statementContent) {
$startPlaceholderIndex = strpos($statementContent, self::PLACEHOLDER_START);
$newStatements = [];
$subStringLength = null;
Expand All @@ -285,11 +296,16 @@ private function replaceGroupPlaceholderInSubstring(Environment $environment, $s
$subStringLength = $endPlaceholderIndex - $startIndex;
}

foreach ($environment->getGroupNames() as $groupName) {
if (strpos($statementContent, $this->getGroupPlaceholder($groupName)) !== false) {
foreach (Util::getUserGroupUsersByGroupName($environment->getUserGroups(), $groupName) as $user) {
foreach ($groups as $group) {
if (strpos($statementContent, $this->getGroupPlaceholder($group->getName())) !== false) {
$users = Util::getUserGroupUsersByGroupName($environment->getUserGroups(), $group->getName());
// empty group -> no sql is produced where group placeholder is present
if (empty($users)) {
return [];
}
foreach ($users as $user) {
$newStatements[] = str_replace(
$this->getGroupPlaceholder($groupName),
$this->getGroupPlaceholder($group->getName()),
$user->getName(),
substr($statementContent, $startIndex, $subStringLength)
);
Expand Down
3 changes: 2 additions & 1 deletion src/Model/IGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,14 @@ public function generateDbChangeIntoFile(Environment $environment, DbChange $dbC
public function generateFragmentIntoFile(Environment $environment, Fragment $fragment);

/**
* @param \Kapcus\DbChanger\Entity\Group[] $groups
* @param \Kapcus\DbChanger\Entity\Environment $environment
* @param \Kapcus\DbChanger\Entity\Fragment $dbChangeFragment
* @param \Kapcus\DbChanger\Entity\UserGroup $userGroup
*
* @return string fragment content
*/
public function getFragmentContent(Environment $environment, Fragment $dbChangeFragment, UserGroup $userGroup);
public function getFragmentContent(array $groups, Environment $environment, Fragment $dbChangeFragment, UserGroup $userGroup);

/**
* @return string
Expand Down
Loading

0 comments on commit d3a9c5d

Please sign in to comment.