Skip to content

Commit 20d8623

Browse files
authored
Support pgsql
1 parent bbee274 commit 20d8623

File tree

1 file changed

+182
-38
lines changed

1 file changed

+182
-38
lines changed

src/Commands/MakeModelCommand.php

Lines changed: 182 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -118,34 +118,99 @@ protected function createModel($class, $namespace, $file, $connection = null)
118118
try {
119119
$prefix = config("database.connections.$connection.prefix") ?? '';
120120
$database = config("database.connections.$connection.database");
121+
$driver = config("database.connections.$connection.driver") ?? 'mysql';
121122
$inflector = InflectorFactory::create()->build();
122123
$table_plura = $inflector->pluralize($inflector->tableize($class));
123124
$con = Db::connection($connection);
124-
if ($con->select("show tables like '{$prefix}{$table_plura}'")) {
125-
$table_val = "'$table'";
126-
$table = "{$prefix}{$table_plura}";
127-
} else if ($con->select("show tables like '{$prefix}{$table}'")) {
128-
$table_val = "'$table'";
129-
$table = "{$prefix}{$table}";
130-
}
131-
$tableComment = $con->select('SELECT table_comment FROM information_schema.`TABLES` WHERE table_schema = ? AND table_name = ?', [$database, $table]);
132-
if (!empty($tableComment)) {
133-
$comments = $tableComment[0]->table_comment ?? $tableComment[0]->TABLE_COMMENT;
134-
$properties .= " * {$table} {$comments}" . PHP_EOL;
125+
126+
// 检查表是否存在(兼容MySQL和PostgreSQL)
127+
if ($driver === 'pgsql') {
128+
// PostgreSQL 表检查
129+
$schema = config("database.connections.$connection.schema") ?? 'public';
130+
$exists_plura = $con->select("SELECT to_regclass('{$schema}.{$prefix}{$table_plura}') as table_exists");
131+
$exists = $con->select("SELECT to_regclass('{$schema}.{$prefix}{$table}') as table_exists");
132+
133+
if (!empty($exists_plura[0]->table_exists)) {
134+
$table_val = "'$table'";
135+
$table = "{$prefix}{$table_plura}";
136+
} else if (!empty($exists[0]->table_exists)) {
137+
$table_val = "'$table'";
138+
$table = "{$prefix}{$table}";
139+
}
140+
} else {
141+
// MySQL 表检查
142+
if ($con->select("show tables like '{$prefix}{$table_plura}'")) {
143+
$table_val = "'$table'";
144+
$table = "{$prefix}{$table_plura}";
145+
} else if ($con->select("show tables like '{$prefix}{$table}'")) {
146+
$table_val = "'$table'";
147+
$table = "{$prefix}{$table}";
148+
}
135149
}
136-
foreach ($con->select("select COLUMN_NAME,DATA_TYPE,COLUMN_KEY,COLUMN_COMMENT from INFORMATION_SCHEMA.COLUMNS where table_name = '$table' and table_schema = '$database' ORDER BY ordinal_position") as $item) {
137-
if ($item->COLUMN_KEY === 'PRI') {
138-
$pk = $item->COLUMN_NAME;
139-
$item->COLUMN_COMMENT .= "(主键)";
150+
151+
// 获取表注释和列信息(兼容MySQL和PostgreSQL)
152+
if ($driver === 'pgsql') {
153+
// PostgreSQL 表注释
154+
$schema = config("database.connections.$connection.schema") ?? 'public';
155+
$tableComment = $con->select("SELECT obj_description('{$schema}.{$table}'::regclass) as table_comment");
156+
if (!empty($tableComment) && !empty($tableComment[0]->table_comment)) {
157+
$comments = $tableComment[0]->table_comment;
158+
$properties .= " * {$table} {$comments}" . PHP_EOL;
140159
}
141-
$type = $this->getType($item->DATA_TYPE);
142-
if ($item->COLUMN_NAME === 'created_at') {
143-
$hasCreatedAt = true;
160+
161+
// PostgreSQL 列信息
162+
$columns = $con->select("
163+
SELECT
164+
a.attname as column_name,
165+
format_type(a.atttypid, a.atttypmod) as data_type,
166+
CASE WHEN con.contype = 'p' THEN 'PRI' ELSE '' END as column_key,
167+
d.description as column_comment
168+
FROM pg_catalog.pg_attribute a
169+
LEFT JOIN pg_catalog.pg_description d ON d.objoid = a.attrelid AND d.objsubid = a.attnum
170+
LEFT JOIN pg_catalog.pg_constraint con ON con.conrelid = a.attrelid AND a.attnum = ANY(con.conkey) AND con.contype = 'p'
171+
WHERE a.attrelid = '{$schema}.{$table}'::regclass
172+
AND a.attnum > 0 AND NOT a.attisdropped
173+
ORDER BY a.attnum
174+
");
175+
176+
foreach ($columns as $item) {
177+
if ($item->column_key === 'PRI') {
178+
$pk = $item->column_name;
179+
$item->column_comment = ($item->column_comment ? $item->column_comment . ' ' : '') . "(主键)";
180+
}
181+
$type = $this->getType($item->data_type);
182+
if ($item->column_name === 'created_at') {
183+
$hasCreatedAt = true;
184+
}
185+
if ($item->column_name === 'updated_at') {
186+
$hasUpdatedAt = true;
187+
}
188+
$properties .= " * @property $type \${$item->column_name} " . ($item->column_comment ?? '') . "\n";
144189
}
145-
if ($item->COLUMN_NAME === 'updated_at') {
146-
$hasUpdatedAt = true;
190+
191+
} else {
192+
// MySQL 表注释
193+
$tableComment = $con->select('SELECT table_comment FROM information_schema.`TABLES` WHERE table_schema = ? AND table_name = ?', [$database, $table]);
194+
if (!empty($tableComment)) {
195+
$comments = $tableComment[0]->table_comment ?? $tableComment[0]->TABLE_COMMENT;
196+
$properties .= " * {$table} {$comments}" . PHP_EOL;
197+
}
198+
199+
// MySQL 列信息
200+
foreach ($con->select("select COLUMN_NAME,DATA_TYPE,COLUMN_KEY,COLUMN_COMMENT from INFORMATION_SCHEMA.COLUMNS where table_name = '$table' and table_schema = '$database' ORDER BY ordinal_position") as $item) {
201+
if ($item->COLUMN_KEY === 'PRI') {
202+
$pk = $item->COLUMN_NAME;
203+
$item->COLUMN_COMMENT .= "(主键)";
204+
}
205+
$type = $this->getType($item->DATA_TYPE);
206+
if ($item->COLUMN_NAME === 'created_at') {
207+
$hasCreatedAt = true;
208+
}
209+
if ($item->COLUMN_NAME === 'updated_at') {
210+
$hasUpdatedAt = true;
211+
}
212+
$properties .= " * @property $type \${$item->COLUMN_NAME} {$item->COLUMN_COMMENT}\n";
147213
}
148-
$properties .= " * @property $type \${$item->COLUMN_NAME} {$item->COLUMN_COMMENT}\n";
149214
}
150215
} catch (\Throwable $e) {
151216
echo $e->getMessage() . PHP_EOL;
@@ -223,31 +288,89 @@ protected function createTpModel($class, $namespace, $file, $connection = null)
223288
$config_name = $is_thinkorm_v2 ? 'think-orm' : 'thinkorm';
224289
$prefix = config("$config_name.connections.$connection.prefix") ?? '';
225290
$database = config("$config_name.connections.$connection.database");
291+
$driver = config("$config_name.connections.$connection.type") ?? 'mysql';
292+
226293
if ($is_thinkorm_v2) {
227294
$con = \support\think\Db::connect($connection);
228295
} else {
229296
$con = \think\facade\Db::connect($connection);
230297
}
231298

232-
if ($con->query("show tables like '{$prefix}{$table}'")) {
233-
$table = "{$prefix}{$table}";
234-
$table_val = "'$table'";
235-
} else if ($con->query("show tables like '{$prefix}{$table}s'")) {
236-
$table = "{$prefix}{$table}s";
237-
$table_val = "'$table'";
238-
}
239-
$tableComment = $con->query('SELECT table_comment FROM information_schema.`TABLES` WHERE table_schema = ? AND table_name = ?', [$database, $table]);
240-
if (!empty($tableComment)) {
241-
$comments = $tableComment[0]['table_comment'] ?? $tableComment[0]['TABLE_COMMENT'];
242-
$properties .= " * {$table} {$comments}" . PHP_EOL;
299+
// 检查表是否存在(兼容MySQL和PostgreSQL)
300+
if ($driver === 'pgsql') {
301+
// PostgreSQL 表检查
302+
$schema = config("$config_name.connections.$connection.schema") ?? 'public';
303+
$exists = $con->query("SELECT to_regclass('{$schema}.{$prefix}{$table}') as table_exists");
304+
$exists_plural = $con->query("SELECT to_regclass('{$schema}.{$prefix}{$table}s') as table_exists");
305+
306+
if (!empty($exists[0]['table_exists'])) {
307+
$table = "{$prefix}{$table}";
308+
$table_val = "'$table'";
309+
} else if (!empty($exists_plural[0]['table_exists'])) {
310+
$table = "{$prefix}{$table}s";
311+
$table_val = "'$table'";
312+
}
313+
} else {
314+
// MySQL 表检查
315+
if ($con->query("show tables like '{$prefix}{$table}'")) {
316+
$table = "{$prefix}{$table}";
317+
$table_val = "'$table'";
318+
} else if ($con->query("show tables like '{$prefix}{$table}s'")) {
319+
$table = "{$prefix}{$table}s";
320+
$table_val = "'$table'";
321+
}
243322
}
244-
foreach ($con->query("select COLUMN_NAME,DATA_TYPE,COLUMN_KEY,COLUMN_COMMENT from INFORMATION_SCHEMA.COLUMNS where table_name = '$table' and table_schema = '$database' ORDER BY ordinal_position") as $item) {
245-
if ($item['COLUMN_KEY'] === 'PRI') {
246-
$pk = $item['COLUMN_NAME'];
247-
$item['COLUMN_COMMENT'] .= "(主键)";
323+
324+
// 获取表注释和列信息(兼容MySQL和PostgreSQL)
325+
if ($driver === 'pgsql') {
326+
// PostgreSQL 表注释
327+
$schema = config("$config_name.connections.$connection.schema") ?? 'public';
328+
$tableComment = $con->query("SELECT obj_description('{$schema}.{$table}'::regclass) as table_comment");
329+
if (!empty($tableComment) && !empty($tableComment[0]['table_comment'])) {
330+
$comments = $tableComment[0]['table_comment'];
331+
$properties .= " * {$table} {$comments}" . PHP_EOL;
332+
}
333+
334+
// PostgreSQL 列信息
335+
$columns = $con->query("
336+
SELECT
337+
a.attname as column_name,
338+
format_type(a.atttypid, a.atttypmod) as data_type,
339+
CASE WHEN con.contype = 'p' THEN 'PRI' ELSE '' END as column_key,
340+
d.description as column_comment
341+
FROM pg_catalog.pg_attribute a
342+
LEFT JOIN pg_catalog.pg_description d ON d.objoid = a.attrelid AND d.objsubid = a.attnum
343+
LEFT JOIN pg_catalog.pg_constraint con ON con.conrelid = a.attrelid AND a.attnum = ANY(con.conkey) AND con.contype = 'p'
344+
WHERE a.attrelid = '{$schema}.{$table}'::regclass
345+
AND a.attnum > 0 AND NOT a.attisdropped
346+
ORDER BY a.attnum
347+
");
348+
349+
foreach ($columns as $item) {
350+
if ($item['column_key'] === 'PRI') {
351+
$pk = $item['column_name'];
352+
$item['column_comment'] = ($item['column_comment'] ? $item['column_comment'] . ' ' : '') . "(主键)";
353+
}
354+
$type = $this->getType($item['data_type']);
355+
$properties .= " * @property $type \${$item['column_name']} " . ($item['column_comment'] ?? '') . "\n";
356+
}
357+
} else {
358+
// MySQL 表注释
359+
$tableComment = $con->query('SELECT table_comment FROM information_schema.`TABLES` WHERE table_schema = ? AND table_name = ?', [$database, $table]);
360+
if (!empty($tableComment)) {
361+
$comments = $tableComment[0]['table_comment'] ?? $tableComment[0]['TABLE_COMMENT'];
362+
$properties .= " * {$table} {$comments}" . PHP_EOL;
363+
}
364+
365+
// MySQL 列信息
366+
foreach ($con->query("select COLUMN_NAME,DATA_TYPE,COLUMN_KEY,COLUMN_COMMENT from INFORMATION_SCHEMA.COLUMNS where table_name = '$table' and table_schema = '$database' ORDER BY ordinal_position") as $item) {
367+
if ($item['COLUMN_KEY'] === 'PRI') {
368+
$pk = $item['COLUMN_NAME'];
369+
$item['COLUMN_COMMENT'] .= "(主键)";
370+
}
371+
$type = $this->getType($item['DATA_TYPE']);
372+
$properties .= " * @property $type \${$item['COLUMN_NAME']} {$item['COLUMN_COMMENT']}\n";
248373
}
249-
$type = $this->getType($item['DATA_TYPE']);
250-
$properties .= " * @property $type \${$item['COLUMN_NAME']} {$item['COLUMN_COMMENT']}\n";
251374
}
252375
} catch (\Throwable $e) {
253376
echo $e;
@@ -303,6 +426,15 @@ protected function getType(string $type)
303426
if (strpos($type, 'int') !== false) {
304427
return 'integer';
305428
}
429+
430+
if (strpos($type, 'character varying') !== false || strpos($type, 'varchar') !== false) {
431+
return 'string';
432+
}
433+
434+
if (strpos($type, 'timestamp') !== false) {
435+
return 'string';
436+
}
437+
306438
switch ($type) {
307439
case 'varchar':
308440
case 'string':
@@ -314,11 +446,23 @@ protected function getType(string $type)
314446
case 'datetime':
315447
case 'decimal':
316448
case 'enum':
449+
case 'character': // PostgreSQL类型
450+
case 'char': // PostgreSQL类型
451+
case 'json': // PostgreSQL类型
452+
case 'jsonb': // PostgreSQL类型
453+
case 'uuid': // PostgreSQL类型
454+
case 'timestamptz': // PostgreSQL类型
455+
case 'citext': // PostgreSQL类型
317456
return 'string';
318457
case 'boolean':
458+
case 'bool': // PostgreSQL类型
319459
return 'integer';
320460
case 'float':
461+
case 'float4': // PostgreSQL类型 (real)
462+
case 'float8': // PostgreSQL类型 (double precision)
321463
return 'float';
464+
case 'numeric': // PostgreSQL类型
465+
return 'string';
322466
default:
323467
return 'mixed';
324468
}

0 commit comments

Comments
 (0)