From a4d44da3ba08f3974a1868901cbb4579f52c6130 Mon Sep 17 00:00:00 2001 From: fab2s Date: Wed, 17 Aug 2022 18:06:40 +0200 Subject: [PATCH] Allow custom dbms pagination support through PaginatedQueryInterface --- src/Extractors/PaginatedQueryInterface.php | 18 ++++++++ src/Extractors/PdoExtractor.php | 2 +- src/Extractors/PdoExtractorTrait.php | 6 +-- src/Extractors/PdoUniqueKeyExtractor.php | 40 +++++++++--------- src/Laravel/Extractors/DbExtractor.php | 31 +++----------- .../Extractors/DelayedExtractQueryTrait.php | 41 +++++++++++++++++++ src/Laravel/Extractors/UniqueKeyExtractor.php | 34 +++++---------- 7 files changed, 99 insertions(+), 73 deletions(-) create mode 100644 src/Extractors/PaginatedQueryInterface.php create mode 100644 src/Laravel/Extractors/DelayedExtractQueryTrait.php diff --git a/src/Extractors/PaginatedQueryInterface.php b/src/Extractors/PaginatedQueryInterface.php new file mode 100644 index 0000000..5bc1c19 --- /dev/null +++ b/src/Extractors/PaginatedQueryInterface.php @@ -0,0 +1,18 @@ +extractQuery . $this->getLimitOffsetBit(); } diff --git a/src/Extractors/PdoExtractorTrait.php b/src/Extractors/PdoExtractorTrait.php index 8a6c3fb..b4e4076 100644 --- a/src/Extractors/PdoExtractorTrait.php +++ b/src/Extractors/PdoExtractorTrait.php @@ -78,8 +78,8 @@ public function configurePdo(\PDO $pdo) $this->pdo = $pdo; $this->dbDriverName = $this->pdo->getAttribute(\PDO::ATTR_DRIVER_NAME); - if (!isset($this->supportedDrivers[$this->dbDriverName])) { - throw new YaEtlException('Pdo driver not supported, must be one of: ' . \implode(', ', \array_keys($this->supportedDrivers))); + if (!($this instanceof PaginatedQueryInterface) && !isset($this->supportedDrivers[$this->dbDriverName])) { + throw new YaEtlException(\get_class($this) . ' does not implement PaginatedQueryInterface and does not uses a supported Pdo driver, supported drivers are: ' . \implode(', ', \array_keys($this->supportedDrivers))); } if ($this->dbDriverName === 'mysql') { @@ -127,5 +127,5 @@ public function fetchRecords(): bool /** * @return string the paginated query with current offset and limit */ - abstract protected function getPaginatedQuery(): string; + abstract public function getPaginatedQuery(): string; } diff --git a/src/Extractors/PdoUniqueKeyExtractor.php b/src/Extractors/PdoUniqueKeyExtractor.php index 57d37ec..0db9fdb 100644 --- a/src/Extractors/PdoUniqueKeyExtractor.php +++ b/src/Extractors/PdoUniqueKeyExtractor.php @@ -82,6 +82,26 @@ public function fetchRecords(): bool return true; } + /** + * This method sets offset and limit in the query + * WARNING : if you set an offset without limit, + * the limit will be set to $this->maxdefaultLimit + * + * @return string the paginated query with current offset and limit + */ + public function getPaginatedQuery(): string + { + if ($this->joinFrom) { + $this->queryBindings = array_values($this->uniqueKeyValues); + + $whereOrAndStr = stripos($this->extractQuery, 'WHERE') !== false ? 'AND' : 'WHERE'; + + return $this->extractQuery . " $whereOrAndStr $this->uniqueKeyName IN (" . implode(',', array_fill(0, count($this->uniqueKeyValues), '?')) . ')'; + } + + return $this->extractQuery . $this->getLimitOffsetBit(); + } + /** * @return bool */ @@ -106,24 +126,4 @@ protected function fetchJoinedRecords(): bool return !empty($this->joinedRecords); } - - /** - * This method sets offset and limit in the query - * WARNING : if you set an offset without limit, - * the limit will be set to $this->maxdefaultLimit - * - * @return string the paginated query with current offset and limit - */ - protected function getPaginatedQuery(): string - { - if ($this->joinFrom) { - $this->queryBindings = array_values($this->uniqueKeyValues); - - $whereOrAndStr = stripos($this->extractQuery, 'WHERE') !== false ? 'AND' : 'WHERE'; - - return $this->extractQuery . " $whereOrAndStr $this->uniqueKeyName IN (" . implode(',', array_fill(0, count($this->uniqueKeyValues), '?')) . ')'; - } - - return $this->extractQuery . $this->getLimitOffsetBit(); - } } diff --git a/src/Laravel/Extractors/DbExtractor.php b/src/Laravel/Extractors/DbExtractor.php index 4d6f5dd..6b92a20 100644 --- a/src/Laravel/Extractors/DbExtractor.php +++ b/src/Laravel/Extractors/DbExtractor.php @@ -12,14 +12,17 @@ use fab2s\NodalFlow\NodalFlowException; use fab2s\NodalFlow\YaEtlException; use fab2s\YaEtl\Extractors\DbExtractorAbstract; +use fab2s\YaEtl\Extractors\PaginatedQueryInterface; use fab2s\YaEtl\Extractors\PdoExtractor; use Illuminate\Database\Query\Builder; /** * Class DbExtractor */ -class DbExtractor extends PdoExtractor +class DbExtractor extends PdoExtractor implements PaginatedQueryInterface { + use DelayedExtractQueryTrait; + /** * The record collection structure * @@ -52,36 +55,12 @@ public function __construct(?Builder $extractQuery = null) DbExtractorAbstract::__construct(); } - /** - * Set the extract query - * - * @param Builder $extractQuery - * - * @throws YaEtlException - * - * @return static - */ - public function setExtractQuery($extractQuery): DbExtractorAbstract - { - if (!($extractQuery instanceof Builder)) { - throw new YaEtlException('Argument 1 passed to ' . __METHOD__ . ' must be an instance of ' . Builder::class . ', ' . \gettype($extractQuery) . ' given'); - } - - if (!isset($this->pdo)) { - $this->configurePdo($extractQuery->getConnection()->getPdo()); - } - - parent::setExtractQuery($extractQuery); - - return $this; - } - /** * This method sets offset and limit in the query * * @return string the paginated query with current offset and limit */ - protected function getPaginatedQuery(): string + public function getPaginatedQuery(): string { $extractQuery = $this->extractQuery ->offset($this->offset) diff --git a/src/Laravel/Extractors/DelayedExtractQueryTrait.php b/src/Laravel/Extractors/DelayedExtractQueryTrait.php new file mode 100644 index 0000000..b191710 --- /dev/null +++ b/src/Laravel/Extractors/DelayedExtractQueryTrait.php @@ -0,0 +1,41 @@ +pdo)) { + $this->configurePdo($extractQuery->getConnection()->getPdo()); + } + + parent::setExtractQuery($extractQuery); + + return $this; + } +} diff --git a/src/Laravel/Extractors/UniqueKeyExtractor.php b/src/Laravel/Extractors/UniqueKeyExtractor.php index 1b22878..290e8ce 100644 --- a/src/Laravel/Extractors/UniqueKeyExtractor.php +++ b/src/Laravel/Extractors/UniqueKeyExtractor.php @@ -11,15 +11,18 @@ use fab2s\NodalFlow\NodalFlowException; use fab2s\NodalFlow\YaEtlException; -use fab2s\YaEtl\Extractors\DbExtractorAbstract; +use fab2s\YaEtl\Extractors\PaginatedQueryInterface; use fab2s\YaEtl\Extractors\PdoUniqueKeyExtractor; +use fab2s\YaEtl\Extractors\UniqueKeyExtractorAbstract; use Illuminate\Database\Query\Builder; /** * Class UniqueKeyExtractor */ -class UniqueKeyExtractor extends PdoUniqueKeyExtractor +class UniqueKeyExtractor extends PdoUniqueKeyExtractor implements PaginatedQueryInterface { + use DelayedExtractQueryTrait; + /** * Generic extraction from tables with unique (composite) key * @@ -39,29 +42,14 @@ class UniqueKeyExtractor extends PdoUniqueKeyExtractor * @throws YaEtlException * @throws NodalFlowException */ - public function __construct(Builder $extractQuery, $uniqueKey = 'id') + public function __construct(?Builder $extractQuery = null, $uniqueKey = 'id') { - parent::__construct($extractQuery->getConnection()->getPdo(), $extractQuery, $uniqueKey); - } - - /** - * Set the extract query - * - * @param Builder $extractQuery - * - * @throws YaEtlException - * - * @return static - */ - public function setExtractQuery($extractQuery): DbExtractorAbstract - { - if (!($extractQuery instanceof Builder)) { - throw new YaEtlException('Argument 1 passed to ' . __METHOD__ . ' must be an instance of ' . Builder::class . ', ' . \gettype($extractQuery) . ' given'); + if ($extractQuery !== null) { + $this->setExtractQuery($extractQuery); } - parent::setExtractQuery($extractQuery); - - return $this; + // delay configuring pdo to flow start + UniqueKeyExtractorAbstract::__construct(null, $uniqueKey); } /** @@ -69,7 +57,7 @@ public function setExtractQuery($extractQuery): DbExtractorAbstract * * @return string the paginated query with current offset and limit */ - protected function getPaginatedQuery(): string + public function getPaginatedQuery(): string { if ($this->joinFrom) { $extractQuery = $this->extractQuery