/** * @depends test_parseOneParameter * @dataProvider query_provider */ public function test_parseAllParameters($query, $type, $target) { PMA_RTN_setGlobals(); $this->assertEquals($target, PMA_RTN_parseAllParameters(PMA_SQP_parse($query), $type)); }
/** * This function will generate the values that are required to complete * the "Edit routine" form given the name of a routine. * * @param string $name The name of the routine. * @param string $type Type of routine (ROUTINE|PROCEDURE) * @param bool $all Whether to return all data or just * the info about parameters. * * @return array Data necessary to create the routine editor. */ function PMA_RTN_getDataFromName($name, $type, $all = true) { global $db; $retval = array(); // Build and execute the query $fields = "SPECIFIC_NAME, ROUTINE_TYPE, DTD_IDENTIFIER, " . "ROUTINE_DEFINITION, IS_DETERMINISTIC, SQL_DATA_ACCESS, " . "ROUTINE_COMMENT, SECURITY_TYPE"; $where = "ROUTINE_SCHEMA='" . PMA_Util::sqlAddSlashes($db) . "' " . "AND SPECIFIC_NAME='" . PMA_Util::sqlAddSlashes($name) . "'" . "AND ROUTINE_TYPE='" . PMA_Util::sqlAddSlashes($type) . "'"; $query = "SELECT {$fields} FROM INFORMATION_SCHEMA.ROUTINES WHERE {$where};"; $routine = PMA_DBI_fetch_single_row($query); if (!$routine) { return false; } // Get required data $retval['item_name'] = $routine['SPECIFIC_NAME']; $retval['item_type'] = $routine['ROUTINE_TYPE']; $parsed_query = PMA_SQP_parse(PMA_DBI_get_definition($db, $routine['ROUTINE_TYPE'], $routine['SPECIFIC_NAME'])); $params = PMA_RTN_parseAllParameters($parsed_query, $routine['ROUTINE_TYPE']); $retval['item_num_params'] = $params['num']; $retval['item_param_dir'] = $params['dir']; $retval['item_param_name'] = $params['name']; $retval['item_param_type'] = $params['type']; $retval['item_param_length'] = $params['length']; $retval['item_param_opts_num'] = $params['opts']; $retval['item_param_opts_text'] = $params['opts']; // Get extra data if ($all) { if ($retval['item_type'] == 'FUNCTION') { $retval['item_type_toggle'] = 'PROCEDURE'; } else { $retval['item_type_toggle'] = 'FUNCTION'; } $retval['item_returntype'] = ''; $retval['item_returnlength'] = ''; $retval['item_returnopts_num'] = ''; $retval['item_returnopts_text'] = ''; if (!empty($routine['DTD_IDENTIFIER'])) { if (strlen($routine['DTD_IDENTIFIER']) > 63) { // If the DTD_IDENTIFIER string from INFORMATION_SCHEMA is // at least 64 characters, then it may actually have been // chopped because that column is a varchar(64), so we will // parse the output of SHOW CREATE query to get accurate // information about the return variable. $dtd = ''; $fetching = false; for ($i = 0; $i < $parsed_query['len']; $i++) { if ($parsed_query[$i]['type'] == 'alpha_reservedWord' && strtoupper($parsed_query[$i]['data']) == 'RETURNS') { $fetching = true; } else { if ($fetching == true && $parsed_query[$i]['type'] == 'alpha_reservedWord') { // We will not be looking for options such as UNSIGNED // or ZEROFILL because there is no way that a numeric // field's DTD_IDENTIFIER can be longer than 64 // characters. We can safely assume that the return // datatype is either ENUM or SET, so we only look // for CHARSET. $word = strtoupper($parsed_query[$i]['data']); if ($word == 'CHARSET' && ($parsed_query[$i + 1]['type'] == 'alpha_charset' || $parsed_query[$i + 1]['type'] == 'alpha_identifier')) { $dtd .= $word . ' ' . $parsed_query[$i + 1]['data']; } break; } else { if ($fetching == true) { $dtd .= $parsed_query[$i]['data'] . ' '; } } } } $routine['DTD_IDENTIFIER'] = $dtd; } $returnparam = PMA_RTN_parseOneParameter($routine['DTD_IDENTIFIER']); $retval['item_returntype'] = $returnparam[2]; $retval['item_returnlength'] = $returnparam[3]; $retval['item_returnopts_num'] = $returnparam[4]; $retval['item_returnopts_text'] = $returnparam[4]; } $retval['item_definer'] = PMA_RTN_parseRoutineDefiner($parsed_query); $retval['item_definition'] = $routine['ROUTINE_DEFINITION']; $retval['item_isdeterministic'] = ''; if ($routine['IS_DETERMINISTIC'] == 'YES') { $retval['item_isdeterministic'] = " checked='checked'"; } $retval['item_securitytype_definer'] = ''; $retval['item_securitytype_invoker'] = ''; if ($routine['SECURITY_TYPE'] == 'DEFINER') { $retval['item_securitytype_definer'] = " selected='selected'"; } else { if ($routine['SECURITY_TYPE'] == 'INVOKER') { $retval['item_securitytype_invoker'] = " selected='selected'"; } } $retval['item_sqldataaccess'] = $routine['SQL_DATA_ACCESS']; $retval['item_comment'] = $routine['ROUTINE_COMMENT']; } return $retval; }
/** * Creates the contents for a row in the list of routines * * @param array $routine An array of routine data * @param string $rowclass Empty or one of ['even'|'odd'] * * @return string HTML code of a row for the list of routines */ function PMA_RTN_getRowForList($routine, $rowclass = '') { global $ajax_class, $url_query, $db, $titles; $sql_drop = sprintf('DROP %s IF EXISTS %s', $routine['type'], PMA_Util::backquote($routine['name'])); $type_link = "item_type={$routine['type']}"; $retval = " <tr class='{$rowclass}'>\n"; $retval .= " <td>\n"; $retval .= ' <input type="checkbox"' . ' class="checkall" name="item_name[]"' . ' value="' . htmlspecialchars($routine['name']) . '" />'; $retval .= " </td>\n"; $retval .= " <td>\n"; $retval .= " <span class='drop_sql hide'>" . htmlspecialchars($sql_drop) . "</span>\n"; $retval .= " <strong>\n"; $retval .= " " . htmlspecialchars($routine['name']) . "\n"; $retval .= " </strong>\n"; $retval .= " </td>\n"; $retval .= " <td>\n"; // Since editing a procedure involved dropping and recreating, check also for // CREATE ROUTINE privilege to avoid lost procedures. if (PMA_Util::currentUserHasPrivilege('CREATE ROUTINE', $db)) { $retval .= ' <a ' . $ajax_class['edit'] . ' href="db_routines.php' . $url_query . '&edit_item=1' . '&item_name=' . urlencode($routine['name']) . '&' . $type_link . '">' . $titles['Edit'] . "</a>\n"; } else { $retval .= " {$titles['NoEdit']}\n"; } $retval .= " </td>\n"; $retval .= " <td>\n"; // There is a problem with PMA_Util::currentUserHasPrivilege(): // it does not detect all kinds of privileges, for example // a direct privilege on a specific routine. So, at this point, // we show the Execute link, hoping that the user has the correct rights. // Also, information_schema might be hiding the ROUTINE_DEFINITION // but a routine with no input parameters can be nonetheless executed. // Check if the routine has any input parameters. If it does, // we will show a dialog to get values for these parameters, // otherwise we can execute it directly. $params = PMA_RTN_parseAllParameters(PMA_SQP_parse($GLOBALS['dbi']->getDefinition($db, $routine['type'], $routine['name'])), $routine['type']); if ($routine !== false) { if (PMA_Util::currentUserHasPrivilege('EXECUTE', $db)) { $execute_action = 'execute_routine'; for ($i = 0; $i < $params['num']; $i++) { if ($routine['type'] == 'PROCEDURE' && $params['dir'][$i] == 'OUT') { continue; } $execute_action = 'execute_dialog'; break; } $retval .= ' <a ' . $ajax_class['exec'] . ' href="db_routines.php' . $url_query . '&' . $execute_action . '=1' . '&item_name=' . urlencode($routine['name']) . '&' . $type_link . '">' . $titles['Execute'] . "</a>\n"; } else { $retval .= " {$titles['NoExecute']}\n"; } } $retval .= " </td>\n"; $retval .= " <td>\n"; $retval .= ' <a ' . $ajax_class['export'] . ' href="db_routines.php' . $url_query . '&export_item=1' . '&item_name=' . urlencode($routine['name']) . '&' . $type_link . '">' . $titles['Export'] . "</a>\n"; $retval .= " </td>\n"; $retval .= " <td>\n"; $retval .= ' <a ' . $ajax_class['drop'] . ' href="sql.php' . $url_query . '&sql_query=' . urlencode($sql_drop) . '&goto=db_routines.php' . urlencode("?db={$db}") . '" >' . $titles['Drop'] . "</a>\n"; $retval .= " </td>\n"; $retval .= " <td>\n"; $retval .= " {$routine['type']}\n"; $retval .= " </td>\n"; $retval .= " <td>\n"; $retval .= " " . htmlspecialchars($routine['returns']) . "\n"; $retval .= " </td>\n"; $retval .= " </tr>\n"; return $retval; }