public static function get_creation_sql($node_schema, $node_function) { $name = static::get_declaration($node_schema, $node_function); $definer = strlen($node_function['owner']) > 0 ? xml_parser::role_enum(dbsteward::$new_database, $node_function['owner']) : 'CURRENT_USER'; // always drop the function first, just to be safe, and to be compatible with pgsql8's CREATE OR REPLACE $sql = static::get_drop_sql($node_schema, $node_function) . "\n"; if (mysql5::$swap_function_delimiters) { $sql .= 'DELIMITER ' . static::ALT_DELIMITER . "\n"; } $function_type = static::is_procedure($node_function) ? 'PROCEDURE' : 'FUNCTION'; $sql .= "CREATE DEFINER = {$definer} {$function_type} {$name} ("; if (isset($node_function->functionParameter)) { $params = array(); foreach ($node_function->functionParameter as $param) { if (isset($param['direction']) && !static::is_procedure($node_function)) { throw new exception("Parameter directions are not supported in MySQL functions"); } if (empty($param['name'])) { throw new exception("Function parameters must have names in MySQL. In function '{$node_function['name']}'"); } $type = $param['type']; if ($node_type = mysql5_type::get_type_node(dbsteward::$new_database, $node_schema, $type)) { $type = mysql5_type::get_enum_type_declaration($node_type); } $sparam = ''; if (isset($param['direction'])) { $sparam .= (string) $param['direction'] . ' '; } $sparam .= mysql5::get_quoted_function_parameter($param['name']) . ' ' . $type; $params[] = $sparam; } $sql .= implode(', ', $params); } $sql .= ")\n"; // Procedures don't have a return statement if (!static::is_procedure($node_function)) { $returns = $node_function['returns']; if ($node_type = mysql5_type::get_type_node(dbsteward::$new_database, $node_schema, $returns)) { $returns = mysql5_type::get_enum_type_declaration($node_type); } $sql .= "RETURNS " . $returns . "\n"; } $sql .= "LANGUAGE SQL\n"; list($eval_type, $determinism) = static::get_characteristics((string) $node_function['cachePolicy'], (string) $node_function['mysqlEvalType']); $eval_type = str_replace('_', ' ', $eval_type); $sql .= "{$eval_type}\n{$determinism}\n"; // unlike pgsql8, mysql5 defaults to SECURITY DEFINER, so we need to set it to INVOKER unless explicitly told to leave it DEFINER if (!isset($node_function['securityDefiner']) || strcasecmp($node_function['securityDefiner'], 'false') == 0) { $sql .= "SQL SECURITY INVOKER\n"; } else { $sql .= "SQL SECURITY DEFINER\n"; } if (!empty($node_function['description'])) { $sql .= "COMMENT " . mysql5::quote_string_value($node_function['description']) . "\n"; } $sql .= trim(static::get_definition($node_function)); $sql = rtrim($sql, ';'); if (mysql5::$swap_function_delimiters) { $sql .= static::ALT_DELIMITER . "\nDELIMITER ;"; } else { $sql .= ';'; } return $sql; }