DeveelDB  20151217
complete SQL database system, primarly developed for .NET/Mono frameworks
InvokeContext.cs
Go to the documentation of this file.
1 //
2 // Copyright 2010-2015 Deveel
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16 
17 using System;
18 using System.Collections.Generic;
19 using System.Linq;
20 
21 using Deveel.Data.Sql;
23 
24 namespace Deveel.Data.Routines {
28  public sealed class InvokeContext : IDisposable {
30  private Dictionary<string, DataObject> output;
31 
32  internal InvokeContext(Invoke invoke, IRoutine routine, IVariableResolver resolver, IGroupResolver group, IRequest request) {
33  if (invoke == null)
34  throw new ArgumentNullException("invoke");
35  if (routine == null)
36  throw new ArgumentNullException("routine");
37 
38  Request = request;
39  GroupResolver = group;
40  VariableResolver = resolver;
41  Invoke = invoke;
42  Routine = routine;
43  }
44 
46  Dispose(false);
47  }
48 
53  public Invoke Invoke { get; private set; }
54 
59  public IRoutine Routine { get; private set; }
60 
67  get { return Routine.Type; }
68  }
69 
76  public SqlExpression[] Arguments {
77  get { return Invoke.Arguments; }
78  }
79 
80  public IVariableResolver VariableResolver { get; private set; }
81 
82  public IGroupResolver GroupResolver { get; private set; }
83 
84  public IRequest Request { get; private set; }
85 
86  public DataObject[] EvaluatedArguments {
87  get {
88  if (evaluatedArgs == null) {
89  evaluatedArgs = new DataObject[Arguments.Length];
90  for (int i = 0; i < Arguments.Length; i++) {
91  evaluatedArgs[i] = Arguments[i].EvaluateToConstant(Request, VariableResolver);
92  }
93  }
94 
95  return evaluatedArgs;
96  }
97  }
98 
103  public int ArgumentCount {
104  get { return Arguments == null ? 0 : Arguments.Length; }
105  }
106 
107  public bool TryGetArgument(string argName, out SqlExpression value) {
108  var parameter = Routine.RoutineInfo.Parameters.FirstOrDefault(x => x.Name.Equals(argName, StringComparison.Ordinal));
109  if (parameter == null) {
110  value = null;
111  return false;
112  }
113 
114  var offset = parameter.Offset;
115  if (parameter.IsUnbounded) {
116  // TODO: Copy all arguments starting at the given offset and make an Array
117  var tuple = SqlExpression.Tuple(new SqlExpression[0]);
118  value = tuple;
119  } else {
120  value = Invoke.Arguments[offset];
121  }
122 
123  return true;
124  }
125 
126  public bool TryGetArgument(string argName, out DataObject value) {
127  SqlExpression exp;
128  if (!TryGetArgument(argName, out exp)) {
129  value = DataObject.Null();
130  return false;
131  }
132 
133  value = exp.EvaluateToConstant(Request, VariableResolver);
134  return true;
135  }
136 
137  public bool HasArgument(string argName) {
138  throw new NotImplementedException();
139  }
140 
142  if (Routine.Type != RoutineType.Function)
143  throw new InvalidOperationException("The routine is not a function.");
144 
145  return new InvokeResult(this, value);
146  }
147 
148  public InvokeResult Result() {
149  if (Routine.Type != RoutineType.Procedure)
150  throw new InvalidOperationException("The routine is not a procedure: a return value is required.");
151 
152  return new InvokeResult(this);
153  }
154 
155  private RoutineParameter GetParameter(string name) {
156  return Routine.RoutineInfo.Parameters.FirstOrDefault(x => x.Name.Equals(name, StringComparison.Ordinal));
157  }
158 
159  public void SetOutput(string argName, DataObject value) {
160  var parameter = GetParameter(argName);
161  if (parameter == null)
162  throw new InvalidOperationException(String.Format("Routine {0} has none parameter named '{1}'.", Routine.FullName, argName));
163  if (!parameter.IsOutput)
164  throw new InvalidOperationException();
165 
166  if (!parameter.IsNullable &&
167  value.IsNull)
168  throw new ArgumentException();
169 
170  if (!parameter.IsUnbounded)
171  throw new ArgumentException();
172 
173  if (!parameter.Type.IsComparable(value.Type))
174  throw new ArgumentException();
175 
176  if (output == null)
177  output = new Dictionary<string, DataObject>();
178 
179  output[argName] = value;
180  }
181 
182  private void Dispose(bool disposing) {
183  Routine = null;
184  Invoke = null;
185  evaluatedArgs = null;
186  output = null;
187  }
188 
189  public void Dispose() {
190  Dispose(true);
191  GC.SuppressFinalize(this);
192  }
193  }
194 }
bool IsNull
Gets a value that indicates if this object is materialized as null.
Definition: DataObject.cs:91
SqlType Type
Gets the SqlType that defines the object properties
Definition: DataObject.cs:78
SqlExpression[] Arguments
Gets an array of arguments to be passed to the invoked routine.
Definition: Invoke.cs:63
static DataObject Null(SqlType type)
Definition: DataObject.cs:630
static SqlTupleExpression Tuple(SqlExpression[] expressions)
bool TryGetArgument(string argName, out SqlExpression value)
The contract to define a program routine that can interact with database objects. ...
Definition: IRoutine.cs:26
RoutineParameter GetParameter(string name)
A routine (PROCEDURE or FUNCTION) defined in a database, that is a program with defined input paramet...
RoutineType
The type of routine program.
Definition: RoutineType.cs:23
bool TryGetArgument(string argName, out DataObject value)
Defines a contract used by grouping functions to find information about the current group being evalu...
Represents the result of the execution of a routine.
Definition: InvokeResult.cs:25
bool HasArgument(string argName)
Represents a dynamic object that encapsulates a defined SqlType and a compatible constant ISqlObject ...
Definition: DataObject.cs:35
void SetOutput(string argName, DataObject value)
The information about the invocation of a routine, including the full name and arguments (as SqlExpre...
Definition: Invoke.cs:30
An interface to resolve a variable name to a constant object.
InvokeResult Result(DataObject value)
Dictionary< string, DataObject > output
Defines the base class for instances that represent SQL expression tree nodes.
InvokeContext(Invoke invoke, IRoutine routine, IVariableResolver resolver, IGroupResolver group, IRequest request)