← All changes
|
vendor/wpfluent/framework/src/WPFluent/Database/Schema.php
+144
-18
1.3.23
→
1.6.5
View file →
| @@ -33,8 +33,23 @@ | ||
| 33 | 33 | public static function getInfo($key = null) |
| 34 | 34 | { |
| 35 | 35 | $db = static::db(); |
| 36 | 36 | |
| 37 | + if (static::isSqlite()) { | |
| 38 | + $info = [ | |
| 39 | + 'dbname' => 'sqlite', | |
| 40 | + 'prefix' => $db->prefix, | |
| 41 | + 'dbhost' => '', | |
| 42 | + 'username' => '', | |
| 43 | + 'password' => '', | |
| 44 | + 'charset' => 'utf8', | |
| 45 | + 'collation' => '', | |
| 46 | + 'tables' => static::getTableList(), | |
| 47 | + ]; | |
| 48 | + | |
| 49 | + return $key ? ($info[$key] ?? null) : $info; | |
| 50 | + } | |
| 51 | + | |
| 37 | 52 | $info = [ |
| 38 | 53 | // @phpstan-ignore-next-line |
| 39 | 54 | 'dbname' => $db->dbname, |
| 40 | 55 | 'prefix' => $db->prefix, |
| @@ -135,9 +150,9 @@ | ||
| 135 | 150 | // error and then turn off the error from being shown, so |
| 136 | 151 | // error will be not shown if there is no temporary |
| 137 | 152 | // table, then restore the error state. |
| 138 | 153 | $isErrorSuppressed = $wpdb->suppress_errors; |
| 139 | - | |
| 154 | + | |
| 140 | 155 | $wpdb->suppress_errors = true; |
| 141 | 156 | |
| 142 | 157 | static::query("SELECT 1 FROM %{$table}% WHERE 0"); |
| 143 | 158 | |
| @@ -379,17 +394,13 @@ | ||
| 379 | 394 | // SQLite cannot drop PRIMARY KEY columns or columns referenced by indexes |
| 380 | 395 | // via native ALTER TABLE DROP COLUMN. |
| 381 | 396 | // |
| 382 | 397 | // Workarounds: |
| 383 | - // - Indexed columns: drop the index first with ALTER TABLE DROP INDEX, | |
| 398 | + // - Indexed columns: drop the index first with DROP INDEX, | |
| 384 | 399 | // then drop the column. |
| 385 | 400 | // - PRIMARY KEY columns: use CHANGE COLUMN to rebuild the table without |
| 386 | 401 | // the PK attribute (renaming the column to a temp name), then drop |
| 387 | 402 | // the renamed column. |
| 388 | - // | |
| 389 | - // Note: ALTER TABLE … RENAME TO and standalone DROP INDEX are NOT | |
| 390 | - // supported by this version of the WP SQLite integration, so we cannot | |
| 391 | - // use a full-table-rebuild via rename. | |
| 392 | 403 | if (static::isSqlite()) { |
| 393 | 404 | // Collect PRIMARY KEY columns and per-column index key names. |
| 394 | 405 | $indexRows = (array) static::db()->get_results("SHOW INDEX FROM {$tbl}"); |
| 395 | 406 | $pkColumns = []; |
| @@ -544,12 +555,65 @@ | ||
| 544 | 555 | * @see https://developer.wordpress.org/reference/functions/drop_index |
| 545 | 556 | */ |
| 546 | 557 | public static function dropIndex($table, $index) |
| 547 | 558 | { |
| 559 | + if (static::isSqlite()) { | |
| 560 | + $tbl = static::table($table); | |
| 561 | + return static::db()->query("ALTER TABLE {$tbl} DROP INDEX {$index}"); | |
| 562 | + } | |
| 563 | + | |
| 548 | 564 | return drop_index(static::table($table), $index); |
| 549 | 565 | } |
| 550 | 566 | |
| 551 | 567 | /** |
| 568 | + * Add a FULLTEXT index to the given columns, required by the query | |
| 569 | + * builder's relevance ranking (selectRelevance/orderByRelevance and the | |
| 570 | + * Searchable relevanceSearch scope). No-ops on SQLite, which has no | |
| 571 | + * native FULLTEXT support and degrades to LIKE-based matching. | |
| 572 | + * | |
| 573 | + * @param string $table Table name without prefix | |
| 574 | + * @param string|array $columns | |
| 575 | + * @param string|null $name Optional index name | |
| 576 | + * @return mixed | |
| 577 | + */ | |
| 578 | + public static function fullText($table, $columns, $name = null) | |
| 579 | + { | |
| 580 | + if (static::isSqlite()) { | |
| 581 | + return false; | |
| 582 | + } | |
| 583 | + | |
| 584 | + $columns = is_array($columns) | |
| 585 | + ? $columns | |
| 586 | + : array_map('trim', explode(',', $columns)); | |
| 587 | + | |
| 588 | + $tbl = static::table($table); | |
| 589 | + $name = $name ?: ('ft_' . implode('_', $columns)); | |
| 590 | + $list = implode(', ', $columns); | |
| 591 | + | |
| 592 | + return static::db()->query( | |
| 593 | + "ALTER TABLE {$tbl} ADD FULLTEXT {$name} ({$list})" | |
| 594 | + ); | |
| 595 | + } | |
| 596 | + | |
| 597 | + /** | |
| 598 | + * Drop a FULLTEXT index by name. | |
| 599 | + * | |
| 600 | + * @param string $table Table name without prefix | |
| 601 | + * @param string $name Index name | |
| 602 | + * @return mixed | |
| 603 | + */ | |
| 604 | + public static function dropFullText($table, $name) | |
| 605 | + { | |
| 606 | + if (static::isSqlite()) { | |
| 607 | + return false; | |
| 608 | + } | |
| 609 | + | |
| 610 | + $tbl = static::table($table); | |
| 611 | + | |
| 612 | + return static::db()->query("ALTER TABLE {$tbl} DROP INDEX {$name}"); | |
| 613 | + } | |
| 614 | + | |
| 615 | + /** | |
| 552 | 616 | * Makes raw query and can resolve the table name from the query |
| 553 | 617 | * and can form a full table name including the table prefix if |
| 554 | 618 | * the table name is wrapped like: %table_name% in the query. |
| 555 | 619 | * |
| @@ -581,9 +645,9 @@ | ||
| 581 | 645 | return null; |
| 582 | 646 | } |
| 583 | 647 | |
| 584 | 648 | return static::db()->get_col( |
| 585 | - 'SHOW COLUMNS FROM ' . static::table($table), 0 | |
| 649 | + 'DESCRIBE ' . static::table($table), 0 | |
| 586 | 650 | ); |
| 587 | 651 | } |
| 588 | 652 | |
| 589 | 653 | /** |
| @@ -595,12 +659,47 @@ | ||
| 595 | 659 | protected static function protectedGetColumnsWithTypes($table) |
| 596 | 660 | { |
| 597 | 661 | if (!static::hasTable($table)) return; |
| 598 | 662 | |
| 599 | - // @phpstan-ignore-next-line | |
| 663 | + $table = static::table($table); | |
| 664 | + | |
| 665 | + if (static::isSqlite()) { | |
| 666 | + // INFORMATION_SCHEMA is not available in SQLite. | |
| 667 | + // Use DESCRIBE which the WP SQLite plugin translates with | |
| 668 | + // proper MySQL type mapping from its data type cache. | |
| 669 | + $columns = (array) static::db()->get_results("DESCRIBE {$table}"); | |
| 670 | + return array_map(function ($col, $pos) { | |
| 671 | + $extra = $col->Extra ?? ''; | |
| 672 | + // SQLite INTEGER PRIMARY KEY is auto_increment but DESCRIBE | |
| 673 | + // doesn't report it in Extra — detect from Key + Type. | |
| 674 | + if (empty($extra) && ($col->Key ?? '') === 'PRI') { | |
| 675 | + $type = strtoupper($col->Type ?? ''); | |
| 676 | + if (in_array($type, ['INTEGER', 'BIGINT', 'BIGINT(20)', 'BIGINT(20) UNSIGNED', 'INT'])) { | |
| 677 | + $extra = 'auto_increment'; | |
| 678 | + } | |
| 679 | + } | |
| 680 | + | |
| 681 | + return [ | |
| 682 | + 'column_name' => $col->Field, | |
| 683 | + 'ordinal_position' => $pos + 1, | |
| 684 | + 'column_default' => $col->Default, | |
| 685 | + 'is_nullable' => ($col->Null === 'YES' ? 'YES' : 'NO'), | |
| 686 | + 'data_type' => strtolower( | |
| 687 | + preg_replace('/\(.*/', '', $col->Type) | |
| 688 | + ), | |
| 689 | + 'character_maximum_length' => preg_match( | |
| 690 | + '/\((\d+)\)/', $col->Type, $matches | |
| 691 | + ) ? (int)$matches[1] : null, | |
| 692 | + 'numeric_precision' => null, | |
| 693 | + 'numeric_scale' => null, | |
| 694 | + 'column_key' => $col->Key ?? '', | |
| 695 | + 'extra' => $extra, | |
| 696 | + ]; | |
| 697 | + }, $columns, array_keys($columns)); | |
| 698 | + } | |
| 699 | + | |
| 700 | + // @phpstan-ignore-next-line | |
| 600 | 701 | $db = static::db()->dbname; |
| 601 | - | |
| 602 | - $table = static::table($table); | |
| 603 | 702 | |
| 604 | 703 | $fields = [ |
| 605 | 704 | 'COLUMN_NAME', |
| 606 | 705 | 'ORDINAL_POSITION', |
| @@ -612,9 +711,9 @@ | ||
| 612 | 711 | 'NUMERIC_SCALE', |
| 613 | 712 | 'COLUMN_KEY', |
| 614 | 713 | 'EXTRA', |
| 615 | 714 | ]; |
| 616 | - | |
| 715 | + | |
| 617 | 716 | $sql = "SELECT " . implode(',', $fields) . " FROM INFORMATION_SCHEMA.COLUMNS"; |
| 618 | 717 | $sql .= " WHERE TABLE_NAME = '".$table."' AND TABLE_SCHEMA = '".$db."'"; |
| 619 | 718 | |
| 620 | 719 | return array_map(function($i) { |
| @@ -633,8 +732,12 @@ | ||
| 633 | 732 | if (!empty($columns)) { |
| 634 | 733 | return $columns; |
| 635 | 734 | } |
| 636 | 735 | |
| 736 | + if (static::isSqlite()) { | |
| 737 | + return []; | |
| 738 | + } | |
| 739 | + | |
| 637 | 740 | $columns = static::db()->get_results( |
| 638 | 741 | 'SHOW COLUMNS FROM `'.static::table($table).'`' |
| 639 | 742 | ); |
| 640 | 743 | |
| @@ -679,15 +782,30 @@ | ||
| 679 | 782 | { |
| 680 | 783 | $table = static::table($table); |
| 681 | 784 | |
| 682 | 785 | if (static::isSqlite()) { |
| 683 | - return array_map(function ($i) { | |
| 684 | - return [ | |
| 685 | - 'column_name' => $i->from, | |
| 686 | - 'referenced_table' => $i->table, | |
| 687 | - 'referenced_column' => $i->to, | |
| 688 | - ]; | |
| 689 | - }, (array) static::db()->get_results("PRAGMA foreign_key_list({$table})")); | |
| 786 | + // Parse foreign keys from the CREATE TABLE statement in sqlite_master | |
| 787 | + // since PRAGMA queries cannot go through $wpdb. | |
| 788 | + $row = static::db()->get_row( | |
| 789 | + "SELECT sql FROM sqlite_master WHERE type='table' AND name='{$table}'" | |
| 790 | + ); | |
| 791 | + if (!$row || empty($row->sql)) { | |
| 792 | + return []; | |
| 793 | + } | |
| 794 | + $fks = []; | |
| 795 | + if (preg_match_all( | |
| 796 | + '/FOREIGN\s+KEY\s*\(\s*[`"]?(\w+)[`"]?\s*\)\s*REFERENCES\s+[`"]?(\w+)[`"]?\s*\(\s*[`"]?(\w+)[`"]?\s*\)/i', | |
| 797 | + $row->sql, $matches, PREG_SET_ORDER | |
| 798 | + )) { | |
| 799 | + foreach ($matches as $m) { | |
| 800 | + $fks[] = [ | |
| 801 | + 'column_name' => $m[1], | |
| 802 | + 'referenced_table' => $m[2], | |
| 803 | + 'referenced_column' => $m[3], | |
| 804 | + ]; | |
| 805 | + } | |
| 806 | + } | |
| 807 | + return $fks; | |
| 690 | 808 | } |
| 691 | 809 | |
| 692 | 810 | // @phpstan-ignore-next-line |
| 693 | 811 | $db = static::db()->dbname; |
| @@ -830,8 +948,12 @@ | ||
| 830 | 948 | * @return bool |
| 831 | 949 | */ |
| 832 | 950 | public static function isMaria() |
| 833 | 951 | { |
| 952 | + if (static::isSqlite()) { | |
| 953 | + return false; | |
| 954 | + } | |
| 955 | + | |
| 834 | 956 | return str_contains( |
| 835 | 957 | static::db()->get_var('SELECT VERSION()'), 'MariaDB' |
| 836 | 958 | ); |
| 837 | 959 | } |
| @@ -843,8 +965,12 @@ | ||
| 843 | 965 | * @return string |
| 844 | 966 | */ |
| 845 | 967 | public static function getEngine($table) |
| 846 | 968 | { |
| 969 | + if (static::isSqlite()) { | |
| 970 | + return 'sqlite'; | |
| 971 | + } | |
| 972 | + | |
| 847 | 973 | return static::db()->get_var( |
| 848 | 974 | 'SELECT ENGINE FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = "' . static::table($table) . '"' |
| 849 | 975 | ); |
| 850 | 976 | } |