⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fastdbcommand.cs

📁 嵌入式数据库软件 嵌入式数据库软件 嵌入式数据库软件
💻 CS
字号:
using System;using System.Collections;using System.Text.RegularExpressions;namespace FastDbNet{  //-------------------------------------------------------------------------  /// <summary>  /// A class that implements a select/insert query that can be executed in   /// FastDb database.  A new command is created using the following code:  /// <code>  /// FastDbCommand command = connection.CreateCommand("select * from Table");  /// </code>  /// <seealso cref="FastDbConnection.CreateCommand"/>  /// </summary>  public class FastDbCommand: IDisposable {    private FastDbConnection connection;    private int     statement;    private string  sql;    private bool    described;    private bool    sql_changed;    private bool    bof;    private bool    eof;    private int     rec_no;    private string  table_name;    private bool    read_only;    private int     row_count;    private FastDbFields     fields;    private FastDbParameters vars;    internal FastDbCommand(FastDbConnection connection, string sql): this(connection) {      this.sql = sql;    }    internal FastDbCommand(FastDbConnection connection) {      this.connection = connection;      statement   = -1;      sql         = "";      described   = false;      sql_changed = false;      bof         = false;      eof         = false;      rec_no      = -1;      table_name  = "";      read_only   = true;      row_count   = 0;      fields      = new FastDbFields();      vars        = new FastDbParameters();    }    ~FastDbCommand() { Dispose(false); }    public void Free() { this.Free(true); }    public void Free(bool CheckError) {      if (statement == -1) return;      if (connection.Threaded) connection.Detach();      connection.RemoveCommand(this);      int rc;      if (connection.Session == -1)        rc = (int)CLI.ErrorCode.cli_ok;      else        rc = CLI.cli_free(statement);      statement = -1;      if (CheckError) CLI.CliCheck(rc, "cli_free failed");      Fields.Clear();      Parameters.Clear();      table_name = "";      described  = false;    }    /// <summary>    /// A reference to the FastDb connection where this command is defined.    /// </summary>    public FastDbConnection Connection { get { return connection; } }     /// <summary>    /// Internal statement handle.    /// </summary>    public int              Statement  { get { return statement; } }     /// <summary>    /// A container of fields defined in current command.    /// </summary>    public FastDbFields     Fields     { get { return fields; } }     /// <summary>    /// A container of parameters defined in current command.    /// </summary>    public FastDbParameters Parameters { get { return vars; } }     /// <summary>    /// An SQL string representing a query against the database.    /// </summary>    public string           SQL        { get { return sql; } set { sql = value; sql_changed = true; } }    /// <summary>    /// A property indicating whether current query is read-only or updatable.    /// </summary>    public bool             ReadOnly   { get { return read_only; } }    /// <summary>    /// If true - the cursor is at the beginning of the record-set.    /// </summary>    public bool             Bof        { get { return bof; } }    /// <summary>    /// If true - the cursor is at the end of the record-set.    /// </summary>    public bool             Eof        { get { return eof; } }    /// <summary>    /// Current number of record within the record-set: 0 ... RowCount    /// </summary>    public int              RecNo      { get { return rec_no; } }    /// <summary>    /// Total number of records within the record-set.    /// </summary>    public int              RowCount      { get { return row_count; } }    /// <summary>    /// Name of the table parsed out of the SQL property.    /// </summary>    public string           TableName  { get { return table_name; } }    private bool IsSelectQuery() { return String.Compare(sql.Substring(0, 6), "select", true) == 0; }    private string GetTableName() {      if (!sql_changed && table_name != "") return table_name;      if (sql == "")    return "";      // The tablename is the first identifier after FROM      Match m = Regex.Match(sql, @"insert\s+into\s+([a-zA-Z0-9_]+)\s*");      if (m.Success) return table_name = m.Groups[1].ToString();      m = Regex.Match(sql, @"select\s+\*?\s*from\s+([a-zA-Z0-9_]+)\s*");      if (m.Success)         return table_name = m.Groups[1].ToString();      else        throw new CliError((int)CLI.ErrorCode.cli_table_not_found);    }    /// <summary>    /// Fetch definition of fields from the database.  SQL property must be assigned    /// </summary>    public void Describe() {      if (described && !sql_changed) return;      else if (statement != -1) Free(false);      if (SQL == "") throw new CliError("SQL not assigned!");      string s = GetTableName();      if (SQL == "") throw new CliError("Error parsing table name from the SQL!");      if (fields.Count == 0)         fields.Assign(connection.DescribeTable(GetTableName()));      statement = CLI.CliCheck(CLI.cli_statement(connection.Session, sql), "cli_statement failed");      fields.Bind(statement);      vars.Bind(statement);      described = true;      sql_changed = false;    }    public int  Execute()               { return this.Execute(false, true); }    public int  Execute(bool Updatable) { return this.Execute(Updatable, true); }    /// <summary>    /// Executes an SQL command agains a FastDB connection.    /// </summary>    /// <param name="Updatable">Determines if records can be updated (optional, default: false).</param>    /// <param name="FetchFirst">Instructs to fetch the first record (optional, default: false).     /// If false, the user must call First() method after Execute().</param>    /// <returns>Number of records in the record-set fetched from the database.</returns>    public int  Execute(bool Updatable, bool FetchFirst) {      if (connection.Threaded) connection.Attach();      Describe();      read_only = !Updatable;      row_count =         CLI.CliCheck(        CLI.cli_fetch(statement, (Updatable) ? CLI.QueryType.cli_for_update : CLI.QueryType.cli_view_only));      rec_no = (FetchFirst) ? 0 : -1;      eof    = row_count <= 0;      if (FetchFirst && !eof) First();      else bof = FetchFirst;      return row_count;    }    public Cursor Select() { return Select(false); }    public Cursor Select(bool Updatable) {      Execute(Updatable, false);      return new Cursor(this);    }    /// <summary>    /// Inserts a record in the database.  Requires the SQL to be in the form:     /// "insert into TableName".    /// </summary>    /// <returns>An OID of the newly inserted record.</returns>    public uint Insert() {      uint oid = 0;      if (connection.Threaded) connection.Attach();      Describe();      CLI.CliCheck(CLI.cli_insert(statement, ref oid));      if (connection.Threaded) connection.Detach();      return oid;    }    /// <summary>    /// Updates a record in the database.  Requires the SQL to be in the form:     /// "select * from TableName ...", and the command must be updatable:    /// command.Execute(true).    /// </summary>    public void Update() {       if (read_only)         throw new CliError((int)CLI.ErrorCode.cli_not_update_mode);       CLI.CliCheck(CLI.cli_update(statement));     }    /// <summary>    /// Deletes all records in the current record-set returned by the select statement.    /// Requires the SQL to be in the form:     /// "select * from TableName ...", and the command must be updatable:    /// command.Execute(true);    /// command.Delete();    /// </summary>    public void Delete()   { CLI.CliCheck(CLI.cli_remove(statement)); }    /// <summary>    /// Freeze cursor. Make it possible to reuse cursor after commit of     /// the current transaction.    /// </summary>    public void Freeze()   { CLI.CliCheck(CLI.cli_freeze(statement)); }    /// <summary>    /// Unfreeze cursor. Reuse previously frozen cursor.    /// </summary>    public void UnFreeze() { CLI.CliCheck(CLI.cli_unfreeze(statement)); }    /// <summary>    /// Return the OID of the currently fetched record in the cursor.    /// </summary>    public uint OID        { get { return CLI.cli_get_oid(statement); } }    /// <summary>    /// Refresh the selected record the cursor points to.    /// </summary>    public void RefreshRecord() { CLI.CliCheck(CLI.cli_skip(statement, 0)); }    /// <summary>    /// Determines if the current command has an open cursor.    /// </summary>    /// <returns>true - the current query is open.</returns>    public bool IsOpen()        { return statement != -1; }    /// <summary>    /// Go to the first row of the current record-set.    /// </summary>    public void First()         { CLI.CliCheck(CLI.cli_get_first(statement)); rec_no = 0; }    /// <summary>    /// Go to the last row of the current record-set.    /// </summary>    public void Last()          { CLI.CliCheck(CLI.cli_get_last(statement)); rec_no = row_count; }        /// <summary>    /// Go to the next row of the current record-set.    /// </summary>    public bool Next() {       int n = CLI.cli_get_next(statement);       eof = n != (int)CLI.ErrorCode.cli_ok;      bof = false;      if (!eof) rec_no++;      return !eof;    }        /// <summary>    /// Go to the previous row of the current record-set.    /// </summary>    public bool Prev() {       int n = CLI.cli_get_prev(statement);       bof = n != (int)CLI.ErrorCode.cli_ok;      eof = false;      if (!bof) rec_no--;      return !bof;    }    public void Skip(int Records) { Skip(Records, false); }    /// <summary>    /// Skip N rows of the current record-set.    /// </summary>    /// <param name="Records">Number of records to skip</param>    /// <param name="RefreshOnNoSkip">Optional parameter (default: false). If true, forces a refresh when parameter Records=0.</param>    public void Skip(int Records, bool RefreshOnNoSkip) {      if ((Records == 0) && !RefreshOnNoSkip) return;      int n = CLI.cli_skip(statement, Records);      if (n == (int)CLI.ErrorCode.cli_not_found) {        if (Records >= 0) {          eof = true;          bof = false;          rec_no = row_count;        }        else {          bof = true;          eof = false;          rec_no = 0;        }      }      else {        CLI.CliCheck(n, "cli_skip failed");        rec_no += Records;      }    }    /// <summary>    /// Seeks for a given OID in the current record-set.    /// </summary>    /// <param name="oid">OID to search for.</param>    /// <returns>Position of the record in the selection.</returns>    public int  Seek(uint oid) {      return rec_no = CLI.CliCheck(CLI.cli_seek(statement, oid));    }    /// <summary>    /// Clears the current command, empties fields/parameters, and frees unmanaged resources.    /// </summary>    public void Clear() { Free(); }    /// <summary>    /// This class is used to iterate over a record set using foreach() statement.    /// Example:    /// <code>    /// FastDbCommand command = connection.CreateCommand("select * from persons");    /// foreach(FastDbCommand.Cursor cur in command.Select()) {    ///   foreach(FastDbField f in cur.Fields)     ///     Console.WriteLine(f.asString);    /// }    /// </code>    /// </summary>    public class Cursor: IEnumerable {      FastDbCommand command;      public Cursor(FastDbCommand command) {        this.command = command;      }      public FastDbFields  Fields   { get { return command.Fields; } }      public FastDbCommand Command  { get { return command; } }      #region IEnumerable Members      IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }      public Iterator GetEnumerator()         { return new Iterator(this); }      /// <summary>      /// This class implements IEnumerator interface. Use its methods within a       /// foreach() loop.        /// </summary>      public class Iterator: IEnumerator {        #region Private Fields        Cursor cursor;        #endregion        #region Constructors        public Iterator(Cursor cursor) {          this.cursor = cursor;        }        #endregion        #region Methods        public void Reset()         { cursor.command.First(); }        public bool MoveNext()      {           if (cursor.Command.RecNo == -1) {             Reset();             return !cursor.command.Eof;          } else {             return cursor.command.Next();           }        }        public Cursor Current { get { return cursor; } }        // The current property on the IEnumerator interface:        object IEnumerator.Current  { get { return Current; } }        #endregion      }      #endregion    }    #region IDisposable Members    // Implement IDisposable.    // This method is not virtual. A derived class should not be able to override this method.    public void Dispose() {      Dispose(true);      // Take yourself off the Finalization queue       // to prevent finalization code for this object      // from executing a second time.      GC.SuppressFinalize(this);    }    // Dispose(bool disposing) executes in two distinct scenarios.    // If disposing equals true, the method has been called directly    // or indirectly by a user's code. Managed and unmanaged resources    // can be disposed.    // If disposing equals false, the method has been called by the     // runtime from inside the finalizer and you should not reference     // other objects. Only unmanaged resources can be disposed.    protected virtual void Dispose(bool disposing) {      if(this.statement != -1) {   // Check to see if Dispose has already been called.        if(disposing) {} // Dispose managed resources here.        Free();          // Release unmanaged resources.       }    }    #endregion  }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -