Пример #1
0
        public void Open()
        {
            if (conn_str == null)
            {
                throw new InvalidOperationException("No database specified");
            }

            if (state != ConnectionState.Closed)
            {
                return;
            }

            IntPtr errmsg = IntPtr.Zero;

            if (Version == 2)
            {
                try {
                    sqlite_handle = Sqlite.sqlite_open(db_file, db_mode, out errmsg);
                    if (errmsg != IntPtr.Zero)
                    {
                        string msg = Marshal.PtrToStringAnsi(errmsg);
                        Sqlite.sqliteFree(errmsg);
                        throw new ApplicationException(msg);
                    }
                } catch (DllNotFoundException) {
                    db_version = 3;
                } catch (EntryPointNotFoundException) {
                    db_version = 3;
                }

                if (busy_timeout != 0)
                {
                    Sqlite.sqlite_busy_timeout(sqlite_handle, busy_timeout);
                }
            }
            if (Version == 3)
            {
                int err = Sqlite.sqlite3_open16(db_file, out sqlite_handle);
                if (err == (int)SqliteError.ERROR)
                {
                    throw new ApplicationException(Marshal.PtrToStringUni(Sqlite.sqlite3_errmsg16(sqlite_handle)));
                }
                if (busy_timeout != 0)
                {
                    Sqlite.sqlite3_busy_timeout(sqlite_handle, busy_timeout);
                }
            }
            else
            {
            }
            state = ConnectionState.Open;
        }
Пример #2
0
        public void Close()
        {
            if (state != ConnectionState.Open)
            {
                return;
            }

            state = ConnectionState.Closed;

            if (Version == 3)
            {
                Sqlite.sqlite3_close(sqlite_handle);
            }
            else
            {
                Sqlite.sqlite_close(sqlite_handle);
            }
            sqlite_handle = IntPtr.Zero;
        }
Пример #3
0
        // Executes a statement and returns whether there is more data available.
        internal bool ExecuteStatement(IntPtr pStmt, out int cols, out IntPtr pazValue, out IntPtr pazColName)
        {
            SqliteError err;

            if (parent_conn.Version == 3)
            {
                err = Sqlite.sqlite3_step(pStmt);
                if (err == SqliteError.ERROR)
                {
                    throw new SqliteExecutionException(GetError3());
                }
                pazValue = IntPtr.Zero; pazColName = IntPtr.Zero;                 // not used for v=3
                cols     = Sqlite.sqlite3_column_count(pStmt);
            }
            else
            {
                err = Sqlite.sqlite_step(pStmt, out cols, out pazValue, out pazColName);
                if (err == SqliteError.ERROR)
                {
                    throw new SqliteExecutionException();
                }
            }

            if (err == SqliteError.BUSY)
            {
                throw new SqliteBusyException();
            }

            if (err == SqliteError.MISUSE)
            {
                throw new SqliteExecutionException();
            }

            // err is either ROW or DONE.
            return(err == SqliteError.ROW);
        }
Пример #4
0
        internal void ReadpVm(IntPtr pVm, int version, SqliteCommand cmd)
        {
            int    pN;
            IntPtr pazValue;
            IntPtr pazColName;
            bool   first = true;

            int[] declmode = null;

            while (true)
            {
                bool hasdata = cmd.ExecuteStatement(pVm, out pN, out pazValue, out pazColName);

                // For the first row, get the column information
                if (first)
                {
                    first = false;

                    if (version == 3)
                    {
                        // A decltype might be null if the type is unknown to sqlite.
                        decltypes = new string[pN];
                        declmode  = new int[pN];                        // 1 == integer, 2 == datetime
                        for (int i = 0; i < pN; i++)
                        {
                            IntPtr decl = Sqlite.sqlite3_column_decltype16(pVm, i);
                            if (decl != IntPtr.Zero)
                            {
                                decltypes[i] = Marshal.PtrToStringUni(decl).ToLower(System.Globalization.CultureInfo.InvariantCulture);
                                if (decltypes[i] == "int" || decltypes[i] == "integer")
                                {
                                    declmode[i] = 1;
                                }
                                else if (decltypes[i] == "date" || decltypes[i] == "datetime")
                                {
                                    declmode[i] = 2;
                                }
                            }
                        }
                    }

                    columns = new string[pN];
                    for (int i = 0; i < pN; i++)
                    {
                        string colName;
                        if (version == 2)
                        {
                            IntPtr fieldPtr = Marshal.ReadIntPtr(pazColName, i * IntPtr.Size);
                            colName = Sqlite.HeapToString(fieldPtr, ((SqliteConnection)cmd.Connection).Encoding);
                        }
                        else
                        {
                            colName = Marshal.PtrToStringUni(Sqlite.sqlite3_column_name16(pVm, i));
                        }
                        columns[i] = colName;
                        column_names_sens [colName]   = i;
                        column_names_insens [colName] = i;
                    }
                }

                if (!hasdata)
                {
                    break;
                }

                object[] data_row = new object [pN];
                for (int i = 0; i < pN; i++)
                {
                    if (version == 2)
                    {
                        IntPtr fieldPtr = Marshal.ReadIntPtr(pazValue, i * IntPtr.Size);
                        data_row[i] = Sqlite.HeapToString(fieldPtr, ((SqliteConnection)cmd.Connection).Encoding);
                    }
                    else
                    {
                        switch (Sqlite.sqlite3_column_type(pVm, i))
                        {
                        case 1:
                            long val = Sqlite.sqlite3_column_int64(pVm, i);

                            // If the column was declared as an 'int' or 'integer', let's play
                            // nice and return an int (version 3 only).
                            if (declmode[i] == 1 && val >= int.MinValue && val <= int.MaxValue)
                            {
                                data_row[i] = (int)val;
                            }

                            // Or if it was declared a date or datetime, do the reverse of what we
                            // do for DateTime parameters.
                            else if (declmode[i] == 2)
                            {
                                data_row[i] = DateTime.FromFileTime(val);
                            }

                            else
                            {
                                data_row[i] = val;
                            }

                            break;

                        case 2:
                            data_row[i] = Sqlite.sqlite3_column_double(pVm, i);
                            break;

                        case 3:
                            data_row[i] = Marshal.PtrToStringUni(Sqlite.sqlite3_column_text16(pVm, i));

                            // If the column was declared as a 'date' or 'datetime', let's play
                            // nice and return a DateTime (version 3 only).
                            if (declmode[i] == 2)
                            {
                                data_row[i] = DateTime.Parse((string)data_row[i]);
                            }
                            break;

                        case 4:
                            int    blobbytes = Sqlite.sqlite3_column_bytes16(pVm, i);
                            IntPtr blobptr   = Sqlite.sqlite3_column_blob(pVm, i);
                            byte[] blob      = new byte[blobbytes];
                            Marshal.Copy(blobptr, blob, 0, blobbytes);
                            data_row[i] = blob;
                            break;

                        case 5:
                            data_row[i] = null;
                            break;

                        default:
                            throw new ApplicationException("FATAL: Unknown sqlite3_column_type");
                        }
                    }
                }

                rows.Add(data_row);
            }
        }
Пример #5
0
 private string GetError3()
 {
     return(Marshal.PtrToStringUni(Sqlite.sqlite3_errmsg16(parent_conn.Handle)));
 }
Пример #6
0
        public SqliteDataReader ExecuteReader(CommandBehavior behavior, bool want_results, out int rows_affected)
        {
            Prepare();

            // The SQL string may contain multiple sql commands, so the main
            // thing to do is have Sqlite iterate through the commands.
            // If want_results, only the last command is returned as a
            // DataReader.  Otherwise, no command is returned as a
            // DataReader.

            IntPtr psql;             // pointer to SQL command

            // Sqlite 2 docs say this: By default, SQLite assumes that all data uses a fixed-size 8-bit
            // character (iso8859).  But if you give the --enable-utf8 option to the configure script, then the
            // library assumes UTF-8 variable sized characters. This makes a difference for the LIKE and GLOB
            // operators and the LENGTH() and SUBSTR() functions. The static string sqlite_encoding will be set
            // to either "UTF-8" or "iso8859" to indicate how the library was compiled. In addition, the sqlite.h
            // header file will define one of the macros SQLITE_UTF8 or SQLITE_ISO8859, as appropriate.
            //
            // We have no way of knowing whether Sqlite 2 expects ISO8859 or UTF-8, but ISO8859 seems to be the
            // default.  Therefore, we need to use an ISO8859(-1) compatible encoding, like ANSI.
            // OTOH, the user may want to specify the encoding of the bytes stored in the database, regardless
            // of what Sqlite is treating them as,

            // For Sqlite 3, we use the UTF-16 prepare function, so we need a UTF-16 string.

            if (parent_conn.Version == 2)
            {
                psql = Sqlite.StringToHeap(sql.Trim(), parent_conn.Encoding);
            }
            else
            {
                psql = Marshal.StringToHGlobalUni(sql.Trim());
            }

            IntPtr pzTail = psql;
            IntPtr errMsgPtr;

            parent_conn.StartExec();

            rows_affected = 0;

            try {
                while (true)
                {
                    IntPtr pStmt;

                    GetNextStatement(pzTail, out pzTail, out pStmt);

                    if (pStmt == IntPtr.Zero)
                    {
                        throw new Exception();
                    }

                    // pzTail is positioned after the last byte in the
                    // statement, which will be the NULL character if
                    // this was the last statement.
                    bool last = Marshal.ReadByte(pzTail) == 0;

                    try {
                        if (parent_conn.Version == 3)
                        {
                            BindParameters3(pStmt);
                        }

                        if (last && want_results)
                        {
                            return(new SqliteDataReader(this, pStmt, parent_conn.Version));
                        }

                        ExecuteStatement(pStmt);

                        if (last)                         // rows_affected is only used if !want_results
                        {
                            rows_affected = NumChanges();
                        }
                    } finally {
                        if (parent_conn.Version == 3)
                        {
                            Sqlite.sqlite3_finalize(pStmt);
                        }
                        else
                        {
                            Sqlite.sqlite_finalize(pStmt, out errMsgPtr);
                        }
                    }

                    if (last)
                    {
                        break;
                    }
                }

                return(null);
            } finally {
                parent_conn.EndExec();
                Marshal.FreeHGlobal(psql);
            }
        }
Пример #7
0
        private void BindParameters3(IntPtr pStmt)
        {
            if (sql_params == null)
            {
                return;
            }
            if (sql_params.Count == 0)
            {
                return;
            }

            int pcount = Sqlite.sqlite3_bind_parameter_count(pStmt);

            for (int i = 1; i <= pcount; i++)
            {
                String name = Sqlite.HeapToString(Sqlite.sqlite3_bind_parameter_name(pStmt, i), Encoding.UTF8);

                SqliteParameter param = null;
                if (name != null)
                {
                    param = sql_params[name] as SqliteParameter;
                }
                else
                {
                    param = sql_params[i - 1] as SqliteParameter;
                }

                if (param.Value == null)
                {
                    Sqlite.sqlite3_bind_null(pStmt, i);
                    continue;
                }

                Type ptype = param.Value.GetType();
                if (ptype.IsEnum)
                {
                    ptype = Enum.GetUnderlyingType(ptype);
                }

                SqliteError err;

                if (ptype.Equals(typeof(String)))
                {
                    String s = (String)param.Value;
                    err = Sqlite.sqlite3_bind_text16(pStmt, i, s, -1, (IntPtr)(-1));
                }
                else if (ptype.Equals(typeof(DBNull)))
                {
                    err = Sqlite.sqlite3_bind_null(pStmt, i);
                }
                else if (ptype.Equals(typeof(Boolean)))
                {
                    bool b = (bool)param.Value;
                    err = Sqlite.sqlite3_bind_int(pStmt, i, b ? 1 : 0);
                }
                else if (ptype.Equals(typeof(Byte)))
                {
                    err = Sqlite.sqlite3_bind_int(pStmt, i, (Byte)param.Value);
                }
                else if (ptype.Equals(typeof(Char)))
                {
                    err = Sqlite.sqlite3_bind_int(pStmt, i, (Char)param.Value);
                }
                else if (ptype.IsEnum)
                {
                    err = Sqlite.sqlite3_bind_int(pStmt, i, (Int32)param.Value);
                }
                else if (ptype.Equals(typeof(Int16)))
                {
                    err = Sqlite.sqlite3_bind_int(pStmt, i, (Int16)param.Value);
                }
                else if (ptype.Equals(typeof(Int32)))
                {
                    err = Sqlite.sqlite3_bind_int(pStmt, i, (Int32)param.Value);
                }
                else if (ptype.Equals(typeof(SByte)))
                {
                    err = Sqlite.sqlite3_bind_int(pStmt, i, (SByte)param.Value);
                }
                else if (ptype.Equals(typeof(UInt16)))
                {
                    err = Sqlite.sqlite3_bind_int(pStmt, i, (UInt16)param.Value);
                }
                else if (ptype.Equals(typeof(DateTime)))
                {
                    DateTime dt = (DateTime)param.Value;
                    err = Sqlite.sqlite3_bind_int64(pStmt, i, dt.ToFileTime());
                }
                else if (ptype.Equals(typeof(Double)))
                {
                    err = Sqlite.sqlite3_bind_double(pStmt, i, (Double)param.Value);
                }
                else if (ptype.Equals(typeof(Single)))
                {
                    err = Sqlite.sqlite3_bind_double(pStmt, i, (Single)param.Value);
                }
                else if (ptype.Equals(typeof(UInt32)))
                {
                    err = Sqlite.sqlite3_bind_int64(pStmt, i, (UInt32)param.Value);
                }
                else if (ptype.Equals(typeof(Int64)))
                {
                    err = Sqlite.sqlite3_bind_int64(pStmt, i, (Int64)param.Value);
                }
                else if (ptype.Equals(typeof(Byte[])))
                {
                    err = Sqlite.sqlite3_bind_blob(pStmt, i, (Byte[])param.Value, ((Byte[])param.Value).Length, (IntPtr)(-1));
                }
                else
                {
                    throw new ApplicationException("Unkown Parameter Type");
                }
                if (err != SqliteError.OK)
                {
                    throw new ApplicationException("Sqlite error in bind " + err);
                }
            }
        }