public static StatementPreparerOptions CreateStatementPreparerOptions(this IMySqlCommand command) { var connection = command.Connection !; var statementPreparerOptions = StatementPreparerOptions.None; if (connection.AllowUserVariables || command.CommandType == CommandType.StoredProcedure) { statementPreparerOptions |= StatementPreparerOptions.AllowUserVariables; } if (connection.DateTimeKind == DateTimeKind.Utc) { statementPreparerOptions |= StatementPreparerOptions.DateTimeUtc; } else if (connection.DateTimeKind == DateTimeKind.Local) { statementPreparerOptions |= StatementPreparerOptions.DateTimeLocal; } if (command.CommandType == CommandType.StoredProcedure) { statementPreparerOptions |= StatementPreparerOptions.AllowOutputParameters; } statementPreparerOptions |= connection.GuidFormat switch { MySqlGuidFormat.Char36 => StatementPreparerOptions.GuidFormatChar36, MySqlGuidFormat.Char32 => StatementPreparerOptions.GuidFormatChar32, MySqlGuidFormat.Binary16 => StatementPreparerOptions.GuidFormatBinary16, MySqlGuidFormat.TimeSwapBinary16 => StatementPreparerOptions.GuidFormatTimeSwapBinary16, MySqlGuidFormat.LittleEndianBinary16 => StatementPreparerOptions.GuidFormatLittleEndianBinary16, _ => StatementPreparerOptions.None }; return(statementPreparerOptions); } }
private static void WritePreparedStatement(IMySqlCommand command, PreparedStatement preparedStatement, ByteBufferWriter writer) { var parameterCollection = command.RawParameters; if (Log.IsDebugEnabled()) { Log.Debug("Session{0} Preparing command payload; CommandId: {1}; CommandText: {2}", command.Connection !.Session.Id, preparedStatement.StatementId, command.CommandText); } writer.Write(preparedStatement.StatementId); writer.Write((byte)0); writer.Write(1); if (preparedStatement.Parameters?.Length > 0) { // TODO: How to handle incorrect number of parameters? // build subset of parameters for this statement var parameters = new MySqlParameter[preparedStatement.Statement.ParameterNames.Count]; for (var i = 0; i < preparedStatement.Statement.ParameterNames.Count; i++) { var parameterName = preparedStatement.Statement.ParameterNames[i]; var parameterIndex = parameterName is object?(parameterCollection?.NormalizedIndexOf(parameterName) ?? -1) : preparedStatement.Statement.ParameterIndexes[i]; if (parameterIndex == -1 && parameterName is object) { throw new MySqlException("Parameter '{0}' must be defined.".FormatInvariant(parameterName)); } else if (parameterIndex < 0 || parameterIndex >= (parameterCollection?.Count ?? 0)) { throw new MySqlException("Parameter index {0} is invalid when only {1} parameter{2} defined.".FormatInvariant(parameterIndex, parameterCollection?.Count ?? 0, parameterCollection?.Count == 1 ? " is" : "s are")); } parameters[i] = parameterCollection ![parameterIndex];
internal static MySqlDiagnosticsCommand ToDiagnosticsCommand(this IMySqlCommand sqlCommand) { if (sqlCommand == null) { throw new ArgumentNullException(nameof(sqlCommand)); } return(new MySqlDiagnosticsCommand { CommandId = sqlCommand.CancellableCommand.CommandId, CommandTimeout = sqlCommand.CancellableCommand.CommandTimeout, CommandText = sqlCommand.CommandText, CommandType = sqlCommand.CommandType, AllowUserVariables = sqlCommand.AllowUserVariables, CommandBehavior = sqlCommand.CommandBehavior, RawParameters = sqlCommand.RawParameters, Connection = sqlCommand.Connection }); }
/// <summary> /// Writes the text of <paramref name="command"/> to <paramref name="writer"/>, encoded in UTF-8. /// </summary> /// <param name="command">The command.</param> /// <param name="cachedProcedures">The cached procedures.</param> /// <param name="writer">The output writer.</param> /// <returns><c>true</c> if a complete command was written; otherwise, <c>false</c>.</returns> public static bool WriteQueryPayload(IMySqlCommand command, IDictionary <string, CachedProcedure?> cachedProcedures, ByteBufferWriter writer) => (command.CommandType == CommandType.StoredProcedure) ? WriteStoredProcedure(command, cachedProcedures, writer) : WriteCommand(command, writer);
private void WritePreparedStatement(IMySqlCommand command, PreparedStatement preparedStatement, ByteBufferWriter writer) { var parameterCollection = command.Parameters; if (Log.IsDebugEnabled()) { Log.Debug("Session{0} Preparing command payload; CommandId: {1}; CommandText: {2}", command.Connection.Session.Id, preparedStatement.StatementId, command.CommandText); } writer.Write((byte)CommandKind.StatementExecute); writer.Write(preparedStatement.StatementId); writer.Write((byte)0); writer.Write(1); if (preparedStatement.Parameters?.Length > 0) { // TODO: How to handle incorrect number of parameters? // build subset of parameters for this statement var parameters = new MySqlParameter[preparedStatement.Statement.ParameterNames.Count]; for (var i = 0; i < preparedStatement.Statement.ParameterNames.Count; i++) { var parameterName = preparedStatement.Statement.ParameterNames[i]; var parameterIndex = parameterName != null ? (parameterCollection?.NormalizedIndexOf(parameterName) ?? -1) : preparedStatement.Statement.ParameterIndexes[i]; if (parameterIndex == -1 && parameterName != null) { throw new MySqlException("Parameter '{0}' must be defined.".FormatInvariant(parameterName)); } else if (parameterIndex < 0 || parameterIndex >= (parameterCollection?.Count ?? 0)) { throw new MySqlException("Parameter index {0} is invalid when only {1} parameter{2} defined.".FormatInvariant(parameterIndex, parameterCollection?.Count ?? 0, parameterCollection?.Count == 1 ? " is" : "s are")); } parameters[i] = parameterCollection[parameterIndex]; } // write null bitmap byte nullBitmap = 0; for (var i = 0; i < parameters.Length; i++) { var parameter = parameters[i]; if (parameter.Value is null || parameter.Value == DBNull.Value) { nullBitmap |= (byte)(1 << (i % 8)); } if (i % 8 == 7) { writer.Write(nullBitmap); nullBitmap = 0; } } if (parameters.Length % 8 != 0) { writer.Write(nullBitmap); } // write "new parameters bound" flag writer.Write((byte)1); foreach (var parameter in parameters) { writer.Write(TypeMapper.ConvertToColumnTypeAndFlags(parameter.MySqlDbType, command.Connection.GuidFormat)); } var options = command.CreateStatementPreparerOptions(); foreach (var parameter in parameters) { parameter.AppendBinary(writer, options); } } }
private void WriteCommand(IMySqlCommand command, ByteBufferWriter writer) { var preparer = new StatementPreparer(command.CommandText, command.Parameters, command.CreateStatementPreparerOptions()); preparer.ParseAndBindParameters(writer); }
private void WriteStoredProcedure(IMySqlCommand command, IDictionary <string, CachedProcedure> cachedProcedures, ByteBufferWriter writer) { var parameterCollection = command.Parameters; var cachedProcedure = cachedProcedures[command.CommandText]; if (cachedProcedure is object) { parameterCollection = cachedProcedure.AlignParamsWithDb(parameterCollection); } MySqlParameter returnParameter = null; var outParameters = new MySqlParameterCollection(); var outParameterNames = new List <string>(); var inParameters = new MySqlParameterCollection(); var argParameterNames = new List <string>(); var inOutSetParameters = ""; for (var i = 0; i < (parameterCollection?.Count ?? 0); i++) { var param = parameterCollection[i]; var inName = "@inParam" + i; var outName = "@outParam" + i; switch (param.Direction) { case ParameterDirection.Input: case ParameterDirection.InputOutput: var inParam = param.WithParameterName(inName); inParameters.Add(inParam); if (param.Direction == ParameterDirection.InputOutput) { inOutSetParameters += $"SET {outName}={inName}; "; goto case ParameterDirection.Output; } argParameterNames.Add(inName); break; case ParameterDirection.Output: outParameters.Add(param); outParameterNames.Add(outName); argParameterNames.Add(outName); break; case ParameterDirection.ReturnValue: returnParameter = param; break; } } // if a return param is set, assume it is a function; otherwise, assume stored procedure var commandText = command.CommandText + "(" + string.Join(", ", argParameterNames) + ");"; if (returnParameter is null) { commandText = inOutSetParameters + "CALL " + commandText; if (outParameters.Count > 0) { commandText += "SELECT '" + OutParameterSentinelColumnName + "' AS '" + OutParameterSentinelColumnName + "', " + string.Join(", ", outParameterNames); } } else { commandText = "SELECT " + commandText; } command.OutParameters = outParameters; command.ReturnParameter = returnParameter; var preparer = new StatementPreparer(commandText, inParameters, command.CreateStatementPreparerOptions()); preparer.ParseAndBindParameters(writer); }