-
Notifications
You must be signed in to change notification settings - Fork 46
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add Model\UnionModel
model
#677
Open
georgehristov
wants to merge
210
commits into
develop
Choose a base branch
from
feature/introduce-aggregate-union-models
base: develop
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 205 commits
Commits
Show all changes
210 commits
Select commit
Hold shift + click to select a range
7083cf5
[update] migrate aggregate and union models to data package
georgehristov 9f95593
[update] combine union test in single class
georgehristov 691d9bd
[fix] create db tables with all columns
georgehristov ee88bb5
[update] migrate and update docs
georgehristov e436599
[update] php docs
georgehristov c728ce1
[update] variable names
georgehristov e3432cf
[update] use generic Model::export method
georgehristov 9dcd45d
[fix] typos
georgehristov e2364cb
[update] improve naming consistency
georgehristov 19c6689
[update] provide integration trait for generic support of aggregates …
georgehristov 0b21ab3
Merge branch 'develop' into feature/introduce-aggregate-union-models
georgehristov ebc06d9
Merge branch 'develop' into feature/introduce-aggregate-union-models
georgehristov a03dbc5
[update] add return types
georgehristov 1033a0b
Merge branch 'develop' into feature/introduce-aggregate-union-models
georgehristov 66483ed
[fix] add method return types in Aggregate and Union
georgehristov 4b4affa
[fix] clone test models on use
georgehristov c43694b
[fix] skip non-aggregate fields on union select sub-query
georgehristov 1325b54
[fix] add test export sorting order
georgehristov 650e449
[fix] teardown class properties
georgehristov bb349c1
[fix] mark test incomplete
georgehristov ee3be79
[update] rename properties
georgehristov 1274012
[update] add annotations for $persistence and expr
georgehristov 6e5f66a
[update] use clone of base model
georgehristov 9059644
[update] method signature and phpdoc
georgehristov 8c8bb41
[update] aggregate order
georgehristov 4922475
[refactor] Union::getSubAction
georgehristov 7af4243
[update] code comments
georgehristov 6a08906
[update] Union::addCondition
georgehristov 9936315
[update] fix complex conditions handling using field alias
georgehristov 5289b65
Merge branch 'develop' into feature/introduce-aggregate-union-models
georgehristov a8839b1
[fix] revert field alias usage
georgehristov 2595921
Merge branch 'develop' into feature/introduce-aggregate-union-models
georgehristov b75a23d
[update] to latest develop
georgehristov 30ece17
[fix] test
georgehristov 8c0080e
[fix] static analysis errors
georgehristov 33c0674
[fix] docs
georgehristov 707c070
[update] reorder methods and adjust visibility
georgehristov 690e1ca
[feature] introduce Model\Aggregate
georgehristov 2ee790b
[update] avoid modifying existing model Client
georgehristov 4a9f37c
[update] move setup of properties to constructor
georgehristov d566c62
[update] add docs
georgehristov de06f03
[update] use strong argument typing
georgehristov ae45471
[update] rename properties to intuitive names
georgehristov 3dd1ab0
[update] phpdoc types
georgehristov 5cb2bf8
[update] allow to unset Model::$id_field
georgehristov 68d32d3
[update] use array_merge
georgehristov 8c69320
[update] arguments and return types
georgehristov 47fc81d
[update] tests
georgehristov adb57dc
[update] docs
georgehristov b6b0852
[update] add return type for Invoice
georgehristov a974658
[fix] phpstan issues
georgehristov a176a33
[update] optimize demo
georgehristov 665eb86
[update] LIMIT functionality
georgehristov 4e2221d
Merge branch 'develop' into feature/introduce-aggregate-model
mvorisek ae0a56a
fix renamed TestCase class
mvorisek 722cbdf
fix renamed atk4_money type
mvorisek 1f25740
add missing void return type for test cases
mvorisek 5c40110
fix renamespaced Dsql names
mvorisek d047cd5
fix stan
mvorisek cfae1b1
Merge branch 'develop' into feature/introduce-aggregate-model
mvorisek ad9c90a
fix typo in comment
mvorisek 41637d0
fix SQL render assertions
mvorisek a21ef63
fix renamed API
mvorisek 25dc215
fix comparison/bind for atk4_money typed values for Sqlite
mvorisek 4b956bc
Merge branch 'develop' into feature/introduce-aggregate-union-models
mvorisek f62907b
Merge branch 'develop' into feature/introduce-aggregate-model
mvorisek 0f9bbe8
fix tests by not enforcing use_table_prefixes
mvorisek e7639e8
workaround mysql server 8.0.27 bug in test
mvorisek 787c5d9
fix doc cs
mvorisek 138d064
Merge branch 'feature/introduce-aggregate-model' into feature/introdu…
mvorisek 1fa050b
adjust to the latest atk4/data (by phpstan)
mvorisek 5593643
fix assertions
mvorisek 55df20d
client_id in transaction model
mvorisek 92654fc
skip tests with wrong fields pushdown
mvorisek f403b82
fix grouping for PostgreSQL
mvorisek 98cec38
fix report test
mvorisek 564944c
fix/use non-aliased field name for update/delete where
mvorisek 7353322
fix id typecasting in SQL persistence
mvorisek e0af1c5
dedup/impl insert/update/delete methods in main Persistence
mvorisek af5333b
impl raw write methods
mvorisek 9dd61ba
add support for model nesting for SQL
mvorisek ddc2db3
fix join/hasMany
mvorisek bcd74c5
impl write queries using nested Models
mvorisek a4438ea
use "_tm" as default alias for model-in-model table
mvorisek 79b2743
drop unneeded composer requirements
mvorisek 96f6009
Merge branch 'develop' into feature/introduce-aggregate-model
mvorisek d5337a0
fix/skip one test /w constant column for MSSQL
mvorisek 8374849
Merge branch 'develop' into feature/introduce-aggregate-union-models
mvorisek c7ba8ff
Merge branch 'feature/introduce-aggregate-model' into feature/introdu…
mvorisek 9e95d1c
do not accept badly formatted seeds
mvorisek 934041f
fix unordered export assertions
mvorisek 59cd671
Merge branch 'feature/introduce-aggregate-model' into feature/introdu…
mvorisek eed9609
fix unordered export assertions
mvorisek d654352
subaction must not add table alias
mvorisek 6bf9c9a
subaction must not wrap in parenthesis
mvorisek 8f27132
prepare for Union::groupBy always wraps
mvorisek fbc54ae
drop deprecated hook alias
mvorisek 8e563e5
fix expr seeding
mvorisek a883a75
allow to group by non-selecting expr, but then do not add that field
mvorisek 58b83ee
fix grouping for PostgreSQL
mvorisek 3fb83e6
Merge branch 'feature/introduce-aggregate-model' into feature/introdu…
mvorisek 0540bf9
Merge branch 'model_in_model' into feature/introduce-aggregate-model
mvorisek 6b18dc7
Merge branch 'model_in_model' into feature/introduce-aggregate-union-…
mvorisek 02c64e3
Merge branch 'feature/introduce-aggregate-model' into feature/introdu…
mvorisek fb296e1
use "_tu" as default alias for Union model
mvorisek 035f36b
createInvoiceAggregate must not add default "client" field
mvorisek 65ada49
impl Aggregate using model-in-model
mvorisek abfaabe
do not skip WITH test for MariaDB
mvorisek 12c2c2a
add model-in-model tests incl. hooks
mvorisek aab0bf9
test with "_id" ID column name
mvorisek 1a96086
fix different ID column across nested models
mvorisek d48a037
assert nested transactions
mvorisek e572ff6
Merge branch 'model_in_model' into feature/introduce-aggregate-model
mvorisek 5fe3df9
Merge branch 'model_in_model' into feature/introduce-aggregate-union-…
mvorisek 23a33c4
Merge branch 'feature/introduce-aggregate-model' into feature/introdu…
mvorisek 3f51e91
Merge branch 'develop' into feature/introduce-aggregate-model
mvorisek 0cea47b
Merge branch 'develop' into feature/introduce-aggregate-union-models
mvorisek e29bdee
Merge branch 'feature/introduce-aggregate-model' into feature/introdu…
mvorisek a96f9d8
fixed mysql server 8.0.28 released
mvorisek 755bf26
Merge branch 'develop' into feature/introduce-aggregate-model
mvorisek 0e315a2
Merge branch 'develop' into feature/introduce-aggregate-union-models
mvorisek 8be423b
Merge branch 'feature/introduce-aggregate-model' into feature/introdu…
mvorisek 081f694
Merge branch 'develop' into feature/introduce-aggregate-model
mvorisek f451c5c
drop withAggregateField method
mvorisek e9edb8b
drop AggregatesTrait trait
mvorisek fcbb43c
Merge branch 'develop' into feature/introduce-aggregate-model
mvorisek 254bb67
rename Aggregate to AggregateModel
mvorisek d82ff1f
Merge branch 'develop' into feature/introduce-aggregate-union-models
mvorisek 6492e17
Merge branch 'feature/introduce-aggregate-model' into feature/introdu…
mvorisek 37fffd7
fix merge
mvorisek 91db9f8
rename Union to UnionModel
mvorisek 2a4f6df
DEBUG add infinite recursion detection
mvorisek 4d827b8
drop wrong union grouping pushdown
mvorisek cdbd07a
fix doc
mvorisek da5856f
rename groupBy to setGroupBy as it mutates the model
mvorisek c24d974
Merge branch 'feature/introduce-aggregate-model' into feature/introdu…
mvorisek 25c92cb
Merge branch 'develop' into feature/introduce-aggregate-model
mvorisek 335f261
Merge branch 'develop' into feature/introduce-aggregate-union-models
mvorisek 3db6a8a
adjust to latest develop
mvorisek 3a020b6
Merge branch 'feature/introduce-aggregate-model' into feature/introdu…
mvorisek 485d1ef
adjust to latest develop
mvorisek 9349c88
Merge branch 'develop' into feature/introduce-aggregate-model
mvorisek fc69c68
Merge branch 'develop' into feature/introduce-aggregate-union-models
mvorisek e2cd2e2
adjust to latest develop
mvorisek 8ae2036
simplify
mvorisek 9c9fa6f
fix cloned field - we should either disallow refs or wrap twice
mvorisek 2da2f6a
compact assertSameExportUnordered assertions
mvorisek 07d1838
fix array merge
mvorisek 5d8ee39
fix count query
mvorisek 431da2e
no false for initQueryFields
mvorisek 1a821a8
fix cloned field - we should either disallow refs or wrap twice
mvorisek 8e8bfd5
fix ii - do not clone field
mvorisek ffd69fd
Merge branch 'feature/introduce-aggregate-model' into feature/introdu…
mvorisek e36543d
Merge branch 'feature/introduce-aggregate-model' into feature/introdu…
mvorisek 3716814
fix merge - no false for initQueryFields
mvorisek a46433d
fix unaggregated fields for pgsql
mvorisek 27a9ced
Merge branch 'feature/introduce-aggregate-model' into feature/introdu…
mvorisek 265958f
fix unaggregated fields for pgsql
mvorisek 95af333
compact test code
mvorisek d4063b3
Merge branch 'feature/introduce-aggregate-model' into feature/introdu…
mvorisek f8a2653
compact test code
mvorisek b4aa593
skip unsupported sql tests
mvorisek 222724a
compact test code
mvorisek d57af82
rm ReportTest - same as ModelAggregateTest::testGroupLimit2
mvorisek 5520638
rename hook const
mvorisek c6c8921
fix cs
mvorisek c966abe
rename hook const
mvorisek c424234
Merge branch 'feature/introduce-aggregate-model' into feature/introdu…
mvorisek 6dd0eb2
Merge branch 'develop' into feature/introduce-aggregate-union-models
mvorisek 26d4b26
rm link to archived reports repo from README
mvorisek 002665a
rm debug recursion detection
mvorisek 63c53cb
rm pushdown note, it was wrong
mvorisek af7bba4
comments cleanup
mvorisek 1bb383b
Merge branch 'develop' into feature/introduce-aggregate-union-models
mvorisek 3c12605
Merge branch 'develop' into feature/introduce-aggregate-union-models
mvorisek b65a109
Merge branch 'develop' into feature/introduce-aggregate-union-models
mvorisek b1d090f
Merge branch 'develop' into feature/introduce-aggregate-union-models
mvorisek 4eeaaf8
Merge branch 'develop' into feature/introduce-aggregate-union-models
mvorisek 98b1f70
Merge branch 'develop' into feature/introduce-aggregate-union-models
mvorisek 77b11d8
WIP convert rst to md
mvorisek f3b910a
fix cs
mvorisek f9ee26f
fix merge
mvorisek 639bdb4
fix merge II
mvorisek bd15f65
WIP comment out failing test
mvorisek 8884678
fix cs
mvorisek d4c6fa6
convert rst to md
mvorisek e8ff052
Merge branch 'develop'
mvorisek 48117ac
fix stan
mvorisek 01d93b6
Merge branch 'develop'
mvorisek a53543a
fix test /w reference and has many
mvorisek d2f626d
uncomment remaining test
mvorisek c8646b8
improve coverage
mvorisek c84cfc6
prevent child models mutation
mvorisek 8c7921e
Merge branch 'develop'
mvorisek 06f309c
Merge branch 'develop'
mvorisek 6a5f2b8
Merge branch 'develop'
mvorisek a82a108
do no wrap inner from in extra select
mvorisek b4fbe57
rm UnionModel::createSubAction() method
mvorisek 1c8abad
improve subQuery case
mvorisek 0cc8f36
Merge branch 'develop'
mvorisek 9c0385f
Merge branch 'develop'
mvorisek 3eb55af
Merge branch 'develop'
mvorisek d17f009
adjust for latest atk4/data
mvorisek 62affa7
fix cs
mvorisek 33fb29d
fix typo
mvorisek 0b85726
fix variable names in docs
DarkSide666 26cfd6f
Merge branch 'develop'
mvorisek f35f810
fix cs
mvorisek 526adae
Merge branch 'develop'
mvorisek 5676f2f
improve phpstan ignores
mvorisek File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,6 +22,7 @@ static | |
references | ||
expressions | ||
joins | ||
unions | ||
aggregates | ||
hooks | ||
deriving | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
:::{php:namespace} Atk4\Data | ||
::: | ||
|
||
(Unions)= | ||
|
||
# Model Unions | ||
|
||
:::{php:class} Model\UnionModel | ||
::: | ||
|
||
In some cases data from multiple models need to be combined. In this case the UnionModel model comes very handy. | ||
In the case used below Client model schema may have multiple invoices and multiple payments. Payment is not related to the invoice.: | ||
|
||
``` | ||
class Client extends \Atk4\Data\Model { | ||
public $table = 'client'; | ||
|
||
protected function init(): void | ||
{ | ||
parent::init(); | ||
|
||
$this->addField('name'); | ||
|
||
$this->hasMany('Payment'); | ||
$this->hasMany('Invoice'); | ||
} | ||
} | ||
``` | ||
|
||
(see tests/ModelUnionTest.php, tests/Model/Client.php, tests/Model/Payment.php and tests/Model/Invoice.php files). | ||
|
||
## Union Model Definition | ||
|
||
Normally a model is associated with a single table. Union model can have multiple nested models defined and it fetches | ||
results from that. As a result, Union model will have no "id" field. Below is an example of inline definition of Union model. | ||
The Union model can be separated in a designated class and nested model added within the init() method body of the new class: | ||
|
||
``` | ||
$unionPaymentInvoice = new \Atk4\Data\Model\UnionModel(); | ||
|
||
$nestedPayment = $unionPaymentInvoice->addNestedModel(new Invoice()); | ||
$nestedInvoice = $unionPaymentInvoice->addNestedModel(new Payment()); | ||
``` | ||
|
||
Next, assuming that both models have common fields "name" and "amount", `$unionPaymentInvoice` fields can be set: | ||
|
||
``` | ||
$unionPaymentInvoice->addField('name'); | ||
$unionPaymentInvoice->addField('amount', ['type' => 'atk4_money']); | ||
``` | ||
|
||
Then data can be queried: | ||
|
||
``` | ||
$unionPaymentInvoice->export(); | ||
``` | ||
|
||
## Define Fields | ||
|
||
Below is an example of 3 different ways to define fields for the UnionModel model: | ||
|
||
``` | ||
// will link the "name" field with all the nested models | ||
$unionPaymentInvoice->addField('client_id'); | ||
|
||
// Expression will not affect nested models in any way | ||
$unionPaymentInvoice->addExpression('name_capital', ['expr' => 'upper([name])']); | ||
|
||
// UnionModel model can be joined with extra tables and define some fields from those joins | ||
$unionPaymentInvoice | ||
->join('client', 'client_id') | ||
->addField('client_name', 'name'); | ||
``` | ||
|
||
{ref}`Expressions` and {ref}`Joins` are working just as they would on any other model. | ||
|
||
## Field Mapping | ||
|
||
Sometimes the field that is defined in the UnionModel model may be named differently inside nested models. | ||
E.g. Invoice has field "description" and payment has field "note". | ||
When defining a nested model a field map array needs to be specified: | ||
|
||
``` | ||
$nestedPayment = $unionPaymentInvoice->addNestedModel(new Invoice()); | ||
$nestedInvoice = $unionPaymentInvoice->addNestedModel(new Payment(), ['description' => '[note]']); | ||
$unionPaymentInvoice->addField('description'); | ||
``` | ||
|
||
The key of the field map array must match the UnionModel field. The value is an expression. (See {php:meth}`Model::addExpression`). | ||
This format can also be used to reverse sign on amounts. When we are creating "Transactions", then invoices would be | ||
subtracted from the amount, while payments will be added: | ||
|
||
``` | ||
$nestedPayment = $mUnion->addNestedModel(new Invoice(), ['amount' => '-[amount]']); | ||
$nestedInvoice = $mUnion->addNestedModel(new Payment(), ['description' => '[note]']); | ||
$unionPaymentInvoice->addField('description'); | ||
``` | ||
|
||
Should more flexibility be needed, more expressions (or fields) can be added directly to nested models: | ||
|
||
``` | ||
$nestedPayment = $unionPaymentInvoice->addNestedModel(new Invoice(), ['amount' => '-[amount]']); | ||
$nestedInvoice = $unionPaymentInvoice->addNestedModel(new Payment(), ['description' => '[note]']); | ||
|
||
$nestedPayment->addExpression('type', ['expr' => '\'payment\'']); | ||
$nestedInvoice->addExpression('type', ['expr' => '\'invoice\'']); | ||
$unionPaymentInvoice->addField('type'); | ||
``` | ||
|
||
A new field "type" has been added that will be defined as a static constant. | ||
|
||
## Referencing an UnionModel Model | ||
|
||
Like any other model, UnionModel model can be assigned through a reference. In the case here one Client can have multiple transactions. | ||
Initially a related union can be defined: | ||
|
||
``` | ||
$client->hasMany('Transaction', new Transaction()); | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Atk4\Data\Model; | ||
|
||
use Atk4\Core\TrackableTrait; | ||
use Atk4\Data\Exception; | ||
use Atk4\Data\Model; | ||
use Atk4\Data\Persistence; | ||
|
||
/** | ||
* Map self::action() to self::getOwner()->actionInnerTable(). | ||
* | ||
* Called from https://github.com/atk4/data/blob/5.0.0/src/Persistence/Sql.php#L188. | ||
* | ||
* @method Model getOwner() | ||
* | ||
* @internal | ||
*/ | ||
class UnionInternalTable | ||
{ | ||
use TrackableTrait; | ||
|
||
/** | ||
* @param array<mixed> $args | ||
* | ||
* @return Persistence\Sql\Query | ||
*/ | ||
public function action(string $mode, array $args = []) | ||
{ | ||
if ($mode !== 'select' || $args !== []) { | ||
throw new Exception('Only "select" action with empty arguments is expected'); | ||
} | ||
|
||
$model = $this->getOwner(); | ||
|
||
$tableOrig = $model->table; | ||
$model->table = '_tu'; | ||
try { | ||
return $model->actionSelectInnerTable(); // @phpstan-ignore-line | ||
} finally { | ||
$model->table = $tableOrig; | ||
} | ||
} | ||
} |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is "static constant" here? Minimal example would be good.