internal string GetCacheKey(string spName, ProcedureCacheEntry proc) { string retValue = String.Empty; StringBuilder key = new StringBuilder(spName); key.Append("("); string delimiter = ""; if (proc.parameters != null) { foreach (MySqlSchemaRow row in proc.parameters.Rows) { if (row["ORDINAL_POSITION"].Equals(0)) { retValue = "?="; } else { key.AppendFormat(CultureInfo.InvariantCulture, "{0}?", delimiter); delimiter = ","; } } } key.Append(")"); return(retValue + key.ToString()); }
private ProcedureCacheEntry GetParameters(string procName) { string procCacheKey = GetCacheKey(procName); ProcedureCacheEntry entry = Connection.ProcedureCache.GetProcedure(Connection, procName, procCacheKey); return(entry); }
public ProcedureCacheEntry GetProcedure(MySqlConnection conn, string spName, string cacheKey) { ProcedureCacheEntry proc = null; if (cacheKey != null) { int hash = cacheKey.GetHashCode(); lock (procHash) { procHash.TryGetValue(hash, out proc); } } if (proc == null) { proc = AddNew(conn, spName); conn.PerfMonitor.AddHardProcedureQuery(); if (conn.Settings.Logging) { MySqlTrace.LogInformation(conn.ServerThread, String.Format(MySqlResources.HardProcQuery, spName)); } } else { conn.PerfMonitor.AddSoftProcedureQuery(); if (conn.Settings.Logging) { MySqlTrace.LogInformation(conn.ServerThread, String.Format(MySqlResources.SoftProcQuery, spName)); } } return(proc); }
/// <summary> /// Retrieves parameter information from the stored procedure specified /// in the MySqlCommand and populates the Parameters collection of the /// specified MySqlCommand object. /// This method is not currently supported since stored procedures are /// not available in MySql. /// </summary> /// <param name="command">The MySqlCommand referencing the stored /// procedure from which the parameter information is to be derived. /// The derived parameters are added to the Parameters collection of the /// MySqlCommand.</param> /// <exception cref="InvalidOperationException">The command text is not /// a valid stored procedure name.</exception> public static void DeriveParameters(MySqlCommand command) { if (command.CommandType != CommandType.StoredProcedure) { throw new InvalidOperationException(MySqlResources.CanNotDeriveParametersForTextCommands); } // retrieve the proc definition from the cache. string spName = command.CommandText; if (spName.IndexOf(".") == -1) { spName = command.Connection.Database + "." + spName; } try { ProcedureCacheEntry entry = command.Connection.ProcedureCache.GetProcedure(command.Connection, spName, null); command.Parameters.Clear(); foreach (MySqlSchemaRow row in entry.parameters.Rows) { MySqlParameter p = new MySqlParameter(); p.ParameterName = String.Format("@{0}", row["PARAMETER_NAME"]); if (row["ORDINAL_POSITION"].Equals(0) && p.ParameterName == "@") { p.ParameterName = "@RETURN_VALUE"; } p.Direction = GetDirection(row); bool unsigned = StoredProcedure.GetFlags(row["DTD_IDENTIFIER"].ToString()).IndexOf("UNSIGNED") != -1; bool real_as_float = entry.procedure.Rows[0]["SQL_MODE"].ToString().IndexOf("REAL_AS_FLOAT") != -1; p.MySqlDbType = MetaData.NameToType(row["DATA_TYPE"].ToString(), unsigned, real_as_float, command.Connection); if (row["CHARACTER_MAXIMUM_LENGTH"] != null) { p.Size = (int)row["CHARACTER_MAXIMUM_LENGTH"]; } if (row["NUMERIC_PRECISION"] != null) { p.Precision = Convert.ToByte(row["NUMERIC_PRECISION"]); } if (row["NUMERIC_SCALE"] != null) { p.Scale = Convert.ToByte(row["NUMERIC_SCALE"]); } if (p.MySqlDbType == MySqlDbType.Set || p.MySqlDbType == MySqlDbType.Enum) { p.PossibleValues = GetPossibleValues(row); } command.Parameters.Add(p); } } catch (InvalidOperationException ioe) { throw new MySqlException(MySqlResources.UnableToDeriveParameters, ioe); } }
private static ProcedureCacheEntry GetProcData(MySqlConnection connection, string spName) { string schema = String.Empty; string name = spName; int dotIndex = spName.IndexOf("."); if (dotIndex != -1) { schema = spName.Substring(0, dotIndex); name = spName.Substring(dotIndex + 1, spName.Length - dotIndex - 1); } string[] restrictions = new string[4]; restrictions[1] = schema.Length > 0 ? schema : connection.CurrentDatabase(); restrictions[2] = name; MySqlSchemaCollection proc = connection.GetSchemaCollection("procedures", restrictions); if (proc.Rows.Count > 1) { throw new MySqlException(MySqlResources.ProcAndFuncSameName); } if (proc.Rows.Count == 0) { throw new MySqlException(String.Format(MySqlResources.InvalidProcName, name, schema)); } ProcedureCacheEntry entry = new ProcedureCacheEntry(); entry.procedure = proc; // we don't use GetSchema here because that would cause another // query of procedures and we don't need that since we already // know the procedure we care about. ISSchemaProvider isp = new ISSchemaProvider(connection); string[] rest = isp.CleanRestrictions(restrictions); MySqlSchemaCollection parameters = isp.GetProcedureParameters(rest, proc); entry.parameters = parameters; return(entry); }
private MySqlParameterCollection CheckParameters(string spName) { MySqlParameterCollection newParms = new MySqlParameterCollection(command); MySqlParameter returnParameter = GetReturnParameter(); ProcedureCacheEntry entry = GetParameters(spName); if (entry.procedure == null || entry.procedure.Rows.Count == 0) { throw new InvalidOperationException(String.Format(MySqlResources.RoutineNotFound, spName)); } bool realAsFloat = entry.procedure.Rows[0]["SQL_MODE"].ToString().IndexOf("REAL_AS_FLOAT") != -1; foreach (MySqlSchemaRow param in entry.parameters.Rows) { newParms.Add(GetAndFixParameter(spName, param, realAsFloat, returnParameter)); } return(newParms); }
private ProcedureCacheEntry AddNew(MySqlConnection connection, string spName) { ProcedureCacheEntry procData = GetProcData(connection, spName); if (maxSize > 0) { string cacheKey = GetCacheKey(spName, procData); int hash = cacheKey.GetHashCode(); lock (procHash) { if (procHash.Keys.Count >= maxSize) { TrimHash(); } if (!procHash.ContainsKey(hash)) { procHash[hash] = procData; hashQueue.Enqueue(hash); } } } return(procData); }