Mysql::describe()   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 3

Importance

Changes 0
Metric Value
dl 0
loc 15
rs 9.7666
c 0
b 0
f 0
ccs 4
cts 4
cp 1
cc 3
nc 3
nop 1
crap 3
1
<?php
2
3
namespace ORM\Dbal;
4
5
use ORM\Entity;
6
use ORM\Exception;
7
use PDO;
8
use PDOException;
9
10
/**
11
 * Database abstraction for MySQL databases
12
 *
13
 * @package ORM\Dbal
14
 * @author  Thomas Flori <[email protected]>
15
 */
16
class Mysql extends Dbal
17
{
18
    protected static $typeMapping = [
19
        'tinyint'   => Type\Number::class,
20
        'smallint'  => Type\Number::class,
21
        'mediumint' => Type\Number::class,
22
        'int'       => Type\Number::class,
23
        'bigint'    => Type\Number::class,
24
        'decimal'   => Type\Number::class,
25
        'float'     => Type\Number::class,
26
        'double'    => Type\Number::class,
27
28
        'varchar' => Type\VarChar::class,
29
        'char'    => Type\VarChar::class,
30
31
        'text'       => Type\Text::class,
32
        'tinytext'   => Type\Text::class,
33
        'mediumtext' => Type\Text::class,
34
        'longtext'   => Type\Text::class,
35
36
        'datetime'  => Type\DateTime::class,
37
        'date'      => Type\DateTime::class,
38
        'timestamp' => Type\DateTime::class,
39
40
        'time' => Type\Time::class,
41
        'enum' => Type\Enum::class,
42
        'set'  => Type\Set::class,
43
        'json' => Type\Json::class,
44 6
    ];
45
46 6
    protected static $compositeWhereInTemplate = '(%s) IN (%s)';
47 6
48
    public function insertAndSyncWithAutoInc(Entity ...$entities)
49 6
    {
50 4
        if (count($entities) === 0) {
51 1
            return false;
52
        }
53 2
        static::assertSameType($entities);
54
55
        $entity = reset($entities);
56 3
        $table = $this->escapeIdentifier($entity::getTableName());
57
        $pKey = $this->escapeIdentifier($entity::getColumnName($entity::getPrimaryKeyVars()[0]));
58
        $pdo = $this->entityManager->getConnection();
59 50
        $pdo->beginTransaction();
60
        $pdo->query($this->buildInsertStatement(...$entities));
61
        $rows = $pdo->query('SELECT * FROM ' . $table . ' WHERE ' . $pKey . ' >= LAST_INSERT_ID()')
62 50
            ->fetchAll(PDO::FETCH_ASSOC);
63 1
        $pdo->commit();
64 1
65
        /** @var Entity $entity */
66 View Code Duplication
        foreach (array_values($entities) as $key => $entity) {
67 49
            $entity->setOriginalData($rows[$key]);
68 49
            $entity->reset();
69 49
            $this->entityManager->map($entity, true);
70
        }
71
72 49
        return true;
73
    }
74
75
    public function describe($table)
76
    {
77
        try {
78
            $result = $this->entityManager->getConnection()->query('DESCRIBE ' . $this->escapeIdentifier($table));
79
        } catch (PDOException $exception) {
80
            throw new Exception('Unknown table ' . $table, 0, $exception);
81
        }
82
83
        $cols = [];
84 49
        while ($rawColumn = $result->fetch(PDO::FETCH_ASSOC)) {
85
            $cols[] = new Column($this, $this->normalizeColumnDefinition($rawColumn));
86 49
        }
87
88 49
        return new Table($cols);
89 49
    }
90 44
91
    /**
92
     * Normalize a column definition
93 49
     *
94 49
     * The column definition from "DESCRIBE <table>" is to special as useful. Here we normalize it to a more
95 49
     * ANSI-SQL style.
96 46
     *
97 49
     * @param array $rawColumn
98 49
     * @return array
99
     */
100 49
    protected function normalizeColumnDefinition($rawColumn)
101 49
    {
102 47
        $definition = [];
103 4
104 4
        $definition['data_type'] = $this->normalizeType($rawColumn['Type']);
105 45
        $definition['type'] = isset(static::$typeMapping[$definition['data_type']]) ?
106 41
            static::$typeMapping[$definition['data_type']] : null;
107 37
108 12
        $definition['column_name'] = $rawColumn['Field'];
109 12
        $definition['is_nullable'] = $rawColumn['Null'] === 'YES';
110 33
        $definition['character_maximum_length'] = null;
111 31
        $definition['datetime_precision'] = null;
112 4
        $definition['column_default'] = $rawColumn['Default'] === null && $rawColumn['Extra'] === 'auto_increment' ?
113 4
            'sequence(AUTO_INCREMENT)' : $rawColumn['Default'];
114
115
        if (in_array($definition['data_type'], ['varchar', 'char'])) {
116 49
            $definition['character_maximum_length'] = $this->extractParenthesis($rawColumn['Type']);
117 View Code Duplication
        } elseif (in_array($definition['data_type'], ['datetime', 'timestamp', 'time'])) {
118
            $definition['datetime_precision'] = $this->extractParenthesis($rawColumn['Type']);
119
        } elseif (in_array($definition['data_type'], ['set', 'enum'])) {
120
            $definition['enumeration_values'] = $this->extractParenthesis($rawColumn['Type']);
121
        }
122
123
        return $definition;
124
    }
125
}
126