private void ParseProcedureBody(MyCatSchemaCollection parametersTable, string body, MyCatSchemaRow row, string nameToRestrict) { List <string> modes = new List <string>(new string[3] { "IN", "OUT", "INOUT" }); string sqlMode = row["SQL_MODE"].ToString(); int pos = 1; MyCatTokenizer tokenizer = new MyCatTokenizer(body); tokenizer.AnsiQuotes = sqlMode.IndexOf("ANSI_QUOTES") != -1; tokenizer.BackslashEscapes = sqlMode.IndexOf("NO_BACKSLASH_ESCAPES") == -1; tokenizer.ReturnComments = false; string token = tokenizer.NextToken(); // this block will scan for the opening paren while also determining // if this routine is a function. If so, then we need to add a // parameter row for the return parameter since it is ordinal position // 0 and should appear first. while (token != "(") { if (String.Compare(token, "FUNCTION", StringComparison.OrdinalIgnoreCase) == 0 && nameToRestrict == null) { parametersTable.AddRow(); InitParameterRow(row, parametersTable.Rows[0]); } token = tokenizer.NextToken(); } token = tokenizer.NextToken(); // now move to the next token past the ( while (token != ")") { MyCatSchemaRow parmRow = parametersTable.NewRow(); InitParameterRow(row, parmRow); parmRow["ORDINAL_POSITION"] = pos++; // handle mode and name for the parameter string mode = StringUtility.ToUpperInvariant(token); if (!tokenizer.Quoted && modes.Contains(mode)) { parmRow["PARAMETER_MODE"] = mode; token = tokenizer.NextToken(); } if (tokenizer.Quoted) { token = token.Substring(1, token.Length - 2); } parmRow["PARAMETER_NAME"] = token; // now parse data type token = ParseDataType(parmRow, tokenizer); if (token == ",") { token = tokenizer.NextToken(); } // now determine if we should include this row after all // we need to parse it before this check so we are correctly // positioned for the next parameter if (nameToRestrict == null || String.Compare(parmRow["PARAMETER_NAME"].ToString(), nameToRestrict, StringComparison.OrdinalIgnoreCase) == 0) { parametersTable.Rows.Add(parmRow); } } // now parse out the return parameter if there is one. token = StringUtility.ToUpperInvariant(tokenizer.NextToken()); if (String.Compare(token, "RETURNS", StringComparison.OrdinalIgnoreCase) == 0) { MyCatSchemaRow parameterRow = parametersTable.Rows[0]; parameterRow["PARAMETER_NAME"] = "RETURN_VALUE"; ParseDataType(parameterRow, tokenizer); } }
/// <summary> /// Parses out the elements of a procedure parameter data type. /// </summary> private string ParseDataType(MyCatSchemaRow row, MyCatTokenizer tokenizer) { StringBuilder dtd = new StringBuilder( StringUtility.ToUpperInvariant(tokenizer.NextToken())); row["DATA_TYPE"] = dtd.ToString(); string type = row["DATA_TYPE"].ToString(); string token = tokenizer.NextToken(); if (token == "(") { token = tokenizer.ReadParenthesis(); dtd.AppendFormat(CultureInfo.InvariantCulture, "{0}", token); if (type != "ENUM" && type != "SET") { ParseDataTypeSize(row, token); } token = tokenizer.NextToken(); } else { dtd.Append(GetDataTypeDefaults(type, row)); } while (token != ")" && token != "," && String.Compare(token, "begin", StringComparison.OrdinalIgnoreCase) != 0 && String.Compare(token, "return", StringComparison.OrdinalIgnoreCase) != 0) { if (String.Compare(token, "CHARACTER", StringComparison.OrdinalIgnoreCase) == 0 || String.Compare(token, "BINARY", StringComparison.OrdinalIgnoreCase) == 0) { } // we don't need to do anything with this else if (String.Compare(token, "SET", StringComparison.OrdinalIgnoreCase) == 0 || String.Compare(token, "CHARSET", StringComparison.OrdinalIgnoreCase) == 0) { row["CHARACTER_SET_NAME"] = tokenizer.NextToken(); } else if (String.Compare(token, "ASCII", StringComparison.OrdinalIgnoreCase) == 0) { row["CHARACTER_SET_NAME"] = "latin1"; } else if (String.Compare(token, "UNICODE", StringComparison.OrdinalIgnoreCase) == 0) { row["CHARACTER_SET_NAME"] = "ucs2"; } else if (String.Compare(token, "COLLATE", StringComparison.OrdinalIgnoreCase) == 0) { row["COLLATION_NAME"] = tokenizer.NextToken(); } else { dtd.AppendFormat(CultureInfo.InvariantCulture, " {0}", token); } token = tokenizer.NextToken(); } if (dtd.Length > 0) { row["DTD_IDENTIFIER"] = dtd.ToString(); } // now default the collation if one wasn't given if (string.IsNullOrEmpty(( string )row["COLLATION_NAME"]) && !string.IsNullOrEmpty(( string )row["CHARACTER_SET_NAME"])) { row["COLLATION_NAME"] = CharSetMap.GetDefaultCollation( row["CHARACTER_SET_NAME"].ToString(), connection); } // now set the octet length if (row["CHARACTER_MAXIMUM_LENGTH"] != null) { if (row["CHARACTER_SET_NAME"] == null) { row["CHARACTER_SET_NAME"] = ""; } row["CHARACTER_OCTET_LENGTH"] = CharSetMap.GetMaxLength(( string )row["CHARACTER_SET_NAME"], connection) * (int)row["CHARACTER_MAXIMUM_LENGTH"]; } return(token); }
/// <summary> /// Executes this instance. /// </summary> /// <returns>The number of statements executed as part of the script.</returns> public int Execute() { bool openedConnection = false; if (connection == null) { throw new InvalidOperationException(Resources.ConnectionNotSet); } if (query == null || query.Length == 0) { return(0); } // next we open up the connetion if it is not already open if (connection.State != ConnectionState.Open) { openedConnection = true; connection.Open(); } // since we don't allow setting of parameters on a script we can // therefore safely allow the use of user variables. no one should be using // this connection while we are using it so we can temporarily tell it // to allow the use of user variables bool allowUserVars = connection.Settings.AllowUserVariables; connection.Settings.AllowUserVariables = true; try { string mode = connection.driver.Property("sql_mode"); mode = StringUtility.ToUpperInvariant(mode); bool ansiQuotes = mode.IndexOf("ANSI_QUOTES") != -1; bool noBackslashEscapes = mode.IndexOf("NO_BACKSLASH_ESCAPES") != -1; // first we break the query up into smaller queries List <ScriptStatement> statements = BreakIntoStatements(ansiQuotes, noBackslashEscapes); int count = 0; MyCatCommand cmd = new MyCatCommand(null, connection); foreach (ScriptStatement statement in statements) { if (String.IsNullOrEmpty(statement.text)) { continue; } cmd.CommandText = statement.text; try { cmd.ExecuteNonQuery(); count++; OnQueryExecuted(statement); } catch (Exception ex) { if (Error == null) { throw; } if (!OnScriptError(ex)) { break; } } } OnScriptCompleted(); return(count); } finally { connection.Settings.AllowUserVariables = allowUserVars; if (openedConnection) { connection.Close(); } } }