2 * Firebird ADO.NET Data provider for .NET and Mono
4 * The contents of this file are subject to the Initial
5 * Developer's Public License Version 1.0 (the "License");
6 * you may not use this file except in compliance with the
7 * License. You may obtain a copy of the License at
8 * http://www.firebirdsql.org/index.php?op=doc&id=idpl
10 * Software distributed under the License is distributed on
11 * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either
12 * express or implied. See the License for the specific
13 * language governing rights and limitations under the License.
15 * Copyright (c) 2002, 2005 Carlos Guzman Alvarez
16 * All Rights Reserved.
23 namespace FirebirdSql.Data.Common
27 internal enum StatementState
39 internal abstract class StatementBase : IDisposable
41 #region Protected Static Fields
43 // Plan information items
44 protected static byte[] DescribePlanInfoItems = new byte[]
46 IscCodes.isc_info_sql_get_plan
49 // Records affected items
50 protected static byte[] RecordsAffectedInfoItems = new byte[]
52 IscCodes.isc_info_sql_records
55 // Describe information items
56 protected static byte[] DescribeInfoItems = new byte[]
58 IscCodes.isc_info_sql_select,
59 IscCodes.isc_info_sql_describe_vars,
60 IscCodes.isc_info_sql_sqlda_seq,
61 IscCodes.isc_info_sql_type,
62 IscCodes.isc_info_sql_sub_type,
63 IscCodes.isc_info_sql_length,
64 IscCodes.isc_info_sql_scale,
65 IscCodes.isc_info_sql_field,
66 IscCodes.isc_info_sql_relation,
67 // IscCodes.isc_info_sql_owner,
68 IscCodes.isc_info_sql_alias,
69 IscCodes.isc_info_sql_describe_end
72 protected static byte[] DescribeBindInfoItems = new byte[]
74 IscCodes.isc_info_sql_bind,
75 IscCodes.isc_info_sql_describe_vars,
76 IscCodes.isc_info_sql_sqlda_seq,
77 IscCodes.isc_info_sql_type,
78 IscCodes.isc_info_sql_sub_type,
79 IscCodes.isc_info_sql_length,
80 IscCodes.isc_info_sql_scale,
81 IscCodes.isc_info_sql_field,
82 IscCodes.isc_info_sql_relation,
83 // IscCodes.isc_info_sql_owner,
84 IscCodes.isc_info_sql_alias,
85 IscCodes.isc_info_sql_describe_end
88 protected static byte[] StatementTypeInfoItems = new byte[]
90 IscCodes.isc_info_sql_stmt_type
97 private bool disposed;
101 #region Abstract Properties
103 public abstract IDatabase DB
109 public abstract ITransaction Transaction
115 public abstract Descriptor Parameters
121 public abstract Descriptor Fields
126 public abstract int RecordsAffected
131 public abstract bool IsPrepared
136 public abstract DbStatementType StatementType
142 public abstract StatementState State
148 public abstract int FetchSize
156 #region Protected Properties
158 protected bool IsDisposed
160 get { return this.disposed; }
165 #region Protected Fields
167 protected TransactionUpdateEventHandler TransactionUpdate;
171 #region Abstract Methods
173 public abstract void Describe();
174 public abstract void DescribeParameters();
175 public abstract void Prepare(string commandText);
176 public abstract void Execute();
177 public abstract DbValue[] Fetch();
178 public abstract DbValue[] GetOuputParameters();
179 public abstract byte[] GetSqlInfo(byte[] items, int bufferLength);
181 public abstract BlobBase CreateBlob();
182 public abstract BlobBase CreateBlob(long handle);
184 public abstract ArrayBase CreateArray(ArrayDesc descriptor);
185 public abstract ArrayBase CreateArray(string tableName, string fieldName);
186 public abstract ArrayBase CreateArray(long handle, string tableName, string fieldName);
199 #region IDisposable methods
201 public void Dispose()
204 GC.SuppressFinalize(this);
207 protected virtual void Dispose(bool disposing)
213 this.disposed = true;
220 #region Protected Abstract Methods
222 protected abstract void TransactionUpdated(object sender, EventArgs e);
223 protected abstract void Free(int option);
229 public string GetExecutionPlan()
231 string plan = String.Empty;
233 int bufferSize = IscCodes.MAX_BUFFER_SIZE;
234 byte[] buffer = this.GetSqlInfo(DescribePlanInfoItems, bufferSize);
236 while (buffer[0] == IscCodes.isc_info_truncated && count < 4)
239 buffer = this.GetSqlInfo(DescribePlanInfoItems, bufferSize);
249 len += buffer[2] << 8;
253 plan = this.DB.Charset.GetString(buffer, 4, --len);
259 public virtual void Close()
261 if (this.State == StatementState.Executed ||
262 this.State == StatementState.Error)
264 if (this.StatementType == DbStatementType.Select ||
265 this.StatementType == DbStatementType.SelectForUpdate ||
266 this.StatementType == DbStatementType.StoredProcedure)
268 this.Free(IscCodes.DSQL_close);
269 this.ClearArrayHandles();
270 this.State = StatementState.Closed;
275 public virtual void Release()
277 if (this.Transaction != null &&
278 this.TransactionUpdate != null)
280 this.Transaction.Update -= this.TransactionUpdate;
281 this.TransactionUpdate = null;
284 this.Free(IscCodes.DSQL_drop);
286 this.State = StatementState.Deallocated;
287 this.StatementType = DbStatementType.None;
292 #region Protected Methods
294 protected byte[] GetSqlInfo(byte[] items)
296 return this.GetSqlInfo(items, IscCodes.MAX_BUFFER_SIZE);
299 protected int GetRecordsAffected()
301 byte[] buffer = this.GetSqlInfo(RecordsAffectedInfoItems, IscCodes.ROWS_AFFECTED_BUFFER_SIZE);
303 return this.ProcessRecordsAffectedBuffer(buffer);
306 protected int ProcessRecordsAffectedBuffer(byte[] buffer)
316 while ((type = buffer[pos++]) != IscCodes.isc_info_end)
318 length = IscHelper.VaxInteger(buffer, pos, 2);
322 case IscCodes.isc_info_sql_records:
325 while ((t = buffer[pos++]) != IscCodes.isc_info_end)
327 l = IscHelper.VaxInteger(buffer, pos, 2);
331 case IscCodes.isc_info_req_insert_count:
332 insertCount = IscHelper.VaxInteger(
336 case IscCodes.isc_info_req_update_count:
337 updateCount = IscHelper.VaxInteger(
341 case IscCodes.isc_info_req_delete_count:
342 deleteCount = IscHelper.VaxInteger(
346 case IscCodes.isc_info_req_select_count:
347 selectCount = IscHelper.VaxInteger(
361 return insertCount + updateCount + deleteCount;
364 protected DbStatementType GetStatementType()
366 byte[] buffer = this.GetSqlInfo(StatementTypeInfoItems, IscCodes.STATEMENT_TYPE_BUFFER_SIZE);
368 return this.ParseStatementTypeInfo(buffer);
371 protected DbStatementType ParseStatementTypeInfo(byte[] buffer)
373 DbStatementType stmtType = DbStatementType.None;
378 while ((type = buffer[pos++]) != IscCodes.isc_info_end)
380 length = IscHelper.VaxInteger(buffer, pos, 2);
384 case IscCodes.isc_info_sql_stmt_type:
385 stmtType = (DbStatementType)IscHelper.VaxInteger(buffer, pos, length);
398 protected void ClearArrayHandles()
400 if (this.Fields != null && this.Fields.Count > 0)
402 for (int i = 0; i < this.Fields.Count; i++)
404 if (this.Fields[i].IsArray())
406 this.Fields[i].ArrayHandle = null;