Ejemplo n.º 1
1
            private object queryExecute(CodeContext context, bool multiple, object operation_obj, object args)
            {
                if(!(operation_obj is string))
                    throw CreateThrowable(PythonExceptions.ValueError, "operation parameter must be str or unicode");

                string operation = (string)operation_obj;

                if(string.IsNullOrEmpty(operation))
                    return null;

                int rc;

                connection.checkThread(); connection.checkConnection();

                this.next_row = null;

                IEnumerator parameters_iter = null;
                if(multiple)
                {
                    if(args != null)
                        parameters_iter = PythonOps.CreatePythonEnumerator(args);
                }
                else
                {
                    object[] parameters_list = { args };
                    if(parameters_list[0] == null)
                        parameters_list[0] = new PythonTuple();

                    parameters_iter = parameters_list.GetEnumerator();
                }

                if(this.statement != null)
                    rc = this.statement.Reset();

                this.description = null;
                this.rowcount = -1;

                // TODO: use stmt cache instead ?
                this.statement = (Statement)this.connection.__call__(operation);

                if(this.statement.in_use)
                    this.statement = new Statement(connection, operation);

                this.statement.Reset();
                this.statement.MarkDirty();

                if(!string.IsNullOrEmpty(connection.begin_statement))
                {
                    switch(statement.StatementType)
                    {
                        case StatementType.Update:
                        case StatementType.Insert:
                        case StatementType.Delete:
                        case StatementType.Replace:
                            if(!connection.inTransaction)
                                connection.begin();
                            
                            break;

                        case StatementType.Other:
                            // it's a DDL statement or something similar
                            // we better COMMIT first so it works for all cases
                            if(connection.inTransaction)
                                connection.commit();

                            break;

                        case StatementType.Select:
                            if(multiple)
                                throw MakeProgrammingError("You cannot execute SELECT statements in executemany().");
                            break;

                        default:
                            break;
                    }
                }

                while(true)
                {
                    if(!parameters_iter.MoveNext())
                        break;

                    object parameters = parameters_iter.Current;

                    this.statement.MarkDirty();
                    this.statement.BindParameters(context, parameters);

                    while(true)
                    {
                        rc = this.statement.RawStep();
                        if(rc == Sqlite3.SQLITE_DONE || rc == Sqlite3.SQLITE_ROW)
                            break;

                        rc = this.statement.Reset();
                        if(rc == Sqlite3.SQLITE_SCHEMA)
                        {
                            rc = this.statement.Recompile(context, parameters);
                            if(rc == Sqlite3.SQLITE_OK)
                            {
                                continue;
                            }
                            else
                            {
                                this.statement.Reset();
                                throw GetSqliteError(this.connection.db, null);
                            }
                        }
                        else
                        {
                            this.statement.Reset();
                            throw GetSqliteError(this.connection.db, null);
                        }
                    }

                    if(!buildRowCastMap())
                        throw MakeOperationalError("Error while building row_cast_map");

                    if(rc == Sqlite3.SQLITE_ROW || (rc == Sqlite3.SQLITE_DONE && this.statement.StatementType == StatementType.Select))
                    {
                        if(this.description == null)
                        {
                            int numcols = Sqlite3.sqlite3_column_count(this.statement.st);
                            object[] new_description = new object[numcols];

                            for(int i = 0; i < numcols; ++i)
                            {
                                string name = buildColumnName(Sqlite3.sqlite3_column_name(this.statement.st, i));

                                object descriptor = new object[] {
                                    name,
                                    (object)null,
                                    (int?)null,
                                    (int?)null,
                                    (int?)null,
                                    (int?)null,
                                    (bool?)null
                                };

                                new_description[i] = new PythonTuple(descriptor);
                            }

                            this.description = new PythonTuple(new_description);
                        }
                    }

                    if(rc == Sqlite3.SQLITE_ROW)
                    {
                        if(multiple)
                            throw MakeProgrammingError("executemany() can only execute DML statements.");

                        this.next_row = fetchOneRow(context);
                    }
                    else if(rc == Sqlite3.SQLITE_DONE && !multiple)
                    {
                        this.statement.Reset();
                    }

                    switch(this.statement.StatementType)
                    {
                        case StatementType.Update:
                        case StatementType.Delete:
                        case StatementType.Insert:
                        case StatementType.Replace:
                            if(this.rowcount == -1)
                                this.rowcount = 0;

                            this.rowcount += Sqlite3.sqlite3_changes(this.connection.db);
                            break;
                    }

                    if(!multiple && this.statement.StatementType == StatementType.Insert)
                    {
                        this.lastrowid = Sqlite3.sqlite3_last_insert_rowid(this.connection.db);
                    }
                    else
                    {
                        this.lastrowid = null;
                    }

                    if(multiple)
                        rc = this.statement.Reset();
                }

                return this;
            }
Ejemplo n.º 2
0
        internal int Recompile(CodeContext context, object parameters)
        {
            sqlite3_stmt new_st = null;
            string tail = null;

            int rc = Sqlite3.sqlite3_prepare(this.db, this.sql, -1, ref new_st, ref tail);
            if(rc == Sqlite3.SQLITE_OK)
            {
                Statement new_stmt = new Statement(this.st.db, new_st, this.sql, tail);
                new_stmt.BindParameters(context, parameters);

                Sqlite3.sqlite3_finalize(this.st);
                this.st = new_st;
            }

            return rc;
        }
Ejemplo n.º 3
0
            public object next(CodeContext context)
            {
                object next_row_tuple, next_row;

                connection.checkThread(); connection.checkConnection();

                if(this.next_row == null)
                {
                    if(this.statement != null)
                    {
                        this.statement.Reset();
                        this.statement = null;
                    }

                    throw new StopIterationException();
                }

                next_row_tuple = this.next_row;
                this.next_row = null;

                if(this.row_factory != null)
                {
                    next_row = PythonCalls.Call(context, this.row_factory, this, next_row_tuple);
                }
                else
                {
                    next_row = next_row_tuple;
                }

                if(this.statement != null)
                {
                    int rc = this.statement.RawStep();
                    if(rc != Sqlite3.SQLITE_DONE && rc != Sqlite3.SQLITE_ROW)
                    {
                        this.statement.Reset();
                        throw GetSqliteError(this.connection.db, this.statement.st);
                    }

                    if(rc == Sqlite3.SQLITE_ROW)
                        this.next_row = fetchOneRow(context);
                }

                return next_row;
            }
Ejemplo n.º 4
0
            public object __call__(string sql)
            {
                dropUnusedStatementReferences();

                Statement statement = new Statement(this, sql);
                this.statements.Add(new WeakReference(statement));
                return statement;
            }
Ejemplo n.º 5
0
            private object queryExecute(CodeContext context, bool multiple, object operation_obj, object args)
            {
                if (!(operation_obj is string))
                {
                    throw CreateThrowable(PythonExceptions.ValueError, "operation parameter must be str or unicode");
                }

                string operation = (string)operation_obj;

                if (string.IsNullOrEmpty(operation))
                {
                    return(null);
                }

                int rc;

                connection.checkThread(); connection.checkConnection();

                this.next_row = null;

                IEnumerator parameters_iter = null;

                if (multiple)
                {
                    if (args != null)
                    {
                        parameters_iter = PythonOps.CreatePythonEnumerator(args);
                    }
                }
                else
                {
                    object[] parameters_list = { args };
                    if (parameters_list[0] == null)
                    {
                        parameters_list[0] = new PythonTuple();
                    }

                    parameters_iter = parameters_list.GetEnumerator();
                }

                if (this.statement != null)
                {
                    rc = this.statement.Reset();
                }

                this.description = null;
                this.rowcount    = -1;

                // TODO: use stmt cache instead ?
                this.statement = (Statement)this.connection.__call__(operation);

                if (this.statement.in_use)
                {
                    this.statement = new Statement(connection, operation);
                }

                this.statement.Reset();
                this.statement.MarkDirty();

                if (!string.IsNullOrEmpty(connection.begin_statement))
                {
                    switch (statement.StatementType)
                    {
                    case StatementType.Update:
                    case StatementType.Insert:
                    case StatementType.Delete:
                    case StatementType.Replace:
                        if (!connection.inTransaction)
                        {
                            connection.begin();
                        }

                        break;

                    case StatementType.Other:
                        // it's a DDL statement or something similar
                        // we better COMMIT first so it works for all cases
                        if (connection.inTransaction)
                        {
                            connection.commit();
                        }

                        break;

                    case StatementType.Select:
                        if (multiple)
                        {
                            throw MakeProgrammingError("You cannot execute SELECT statements in executemany().");
                        }
                        break;

                    default:
                        break;
                    }
                }

                while (true)
                {
                    if (!parameters_iter.MoveNext())
                    {
                        break;
                    }

                    object parameters = parameters_iter.Current;

                    this.statement.MarkDirty();
                    this.statement.BindParameters(context, parameters);

                    while (true)
                    {
                        rc = this.statement.RawStep();
                        if (rc == Sqlite3.SQLITE_DONE || rc == Sqlite3.SQLITE_ROW)
                        {
                            break;
                        }

                        rc = this.statement.Reset();
                        if (rc == Sqlite3.SQLITE_SCHEMA)
                        {
                            rc = this.statement.Recompile(context, parameters);
                            if (rc == Sqlite3.SQLITE_OK)
                            {
                                continue;
                            }
                            else
                            {
                                this.statement.Reset();
                                throw GetSqliteError(this.connection.db, null);
                            }
                        }
                        else
                        {
                            this.statement.Reset();
                            throw GetSqliteError(this.connection.db, null);
                        }
                    }

                    if (!buildRowCastMap())
                    {
                        throw MakeOperationalError("Error while building row_cast_map");
                    }

                    if (rc == Sqlite3.SQLITE_ROW || (rc == Sqlite3.SQLITE_DONE && this.statement.StatementType == StatementType.Select))
                    {
                        if (this.description == null)
                        {
                            int      numcols         = Sqlite3.sqlite3_column_count(this.statement.st);
                            object[] new_description = new object[numcols];

                            for (int i = 0; i < numcols; ++i)
                            {
                                string name = buildColumnName(Sqlite3.sqlite3_column_name(this.statement.st, i));

                                object descriptor = new object[] {
                                    name,
                                    (object)null,
                                    (int?)null,
                                    (int?)null,
                                    (int?)null,
                                    (int?)null,
                                    (bool?)null
                                };

                                new_description[i] = new PythonTuple(descriptor);
                            }

                            this.description = new PythonTuple(new_description);
                        }
                    }

                    if (rc == Sqlite3.SQLITE_ROW)
                    {
                        if (multiple)
                        {
                            throw MakeProgrammingError("executemany() can only execute DML statements.");
                        }

                        this.next_row = fetchOneRow(context);
                    }
                    else if (rc == Sqlite3.SQLITE_DONE && !multiple)
                    {
                        this.statement.Reset();
                    }

                    switch (this.statement.StatementType)
                    {
                    case StatementType.Update:
                    case StatementType.Delete:
                    case StatementType.Insert:
                    case StatementType.Replace:
                        if (this.rowcount == -1)
                        {
                            this.rowcount = 0;
                        }

                        this.rowcount += Sqlite3.sqlite3_changes(this.connection.db);
                        break;
                    }

                    if (!multiple && this.statement.StatementType == StatementType.Insert)
                    {
                        this.lastrowid = Sqlite3.sqlite3_last_insert_rowid(this.connection.db);
                    }
                    else
                    {
                        this.lastrowid = null;
                    }

                    if (multiple)
                    {
                        rc = this.statement.Reset();
                    }
                }

                return(this);
            }