Ejemplo n.º 1
0
    /// <summary>
    /// コネクションオープン
    /// </summary>
    /// <returns>コネクション</returns>
    public IntPtr Open()
    {
        // すでに開いている場合、使いまわす
        if (IsOpen())
        {
            return((IntPtr)connection);
        }

        // 新規オープン
        IntPtr con;

        if (SQLiteApi.sqlite3_open(path, out con) != SQLiteApi.SQLITE_OK)
        //if (SQLiteApi.sqlite3_open_v2(path, out con, 0x00000002 | 0x00020000, null) != SQLiteApi.SQLITE_OK)
        {
            throw new SQLiteException("Could not open database file: " + path);
        }

        // タイムアウト設定
        if (SQLiteApi.sqlite3_busy_timeout(con, TIMEOUT) != SQLiteApi.SQLITE_OK)
        {
            throw new SQLiteException("Could not Set timeout: " + path);
        }

        connection = con;
        return((IntPtr)connection);
    }
Ejemplo n.º 2
0
    /// <summary>
    /// バリュー取得
    /// </summary>
    /// <param name="stmt">ステートメント</param>
    /// <param name="clmIndex">カラムインデックス</param>
    /// <returns>バリュー</returns>
    private static object GetValue(IntPtr stmt, int clmIndex)
    {
        // タイプごとに指定されたカラムのデータを抜き出す
        switch (SQLiteApi.sqlite3_column_type(stmt, clmIndex))
        {
        case SQLiteApi.SQLITE_INTEGER:
            return(SQLiteApi.sqlite3_column_int64(stmt, clmIndex));

        case SQLiteApi.SQLITE_TEXT:
            IntPtr text = SQLiteApi.sqlite3_column_text(stmt, clmIndex);
            return(Marshal.PtrToStringAnsi(text));

        case SQLiteApi.SQLITE_FLOAT:
            return(SQLiteApi.sqlite3_column_double(stmt, clmIndex));

        case SQLiteApi.SQLITE_BLOB:
            IntPtr blob = SQLiteApi.sqlite3_column_blob(stmt, clmIndex);
            int    size = SQLiteApi.sqlite3_column_bytes(stmt, clmIndex);
            byte[] data = new byte[size];
            Marshal.Copy(blob, data, 0, size);
            return(data);
        }

        return(null);
    }
Ejemplo n.º 3
0
    /// <summary>
    /// ステップ実行
    /// </summary>
    /// <param name="query">クエリ</param>
    /// <param name="bindList">バインドリスト</param>
    /// <param name="fetchPostAction">フェッチ後処理</param>
    /// <returns>行データ</returns>
    private IEnumerable <Dictionary <string, object> > ExecuteStep(string query, Dictionary <string, object> bindList = null, Action <IntPtr, Dictionary <string, object> > fetchPostAction = null)
    {
        // ポストアクション未指定なら、空アクションを設定
        if (fetchPostAction == null)
        {
            fetchPostAction = (ptr, bind) => { };
        }

        // コネクションオープン
        IntPtr con = System.IntPtr.Zero;

        try
        {
            con = Open();

            // ステートメントオープン
            IntPtr stmt = OpenStmt(con, query);

            // パラメーターバインド
            BindParam(stmt, bindList);

            try
            {
                // カラムインデックス作成
                int columnCount = SQLiteApi.sqlite3_column_count(stmt);
                Dictionary <int, string> clmIndex = new Dictionary <int, string>();
                for (int i = 0; i < columnCount; i++)
                {
                    clmIndex.Add(i, Marshal.PtrToStringAnsi(SQLiteApi.sqlite3_column_name(stmt, i)));
                }

                // 1行ずつデータを取得
                Dictionary <string, object> dataRow = new Dictionary <string, object>();
                while (SQLiteApi.sqlite3_step(stmt) == SQLiteApi.SQLITE_ROW)
                {
                    // すべてのカラムのデータを取得し、カラム名をキーにした連想配列に設定
                    for (int i = 0; i < columnCount; i++)
                    {
                        dataRow[clmIndex[i]] = GetValue(stmt, i);
                    }

                    // データ返却
                    yield return(dataRow);

                    // ポストアクション
                    fetchPostAction(stmt, bindList);
                }
            }
            finally
            {
                CloseStmt(stmt);
            }
        }
        finally
        {
            Close();
        }
    }
Ejemplo n.º 4
0
    /// <summary>
    /// クローズステートメント
    /// </summary>
    /// <param name="stmt">ステートメント</param>
    private static void CloseStmt(IntPtr?stmt)
    {
        // 無効なステートメントは何もしない
        if (stmt == null)
        {
            return;
        }

        // ステートメントクローズのエラーは無視
        SQLiteApi.sqlite3_finalize((IntPtr)stmt);
    }
Ejemplo n.º 5
0
    /// <summary>
    /// クエリ逐次実行
    /// </summary>
    /// <param name="con">コネクション</param>
    /// <param name="query">クエリ</param>
    /// <param name="isSkipExp">エラースキップフラグ</param>
    public static void Exec(IntPtr con, string query, bool isSkipExp = false)
    {
        IntPtr stmt;

        if (SQLiteApi.sqlite3_exec(con, query, IntPtr.Zero, IntPtr.Zero, out stmt) != SQLiteApi.SQLITE_OK)
        {
            if (!isSkipExp)
            {
                throw new SQLiteException("Could not exec SQL statement.", con);
            }
        }
    }
Ejemplo n.º 6
0
    /// <summary>
    /// コンストラクタ
    /// </summary>
    /// <param name="message">メッセージ</param>
    /// <param name="db">DBコネクション</param>
    public SQLiteException(string message, System.IntPtr?db = null) : base(message)
    {
        // コネクション未設定なら何もしない
        if (db == null)
        {
            return;
        }

        // コネクションが有効なら付加情報を追加する
        System.IntPtr dbCon = (System.IntPtr)db;
        addMessage = string.Format("# errcode = {0} errmsg = {1}", SQLiteApi.sqlite3_errcode(dbCon), System.Runtime.InteropServices.Marshal.PtrToStringAnsi(SQLiteApi.sqlite3_errmsg(dbCon)));
    }
Ejemplo n.º 7
0
    /// <summary>
    /// オープンステートメント
    /// </summary>
    /// <param name="con">DBコネクション</param>
    /// <param name="query">クエリ</param>
    /// <returns>ステートメント</returns>
    private static IntPtr OpenStmt(IntPtr con, string query)
    {
        IntPtr stmtHandle;

        SQLLog(query);

        if (SQLiteApi.sqlite3_prepare_v2(con, query, query.Length, out stmtHandle, IntPtr.Zero) != SQLiteApi.SQLITE_OK)
        {
            throw new SQLiteException("Prepare Error " + query, con);
        }

        return(stmtHandle);
    }
Ejemplo n.º 8
0
    /// <summary>
    /// リセットステートメント
    /// </summary>
    /// <param name="stmt">ステートメント</param>
    private static void ResetStmt(IntPtr?stmt)
    {
        // 無効なステートメントは何もしない
        if (stmt == null)
        {
            return;
        }

        // ステートメントリセット
        if (SQLiteApi.sqlite3_reset((IntPtr)stmt) != SQLiteApi.SQLITE_OK)
        {
            throw new SQLiteException("Stmt Reset Error");
        }
    }
Ejemplo n.º 9
0
    /// <summary>
    /// クローズ
    /// </summary>
    public void Close()
    {
        // すでに閉じている場合何もしない
        if (!IsOpen())
        {
            return;
        }

        IntPtr con = (IntPtr)connection;

        connection = null;

        // クローズエラーは何もしない
        SQLiteApi.sqlite3_close(con);
    }
Ejemplo n.º 10
0
    /// <summary>
    /// クエリ遅延実行
    /// </summary>
    /// <param name="con">コネクション</param>
    /// <param name="query">クエリ</param>
    /// <param name="bindList">バインドリスト</param>
    /// <param name="isSkipExp">エラースキップフラグ</param>
    public static void Execute(IntPtr con, string query, Dictionary <string, object> bindList = null, bool isSkipExp = false)
    {
        // ステートメントオープン
        IntPtr stmt = OpenStmt(con, query);

        // バインド
        BindParam(stmt, bindList);

        try
        {
            // 実行
            if (SQLiteApi.sqlite3_step(stmt) != SQLiteApi.SQLITE_DONE)
            {
                if (!isSkipExp)
                {
                    throw new SQLiteException("Could not execute SQL statement." + query, con);
                }
            }
        }
        finally
        {
            CloseStmt(stmt);
        }
    }
Ejemplo n.º 11
0
    /// <summary>
    /// パラメーターバインド
    /// </summary>
    /// <param name="stmHandle">ステートメント</param>
    /// <param name="bindList">バインドリスト</param>
    private static void BindParam(IntPtr stmHandle, Dictionary <string, object> bindList)
    {
        int           paramNo = 0;
        List <string> bindLog = new List <string>();

        // リセット
        ResetStmt(stmHandle);

        // バインド対象がない場合何もしない
        if (bindList == null)
        {
            return;
        }

        // バインド対象を全件ループ
        foreach (KeyValuePair <string, object> bindData in bindList)
        {
            // パラメーターNoを算出
            paramNo = SQLiteApi.sqlite3_bind_parameter_index(stmHandle, bindData.Key);

            if (bindData.Value != null)
            {
                bindLog.Add(bindData.Key + " value= " + bindData.Value.ToString());
            }

            // string
            if (bindData.Value is string)
            {
                string strValue = bindData.Value.ToString();
                ExecBind(() => SQLiteApi.sqlite3_bind_text16(stmHandle, paramNo, strValue, System.Text.Encoding.Unicode.GetByteCount(strValue), disablePtr));
                continue;
            }

            // int
            if (bindData.Value is int)
            {
                ExecBind(() => SQLiteApi.sqlite3_bind_int(stmHandle, paramNo, ((int)bindData.Value)));
                continue;
            }

            // long
            if (bindData.Value is long)
            {
                ExecBind(() => SQLiteApi.sqlite3_bind_int64(stmHandle, paramNo, ((long)bindData.Value)));
                continue;
            }

            // double
            if (bindData.Value is double)
            {
                ExecBind(() => SQLiteApi.sqlite3_bind_double(stmHandle, paramNo, ((double)bindData.Value)));
                continue;
            }

            // blob
            if (bindData.Value is byte[])
            {
                byte[] byteValue = (byte[])bindData.Value;
                ExecBind(() => SQLiteApi.sqlite3_bind_blob(stmHandle, paramNo, byteValue, byteValue.Length, disablePtr));
                continue;
            }
        }

        SQLLog("BIND : " + string.Join(" # ", CollectionUtil.Collection2Array <string>(bindLog)));
    }