Esempio n. 1
0
		internal override SqlStatement VisitInsert(SqlInsert sin)
		{
			SqlScope save = this.CurrentScope;
			this.CurrentScope = new SqlScope(sin, this.CurrentScope.ContainingScope);
			base.VisitInsert(sin);
			this.CurrentScope = save;
			return sin;
		}
Esempio n. 2
0
		internal override SqlStatement VisitInsert(SqlInsert insert)
		{
			bool saveMakeUnique = this.makeUnique;
			this.makeUnique = false;
			bool saveUseMappedNames = this.useMappedNames;
			this.useMappedNames = true;
			SqlStatement stmt = base.VisitInsert(insert);
			this.makeUnique = saveMakeUnique;
			this.useMappedNames = saveUseMappedNames;
			return stmt;
		}
Esempio n. 3
0
 internal virtual SqlStatement VisitInsert(SqlInsert insert) {
     insert.Table = (SqlTable)this.Visit(insert.Table);
     insert.Expression = this.VisitExpression(insert.Expression);
     insert.Row = (SqlRow)this.Visit(insert.Row);
     return insert;
 }
Esempio n. 4
0
		private SqlStatement VisitInsert(Expression item, LambdaExpression resultSelector)
		{
			if(item == null)
			{
				throw Error.ArgumentNull("item");
			}
			_dominatingExpression = item;

			MetaTable metaTable = _services.Model.GetTable(item.Type);
			Expression source = _services.Context.GetTable(metaTable.RowType.Type).Expression;

			MetaType itemMetaType = null;
			SqlNew sqlItem = null;

			// construct insert assignments from 'item' info
			ConstantExpression conItem = item as ConstantExpression;
			if(conItem == null)
			{
				throw Error.InsertItemMustBeConstant();
			}
			if(conItem.Value == null)
			{
				throw Error.ArgumentNull("item");
			}
			// construct insert based on constant value
			List<SqlMemberAssign> bindings = new List<SqlMemberAssign>();
			itemMetaType = metaTable.RowType.GetInheritanceType(conItem.Value.GetType());
			SqlExpression sqlExprItem = _nodeFactory.ValueFromObject(conItem.Value, true, source);
			foreach(MetaDataMember mm in itemMetaType.PersistentDataMembers)
			{
				if(!mm.IsAssociation && !mm.IsDbGenerated && !mm.IsVersion)
				{
					bindings.Add(new SqlMemberAssign(mm.Member, _nodeFactory.Member(sqlExprItem, mm.Member)));
				}
			}
			ConstructorInfo cons = itemMetaType.Type.GetConstructor(Type.EmptyTypes);
			System.Diagnostics.Debug.Assert(cons != null);
			sqlItem = _nodeFactory.New(itemMetaType, cons, null, null, bindings, item);

			SqlTable tab = _nodeFactory.Table(metaTable, metaTable.RowType, _dominatingExpression);
			SqlInsert sin = new SqlInsert(tab, sqlItem, item);

			if(resultSelector == null)
			{
				return sin;
			}
			else
			{
				MetaDataMember id = itemMetaType.DBGeneratedIdentityMember;
				bool isDbGenOnly = false;
				if(id != null)
				{
					isDbGenOnly = this.IsDbGeneratedKeyProjectionOnly(resultSelector.Body, id);
					if(id.Type == typeof(Guid) && (_converterStrategy & ConverterStrategy.CanOutputFromInsert) != 0)
					{
						sin.OutputKey = new SqlColumn(id.Type, _nodeFactory.Default(id), id.Name, id, null, _dominatingExpression);
						if(!isDbGenOnly)
						{
							sin.OutputToLocal = true;
						}
					}
				}

				SqlSelect result = null;
				SqlSelect preResult = null;
				SqlAlias tableAlias = new SqlAlias(tab);
				SqlAliasRef tableAliasRef = new SqlAliasRef(tableAlias);
				System.Diagnostics.Debug.Assert(resultSelector.Parameters.Count == 1);
				_parameterExpressionToSqlExpression.Add(resultSelector.Parameters[0], tableAliasRef);
				SqlExpression projection = this.VisitExpression(resultSelector.Body);

				// build select to return result
				SqlExpression pred = null;
				if(id != null)
				{
					pred = _nodeFactory.Binary(
							SqlNodeType.EQ,
							_nodeFactory.Member(tableAliasRef, id.Member),
							this.GetIdentityExpression(id, sin.OutputKey != null)
							);
				}
				else
				{
					SqlExpression itemExpression = this.VisitExpression(item);
					pred = _nodeFactory.Binary(SqlNodeType.EQ2V, tableAliasRef, itemExpression);
				}
				result = new SqlSelect(projection, tableAlias, resultSelector);
				result.Where = pred;

				// Since we're only projecting back a single generated key, we can
				// optimize the query to a simple selection (e.g. SELECT @@IDENTITY)
				// rather than selecting back from the table.
				if(id != null && isDbGenOnly)
				{
					if(sin.OutputKey == null)
					{
						SqlExpression exp = this.GetIdentityExpression(id, false);
						if(exp.ClrType != id.Type)
						{
							ProviderType sqlType = _nodeFactory.Default(id);
							exp = _nodeFactory.ConvertTo(id.Type, sqlType, exp);
						}
						// The result selector passed in was bound to the table -
						// we need to rebind to the single result as an array projection
						ParameterExpression p = Expression.Parameter(id.Type, "p");
						Expression[] init = new Expression[1] { Expression.Convert(p, typeof(object)) };
						NewArrayExpression arrExp = Expression.NewArrayInit(typeof(object), init);
						LambdaExpression rs = Expression.Lambda(arrExp, p);
						_parameterExpressionToSqlExpression.Add(p, exp);
						SqlExpression proj = this.VisitExpression(rs.Body);
						preResult = new SqlSelect(proj, null, rs);
					}
					else
					{
						// case handled in formatter automatically
					}
					result.DoNotOutput = true;
				}

				// combine insert & result into block
				SqlBlock block = new SqlBlock(_dominatingExpression);
				block.Statements.Add(sin);
				if(preResult != null)
				{
					block.Statements.Add(preResult);
				}
				block.Statements.Add(result);
				return block;
			}
		}
		internal override SqlStatement VisitInsert(SqlInsert si)
		{

			if(si.OutputKey != null)
			{
				_commandStringBuilder.Append("DECLARE @output TABLE(");
				this.WriteName(si.OutputKey.Name);
				_commandStringBuilder.Append(" ");
				_commandStringBuilder.Append(si.OutputKey.SqlType.ToQueryString());
				_commandStringBuilder.Append(")");
				this.NewLine();
				if(si.OutputToLocal)
				{
					_commandStringBuilder.Append("DECLARE @id ");
					_commandStringBuilder.Append(si.OutputKey.SqlType.ToQueryString());
					this.NewLine();
				}
			}

			_commandStringBuilder.Append("INSERT INTO ");
			this.Visit(si.Table);

			if(si.Row.Columns.Count != 0)
			{
				// INSERT INTO table (...columns...) VALUES (...values...)
				_commandStringBuilder.Append("(");
				for(int i = 0, n = si.Row.Columns.Count; i < n; i++)
				{
					if(i > 0) _commandStringBuilder.Append(", ");
					this.WriteName(si.Row.Columns[i].Name);
				}
				_commandStringBuilder.Append(")");
			}

			if(si.OutputKey != null)
			{
				this.NewLine();
				_commandStringBuilder.Append("OUTPUT INSERTED.");
				this.WriteName(si.OutputKey.MetaMember.MappedName);
				_commandStringBuilder.Append(" INTO @output");
			}

			if(si.Row.Columns.Count == 0)
			{
				_commandStringBuilder.Append(" DEFAULT VALUES");
			}
			else
			{
				// VALUES (...values...)
				this.NewLine();
				_commandStringBuilder.Append("VALUES (");
				if(_isDebugMode && si.Row.Columns.Count == 0)
				{
					this.Visit(si.Expression);
				}
				else
				{
					for(int i = 0, n = si.Row.Columns.Count; i < n; i++)
					{
						if(i > 0) _commandStringBuilder.Append(", ");
						this.Visit(si.Row.Columns[i].Expression);
					}
				}
				_commandStringBuilder.Append(")");
			}

			if(si.OutputKey != null)
			{
				this.NewLine();
				if(si.OutputToLocal)
				{
					_commandStringBuilder.Append("SELECT @id = ");
					_commandStringBuilder.Append(si.OutputKey.Name);
					_commandStringBuilder.Append(" FROM @output");
				}
				else
				{
					_commandStringBuilder.Append("SELECT ");
					this.WriteName(si.OutputKey.Name);
					_commandStringBuilder.Append(" FROM @output");
				}
			}

			return si;
		}
		internal override SqlStatement VisitInsert(SqlInsert si)
		{
			SqlInsert n = new SqlInsert(si.Table, this.VisitExpression(si.Expression), si.SourceExpression);
			n.OutputKey = si.OutputKey;
			n.OutputToLocal = si.OutputToLocal;
			n.Row = this.VisitRow(si.Row);
			return n;
		}
		internal override SqlStatement VisitInsert(SqlInsert sin)
		{
			base.VisitInsert(sin);
			sin.Expression = this.FlattenSelection(sin.Row, true, sin.Expression);
			return sin;
		}
		internal override SqlStatement VisitInsert(SqlInsert sin)
		{
			bool saveTop = this.topLevel;
			this.topLevel = false;
			base.VisitInsert(sin);
			this.topLevel = saveTop;
			return sin;
		}