PostgreSQL: Make l10n_cache.lc_value binary
Change-Id I427c6de5a0a29b43cff755db0eb8a750db620173 increases the probability that a null byte will attempt to be stored in the lc_value column. PostgreSQL does not allow that byte in a text column, so convert the column to bytea. If the column already contains corrupted data, the upgrade routine might fail. To prevent this, delete the contents of the table before changing the type. Bug: 62098 Change-Id: Ie8368bde398b2ae4d3cfc9ee7bf35874bd2ded68
This commit is contained in:
parent
e6dd1aa418
commit
0582e3339d
3 changed files with 33 additions and 3 deletions
4
includes/cache/LocalisationCache.php
vendored
4
includes/cache/LocalisationCache.php
vendored
|
|
@ -1171,7 +1171,7 @@ class LCStoreDB implements LCStore {
|
|||
$row = $db->selectRow( 'l10n_cache', array( 'lc_value' ),
|
||||
array( 'lc_lang' => $code, 'lc_key' => $key ), __METHOD__ );
|
||||
if ( $row ) {
|
||||
return unserialize( $row->lc_value );
|
||||
return unserialize( $db->decodeBlob( $row->lc_value ) );
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
|
@ -1233,7 +1233,7 @@ class LCStoreDB implements LCStore {
|
|||
$this->batch[] = array(
|
||||
'lc_lang' => $this->currentLang,
|
||||
'lc_key' => $key,
|
||||
'lc_value' => serialize( $value ) );
|
||||
'lc_value' => $this->dbw->encodeBlob( serialize( $value ) ) );
|
||||
|
||||
if ( count( $this->batch ) >= 100 ) {
|
||||
$this->dbw->insert( 'l10n_cache', $this->batch, __METHOD__ );
|
||||
|
|
|
|||
|
|
@ -406,6 +406,7 @@ class PostgresUpdater extends DatabaseUpdater {
|
|||
array( 'addPgField', 'recentchanges', 'rc_source', "TEXT NOT NULL DEFAULT ''" ),
|
||||
array( 'addPgField', 'page', 'page_links_updated', "TIMESTAMPTZ NULL" ),
|
||||
array( 'addPgField', 'mwuser', 'user_password_expires', 'TIMESTAMPTZ NULL' ),
|
||||
array( 'changeFieldPurgeTable', 'l10n_cache', 'lc_value', 'bytea', "replace(lc_value,'\','\\\\')::bytea" ),
|
||||
|
||||
// 1.24
|
||||
array( 'addPgField', 'page_props', 'pp_sortkey', 'float NULL' ),
|
||||
|
|
@ -677,6 +678,35 @@ END;
|
|||
}
|
||||
}
|
||||
|
||||
protected function changeFieldPurgeTable( $table, $field, $newtype, $default ) {
|
||||
## For a cache table, empty it if the field needs to be changed, because the old contents
|
||||
## may be corrupted. If the column is already the desired type, refrain from purging.
|
||||
$fi = $this->db->fieldInfo( $table, $field );
|
||||
if ( is_null( $fi ) ) {
|
||||
$this->output( "...ERROR: expected column $table.$field to exist\n" );
|
||||
exit( 1 );
|
||||
}
|
||||
|
||||
if ( $fi->type() === $newtype ) {
|
||||
$this->output( "...column '$table.$field' is already of type '$newtype'\n" );
|
||||
} else {
|
||||
$this->output( "Purging data from cache table '$table'\n" );
|
||||
$this->db->query("DELETE from $table" );
|
||||
$this->output( "Changing column type of '$table.$field' from '{$fi->type()}' to '$newtype'\n" );
|
||||
$sql = "ALTER TABLE $table ALTER $field TYPE $newtype";
|
||||
if ( strlen( $default ) ) {
|
||||
$res = array();
|
||||
if ( preg_match( '/DEFAULT (.+)/', $default, $res ) ) {
|
||||
$sqldef = "ALTER TABLE $table ALTER $field SET DEFAULT $res[1]";
|
||||
$this->db->query( $sqldef );
|
||||
$default = preg_replace( '/\s*DEFAULT .+/', '', $default );
|
||||
}
|
||||
$sql .= " USING $default";
|
||||
}
|
||||
$this->db->query( $sql );
|
||||
}
|
||||
}
|
||||
|
||||
protected function setDefault( $table, $field, $default ) {
|
||||
|
||||
$info = $this->db->fieldInfo( $table, $field );
|
||||
|
|
|
|||
|
|
@ -678,7 +678,7 @@ CREATE INDEX user_properties_property ON user_properties (up_property);
|
|||
CREATE TABLE l10n_cache (
|
||||
lc_lang TEXT NOT NULL,
|
||||
lc_key TEXT NOT NULL,
|
||||
lc_value TEXT NOT NULL
|
||||
lc_value BYTEA NOT NULL
|
||||
);
|
||||
CREATE INDEX l10n_cache_lc_lang_key ON l10n_cache (lc_lang, lc_key);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue