Skip to content

Commit

Permalink
Install: special processing for pgsql boolean columns
Browse files Browse the repository at this point in the history
The upgrade of ADOdb library to version 4.96 with Mantis release
1.1.0 introduced a change in the way type 'L' columns are created
(SMALLINT before, BOOLEAN after).

This requires special handling to fix the database schema, because the
normal schema upgrade steps do not cover it (since from the MantisBT
installer's perspective the column type has not changed).

Fixes #16392
  • Loading branch information
dregad committed Mar 24, 2014
1 parent 2d40728 commit e2e0a9d
Show file tree
Hide file tree
Showing 2 changed files with 109 additions and 1 deletion.
51 changes: 50 additions & 1 deletion admin/install.php
Expand Up @@ -838,12 +838,61 @@ function print_test( $p_test_description, $p_result, $p_hard_fail = true, $p_mes
}
}

$dict = NewDataDictionary( $g_db );

# Special processing for specific schema versions
# This allows execution of additional install steps, which are
# not a Mantis schema upgrade but nevertheless required due to
# changes in the code

if( $t_last_update > 51 && $t_last_update < 189 ) {
# Since MantisBT 1.1.0 / ADOdb 4.96 (corresponding to schema 51)
# 'L' columns are BOOLEAN instead of SMALLINT
# Check for any DB discrepancies and update columns if needed
$ret = check_pgsql_bool_columns();
if( $ret !== true ) {
# Some columns need converting
$msg = "PostgreSQL: check Boolean columns' actual type";
if( is_array( $ret ) ) {
print_test(
$msg,
count( $ret ) == 0,
false,
count( $ret ) . ' columns must be converted to BOOLEAN'
);
} else {
# We did not get an array => error occured
print_test( $msg, false, true, $ret );
}

# Convert the columns
foreach( $ret as $row ) {
extract( $row );
$sqlarray = $dict->AlterColumnSQL(
$table_name,
"$column_name L NOTNULL DEFAULT '$column_default'"
);

print_test(
"Converting column $table_name.$column_name to BOOLEAN",
2 == $dict->ExecuteSQLArray( $sqlarray, false ),
true,
print_r( $sqlarray, true )
);
if( $g_failed ) {
# Error occured, bail out
break;
}
}
}
}
# End of special processing for specific schema versions

while(( $i <= $lastid ) && !$g_failed ) {
if( !$f_log_queries ) {
echo '<tr><td bgcolor="#ffffff">';
}

$dict = @NewDataDictionary( $g_db );
$t_sql = true;
$t_target = $upgrade[$i][1][0];

Expand Down
59 changes: 59 additions & 0 deletions core/install_helper_functions_api.php
Expand Up @@ -81,6 +81,65 @@ function db_unixtimestamp( $p_date = null, $p_gmt = false ) {
return $p_timestamp;
}

/**
* Check PostgreSQL boolean columns' type in the DB
* Verifies that columns defined as type "L" (logical) in the Mantis schema
* have the correct type in the underlying database.
* The ADOdb library bundled with MantisBT releases prior to 1.1.0 (schema
* version 51) created type "L" columns in PostgreSQL as SMALLINT, whereas later
* versions created them as BOOLEAN.
* @return mixed true if columns check OK
* error message string if errors occured
* array of invalid columns otherwise (empty if all columns check OK)
*/
function check_pgsql_bool_columns() {
global $f_db_type, $f_database_name;
global $g_db;

# Only applies to PostgreSQL
if( $f_db_type != 'pgsql' ) {
return true;
}

# Build the list of "L" type columns as of schema version 51
$t_bool_columns = array(
'bug' => array( 'sticky' ),
'custom_field' => array( 'advanced', 'require_report', 'require_update', 'display_report', 'display_update', 'require_resolved', 'display_resolved', 'display_closed', 'require_closed' ),
'filters' => array( 'is_public' ),
'news' => array( 'announcement' ),
'project' => array( 'enabled' ),
'project_version' => array( 'released' ),
'sponsorship' => array( 'paid' ),
'user_pref' => array( 'advanced_report', 'advanced_view', 'advanced_update', 'redirect_delay', 'email_on_new', 'email_on_assigned', 'email_on_feedback', 'email_on_resolved', 'email_on_closed', 'email_on_reopened', 'email_on_bugnote', 'email_on_status', 'email_on_priority' ),
'user' => array( 'enabled', 'protected' ),
);

# Generate SQL to check columns against schema
$t_where = '';
foreach( $t_bool_columns as $t_table_name => $t_columns ) {
$t_table = db_get_table( $t_table_name );
$t_where .= "table_name = '$t_table' AND column_name IN ( '"
. implode($t_columns, "', '")
. "' ) OR\n";
}
$sql = "SELECT table_name, column_name, data_type, column_default
FROM information_schema.columns
WHERE
table_catalog = '$f_database_name' AND
data_type <> 'boolean' AND
(\n" . rtrim( $t_where, " OR\n" ) . "\n)";

$t_result = @$g_db->Execute( $sql );
if( $t_result === false ) {
return 'Unable to check information_schema';
} else if( $t_result->RecordCount() == 0 ) {
return array();
}

# Some columns are not BOOLEAN type, return the list
return $t_result->GetArray();
}

/**
* Set the value of $g_db_log_queries as specified
* This is used by install callback functions to ensure that only the relevant
Expand Down

0 comments on commit e2e0a9d

Please sign in to comment.