start merging code for MySQL 4.1.2 TIMESTAMPs
This commit is contained in:
@@ -5,6 +5,10 @@ phpMyAdmin - Changelog
|
||||
$Id$
|
||||
$Source$
|
||||
|
||||
2005-03-12 Marc Delisle <lem9@users.sourceforge.net>
|
||||
* tbl_properties_structure.php, libraries/sqlparser.lib.php:
|
||||
start merging code for MySQL 4.1.2 TIMESTAMP options support
|
||||
|
||||
2005-03-10 Alexander M. Turek <me@derrabus.de>
|
||||
* libraries/relation.lib.php: Bug #1159415.
|
||||
|
||||
|
@@ -702,7 +702,8 @@ if ($is_minimum_common == FALSE) {
|
||||
'queryflags' => array(),
|
||||
'select_expr' => array(),
|
||||
'table_ref' => array(),
|
||||
'foreign_keys' => array()
|
||||
'foreign_keys' => array(),
|
||||
'create_table_fields' => array()
|
||||
);
|
||||
$subresult_empty = $subresult;
|
||||
$seek_queryend = FALSE;
|
||||
@@ -716,10 +717,10 @@ if ($is_minimum_common == FALSE) {
|
||||
// for GROUP_CONCAT( ... )
|
||||
$in_group_concat = FALSE;
|
||||
|
||||
/* Description of analyzer results
|
||||
/* Description of analyzer results by lem9
|
||||
*
|
||||
* lem9: db, table, column, alias
|
||||
* ------------------------
|
||||
* db, table, column, alias
|
||||
* ------------------------
|
||||
*
|
||||
* Inside the $subresult array, we create ['select_expr'] and ['table_ref'] arrays.
|
||||
*
|
||||
@@ -742,8 +743,8 @@ if ($is_minimum_common == FALSE) {
|
||||
* There is a debug section at the end of loop #1, if you want to
|
||||
* see the exact contents of select_expr and table_ref
|
||||
*
|
||||
* lem9: queryflags
|
||||
* ----------
|
||||
* queryflags
|
||||
* ----------
|
||||
*
|
||||
* In $subresult, array 'queryflags' is filled, according to what we
|
||||
* find in the query.
|
||||
@@ -757,8 +758,8 @@ if ($is_minimum_common == FALSE) {
|
||||
* ['queryflags']['join'] = 1; for a JOIN
|
||||
* ['queryflags']['offset'] = 1; for the presence of OFFSET
|
||||
*
|
||||
* lem9: query clauses
|
||||
* -------------
|
||||
* query clauses
|
||||
* -------------
|
||||
*
|
||||
* The select is splitted in those clauses:
|
||||
* ['select_expr_clause']
|
||||
@@ -774,20 +775,31 @@ if ($is_minimum_common == FALSE) {
|
||||
* For a SELECT, the whole query without the ORDER BY clause is put into
|
||||
* ['unsorted_query']
|
||||
*
|
||||
* lem9: foreign keys
|
||||
* ------------
|
||||
* foreign keys
|
||||
* ------------
|
||||
* The CREATE TABLE may contain FOREIGN KEY clauses, so they get
|
||||
* analyzed and ['foreign_keys'] is an array filled with
|
||||
* the constraint name, the index list,
|
||||
* the REFERENCES table name and REFERENCES index list,
|
||||
* and ON UPDATE | ON DELETE clauses
|
||||
*
|
||||
* lem9: position_of_first_select
|
||||
* ------------------------
|
||||
* position_of_first_select
|
||||
* ------------------------
|
||||
*
|
||||
* The array index of the first SELECT we find. Will be used to
|
||||
* insert a SQL_CALC_FOUND_ROWS.
|
||||
*
|
||||
* create_table_fields
|
||||
* -------------------
|
||||
*
|
||||
* For now, mostly used to detect the DEFAULT CURRENT_TIMESTAMP and
|
||||
* ON UPDATE CURRENT_TIMESTAMP clauses of the CREATE TABLE query.
|
||||
* An array, each element is the identifier name.
|
||||
* Sub-elements: ['type'] which contains the column type
|
||||
* optional (currently they are never false but can be absent):
|
||||
* ['default_current_timestamp'] boolean
|
||||
* ['on_update_current_timestamp'] boolean
|
||||
*
|
||||
* End of description of analyzer results
|
||||
*/
|
||||
|
||||
@@ -1461,38 +1473,71 @@ if ($is_minimum_common == FALSE) {
|
||||
} // end for $i (loop #2)
|
||||
|
||||
// -----------------------------------------------------
|
||||
// loop #3: foreign keys
|
||||
// loop #3: foreign keys and MySQL 4.1.2+ TIMESTAMP options
|
||||
// (for now, check only the first query)
|
||||
// (for now, identifiers must be backquoted)
|
||||
// (for now, identifiers are assumed to be backquoted)
|
||||
|
||||
// If we find that we are dealing with a CREATE TABLE query,
|
||||
// we look for the next punct_bracket_open_round, which
|
||||
// introduces the fields list. Then, when we find a
|
||||
// quote_backtick, it must be a field, so we put it into
|
||||
// the create_table_fields array. Even if this field is
|
||||
// not a timestamp, it will be useful when logic has been
|
||||
// added for complete field attributes analysis.
|
||||
|
||||
$seen_foreign = FALSE;
|
||||
$seen_references = FALSE;
|
||||
$seen_constraint = FALSE;
|
||||
$in_bracket = FALSE;
|
||||
$foreign_key_number = -1;
|
||||
$seen_create_table = FALSE;
|
||||
$seen_create = FALSE;
|
||||
$in_create_table_fields = FALSE;
|
||||
$brackets_level = 0;
|
||||
$in_timestamp_options = FALSE;
|
||||
$seen_default = FALSE;
|
||||
|
||||
for ($i = 0; $i < $size; $i++) {
|
||||
// DEBUG echo "<b>" . $arr[$i]['data'] . "</b> " . $arr[$i]['type'] . "<br />";
|
||||
|
||||
if ($arr[$i]['type'] == 'alpha_reservedWord') {
|
||||
$upper_data = strtoupper($arr[$i]['data']);
|
||||
$upper_data = strtoupper($arr[$i]['data']);
|
||||
|
||||
if ($upper_data == 'CONSTRAINT') {
|
||||
$foreign_key_number++;
|
||||
$seen_foreign = FALSE;
|
||||
$seen_references = FALSE;
|
||||
$seen_constraint = TRUE;
|
||||
}
|
||||
if ($upper_data == 'FOREIGN') {
|
||||
$seen_foreign = TRUE;
|
||||
$seen_references = FALSE;
|
||||
$seen_constraint = FALSE;
|
||||
}
|
||||
if ($upper_data == 'REFERENCES') {
|
||||
$seen_foreign = FALSE;
|
||||
$seen_references = TRUE;
|
||||
$seen_constraint = FALSE;
|
||||
}
|
||||
if ($upper_data == 'CREATE') {
|
||||
$seen_create = TRUE;
|
||||
}
|
||||
|
||||
if ($upper_data == 'TABLE' && $seen_create) {
|
||||
$seen_create_table = TRUE;
|
||||
$create_table_fields = array();
|
||||
}
|
||||
|
||||
if ($upper_data == 'CURRENT_TIMESTAMP') {
|
||||
if ($in_timestamp_options) {
|
||||
if ($seen_default) {
|
||||
$create_table_fields[$current_identifier]['default_current_timestamp'] = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($upper_data == 'CONSTRAINT') {
|
||||
$foreign_key_number++;
|
||||
$seen_foreign = FALSE;
|
||||
$seen_references = FALSE;
|
||||
$seen_constraint = TRUE;
|
||||
}
|
||||
if ($upper_data == 'FOREIGN') {
|
||||
$seen_foreign = TRUE;
|
||||
$seen_references = FALSE;
|
||||
$seen_constraint = FALSE;
|
||||
}
|
||||
if ($upper_data == 'REFERENCES') {
|
||||
$seen_foreign = FALSE;
|
||||
$seen_references = TRUE;
|
||||
$seen_constraint = FALSE;
|
||||
}
|
||||
|
||||
|
||||
// Cases covered:
|
||||
|
||||
// [ON DELETE {CASCADE | SET NULL | NO ACTION | RESTRICT}]
|
||||
// [ON UPDATE {CASCADE | SET NULL | NO ACTION | RESTRICT}]
|
||||
@@ -1500,6 +1545,8 @@ if ($is_minimum_common == FALSE) {
|
||||
// but we set ['on_delete'] or ['on_cascade'] to
|
||||
// CASCADE | SET_NULL | NO_ACTION | RESTRICT
|
||||
|
||||
// ON UPDATE CURRENT_TIMESTAMP
|
||||
|
||||
if ($upper_data == 'ON') {
|
||||
unset($clause);
|
||||
if ($arr[$i+1]['type'] == 'alpha_reservedWord') {
|
||||
@@ -1529,9 +1576,14 @@ if ($is_minimum_common == FALSE) {
|
||||
if ($arr[$i+3]['type'] == 'alpha_reservedWord') {
|
||||
$value = $third_upper_data . '_' . strtoupper($arr[$i+3]['data']);
|
||||
}
|
||||
} elseif ($third_upper_data == 'CURRENT_TIMESTAMP') {
|
||||
if ($clause == 'on_update'
|
||||
&& $in_timestamp_options) {
|
||||
$create_table_fields[$current_identifier]['on_update_current_timestamp'] = TRUE;
|
||||
$seen_default = FALSE;
|
||||
}
|
||||
|
||||
} else {
|
||||
// for example: ON UPDATE CURRENT_TIMESTAMP
|
||||
// which is not for a foreign key
|
||||
$value = '';
|
||||
}
|
||||
if (!empty($value)) {
|
||||
@@ -1541,35 +1593,80 @@ if ($is_minimum_common == FALSE) {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} // end of reserved words analysis
|
||||
|
||||
|
||||
if ($arr[$i]['type'] == 'punct_bracket_open_round') {
|
||||
$in_bracket = TRUE;
|
||||
}
|
||||
|
||||
if ($arr[$i]['type'] == 'punct_bracket_close_round') {
|
||||
$in_bracket = FALSE;
|
||||
if ($seen_references) {
|
||||
$seen_references = FALSE;
|
||||
$brackets_level++;
|
||||
if ($seen_create_table && $brackets_level == 1) {
|
||||
$in_create_table_fields = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ($arr[$i]['type'] == 'punct_bracket_close_round') {
|
||||
$brackets_level--;
|
||||
if ($seen_references) {
|
||||
$seen_references = FALSE;
|
||||
}
|
||||
if ($seen_create_table && $brackets_level == 0) {
|
||||
$in_create_table_fields = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (($arr[$i]['type'] == 'alpha_columnAttrib')) {
|
||||
$upper_data = strtoupper($arr[$i]['data']);
|
||||
if ($seen_create_table && $in_create_table_fields) {
|
||||
if ($upper_data == 'DEFAULT') {
|
||||
$seen_default = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (($arr[$i]['type'] == 'alpha_columnType')) {
|
||||
$upper_data = strtoupper($arr[$i]['data']);
|
||||
if ($seen_create_table && $in_create_table_fields) {
|
||||
$create_table_fields[$current_identifier]['type'] = $upper_data;
|
||||
if ($upper_data == 'TIMESTAMP') {
|
||||
$in_timestamp_options = TRUE;
|
||||
} else {
|
||||
$in_timestamp_options = FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (($arr[$i]['type'] == 'quote_backtick')) {
|
||||
|
||||
// TODO: one set of IFs to remove backquotes
|
||||
|
||||
if ($seen_create_table && $in_create_table_fields) {
|
||||
// remove backquotes
|
||||
$identifier = str_replace('`','',$arr[$i]['data']);
|
||||
$current_identifier = $identifier;
|
||||
}
|
||||
|
||||
if ($seen_constraint) {
|
||||
// remove backquotes
|
||||
$identifier = str_replace('`','',$arr[$i]['data']);
|
||||
$foreign[$foreign_key_number]['constraint'] = $identifier;
|
||||
}
|
||||
if ($seen_foreign && $in_bracket) {
|
||||
if ($seen_foreign && $brackets_level > 0) {
|
||||
// remove backquotes
|
||||
$identifier = str_replace('`','',$arr[$i]['data']);
|
||||
$foreign[$foreign_key_number]['index_list'][] = $identifier;
|
||||
}
|
||||
|
||||
if ($seen_references) {
|
||||
// remove backquotes
|
||||
$identifier = str_replace('`','',$arr[$i]['data']);
|
||||
if ($in_bracket) {
|
||||
// here, the first bracket level corresponds to the
|
||||
// bracket of CREATE TABLE
|
||||
// so if we are on level 2, it must be the index list
|
||||
// of the foreign key REFERENCES
|
||||
if ($brackets_level > 1) {
|
||||
$foreign[$foreign_key_number]['ref_index_list'][] = $identifier;
|
||||
} else {
|
||||
// for MySQL 4.0.18, identifier is
|
||||
@@ -1595,10 +1692,16 @@ if ($is_minimum_common == FALSE) {
|
||||
}
|
||||
} // end for $i (loop #3)
|
||||
|
||||
|
||||
// Fill the $subresult array
|
||||
|
||||
if (isset($create_table_fields)) {
|
||||
$subresult['create_table_fields'] = $create_table_fields;
|
||||
}
|
||||
|
||||
if (isset($foreign)) {
|
||||
$subresult['foreign_keys'] = $foreign;
|
||||
}
|
||||
//DEBUG print_r($foreign);
|
||||
|
||||
if (isset($select_expr_clause)) {
|
||||
$subresult['select_expr_clause'] = $select_expr_clause;
|
||||
|
@@ -79,7 +79,23 @@ PMA_DBI_free_result($result);
|
||||
$fields_rs = PMA_DBI_query('SHOW FULL FIELDS FROM ' . PMA_backquote($table) . ';', NULL, PMA_DBI_QUERY_STORE);
|
||||
$fields_cnt = PMA_DBI_num_rows($fields_rs);
|
||||
|
||||
// Get more complete field information
|
||||
// For now, this is done just for MySQL 4.1.2+ new TIMESTAMP options
|
||||
// but later, if the analyser returns more information, it
|
||||
// could be executed for any MySQL version and replace
|
||||
// the info given by the previous SHOW FULL FIELDS FROM query.
|
||||
|
||||
// TODO: use this information for proper treatment of TIMESTAMPs
|
||||
|
||||
if (PMA_MYSQL_INT_VERSION >= 40102) {
|
||||
$show_create_table_query = 'SHOW CREATE TABLE '
|
||||
. PMA_backquote($db) . '.' . PMA_backquote($table);
|
||||
$show_create_table_res = PMA_DBI_query($show_create_table_query);
|
||||
list(,$show_create_table) = PMA_DBI_fetch_row($show_create_table_res);
|
||||
PMA_DBI_free_result($show_create_table_res);
|
||||
unset($show_create_table_res, $show_create_table_query);
|
||||
$analyzed_sql = PMA_SQP_analyze(PMA_SQP_parse($show_create_table));
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays the table structure ('show table' works correct since 3.23.03)
|
||||
|
Reference in New Issue
Block a user