DeveelDB  20151217
complete SQL database system, primarly developed for .NET/Mono frameworks
Cursor.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 
22 using Deveel.Data.Sql.Query;
23 using Deveel.Data.Sql.Tables;
24 
25 namespace Deveel.Data.Sql.Cursors {
26  public sealed class Cursor : IDbObject, IDisposable {
27  internal Cursor(CursorInfo cursorInfo) {
28  if (cursorInfo == null)
29  throw new ArgumentNullException("cursorInfo");
30 
31  CursorInfo = cursorInfo;
32  State = new CursorState(this);
33  }
34 
35  ~Cursor() {
36  Dispose(false);
37  }
38 
39  public CursorInfo CursorInfo { get; private set; }
40 
41  public CursorStatus Status {
42  get { return State.Status; }
43  }
44 
45  public CursorState State { get; private set; }
46 
48  get { return new ObjectName(CursorInfo.CursorName); }
49  }
50 
52  get { return DbObjectType.Cursor; }
53  }
54 
55  public SqlQueryExpression QueryExpression {
56  get { return CursorInfo.QueryExpression; }
57  }
58 
59  private void AssertNotDisposed() {
60  if (Status == CursorStatus.Disposed)
61  throw new ObjectDisposedException("Cursor");
62  }
63 
66  if (CursorInfo.Parameters.Count > 0) {
67  var cursorArgs = BuildArgs(CursorInfo.Parameters, args);
68  var preparer = new CursorArgumentPreparer(cursorArgs);
69  query = query.Prepare(preparer) as SqlQueryExpression;
70  }
71 
72  return query;
73  }
74 
75  private Dictionary<string, SqlExpression> BuildArgs(IEnumerable<CursorParameter> parameters, SqlExpression[] args) {
76  var orderedParams = parameters.OrderBy(x => x.Offset).ToArray();
77  if (args == null || args.Length != orderedParams.Length)
78  throw new ArgumentException();
79 
80  var result = new Dictionary<string, SqlExpression>();
81  for (int i = 0; i < orderedParams.Length; i++) {
82  var param = orderedParams[i];
83  var arg = args[i];
84  result[param.ParameterName] = arg;
85  }
86 
87  return result;
88  }
89 
90  private ITable Evaluate(IRequest context, SqlExpression[] args) {
91  try {
92  var prepared = PrepareQuery(args);
93  var queryPlan = context.Query.Context.QueryPlanner().PlanQuery(new QueryInfo(context, prepared));
94  return queryPlan.Evaluate(context);
95  } catch (Exception) {
96 
97  throw;
98  }
99  }
100 
101  public void Open(IRequest context, params SqlExpression[] args) {
102  lock (this) {
103  AssertNotDisposed();
104 
105  ITable result = null;
107  result = Evaluate(context, args);
108 
109  State.Open(result, args);
110  }
111  }
112 
113  public void Close() {
114  lock (this) {
115  AssertNotDisposed();
116  State.Close();
117  }
118  }
119 
120  public void FetchInto(FetchContext context) {
121  if (context == null)
122  throw new ArgumentNullException("context");
123 
124  if (!CursorInfo.IsScroll &&
125  context.Direction != FetchDirection.Next)
126  throw new ArgumentException(String.Format("Cursor '{0}' is not SCROLL: can fetch only NEXT value.", CursorInfo.CursorName));
127 
128  var table = State.Result;
130  table = Evaluate(context.Request, State.OpenArguments);
131 
132  var fetchRow = State.FetchRowFrom(table, context.Direction, context.Offset);
133 
134  if (context.IsGlobalReference) {
135  var reference = ((SqlReferenceExpression) context.Reference).ReferenceName;
136  FetchIntoReference(context.Request, fetchRow, reference);
137  } else if (context.IsVariableReference) {
138  var varName = ((SqlVariableReferenceExpression) context.Reference).VariableName;
139  FetchIntoVatiable(context.Request, fetchRow, varName);
140  }
141  }
142 
143  private void FetchIntoVatiable(IRequest request, Row row, string varName) {
144  throw new NotImplementedException();
145  }
146 
147  private void FetchIntoReference(IRequest request, Row row, ObjectName reference) {
148  if (reference == null)
149  throw new ArgumentNullException("reference");
150 
151  var table = request.Query.GetMutableTable(reference);
152  if (table == null)
153  throw new ObjectNotFoundException(reference);
154 
155  throw new NotImplementedException();
156  }
157 
158  public void Dispose() {
159  Dispose(true);
160  GC.SuppressFinalize(this);
161  }
162 
163  private void Dispose(bool disposing) {
164  if (disposing) {
165  if (State != null)
166  State.Dispose();
167  }
168 
169  State = null;
170  }
171 
172  #region CursorArgumentPreparer
173 
175  private readonly Dictionary<string, SqlExpression> args;
176 
177  public CursorArgumentPreparer(Dictionary<string, SqlExpression> args) {
178  this.args = args;
179  }
180 
181  public bool CanPrepare(SqlExpression expression) {
182  return expression is SqlVariableReferenceExpression;
183  }
184 
185  public SqlExpression Prepare(SqlExpression expression) {
186  var varRef = ((SqlVariableReferenceExpression) expression).VariableName;
187  SqlExpression exp;
188  if (!args.TryGetValue(varRef, out exp))
189  throw new ArgumentException(String.Format("Variable '{0}' was not found in the cursor arguments", varRef));
190 
191  return exp;
192  }
193  }
194 
195  #endregion
196  }
197 }
SqlQueryExpression PrepareQuery(SqlExpression[] args)
Definition: Cursor.cs:64
bool CanPrepare(SqlExpression expression)
Verifies whether the instance of the interface can prepare the given expression.
Definition: Cursor.cs:181
Defines the contract to access the data contained into a table of a database.
Definition: ITable.cs:40
An expression that references an object within a context.
void Open(IRequest context, params SqlExpression[] args)
Definition: Cursor.cs:101
void FetchIntoReference(IRequest request, Row row, ObjectName reference)
Definition: Cursor.cs:147
Dictionary< string, SqlExpression > BuildArgs(IEnumerable< CursorParameter > parameters, SqlExpression[] args)
Definition: Cursor.cs:75
Cursor(CursorInfo cursorInfo)
Definition: Cursor.cs:27
Represents a database object, such as a table, a trigger, a type or a column.
Definition: IDbObject.cs:24
ObjectName FullName
Gets the fully qualified name of the object used to resolve it uniquely within the database...
Definition: IDbObject.cs:30
Describes the name of an object within a database.
Definition: ObjectName.cs:44
CursorArgumentPreparer(Dictionary< string, SqlExpression > args)
Definition: Cursor.cs:177
A single row in a table of a database.
Definition: Row.cs:44
readonly Dictionary< string, SqlExpression > args
Definition: Cursor.cs:175
SqlQueryExpression QueryExpression
Definition: CursorInfo.cs:59
SqlExpression Prepare(SqlExpression expression)
Returns the new translated object to be mutated from the given expression.
Definition: Cursor.cs:185
void FetchInto(FetchContext context)
Definition: Cursor.cs:120
An interface used to prepare a SqlExpression object.
virtual SqlExpression Prepare(IExpressionPreparer preparer)
DbObjectType ObjectType
Gets the type of database object that the implementation is for
Definition: IDbObject.cs:35
void FetchIntoVatiable(IRequest request, Row row, string varName)
Definition: Cursor.cs:143
ITable Evaluate(IRequest context, SqlExpression[] args)
Definition: Cursor.cs:90
Defines the base class for instances that represent SQL expression tree nodes.
ICollection< CursorParameter > Parameters
Definition: CursorInfo.cs:46
DbObjectType
The kind of objects that can be handled by a database system and its managers
Definition: DbObjectType.cs:27
void Dispose(bool disposing)
Definition: Cursor.cs:163
new IQueryContext Context
Definition: IQuery.cs:21