| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297 |
- //------------------------------------------------------------------------------
- // <copyright file="SqlBatchCommand.cs" company="Microsoft">
- // Copyright (c) Microsoft Corporation. All rights reserved.
- // </copyright>
- // <owner current="true" primary="true">[....]</owner>
- // <owner current="true" primary="false">[....]</owner>
- //------------------------------------------------------------------------------
- namespace System.Data.SqlClient {
- using System;
- using System.Collections.Generic;
- using System.ComponentModel;
- using System.Data;
- using System.Data.Common;
- using System.Diagnostics;
- using System.Globalization;
- using System.Text;
- using System.Text.RegularExpressions;
- internal sealed class SqlCommandSet {
- private const string SqlIdentifierPattern = "^@[\\p{Lo}\\p{Lu}\\p{Ll}\\p{Lm}_@#][\\p{Lo}\\p{Lu}\\p{Ll}\\p{Lm}\\p{Nd}\uff3f_@#\\$]*$";
- private static readonly Regex SqlIdentifierParser = new Regex(SqlIdentifierPattern, RegexOptions.ExplicitCapture|RegexOptions.Singleline);
- private List<LocalCommand> _commandList = new List<LocalCommand>();
- private SqlCommand _batchCommand;
- private static int _objectTypeCount; // Bid counter
- internal readonly int _objectID = System.Threading.Interlocked.Increment(ref _objectTypeCount);
- private sealed class LocalCommand {
- internal readonly string CommandText;
- internal readonly SqlParameterCollection Parameters;
- internal readonly int ReturnParameterIndex;
- internal readonly CommandType CmdType;
- internal readonly SqlCommandColumnEncryptionSetting ColumnEncryptionSetting;
- internal LocalCommand(string commandText, SqlParameterCollection parameters, int returnParameterIndex, CommandType cmdType, SqlCommandColumnEncryptionSetting columnEncryptionSetting) {
- Debug.Assert(0 <= commandText.Length, "no text");
- this.CommandText = commandText;
- this.Parameters = parameters;
- this.ReturnParameterIndex = returnParameterIndex;
- this.CmdType = cmdType;
- this.ColumnEncryptionSetting = columnEncryptionSetting;
- }
- }
- internal SqlCommandSet() : base() {
- _batchCommand = new SqlCommand();
- }
- private SqlCommand BatchCommand {
- get {
- SqlCommand command = _batchCommand;
- if (null == command) {
- throw ADP.ObjectDisposed(this);
- }
- return command;
- }
- }
- internal int CommandCount {
- get {
- return CommandList.Count;
- }
- }
- private List<LocalCommand> CommandList {
- get {
- List<LocalCommand> commandList = _commandList;
- if (null == commandList) {
- throw ADP.ObjectDisposed(this);
- }
- return commandList;
- }
- }
- internal int CommandTimeout {
- /*get {
- return BatchCommand.CommandTimeout;
- }*/
- set {
- BatchCommand.CommandTimeout = value;
- }
- }
- internal SqlConnection Connection {
- get {
- return BatchCommand.Connection;
- }
- set {
- BatchCommand.Connection = value;
- }
- }
- internal SqlTransaction Transaction {
- /*get {
- return BatchCommand.Transaction;
- }*/
- set {
- BatchCommand.Transaction = value;
- }
- }
- internal int ObjectID {
- get {
- return _objectID;
- }
- }
- internal void Append(SqlCommand command) {
- ADP.CheckArgumentNull(command, "command");
- Bid.Trace("<sc.SqlCommandSet.Append|API> %d#, command=%d, parameterCount=%d\n", ObjectID, command.ObjectID, command.Parameters.Count);
- string cmdText = command.CommandText;
- if (ADP.IsEmpty(cmdText)) {
- throw ADP.CommandTextRequired(ADP.Append);
- }
- CommandType commandType = command.CommandType;
- switch(commandType) {
- case CommandType.Text:
- case CommandType.StoredProcedure:
- break;
- case CommandType.TableDirect:
- Debug.Assert(false, "command.CommandType");
- throw System.Data.SqlClient.SQL.NotSupportedCommandType(commandType);
- default:
- Debug.Assert(false, "command.CommandType");
- throw ADP.InvalidCommandType(commandType);
- }
- SqlParameterCollection parameters = null;
- SqlParameterCollection collection = command.Parameters;
- if (0 < collection.Count) {
- parameters = new SqlParameterCollection();
- // clone parameters so they aren't destroyed
- for(int i = 0; i < collection.Count; ++i) {
- SqlParameter p = new SqlParameter();
- collection[i].CopyTo(p);
- parameters.Add(p);
- // SQL Injection awarene
- if (!SqlIdentifierParser.IsMatch(p.ParameterName)) {
- throw ADP.BadParameterName(p.ParameterName);
- }
- }
- foreach(SqlParameter p in parameters) {
- // deep clone the parameter value if byte[] or char[]
- object obj = p.Value;
- byte[] byteValues = (obj as byte[]);
- if (null != byteValues) {
- int offset = p.Offset;
- int size = p.Size;
- int countOfBytes = byteValues.Length - offset;
- if ((0 != size) && (size < countOfBytes)) {
- countOfBytes = size;
- }
- byte[] copy = new byte[Math.Max(countOfBytes, 0)];
- Buffer.BlockCopy(byteValues, offset, copy, 0, copy.Length);
- p.Offset = 0;
- p.Value = copy;
- }
- else {
- char[] charValues = (obj as char[]);
- if (null != charValues) {
- int offset = p.Offset;
- int size = p.Size;
- int countOfChars = charValues.Length - offset;
- if ((0 != size) && (size < countOfChars)) {
- countOfChars = size;
- }
- char[] copy = new char[Math.Max(countOfChars, 0)];
- Buffer.BlockCopy(charValues, offset, copy, 0, copy.Length*2);
- p.Offset = 0;
- p.Value = copy;
- }
- else {
- ICloneable cloneable = (obj as ICloneable);
- if (null != cloneable) {
- p.Value = cloneable.Clone();
- }
- }
- }
- }
- }
- int returnParameterIndex = -1;
- if (null != parameters) {
- for(int i = 0; i < parameters.Count; ++i) {
- if (ParameterDirection.ReturnValue == parameters[i].Direction) {
- returnParameterIndex = i;
- break;
- }
- }
- }
- LocalCommand cmd = new LocalCommand(cmdText, parameters, returnParameterIndex, command.CommandType, command.ColumnEncryptionSetting);
- CommandList.Add(cmd);
- }
- internal static void BuildStoredProcedureName(StringBuilder builder, string part) {
- if ((null != part) && (0 < part.Length)) {
- if ('[' == part[0]) {
- int count = 0;
- foreach(char c in part) {
- if (']' == c) {
- count++;
- }
- }
- if (1 == (count%2)) {
- builder.Append(part);
- return;
- }
- }
- // the part is not escaped, escape it now
- SqlServerEscapeHelper.EscapeIdentifier(builder, part);
- }
- }
- internal void Clear() {
- Bid.Trace("<sc.SqlCommandSet.Clear|API> %d#\n", ObjectID);
- DbCommand batchCommand = BatchCommand;
- if (null != batchCommand) {
- batchCommand.Parameters.Clear();
- batchCommand.CommandText = null;
- }
- List<LocalCommand> commandList = _commandList;
- if (null != commandList) {
- commandList.Clear();
- }
- }
- internal void Dispose() {
- Bid.Trace("<sc.SqlCommandSet.Dispose|API> %d#\n", ObjectID);
- SqlCommand command = _batchCommand;
- _commandList = null;
- _batchCommand = null;
- if (null != command) {
- command.Dispose();
- }
- }
- internal int ExecuteNonQuery() {
- SqlConnection.ExecutePermission.Demand();
- IntPtr hscp;
- Bid.ScopeEnter(out hscp, "<sc.SqlCommandSet.ExecuteNonQuery|API> %d#", ObjectID);
- try {
- if (Connection.IsContextConnection) {
- throw SQL.BatchedUpdatesNotAvailableOnContextConnection();
- }
- ValidateCommandBehavior(ADP.ExecuteNonQuery, CommandBehavior.Default);
- BatchCommand.BatchRPCMode = true;
- BatchCommand.ClearBatchCommand();
- BatchCommand.Parameters.Clear();
- for (int ii = 0 ; ii < _commandList.Count; ii++) {
- LocalCommand cmd = _commandList[ii];
- BatchCommand.AddBatchCommand(cmd.CommandText, cmd.Parameters, cmd.CmdType, cmd.ColumnEncryptionSetting);
- }
- return BatchCommand.ExecuteBatchRPCCommand();
- }
- finally {
- Bid.ScopeLeave(ref hscp);
- }
- }
- internal SqlParameter GetParameter(int commandIndex, int parameterIndex) {
- return CommandList[commandIndex].Parameters[parameterIndex];
- }
- internal bool GetBatchedAffected(int commandIdentifier, out int recordsAffected, out Exception error) {
- error = BatchCommand.GetErrors(commandIdentifier);
- int? affected = BatchCommand.GetRecordsAffected(commandIdentifier);
- recordsAffected = affected.GetValueOrDefault();
- return affected.HasValue;
- }
- internal int GetParameterCount(int commandIndex) {
- return CommandList[commandIndex].Parameters.Count;
- }
- private void ValidateCommandBehavior(string method, CommandBehavior behavior) {
- if (0 != (behavior & ~(CommandBehavior.SequentialAccess|CommandBehavior.CloseConnection))) {
- ADP.ValidateCommandBehavior(behavior);
- throw ADP.NotSupportedCommandBehavior(behavior & ~(CommandBehavior.SequentialAccess|CommandBehavior.CloseConnection), method);
- }
- }
- }
- }
|