Skip to content

Commit a94c4f6

Browse files
committed
Add COLUMN_TYPE MySQL reflection
1 parent af55570 commit a94c4f6

File tree

6 files changed

+103
-16
lines changed

6 files changed

+103
-16
lines changed

api.php

Lines changed: 51 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3560,13 +3560,54 @@ public function __construct(string $name, string $type, int $length, int $precis
35603560
$this->sanitize();
35613561
}
35623562

3563+
private static function parseColumnType(string $columnType, int &$length, int &$precision, int &$scale) /*: void*/
3564+
{
3565+
$pos = strpos($columnType, '(');
3566+
if ($pos) {
3567+
$dataSize = rtrim(substr($columnType, $pos + 1), ')');
3568+
if ($length) {
3569+
$length = (int) $dataSize;
3570+
} else {
3571+
$pos = strpos($dataSize, ',');
3572+
if ($pos) {
3573+
$precision = (int) substr($dataSize, 0, $pos);
3574+
$scale = (int) substr($dataSize, $pos + 1);
3575+
} else {
3576+
$precision = (int) $dataSize;
3577+
$scale = 0;
3578+
}
3579+
}
3580+
}
3581+
}
3582+
3583+
private static function getDataSize(int $length, int $precision, int $scale): string
3584+
{
3585+
$dataSize = '';
3586+
if ($length) {
3587+
$dataSize = $length;
3588+
} elseif ($precision) {
3589+
if ($scale) {
3590+
$dataSize = $precision . ',' . $scale;
3591+
} else {
3592+
$dataSize = $precision;
3593+
}
3594+
}
3595+
return $dataSize;
3596+
}
3597+
35633598
public static function fromReflection(GenericReflection $reflection, array $columnResult): ReflectedColumn
35643599
{
35653600
$name = $columnResult['COLUMN_NAME'];
3601+
$dataType = $columnResult['DATA_TYPE'];
35663602
$length = (int) $columnResult['CHARACTER_MAXIMUM_LENGTH'];
3567-
$type = $reflection->toJdbcType($columnResult['DATA_TYPE'], $length);
35683603
$precision = (int) $columnResult['NUMERIC_PRECISION'];
35693604
$scale = (int) $columnResult['NUMERIC_SCALE'];
3605+
$columnType = $columnResult['COLUMN_TYPE'];
3606+
if ($columnType) {
3607+
self::parseColumnType($columnType, $length, $precision, $scale);
3608+
}
3609+
$dataSize = self::getDataSize($length, $precision, $scale);
3610+
$type = $reflection->toJdbcType($dataType, $dataSize);
35703611
$nullable = in_array(strtoupper($columnResult['IS_NULLABLE']), ['TRUE', 'YES', 'T', 'Y', '1']);
35713612
$pk = false;
35723613
$fk = '';
@@ -4107,9 +4148,10 @@ public function __construct(GenericDB $db, Cache $cache, int $ttl)
41074148

41084149
private function database(): ReflectedDatabase
41094150
{
4110-
if (!$this->database) {
4111-
$this->database = $this->loadDatabase(true);
4151+
if ($this->database) {
4152+
return $this->database;
41124153
}
4154+
$this->database = $this->loadDatabase(true);
41134155
return $this->database;
41144156
}
41154157

@@ -5961,11 +6003,11 @@ private function getTableColumnsSQL(): string
59616003
{
59626004
switch ($this->driver) {
59636005
case 'mysql':
5964-
return 'SELECT "COLUMN_NAME", "IS_NULLABLE", "DATA_TYPE", if ("DATA_TYPE"=\'tinyint\' OR "DATA_TYPE"=\'bit\',SUBSTRING_INDEX(SUBSTRING_INDEX("COLUMN_TYPE",\'(\',-1),\')\',1),"CHARACTER_MAXIMUM_LENGTH") as "CHARACTER_MAXIMUM_LENGTH", "NUMERIC_PRECISION", "NUMERIC_SCALE" FROM "INFORMATION_SCHEMA"."COLUMNS" WHERE "TABLE_NAME" = ? AND "TABLE_SCHEMA" = ?';
6006+
return 'SELECT "COLUMN_NAME", "IS_NULLABLE", "DATA_TYPE", "CHARACTER_MAXIMUM_LENGTH" as "CHARACTER_MAXIMUM_LENGTH", "NUMERIC_PRECISION", "NUMERIC_SCALE", "COLUMN_TYPE" FROM "INFORMATION_SCHEMA"."COLUMNS" WHERE "TABLE_NAME" = ? AND "TABLE_SCHEMA" = ?';
59656007
case 'pgsql':
5966-
return 'SELECT a.attname AS "COLUMN_NAME", case when a.attnotnull then \'NO\' else \'YES\' end as "IS_NULLABLE", pg_catalog.format_type(a.atttypid, -1) as "DATA_TYPE", case when a.atttypmod < 0 then NULL else a.atttypmod-4 end as "CHARACTER_MAXIMUM_LENGTH", case when a.atttypid != 1700 then NULL else ((a.atttypmod - 4) >> 16) & 65535 end as "NUMERIC_PRECISION", case when a.atttypid != 1700 then NULL else (a.atttypmod - 4) & 65535 end as "NUMERIC_SCALE" FROM pg_attribute a JOIN pg_class pgc ON pgc.oid = a.attrelid WHERE pgc.relname = ? AND \'\' <> ? AND a.attnum > 0 AND NOT a.attisdropped;';
6008+
return 'SELECT a.attname AS "COLUMN_NAME", case when a.attnotnull then \'NO\' else \'YES\' end as "IS_NULLABLE", pg_catalog.format_type(a.atttypid, -1) as "DATA_TYPE", case when a.atttypmod < 0 then NULL else a.atttypmod-4 end as "CHARACTER_MAXIMUM_LENGTH", case when a.atttypid != 1700 then NULL else ((a.atttypmod - 4) >> 16) & 65535 end as "NUMERIC_PRECISION", case when a.atttypid != 1700 then NULL else (a.atttypmod - 4) & 65535 end as "NUMERIC_SCALE", \'\' AS "COLUMN_TYPE" FROM pg_attribute a JOIN pg_class pgc ON pgc.oid = a.attrelid WHERE pgc.relname = ? AND \'\' <> ? AND a.attnum > 0 AND NOT a.attisdropped;';
59676009
case 'sqlsrv':
5968-
return 'SELECT c.name AS "COLUMN_NAME", c.is_nullable AS "IS_NULLABLE", t.Name AS "DATA_TYPE", (c.max_length/2) AS "CHARACTER_MAXIMUM_LENGTH", c.precision AS "NUMERIC_PRECISION", c.scale AS "NUMERIC_SCALE" FROM sys.columns c INNER JOIN sys.types t ON c.user_type_id = t.user_type_id WHERE c.object_id = OBJECT_ID(?) AND \'\' <> ?';
6010+
return 'SELECT c.name AS "COLUMN_NAME", c.is_nullable AS "IS_NULLABLE", t.Name AS "DATA_TYPE", (c.max_length/2) AS "CHARACTER_MAXIMUM_LENGTH", c.precision AS "NUMERIC_PRECISION", c.scale AS "NUMERIC_SCALE", \'\' AS "COLUMN_TYPE" FROM sys.columns c INNER JOIN sys.types t ON c.user_type_id = t.user_type_id WHERE c.object_id = OBJECT_ID(?) AND \'\' <> ?';
59696011
}
59706012
}
59716013

@@ -6070,7 +6112,7 @@ public function getTableForeignKeys(string $tableName): array
60706112
return $foreignKeys;
60716113
}
60726114

6073-
public function toJdbcType(string $type, int $size): string
6115+
public function toJdbcType(string $type, string $size): string
60746116
{
60756117
return $this->typeConverter->toJdbc($type, $size);
60766118
}
@@ -6377,7 +6419,7 @@ public function __construct(string $driver)
63776419
'geometry' => true,
63786420
];
63796421

6380-
public function toJdbc(string $type, int $size): string
6422+
public function toJdbc(string $type, string $size): string
63816423
{
63826424
$jdbcType = strtolower($type);
63836425
if (isset($this->toJdbc[$this->driver]["$jdbcType($size)"])) {
@@ -10299,6 +10341,7 @@ public static function toString(ResponseInterface $response): string
1029910341
'username' => 'php-crud-api',
1030010342
'password' => 'php-crud-api',
1030110343
'database' => 'php-crud-api',
10344+
'controllers' => 'records,columns,openapi',
1030210345
]);
1030310346
$request = RequestFactory::fromGlobals();
1030410347
$api = new Api($config);

src/Tqdev/PhpCrudApi/Column/Reflection/ReflectedColumn.php

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,55 @@ public function __construct(string $name, string $type, int $length, int $precis
3232
$this->sanitize();
3333
}
3434

35+
private static function parseColumnType(string $columnType, int &$length, int &$precision, int &$scale) /*: void*/
36+
{
37+
if (!$columnType) {
38+
return;
39+
}
40+
$pos = strpos($columnType, '(');
41+
if ($pos) {
42+
$dataSize = rtrim(substr($columnType, $pos + 1), ')');
43+
if ($length) {
44+
$length = (int) $dataSize;
45+
} else {
46+
$pos = strpos($dataSize, ',');
47+
if ($pos) {
48+
$precision = (int) substr($dataSize, 0, $pos);
49+
$scale = (int) substr($dataSize, $pos + 1);
50+
} else {
51+
$precision = (int) $dataSize;
52+
$scale = 0;
53+
}
54+
}
55+
}
56+
}
57+
58+
private static function getDataSize(int $length, int $precision, int $scale): string
59+
{
60+
$dataSize = '';
61+
if ($length) {
62+
$dataSize = $length;
63+
} elseif ($precision) {
64+
if ($scale) {
65+
$dataSize = $precision . ',' . $scale;
66+
} else {
67+
$dataSize = $precision;
68+
}
69+
}
70+
return $dataSize;
71+
}
72+
3573
public static function fromReflection(GenericReflection $reflection, array $columnResult): ReflectedColumn
3674
{
3775
$name = $columnResult['COLUMN_NAME'];
76+
$dataType = $columnResult['DATA_TYPE'];
3877
$length = (int) $columnResult['CHARACTER_MAXIMUM_LENGTH'];
39-
$type = $reflection->toJdbcType($columnResult['DATA_TYPE'], $length);
4078
$precision = (int) $columnResult['NUMERIC_PRECISION'];
4179
$scale = (int) $columnResult['NUMERIC_SCALE'];
80+
$columnType = $columnResult['COLUMN_TYPE'];
81+
self::parseColumnType($columnType, $length, $precision, $scale);
82+
$dataSize = self::getDataSize($length, $precision, $scale);
83+
$type = $reflection->toJdbcType($dataType, $dataSize);
4284
$nullable = in_array(strtoupper($columnResult['IS_NULLABLE']), ['TRUE', 'YES', 'T', 'Y', '1']);
4385
$pk = false;
4486
$fk = '';

src/Tqdev/PhpCrudApi/Column/ReflectionService.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,10 @@ public function __construct(GenericDB $db, Cache $cache, int $ttl)
2626

2727
private function database(): ReflectedDatabase
2828
{
29-
if (!$this->database) {
30-
$this->database = $this->loadDatabase(true);
29+
if ($this->database) {
30+
return $this->database;
3131
}
32+
$this->database = $this->loadDatabase(true);
3233
return $this->database;
3334
}
3435

src/Tqdev/PhpCrudApi/Database/GenericReflection.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,11 @@ private function getTableColumnsSQL(): string
4747
{
4848
switch ($this->driver) {
4949
case 'mysql':
50-
return 'SELECT "COLUMN_NAME", "IS_NULLABLE", "DATA_TYPE", if ("DATA_TYPE"=\'tinyint\' OR "DATA_TYPE"=\'bit\',SUBSTRING_INDEX(SUBSTRING_INDEX("COLUMN_TYPE",\'(\',-1),\')\',1),"CHARACTER_MAXIMUM_LENGTH") as "CHARACTER_MAXIMUM_LENGTH", "NUMERIC_PRECISION", "NUMERIC_SCALE" FROM "INFORMATION_SCHEMA"."COLUMNS" WHERE "TABLE_NAME" = ? AND "TABLE_SCHEMA" = ?';
50+
return 'SELECT "COLUMN_NAME", "IS_NULLABLE", "DATA_TYPE", "CHARACTER_MAXIMUM_LENGTH" as "CHARACTER_MAXIMUM_LENGTH", "NUMERIC_PRECISION", "NUMERIC_SCALE", "COLUMN_TYPE" FROM "INFORMATION_SCHEMA"."COLUMNS" WHERE "TABLE_NAME" = ? AND "TABLE_SCHEMA" = ?';
5151
case 'pgsql':
52-
return 'SELECT a.attname AS "COLUMN_NAME", case when a.attnotnull then \'NO\' else \'YES\' end as "IS_NULLABLE", pg_catalog.format_type(a.atttypid, -1) as "DATA_TYPE", case when a.atttypmod < 0 then NULL else a.atttypmod-4 end as "CHARACTER_MAXIMUM_LENGTH", case when a.atttypid != 1700 then NULL else ((a.atttypmod - 4) >> 16) & 65535 end as "NUMERIC_PRECISION", case when a.atttypid != 1700 then NULL else (a.atttypmod - 4) & 65535 end as "NUMERIC_SCALE" FROM pg_attribute a JOIN pg_class pgc ON pgc.oid = a.attrelid WHERE pgc.relname = ? AND \'\' <> ? AND a.attnum > 0 AND NOT a.attisdropped;';
52+
return 'SELECT a.attname AS "COLUMN_NAME", case when a.attnotnull then \'NO\' else \'YES\' end as "IS_NULLABLE", pg_catalog.format_type(a.atttypid, -1) as "DATA_TYPE", case when a.atttypmod < 0 then NULL else a.atttypmod-4 end as "CHARACTER_MAXIMUM_LENGTH", case when a.atttypid != 1700 then NULL else ((a.atttypmod - 4) >> 16) & 65535 end as "NUMERIC_PRECISION", case when a.atttypid != 1700 then NULL else (a.atttypmod - 4) & 65535 end as "NUMERIC_SCALE", \'\' AS "COLUMN_TYPE" FROM pg_attribute a JOIN pg_class pgc ON pgc.oid = a.attrelid WHERE pgc.relname = ? AND \'\' <> ? AND a.attnum > 0 AND NOT a.attisdropped;';
5353
case 'sqlsrv':
54-
return 'SELECT c.name AS "COLUMN_NAME", c.is_nullable AS "IS_NULLABLE", t.Name AS "DATA_TYPE", (c.max_length/2) AS "CHARACTER_MAXIMUM_LENGTH", c.precision AS "NUMERIC_PRECISION", c.scale AS "NUMERIC_SCALE" FROM sys.columns c INNER JOIN sys.types t ON c.user_type_id = t.user_type_id WHERE c.object_id = OBJECT_ID(?) AND \'\' <> ?';
54+
return 'SELECT c.name AS "COLUMN_NAME", c.is_nullable AS "IS_NULLABLE", t.Name AS "DATA_TYPE", (c.max_length/2) AS "CHARACTER_MAXIMUM_LENGTH", c.precision AS "NUMERIC_PRECISION", c.scale AS "NUMERIC_SCALE", \'\' AS "COLUMN_TYPE" FROM sys.columns c INNER JOIN sys.types t ON c.user_type_id = t.user_type_id WHERE c.object_id = OBJECT_ID(?) AND \'\' <> ?';
5555
}
5656
}
5757

@@ -156,7 +156,7 @@ public function getTableForeignKeys(string $tableName): array
156156
return $foreignKeys;
157157
}
158158

159-
public function toJdbcType(string $type, int $size): string
159+
public function toJdbcType(string $type, string $size): string
160160
{
161161
return $this->typeConverter->toJdbc($type, $size);
162162
}

src/Tqdev/PhpCrudApi/Database/TypeConverter.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ public function __construct(string $driver)
166166
'geometry' => true,
167167
];
168168

169-
public function toJdbc(string $type, int $size): string
169+
public function toJdbc(string $type, string $size): string
170170
{
171171
$jdbcType = strtolower($type);
172172
if (isset($this->toJdbc[$this->driver]["$jdbcType($size)"])) {

src/index.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
'username' => 'php-crud-api',
1414
'password' => 'php-crud-api',
1515
'database' => 'php-crud-api',
16+
'controllers' => 'records,columns,openapi',
1617
]);
1718
$request = RequestFactory::fromGlobals();
1819
$api = new Api($config);

0 commit comments

Comments
 (0)