Skip to content
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
wants to merge 210 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
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 Jul 26, 2020
9f95593
[update] combine union test in single class
georgehristov Jul 26, 2020
691d9bd
[fix] create db tables with all columns
georgehristov Jul 27, 2020
ee88bb5
[update] migrate and update docs
georgehristov Jul 27, 2020
e436599
[update] php docs
georgehristov Jul 27, 2020
c728ce1
[update] variable names
georgehristov Jul 27, 2020
e3432cf
[update] use generic Model::export method
georgehristov Jul 27, 2020
9dcd45d
[fix] typos
georgehristov Jul 27, 2020
e2364cb
[update] improve naming consistency
georgehristov Jul 27, 2020
19c6689
[update] provide integration trait for generic support of aggregates …
georgehristov Jul 27, 2020
0b21ab3
Merge branch 'develop' into feature/introduce-aggregate-union-models
georgehristov Jul 27, 2020
ebc06d9
Merge branch 'develop' into feature/introduce-aggregate-union-models
georgehristov Dec 1, 2020
a03dbc5
[update] add return types
georgehristov Dec 2, 2020
1033a0b
Merge branch 'develop' into feature/introduce-aggregate-union-models
georgehristov Dec 2, 2020
66483ed
[fix] add method return types in Aggregate and Union
georgehristov Dec 2, 2020
4b4affa
[fix] clone test models on use
georgehristov Dec 2, 2020
c43694b
[fix] skip non-aggregate fields on union select sub-query
georgehristov Dec 2, 2020
1325b54
[fix] add test export sorting order
georgehristov Dec 2, 2020
650e449
[fix] teardown class properties
georgehristov Dec 2, 2020
bb349c1
[fix] mark test incomplete
georgehristov Dec 2, 2020
ee3be79
[update] rename properties
georgehristov Dec 2, 2020
1274012
[update] add annotations for $persistence and expr
georgehristov Dec 2, 2020
6e5f66a
[update] use clone of base model
georgehristov Dec 3, 2020
9059644
[update] method signature and phpdoc
georgehristov Dec 3, 2020
8c8bb41
[update] aggregate order
georgehristov Dec 3, 2020
4922475
[refactor] Union::getSubAction
georgehristov Dec 3, 2020
7af4243
[update] code comments
georgehristov Dec 3, 2020
6a08906
[update] Union::addCondition
georgehristov Dec 3, 2020
9936315
[update] fix complex conditions handling using field alias
georgehristov Dec 7, 2020
5289b65
Merge branch 'develop' into feature/introduce-aggregate-union-models
georgehristov Dec 7, 2020
a8839b1
[fix] revert field alias usage
georgehristov Dec 8, 2020
2595921
Merge branch 'develop' into feature/introduce-aggregate-union-models
georgehristov Dec 26, 2020
b75a23d
[update] to latest develop
georgehristov Dec 26, 2020
30ece17
[fix] test
georgehristov Dec 27, 2020
8c0080e
[fix] static analysis errors
georgehristov Dec 27, 2020
33c0674
[fix] docs
georgehristov Dec 27, 2020
707c070
[update] reorder methods and adjust visibility
georgehristov Dec 29, 2020
690e1ca
[feature] introduce Model\Aggregate
georgehristov Dec 29, 2020
2ee790b
[update] avoid modifying existing model Client
georgehristov Dec 29, 2020
4a9f37c
[update] move setup of properties to constructor
georgehristov Dec 29, 2020
d566c62
[update] add docs
georgehristov Dec 29, 2020
de06f03
[update] use strong argument typing
georgehristov Dec 29, 2020
ae45471
[update] rename properties to intuitive names
georgehristov Dec 29, 2020
3dd1ab0
[update] phpdoc types
georgehristov Dec 29, 2020
5cb2bf8
[update] allow to unset Model::$id_field
georgehristov Dec 29, 2020
68d32d3
[update] use array_merge
georgehristov Dec 29, 2020
8c69320
[update] arguments and return types
georgehristov Dec 29, 2020
47fc81d
[update] tests
georgehristov Dec 29, 2020
adb57dc
[update] docs
georgehristov Dec 29, 2020
b6b0852
[update] add return type for Invoice
georgehristov Dec 29, 2020
a974658
[fix] phpstan issues
georgehristov Dec 29, 2020
a176a33
[update] optimize demo
georgehristov Dec 29, 2020
665eb86
[update] LIMIT functionality
georgehristov Dec 30, 2020
4e2221d
Merge branch 'develop' into feature/introduce-aggregate-model
mvorisek Nov 6, 2021
ae0a56a
fix renamed TestCase class
mvorisek Nov 6, 2021
722cbdf
fix renamed atk4_money type
mvorisek Nov 6, 2021
1f25740
add missing void return type for test cases
mvorisek Nov 6, 2021
5c40110
fix renamespaced Dsql names
mvorisek Nov 6, 2021
d047cd5
fix stan
mvorisek Nov 6, 2021
cfae1b1
Merge branch 'develop' into feature/introduce-aggregate-model
mvorisek Jan 5, 2022
ad9c90a
fix typo in comment
mvorisek Jan 5, 2022
41637d0
fix SQL render assertions
mvorisek Jan 5, 2022
a21ef63
fix renamed API
mvorisek Jan 5, 2022
25dc215
fix comparison/bind for atk4_money typed values for Sqlite
mvorisek Jan 5, 2022
4b956bc
Merge branch 'develop' into feature/introduce-aggregate-union-models
mvorisek Jan 6, 2022
f62907b
Merge branch 'develop' into feature/introduce-aggregate-model
mvorisek Jan 6, 2022
0f9bbe8
fix tests by not enforcing use_table_prefixes
mvorisek Jan 5, 2022
e7639e8
workaround mysql server 8.0.27 bug in test
mvorisek Jan 6, 2022
787c5d9
fix doc cs
mvorisek Jan 6, 2022
138d064
Merge branch 'feature/introduce-aggregate-model' into feature/introdu…
mvorisek Jan 6, 2022
1fa050b
adjust to the latest atk4/data (by phpstan)
mvorisek Jan 5, 2022
5593643
fix assertions
mvorisek Jan 6, 2022
55df20d
client_id in transaction model
mvorisek Jan 6, 2022
92654fc
skip tests with wrong fields pushdown
mvorisek Jan 6, 2022
f403b82
fix grouping for PostgreSQL
mvorisek Jan 6, 2022
98cec38
fix report test
mvorisek Jan 6, 2022
564944c
fix/use non-aliased field name for update/delete where
mvorisek Jan 2, 2022
7353322
fix id typecasting in SQL persistence
mvorisek Jan 4, 2022
e0af1c5
dedup/impl insert/update/delete methods in main Persistence
mvorisek Jan 4, 2022
af5333b
impl raw write methods
mvorisek Jan 4, 2022
9dd61ba
add support for model nesting for SQL
mvorisek Jan 9, 2022
ddc2db3
fix join/hasMany
mvorisek Jan 9, 2022
bcd74c5
impl write queries using nested Models
mvorisek Jan 4, 2022
a4438ea
use "_tm" as default alias for model-in-model table
mvorisek Jan 9, 2022
79b2743
drop unneeded composer requirements
mvorisek Jan 9, 2022
96f6009
Merge branch 'develop' into feature/introduce-aggregate-model
mvorisek Jan 10, 2022
d5337a0
fix/skip one test /w constant column for MSSQL
mvorisek Jan 6, 2022
8374849
Merge branch 'develop' into feature/introduce-aggregate-union-models
mvorisek Jan 10, 2022
c7ba8ff
Merge branch 'feature/introduce-aggregate-model' into feature/introdu…
mvorisek Jan 10, 2022
9e95d1c
do not accept badly formatted seeds
mvorisek Jan 7, 2022
934041f
fix unordered export assertions
mvorisek Jan 10, 2022
59cd671
Merge branch 'feature/introduce-aggregate-model' into feature/introdu…
mvorisek Jan 10, 2022
eed9609
fix unordered export assertions
mvorisek Jan 9, 2022
d654352
subaction must not add table alias
mvorisek Jan 10, 2022
6bf9c9a
subaction must not wrap in parenthesis
mvorisek Jan 10, 2022
8f27132
prepare for Union::groupBy always wraps
mvorisek Jan 10, 2022
fbc54ae
drop deprecated hook alias
mvorisek Jan 10, 2022
8e563e5
fix expr seeding
mvorisek Jan 10, 2022
a883a75
allow to group by non-selecting expr, but then do not add that field
mvorisek Jan 10, 2022
58b83ee
fix grouping for PostgreSQL
mvorisek Jan 10, 2022
3fb83e6
Merge branch 'feature/introduce-aggregate-model' into feature/introdu…
mvorisek Jan 10, 2022
0540bf9
Merge branch 'model_in_model' into feature/introduce-aggregate-model
mvorisek Jan 10, 2022
6b18dc7
Merge branch 'model_in_model' into feature/introduce-aggregate-union-…
mvorisek Jan 10, 2022
02c64e3
Merge branch 'feature/introduce-aggregate-model' into feature/introdu…
mvorisek Jan 10, 2022
fb296e1
use "_tu" as default alias for Union model
mvorisek Jan 10, 2022
035f36b
createInvoiceAggregate must not add default "client" field
mvorisek Jan 10, 2022
65ada49
impl Aggregate using model-in-model
mvorisek Jan 10, 2022
abfaabe
do not skip WITH test for MariaDB
mvorisek Jan 11, 2022
12c2c2a
add model-in-model tests incl. hooks
mvorisek Jan 11, 2022
aab0bf9
test with "_id" ID column name
mvorisek Jan 11, 2022
1a96086
fix different ID column across nested models
mvorisek Jan 11, 2022
d48a037
assert nested transactions
mvorisek Jan 11, 2022
e572ff6
Merge branch 'model_in_model' into feature/introduce-aggregate-model
mvorisek Jan 12, 2022
5fe3df9
Merge branch 'model_in_model' into feature/introduce-aggregate-union-…
mvorisek Jan 12, 2022
23a33c4
Merge branch 'feature/introduce-aggregate-model' into feature/introdu…
mvorisek Jan 12, 2022
3f51e91
Merge branch 'develop' into feature/introduce-aggregate-model
mvorisek Jan 12, 2022
0cea47b
Merge branch 'develop' into feature/introduce-aggregate-union-models
mvorisek Jan 12, 2022
e29bdee
Merge branch 'feature/introduce-aggregate-model' into feature/introdu…
mvorisek Jan 12, 2022
a96f9d8
fixed mysql server 8.0.28 released
mvorisek Jan 19, 2022
755bf26
Merge branch 'develop' into feature/introduce-aggregate-model
mvorisek Jan 21, 2022
0e315a2
Merge branch 'develop' into feature/introduce-aggregate-union-models
mvorisek Jan 21, 2022
8be423b
Merge branch 'feature/introduce-aggregate-model' into feature/introdu…
mvorisek Jan 21, 2022
081f694
Merge branch 'develop' into feature/introduce-aggregate-model
mvorisek Jan 23, 2022
f451c5c
drop withAggregateField method
mvorisek Jan 23, 2022
e9edb8b
drop AggregatesTrait trait
mvorisek Jan 23, 2022
fcbb43c
Merge branch 'develop' into feature/introduce-aggregate-model
mvorisek Jan 30, 2022
254bb67
rename Aggregate to AggregateModel
mvorisek Jan 30, 2022
d82ff1f
Merge branch 'develop' into feature/introduce-aggregate-union-models
mvorisek Jan 30, 2022
6492e17
Merge branch 'feature/introduce-aggregate-model' into feature/introdu…
mvorisek Jan 30, 2022
37fffd7
fix merge
mvorisek Jan 30, 2022
91db9f8
rename Union to UnionModel
mvorisek Jan 30, 2022
2a4f6df
DEBUG add infinite recursion detection
mvorisek Jan 10, 2022
4d827b8
drop wrong union grouping pushdown
mvorisek Jan 30, 2022
cdbd07a
fix doc
mvorisek Jan 30, 2022
da5856f
rename groupBy to setGroupBy as it mutates the model
mvorisek Jan 30, 2022
c24d974
Merge branch 'feature/introduce-aggregate-model' into feature/introdu…
mvorisek Jan 30, 2022
25c92cb
Merge branch 'develop' into feature/introduce-aggregate-model
mvorisek Mar 13, 2022
335f261
Merge branch 'develop' into feature/introduce-aggregate-union-models
mvorisek Mar 13, 2022
3db6a8a
adjust to latest develop
mvorisek Mar 14, 2022
3a020b6
Merge branch 'feature/introduce-aggregate-model' into feature/introdu…
mvorisek Mar 14, 2022
485d1ef
adjust to latest develop
mvorisek Mar 14, 2022
9349c88
Merge branch 'develop' into feature/introduce-aggregate-model
mvorisek Apr 15, 2022
fc69c68
Merge branch 'develop' into feature/introduce-aggregate-union-models
mvorisek Apr 15, 2022
e2cd2e2
adjust to latest develop
mvorisek Apr 15, 2022
8ae2036
simplify
mvorisek Mar 21, 2022
9c9fa6f
fix cloned field - we should either disallow refs or wrap twice
mvorisek Mar 21, 2022
2da2f6a
compact assertSameExportUnordered assertions
mvorisek Apr 15, 2022
07d1838
fix array merge
mvorisek Mar 21, 2022
5d8ee39
fix count query
mvorisek Mar 21, 2022
431da2e
no false for initQueryFields
mvorisek Mar 21, 2022
1a821a8
fix cloned field - we should either disallow refs or wrap twice
mvorisek Mar 21, 2022
8e8bfd5
fix ii - do not clone field
mvorisek Mar 21, 2022
ffd69fd
Merge branch 'feature/introduce-aggregate-model' into feature/introdu…
mvorisek Apr 15, 2022
e36543d
Merge branch 'feature/introduce-aggregate-model' into feature/introdu…
mvorisek Apr 15, 2022
3716814
fix merge - no false for initQueryFields
mvorisek Apr 15, 2022
a46433d
fix unaggregated fields for pgsql
mvorisek Apr 15, 2022
27a9ced
Merge branch 'feature/introduce-aggregate-model' into feature/introdu…
mvorisek Apr 15, 2022
265958f
fix unaggregated fields for pgsql
mvorisek Apr 15, 2022
95af333
compact test code
mvorisek Apr 15, 2022
d4063b3
Merge branch 'feature/introduce-aggregate-model' into feature/introdu…
mvorisek Apr 15, 2022
f8a2653
compact test code
mvorisek Apr 15, 2022
b4aa593
skip unsupported sql tests
mvorisek Apr 15, 2022
222724a
compact test code
mvorisek Apr 15, 2022
d57af82
rm ReportTest - same as ModelAggregateTest::testGroupLimit2
mvorisek Apr 15, 2022
5520638
rename hook const
mvorisek Apr 15, 2022
c6c8921
fix cs
mvorisek Apr 15, 2022
c966abe
rename hook const
mvorisek Apr 15, 2022
c424234
Merge branch 'feature/introduce-aggregate-model' into feature/introdu…
mvorisek Apr 15, 2022
6dd0eb2
Merge branch 'develop' into feature/introduce-aggregate-union-models
mvorisek Apr 15, 2022
26d4b26
rm link to archived reports repo from README
mvorisek Apr 15, 2022
002665a
rm debug recursion detection
mvorisek Apr 15, 2022
63c53cb
rm pushdown note, it was wrong
mvorisek Apr 15, 2022
af7bba4
comments cleanup
mvorisek Apr 15, 2022
1bb383b
Merge branch 'develop' into feature/introduce-aggregate-union-models
mvorisek Apr 21, 2022
3c12605
Merge branch 'develop' into feature/introduce-aggregate-union-models
mvorisek Apr 21, 2022
b65a109
Merge branch 'develop' into feature/introduce-aggregate-union-models
mvorisek Apr 24, 2022
b1d090f
Merge branch 'develop' into feature/introduce-aggregate-union-models
mvorisek May 9, 2022
4eeaaf8
Merge branch 'develop' into feature/introduce-aggregate-union-models
mvorisek Jun 25, 2022
98b1f70
Merge branch 'develop' into feature/introduce-aggregate-union-models
mvorisek Aug 12, 2023
77b11d8
WIP convert rst to md
mvorisek Aug 12, 2023
f3b910a
fix cs
mvorisek Aug 12, 2023
f9ee26f
fix merge
mvorisek Aug 12, 2023
639bdb4
fix merge II
mvorisek Aug 12, 2023
bd15f65
WIP comment out failing test
mvorisek Aug 12, 2023
8884678
fix cs
mvorisek Aug 12, 2023
d4c6fa6
convert rst to md
mvorisek Aug 12, 2023
e8ff052
Merge branch 'develop'
mvorisek Feb 1, 2024
48117ac
fix stan
mvorisek Feb 1, 2024
01d93b6
Merge branch 'develop'
mvorisek Feb 2, 2024
a53543a
fix test /w reference and has many
mvorisek Feb 2, 2024
d2f626d
uncomment remaining test
mvorisek Feb 2, 2024
c8646b8
improve coverage
mvorisek Feb 3, 2024
c84cfc6
prevent child models mutation
mvorisek Feb 3, 2024
8c7921e
Merge branch 'develop'
mvorisek Feb 4, 2024
06f309c
Merge branch 'develop'
mvorisek Feb 20, 2024
6a5f2b8
Merge branch 'develop'
mvorisek Feb 21, 2024
a82a108
do no wrap inner from in extra select
mvorisek Feb 21, 2024
b4fbe57
rm UnionModel::createSubAction() method
mvorisek Feb 21, 2024
1c8abad
improve subQuery case
mvorisek Feb 21, 2024
0cc8f36
Merge branch 'develop'
mvorisek Feb 23, 2024
9c0385f
Merge branch 'develop'
mvorisek Feb 26, 2024
3eb55af
Merge branch 'develop'
mvorisek Mar 16, 2024
d17f009
adjust for latest atk4/data
mvorisek Mar 16, 2024
62affa7
fix cs
mvorisek Mar 17, 2024
33fb29d
fix typo
mvorisek Mar 17, 2024
0b85726
fix variable names in docs
DarkSide666 Mar 18, 2024
26cfd6f
Merge branch 'develop'
mvorisek May 4, 2024
f35f810
fix cs
mvorisek May 4, 2024
526adae
Merge branch 'develop'
mvorisek Jun 8, 2024
5676f2f
improve phpstan ignores
mvorisek Jun 8, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ static
references
expressions
joins
unions
aggregates
hooks
deriving
Expand Down
119 changes: 119 additions & 0 deletions docs/unions.md
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.
Copy link
Member

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.


## 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());
```
46 changes: 46 additions & 0 deletions src/Model/UnionInternalTable.php
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;
}
}
}
Loading
Loading