StructuredExpression   A
last analyzed

Complexity

Total Complexity 9

Size/Duplication

Total Lines 74
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 16
dl 0
loc 74
rs 10
c 0
b 0
f 0
wmc 9

5 Methods

Rating   Name   Duplication   Size   Complexity  
A getValue() 0 3 1
A __construct() 0 5 1
A getType() 0 3 1
A getNormalizedValue() 0 23 5
A getColumns() 0 3 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Db\Pgsql;
6
7
use Traversable;
8
use Yiisoft\Db\Expression\ExpressionInterface;
9
use Yiisoft\Db\Schema\ColumnSchemaInterface;
10
11
use function array_key_exists;
12
use function array_keys;
13
use function is_iterable;
14
use function iterator_to_array;
15
16
/**
17
 * Represents a structured type SQL expression.
18
 *
19
 * @see https://en.wikipedia.org/wiki/Structured_type
20
 *
21
 * For example:
22
 *
23
 * ```php
24
 * new StructuredExpression(['price' => 10, 'currency_code' => 'USD']);
25
 * ```
26
 *
27
 * Will be encoded to `ROW(10, USD)`
28
 */
29
class StructuredExpression implements ExpressionInterface
30
{
31
    /**
32
     * @param ColumnSchemaInterface[] $columns
33
     * @psalm-param array<string, ColumnSchemaInterface> $columns
34
     */
35
    public function __construct(
36
        private mixed $value,
37
        private string|null $type = null,
38
        private array $columns = [],
39
    ) {
40
    }
41
42
    /**
43
     * The structured type name.
44
     *
45
     * Defaults to `null` which means the type is not explicitly specified.
46
     *
47
     * Note that in the case where a type is not specified explicitly and DBMS cannot guess it from the context,
48
     * SQL error will be raised.
49
     */
50
    public function getType(): string|null
51
    {
52
        return $this->type;
53
    }
54
55
    /**
56
     * The structured type columns that are used for value normalization and type casting.
57
     *
58
     * @return ColumnSchemaInterface[]
59
     */
60
    public function getColumns(): array
61
    {
62
        return $this->columns;
63
    }
64
65
    /**
66
     * The content of the structured type. It can be represented as an associative array of structured type column names
67
     * and values.
68
     */
69
    public function getValue(): mixed
70
    {
71
        return $this->value;
72
    }
73
74
    /**
75
     * Sorted values according to the order of structured type columns,
76
     * indexed keys are replaced with column names,
77
     * missing elements are filled in with default values,
78
     * excessive elements are removed.
79
     */
80
    public function getNormalizedValue(): mixed
81
    {
82
        if (empty($this->columns) || !is_iterable($this->value)) {
83
            return $this->value;
84
        }
85
86
        $normalized = [];
87
        $value = $this->value;
88
        $columnsNames = array_keys($this->columns);
89
90
        if ($value instanceof Traversable) {
91
            $value = iterator_to_array($value);
92
        }
93
94
        foreach ($columnsNames as $i => $columnsName) {
95
            $normalized[$columnsName] = match (true) {
96
                array_key_exists($columnsName, $value) => $value[$columnsName],
97
                array_key_exists($i, $value) => $value[$i],
98
                default => $this->columns[$columnsName]->getDefaultValue(),
99
            };
100
        }
101
102
        return $normalized;
103
    }
104
}
105