Passed
Pull Request — dev (#131)
by Def
15:27 queued 02:57
created

QueryBuilder   A

Complexity

Total Complexity 3

Size/Duplication

Total Lines 81
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
eloc 37
dl 0
loc 81
ccs 10
cts 10
cp 1
rs 10
c 0
b 0
f 0
wmc 3

3 Methods

Rating   Name   Duplication   Size   Complexity  
A getColumnType() 0 4 1
A defaultTimeTypeMap() 0 6 1
A __construct() 0 8 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Db\Mysql;
6
7
use Yiisoft\Db\QueryBuilder\QueryBuilder as AbstractQueryBuilder;
8
use Yiisoft\Db\Schema\ColumnSchemaBuilder;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, Yiisoft\Db\Mysql\ColumnSchemaBuilder. Consider defining an alias.

Let?s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let?s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
9
use Yiisoft\Db\Schema\QuoterInterface;
10
use Yiisoft\Db\Schema\Schema;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, Yiisoft\Db\Mysql\Schema. Consider defining an alias.

Let?s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let?s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
11
use Yiisoft\Db\Schema\SchemaInterface;
12
13
use function array_merge;
14
15
/**
16
 * The class QueryBuilder is the query builder for Mysql databases.
17
 */
18
final class QueryBuilder extends AbstractQueryBuilder
19
{
20
    /**
21
     * Defines a FULLTEXT index type for {@see createIndex()}.
22
     */
23
    public const INDEX_FULLTEXT = 'FULLTEXT';
24
25
    /**
26
     * Defines a SPATIAL index type for {@see createIndex()}.
27
     */
28
    public const INDEX_SPATIAL = 'SPATIAL';
29
30
    /**
31
     * Defines a B-tree index method for {@see createIndex()}.
32
     */
33
    public const INDEX_B_TREE = 'btree';
34
35
    /**
36
     * Defines a hash index method for {@see createIndex()}.
37
     */
38
    public const INDEX_HASH = 'hash';
39
40
    /**
41
     * @psalm-var string[] $typeMap Mapping from abstract column types (keys) to physical column types (values).
42
     */
43
    protected array $typeMap = [
44
        Schema::TYPE_PK => 'int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY',
45
        Schema::TYPE_UPK => 'int(10) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY',
46
        Schema::TYPE_BIGPK => 'bigint(20) NOT NULL AUTO_INCREMENT PRIMARY KEY',
47
        Schema::TYPE_UBIGPK => 'bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY',
48
        Schema::TYPE_CHAR => 'char(1)',
49
        Schema::TYPE_STRING => 'varchar(255)',
50
        Schema::TYPE_TEXT => 'text',
51
        Schema::TYPE_TINYINT => 'tinyint(3)',
52
        Schema::TYPE_SMALLINT => 'smallint(6)',
53
        Schema::TYPE_INTEGER => 'int(11)',
54
        Schema::TYPE_BIGINT => 'bigint(20)',
55
        Schema::TYPE_FLOAT => 'float',
56
        Schema::TYPE_DOUBLE => 'double',
57
        Schema::TYPE_DECIMAL => 'decimal(10,0)',
58
        Schema::TYPE_DATE => 'date',
59
        Schema::TYPE_BINARY => 'blob',
60
        Schema::TYPE_BOOLEAN => 'tinyint(1)',
61
        Schema::TYPE_MONEY => 'decimal(19,4)',
62
        Schema::TYPE_JSON => 'json',
63
    ];
64
    private DDLQueryBuilder $ddlBuilder;
65
    private DMLQueryBuilder $dmlBuilder;
66
    private DQLQueryBuilder $dqlBuilder;
67
68 356
    public function __construct(
69
        QuoterInterface $quoter,
70
        SchemaInterface $schema,
71
    ) {
72 356
        $this->ddlBuilder = new DDLQueryBuilder($this, $quoter, $schema);
73 356
        $this->dmlBuilder = new DMLQueryBuilder($this, $quoter, $schema);
74 356
        $this->dqlBuilder = new DQLQueryBuilder($this, $quoter, $schema);
75 356
        parent::__construct($quoter, $schema, $this->ddlBuilder, $this->dmlBuilder, $this->dqlBuilder);
76
    }
77
78 12
    public function getColumnType(ColumnSchemaBuilder|string $type): string
79
    {
80 12
        $this->typeMap = array_merge($this->typeMap, $this->defaultTimeTypeMap());
81 12
        return parent::getColumnType($type);
82
    }
83
84
    /**
85
     * Returns the map for default time type.
86
     *
87
     * If the version of MySQL is lower than 5.6.4, then the types will be without fractional seconds, otherwise with
88
     * fractional seconds.
89
     *
90
     * @return array
91
     * @psalm-return array<string, string>
92
     */
93 12
    private function defaultTimeTypeMap(): array
94
    {
95
        return [
96 12
            Schema::TYPE_DATETIME => 'datetime(0)',
97
            Schema::TYPE_TIMESTAMP => 'timestamp(0)',
98
            Schema::TYPE_TIME => 'time(0)',
99
        ];
100
    }
101
}
102