diff options
author | Gábor Hojtsy <gabor@hojtsy.hu> | 2007-08-26 08:27:09 +0000 |
---|---|---|
committer | Gábor Hojtsy <gabor@hojtsy.hu> | 2007-08-26 08:27:09 +0000 |
commit | 39d776faa951a40eab75d035aa728fecd2803b58 (patch) | |
tree | d203a5539ccf1c42bb9671c2635df821d6bc2ad6 /includes | |
parent | 7531f956aa542558d601a3d4f3039f4041793ec0 (diff) | |
download | brdo-39d776faa951a40eab75d035aa728fecd2803b58.tar.gz brdo-39d776faa951a40eab75d035aa728fecd2803b58.tar.bz2 |
#157682 by bjaspan, chx and JirkaRybka: update.php for Drupal 6, to allow near flowless updates
Diffstat (limited to 'includes')
-rw-r--r-- | includes/database.inc | 42 | ||||
-rw-r--r-- | includes/database.mysql-common.inc | 40 | ||||
-rw-r--r-- | includes/database.pgsql.inc | 34 |
3 files changed, 100 insertions, 16 deletions
diff --git a/includes/database.inc b/includes/database.inc index 053228310..ee60b80d9 100644 --- a/includes/database.inc +++ b/includes/database.inc @@ -445,5 +445,47 @@ function db_field_names($fields) { } /** + * Given a Schema API field type, return the correct %-placeholder to + * embed in a query to be passed to db_query along with a value from a + * column of the specified type. + * + * @param $type + * The Schema API type of a field. + * @return + * The placeholder string to embed in a query for that type. + */ +function _db_type_placeholder($type) { + switch ($type) { + case 'varchar': + case 'text': + case 'datetime': + return '\'%s\''; + + case 'numeric': + // For 'numeric' values, we use '%s', not '\'%s\'' as with + // string types, because numeric values should not be enclosed + // in quotes in queries (though they can be, at least on mysql + // and pgsql). Numerics should only have [0-9.+-] and + // presumably no db's "escape string" function will mess with + // those characters. + return '%s'; + + case 'serial': + case 'int': + return '%d'; + + case 'float': + return '%f'; + + case 'blob': + return '%b'; + } + + // There is no safe value to return here, so return something that + // will cause the query to fail. + return 'unsupported type '. $type . 'for _db_type_placeholder'; +} + +/** * @} End of "defgroup schemaapi". */ diff --git a/includes/database.mysql-common.inc b/includes/database.mysql-common.inc index 7bb4580c6..ce96918e8 100644 --- a/includes/database.mysql-common.inc +++ b/includes/database.mysql-common.inc @@ -257,12 +257,31 @@ function db_drop_table(&$ret, $table) { * @param $field * Name of the field to be added. * @param $spec - * The field specification array, as taken from a schema definition + * The field specification array, as taken from a schema definition. + * The specification may also contain the key 'initial', the newly + * created field will be set to the value of the key in all rows. + * This is most useful for creating NOT NULL columns with no default + * value in existing tables. */ function db_add_field(&$ret, $table, $field, $spec) { + $fixnull = FALSE; + if (!empty($spec['not null']) && !isset($spec['default'])) { + $fixnull = TRUE; + $spec['not null'] = FALSE; + } $query = 'ALTER TABLE {'. $table .'} ADD '; $query .= _db_create_field_sql($field, _db_process_field($spec)); $ret[] = update_sql($query); + if (isset($spec['initial'])) { + // All this because update_sql does not support %-placeholders. + $sql = 'UPDATE {'. $table .'} SET '. $field .' = '. _db_type_placeholder($spec['type']); + $result = db_query($sql, $spec['initial']); + $ret[] = array('success' => $result !== FALSE, 'query' => check_plain($sql .' ('. $spec['initial'] .')')); + } + if ($fixnull) { + $spec['not null'] = TRUE; + db_change_field($ret, $table, $field, $field, $spec); + } } /** @@ -387,15 +406,7 @@ function db_drop_unique_key(&$ret, $table, $name) { * An array of field names. */ function db_add_index(&$ret, $table, $name, $fields) { - $query = 'ALTER TABLE {'. $table .'} ADD INDEX '. $name .' ('; - - foreach ($fields as $current) { - $query .= $current .', '; - } - - // Remove the last comma, add a closing bracket. - $query = substr($query, 0, -2) .')'; - + $query = 'ALTER TABLE {'. $table .'} ADD INDEX '. $name .' ('. _db_create_key_sql($fields) . ')'; $ret[] = update_sql($query); } @@ -416,6 +427,15 @@ function db_drop_index(&$ret, $table, $name) { /** * Change a field definition. * + * IMPORTANT NOTE: On some database systems (notably PostgreSQL), + * changing a field definition involves adding a new field and + * dropping an old one. This means that any indices, primary keys and + * sequences (from serial-type fields) that use the field to be + * changed get dropped. For database portability, you MUST drop them + * explicitly before calling db_change_field() and then re-create them + * afterwards. Use db_{add,drop}_{primary_key,unique_key,index} for + * this purpose. + * * @param $ret * Array to which query results will be added. * @param $table diff --git a/includes/database.pgsql.inc b/includes/database.pgsql.inc index c5fd4401b..23fd2b8d6 100644 --- a/includes/database.pgsql.inc +++ b/includes/database.pgsql.inc @@ -251,7 +251,7 @@ function db_last_insert_id($table, $field) { */ function db_affected_rows() { global $last_result; - return pg_affected_rows($last_result); + return empty($last_result) ? 0 : pg_affected_rows($last_result); } /** @@ -658,12 +658,30 @@ function db_drop_table(&$ret, $table) { * @param $field * Name of the field to be added. * @param $spec - * The field specification array, as taken from a schema definition + * The field specification array, as taken from a schema definition. + * The specification may also contain the key 'initial', the newly + * created field will be set to the value of the key in all rows. + * This is most useful for creating NOT NULL columns with no default + * value in existing tables. */ function db_add_field(&$ret, $table, $field, $spec) { + $fixnull = FALSE; + if (!empty($spec['not null']) && !isset($spec['default'])) { + $fixnull = TRUE; + $spec['not null'] = FALSE; + } $query = 'ALTER TABLE {'. $table .'} ADD COLUMN '; $query .= _db_create_field_sql($field, _db_process_field($spec)); $ret[] = update_sql($query); + if (isset($spec['initial'])) { + // All this because update_sql does not support %-placeholders. + $sql = 'UPDATE {'. $table .'} SET '. $field .' = '. _db_type_placeholder($spec['type']); + $result = db_query($sql, $spec['initial']); + $ret[] = array('success' => $result !== FALSE, 'query' => check_plain($sql .' ('. $spec['initial'] .')')); + } + if ($fixnull) { + $ret[] = update_sql("ALTER TABLE {". $table ."} ALTER $field SET NOT NULL"); + } } /** @@ -811,10 +829,14 @@ function db_drop_index(&$ret, $table, $name) { /** * Change a field definition. * - * Remember that changing a field definition involves adding a new field - * and dropping an old one. This means that any indices, primary keys and - * sequences from serial-type fields are dropped and might need to be - * recreated. + * IMPORTANT NOTE: On some database systems (notably PostgreSQL), + * changing a field definition involves adding a new field and + * dropping an old one. This means that any indices, primary keys and + * sequences (from serial-type fields) that use the field to be + * changed get dropped. For database portability, you MUST drop them + * explicitly before calling db_change_field() and then re-create them + * afterwards. Use db_{add,drop}_{primary_key,unique_key,index} for + * this purpose. * * @param $ret * Array to which query results will be added. |