在 MediaWiki 扩展中创建新 SQL table 的正确方法

Proper way to create new SQL table in a MediaWiki Extension

我正在创建一个需要自己的 mediawiki 扩展 SQL table。在扩展中创建它的正确方法是什么,我是否需要像 OATHAuth extension 那样为我想要支持的每个数据库创建单独的 SQL 代码?这似乎不是正确的方法。

(OATHAuth 挂钩 onLoadExtensionSchemaUpdates

对于扩展的架构更改,LoadExtensionSchemaUpdates hook page 是正确的查找位置。

LoadExtensionSchemaUpdates 挂钩是

fired when MediaWiki is updated (php maintenance/update.php) to allow extensions to update the database

如果你看一下 ArticleFeedbackv5.sql file, that's basically what the sql file 应该看起来像

CREATE TABLE IF NOT EXISTS /*_*/aft_feedback (
      -- id is no auto-increment, but a in PHP generated unique value
      aft_id binary(32) NOT NULL PRIMARY KEY,
      aft_page integer unsigned NOT NULL,
    ...
    ) /*$wgDBTableOptions*/;

    -- sort indexes (central feedback page; lots of data - more details indexes for most popular actions)
    CREATE INDEX /*i*/relevance ON /*_*/aft_feedback (aft_relevance_score, aft_id, aft_has_comment, aft_oversight, aft_archive, aft_hide);
    CREATE INDEX /*i*/age ON /*_*/aft_feedback (aft_timestamp, aft_id, aft_has_comment, aft_oversight, aft_archive, aft_hide);
    CREATE INDEX /*i*/helpful ON /*_*/aft_feedback (aft_net_helpful, aft_id, aft_has_comment, aft_oversight, aft_archive, aft_hide);

    -- page-specific
    CREATE INDEX /*i*/relevance_page ON /*_*/aft_feedback (aft_page, aft_relevance_score);
    CREATE INDEX /*i*/age_page ON /*_*/aft_feedback (aft_page, aft_timestamp);
    CREATE INDEX /*i*/helpful_page ON /*_*/aft_feedback (aft_page, aft_net_helpful);

    -- index for archive-job
    CREATE INDEX /*i*/archive_queue ON /*_*/aft_feedback (aft_archive, aft_archive_date);

    -- index for mycontribs data
    CREATE INDEX /*i*/contribs ON /*_*/aft_feedback (aft_user, aft_timestamp);
    CREATE INDEX /*i*/contribs_anon ON /*_*/aft_feedback (aft_user, aft_user_text, aft_timestamp);

然后你在钩子文件hook中引用这个文件

public static function loadExtensionSchemaUpdates( $updater = null ) {
            // that's for adding a table
            $updater->addExtensionTable(
                'aft_feedback',
                dirname( __FILE__ ) . '/sql/ArticleFeedbackv5.sql' //that's the previous sql file
            );
            ...
}

不要忘记在 extension.json 文件的挂钩部分添加挂钩。 table 将在您 运行 update.php 文件时创建。

关于您关于为每个数据库引擎创建文件的问题,我们不能为每个数据库引擎使用相同的文件,因为查询可能存在一些差异。看看 说了什么。

如果您还没有,请查看 hook file

protected function execute() {
        switch ( $this->updater->getDB()->getType() ) {
            case 'mysql':
            case 'sqlite':
                $this->updater->addExtensionTable( 'oathauth_users', "{$this->base}/sql/mysql/tables.sql" );
                $this->updater->addExtensionUpdate( [ [ $this, 'schemaUpdateOldUsersFromInstaller' ] ] );
                $this->updater->dropExtensionField(
                    'oathauth_users',
                    'secret_reset',
                    "{$this->base}/sql/mysql/patch-remove_reset.sql"
                );
                $this->updater->addExtensionField(
                    'oathauth_users',
                    'module',
                    "{$this->base}/sql/mysql/patch-add_generic_fields.sql"
                );
                $this->updater->addExtensionUpdate(
                    [ [ __CLASS__, 'schemaUpdateSubstituteForGenericFields' ] ]
                );
                $this->updater->dropExtensionField(
                    'oathauth_users',
                    'secret',
                    "{$this->base}/sql/mysql/patch-remove_module_specific_fields.sql"
                );
                /*$this->updaterAddExtensionUpdate(
                    [ [ __CLASS__, 'schemaUpdateTOTPToMultipleKeys' ] ]
                );*/
                break;
            case 'oracle':
                $this->updater->addExtensionTable( 'oathauth_users', "{$this->base}/sql/oracle/tables.sql" );
                break;
            case 'postgres':
                $this->updater->addExtensionTable( 'oathauth_users', "{$this->base}/sql/postgres/tables.sql" );
                break;
        }
        return true;
    }

是的,您确实需要为每个支持的数据库引擎准备一个补丁文件。理论上它可以是同一个补丁文件,但实际上通常存在细微的语法差异,需要单独的文件。有一些 planned changes 用抽象模式更改替换当前模式更新程序系统,这样扩展开发人员就不必处理数据库引擎差异,但这需要一段时间才能实现。

实际上,大多数扩展通过仅支持 MySQL 和可能的 Postgres 来解决这个问题。