sqlparser.lib.php
来自「php绿色服务器,让大家试用greenamp」· PHP 代码 · 共 1,652 行 · 第 1/5 页
PHP
1,652 行
} // end if ( quote_backtick or double quote or alpha_identifier)// =================================== if ($arr[$i]['type'] == 'punct_qualifier') { // to be able to detect an identifier following another $previous_was_identifier = FALSE; continue; } // end if (punct_qualifier) // TODO: check if 3 identifiers following one another -> error // s a v e a s e l e c t e x p r // finding a list separator or FROM // means that we must save the current chain of identifiers // into a select expression // for now, we only save a select expression if it contains // at least one identifier, as we are interested in checking // the columns and table names, so in "select * from persons", // the "*" is not saved if (isset($chain) && !$seen_end_of_table_ref && ( (!$seen_from && $arr[$i]['type'] == 'punct_listsep') || ($arr[$i]['type'] == 'alpha_reservedWord' && $upper_data == 'FROM')) ) { $size_chain = count($chain); $current_select_expr++; $subresult['select_expr'][$current_select_expr] = array( 'expr' => '', 'alias' => '', 'db' => '', 'table_name' => '', 'table_true_name' => '', 'column' => '' ); if (!empty($alias_for_select_expr)) { // we had found an alias for this select expression $subresult['select_expr'][$current_select_expr]['alias'] = $alias_for_select_expr; unset($alias_for_select_expr); } // there is at least a column $subresult['select_expr'][$current_select_expr]['column'] = $chain[$size_chain - 1]; $subresult['select_expr'][$current_select_expr]['expr'] = $chain[$size_chain - 1]; // maybe a table if ($size_chain > 1) { $subresult['select_expr'][$current_select_expr]['table_name'] = $chain[$size_chain - 2]; // we assume for now that this is also the true name $subresult['select_expr'][$current_select_expr]['table_true_name'] = $chain[$size_chain - 2]; $subresult['select_expr'][$current_select_expr]['expr'] = $subresult['select_expr'][$current_select_expr]['table_name'] . '.' . $subresult['select_expr'][$current_select_expr]['expr']; } // end if ($size_chain > 1) // maybe a db if ($size_chain > 2) { $subresult['select_expr'][$current_select_expr]['db'] = $chain[$size_chain - 3]; $subresult['select_expr'][$current_select_expr]['expr'] = $subresult['select_expr'][$current_select_expr]['db'] . '.' . $subresult['select_expr'][$current_select_expr]['expr']; } // end if ($size_chain > 2) unset($chain); // TODO: explain this: if (($arr[$i]['type'] == 'alpha_reservedWord') && ($upper_data != 'FROM')) { $previous_was_identifier = TRUE; } } // end if (save a select expr) //====================================== // s a v e a t a b l e r e f //====================================== // maybe we just saw the end of table refs // but the last table ref has to be saved // or we are at the last token (TODO: there could be another // query after this one) // or we just got a reserved word if (isset($chain) && $seen_from && $save_table_ref && ($arr[$i]['type'] == 'punct_listsep' || ($arr[$i]['type'] == 'alpha_reservedWord' && $upper_data!="AS") || $seen_end_of_table_ref || $i==$size-1 )) { $size_chain = count($chain); $current_table_ref++; $subresult['table_ref'][$current_table_ref] = array( 'expr' => '', 'db' => '', 'table_name' => '', 'table_alias' => '', 'table_true_name' => '' ); if (!empty($alias_for_table_ref)) { $subresult['table_ref'][$current_table_ref]['table_alias'] = $alias_for_table_ref; unset($alias_for_table_ref); } $subresult['table_ref'][$current_table_ref]['table_name'] = $chain[$size_chain - 1]; // we assume for now that this is also the true name $subresult['table_ref'][$current_table_ref]['table_true_name'] = $chain[$size_chain - 1]; $subresult['table_ref'][$current_table_ref]['expr'] = $subresult['table_ref'][$current_table_ref]['table_name']; // maybe a db if ($size_chain > 1) { $subresult['table_ref'][$current_table_ref]['db'] = $chain[$size_chain - 2]; $subresult['table_ref'][$current_table_ref]['expr'] = $subresult['table_ref'][$current_table_ref]['db'] . '.' . $subresult['table_ref'][$current_table_ref]['expr']; } // end if ($size_chain > 1) // add the table alias into the whole expression $subresult['table_ref'][$current_table_ref]['expr'] .= ' ' . $subresult['table_ref'][$current_table_ref]['table_alias']; unset($chain); $previous_was_identifier = TRUE; //continue; } // end if (save a table ref) // when we have found all table refs, // for each table_ref alias, put the true name of the table // in the corresponding select expressions if (isset($current_table_ref) && ($seen_end_of_table_ref || $i == $size-1)) { for ($tr=0; $tr <= $current_table_ref; $tr++) { $alias = $subresult['table_ref'][$tr]['table_alias']; $truename = $subresult['table_ref'][$tr]['table_true_name']; for ($se=0; $se <= $current_select_expr; $se++) { if (!empty($alias) && $subresult['select_expr'][$se]['table_true_name'] == $alias) { $subresult['select_expr'][$se]['table_true_name'] = $truename; } // end if (found the alias) } // end for (select expressions) } // end for (table refs) } // end if (set the true names) // e n d i n g l o o p #1 // set the $previous_was_identifier to FALSE if the current // token is not an identifier if (($arr[$i]['type'] != 'alpha_identifier') && ($arr[$i]['type'] != 'quote_double') && ($arr[$i]['type'] != 'quote_single') && ($arr[$i]['type'] != 'quote_backtick')) { $previous_was_identifier = FALSE; } // end if // however, if we are on AS, we must keep the $previous_was_identifier if (($arr[$i]['type'] == 'alpha_reservedWord') && ($upper_data == 'AS')) { $previous_was_identifier = TRUE; } if (($arr[$i]['type'] == 'alpha_reservedWord') && ($upper_data =='ON' || $upper_data =='USING')) { $save_table_ref = FALSE; } // end if (data == ON) if (($arr[$i]['type'] == 'alpha_reservedWord') && ($upper_data =='JOIN' || $upper_data =='FROM')) { $save_table_ref = TRUE; } // end if (data == JOIN) // no need to check the end of table ref if we already did // TODO: maybe add "&& $seen_from" if (!$seen_end_of_table_ref) { // if this is the last token, it implies that we have // seen the end of table references // Check for the end of table references // // Note: if we are analyzing a GROUP_CONCAT clause, // we might find a word that seems to indicate that // we have found the end of table refs (like ORDER) // but it's a modifier of the GROUP_CONCAT so // it's not the real end of table refs if (($i == $size-1) || ($arr[$i]['type'] == 'alpha_reservedWord' && !$in_group_concat && PMA_STR_binarySearchInArr($upper_data, $words_ending_table_ref, $words_ending_table_ref_cnt))) { $seen_end_of_table_ref = TRUE; // to be able to save the last table ref, but do not // set it true if we found a word like "ON" that has // already set it to false if (isset($save_table_ref) && $save_table_ref != FALSE) { $save_table_ref = TRUE; } //end if } // end if (check for end of table ref) } //end if (!$seen_end_of_table_ref) if ($seen_end_of_table_ref) { $save_table_ref = FALSE; } // end if } // end for $i (loop #1) // ------------------------------------------------------- // This is a big hunk of debugging code by Marc for this. // ------------------------------------------------------- /* if (isset($current_select_expr)) { for ($trace=0; $trace<=$current_select_expr; $trace++) { echo "<br />"; reset ($subresult['select_expr'][$trace]); while (list ($key, $val) = each ($subresult['select_expr'][$trace])) echo "sel expr $trace $key => $val<br />\n"; } } if (isset($current_table_ref)) { echo "current_table_ref = " . $current_table_ref . "<br>"; for ($trace=0; $trace<=$current_table_ref; $trace++) { echo "<br />"; reset ($subresult['table_ref'][$trace]); while (list ($key, $val) = each ($subresult['table_ref'][$trace])) echo "table ref $trace $key => $val<br />\n"; } } */ // ------------------------------------------------------- // loop #2: for queryflags // ,querytype (for queries != 'SELECT') // // we will also need this queryflag in loop 2 // so set it here if (isset($current_table_ref) && $current_table_ref > -1) { $subresult['queryflags']['select_from'] = 1; } $seen_reserved_word = FALSE; $seen_group = FALSE; $seen_order = FALSE; $in_group_by = FALSE; // true when we are into the GROUP BY clause $in_order_by = FALSE; // true when we are into the ORDER BY clause $in_having = FALSE; // true when we are into the HAVING clause $in_select_expr = FALSE; // true when we are into the select expr clause $in_where = FALSE; // true when we are into the WHERE clause $in_from = FALSE; $in_group_concat = FALSE; for ($i = 0; $i < $size; $i++) {//DEBUG echo "trace loop2 <b>" . $arr[$i]['data'] . "</b> (" . $arr[$i]['type'] . ")<br />"; // need_confirm // // check for reserved words that will have to generate // a confirmation request later in sql.php // the cases are: // DROP TABLE // DROP DATABASE // ALTER TABLE... DROP // DELETE FROM... // // this code is not used for confirmations coming from functions.js // TODO: check for punct_queryend if ($arr[$i]['type'] == 'alpha_reservedWord') { $upper_data = strtoupper($arr[$i]['data']); if (!$seen_reserved_word) { $first_reserved_word = $upper_data; $subresult['querytype'] = $upper_data; $seen_reserved_word = TRUE; // if the first reserved word is DROP or DELETE, // we know this is a query that needs to be confirmed if ($first_reserved_word=='DROP' || $first_reserved_word == 'DELETE' || $first_reserved_word == 'TRUNCATE') { $subresult['queryflags']['need_confirm'] = 1; } if ($first_reserved_word=='SELECT'){ $position_of_first_select = $i; } } else { if ($upper_data=='DROP' && $first_reserved_word=='ALTER') { $subresult['queryflags']['need_confirm'] = 1; } } if ($upper_data == 'SELECT') { $in_select_expr = TRUE; $select_expr_clause = ''; } if ($upper_data == 'DISTINCT' && !$in_group_concat) { $subresult['queryflags']['distinct'] = 1; } if ($upper_data == 'UNION') { $subresult['queryflags']['union'] = 1; } // if this is a real SELECT...FROM if ($upper_data == 'FROM' && isset($subresult['queryflags']['select_from']) && $subresult['queryflags']['select_from'] == 1) { $in_from = TRUE; $from_clause = ''; $in_select_expr = FALSE; } // (we could have less resetting of variables to FALSE // if we trust that the query respects the standard // MySQL order for clauses) // we use $seen_group and $seen_order because we are looking // for the BY if ($upper_data == 'GROUP') { $seen_group = TRUE; $seen_order = FALSE; $in_having = FALSE; $in_order_by = FALSE; $in_where = FALSE; $in_select_expr = FALSE; $in_from = FALSE; } if ($upper_data == 'ORDER' && !$in_group_concat) { $seen_order = TRUE;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?