SQLiteProgram.java revision 6d1ec0d81cd8ecdd390b31e724bac554bb955a94
1/*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.database.sqlite;
18
19import android.util.Log;
20
21/**
22 * A base class for compiled SQLite programs.
23 */
24public abstract class SQLiteProgram extends SQLiteClosable {
25    private static final String TAG = "SQLiteProgram";
26
27    /** The database this program is compiled against. */
28    protected SQLiteDatabase mDatabase;
29
30    /** The SQL used to create this query */
31    /* package */ final String mSql;
32
33    /**
34     * Native linkage, do not modify. This comes from the database and should not be modified
35     * in here or in the native code.
36     */
37    protected int nHandle = 0;
38
39    /**
40     * the compiledSql object for the given sql statement.
41     */
42    private SQLiteCompiledSql compiledSql;
43    private boolean myCompiledSqlIsInCache;
44
45    /**
46     * compiledSql statement id is populated with the corresponding object from the above
47     * member compiledSql.
48     * this member is used by the native_bind_* methods
49     */
50    protected int nStatement = 0;
51
52    /* package */ SQLiteProgram(SQLiteDatabase db, String sql) {
53        if (SQLiteDebug.DEBUG_SQL_STATEMENTS) {
54            Log.d(TAG, "processing sql: " + sql);
55        }
56
57        mDatabase = db;
58        mSql = sql;
59        db.acquireReference();
60        db.addSQLiteClosable(this);
61        this.nHandle = db.mNativeHandle;
62
63        compiledSql = db.getCompiledStatementForSql(sql);
64        if (compiledSql == null) {
65            // create a new compiled-sql obj
66            compiledSql = new SQLiteCompiledSql(db, sql);
67
68            // add it to the cache of compiled-sqls
69            myCompiledSqlIsInCache = db.addToCompiledQueries(sql, compiledSql);
70        } else {
71            myCompiledSqlIsInCache = true;
72        }
73        nStatement = compiledSql.nStatement;
74    }
75
76    @Override
77    protected void onAllReferencesReleased() {
78        // release the compiled sql statement used by me if it is NOT in cache
79        if (!myCompiledSqlIsInCache && compiledSql != null) {
80            compiledSql.releaseSqlStatement();
81            compiledSql = null; // so that GC doesn't call finalize() on it
82        }
83        mDatabase.releaseReference();
84        mDatabase.removeSQLiteClosable(this);
85    }
86
87    @Override
88    protected void onAllReferencesReleasedFromContainer() {
89        // release the compiled sql statement used by me if it is NOT in cache
90      if (!myCompiledSqlIsInCache && compiledSql != null) {
91            compiledSql.releaseSqlStatement();
92            compiledSql = null; // so that GC doesn't call finalize() on it
93        }
94        mDatabase.releaseReference();
95    }
96
97    /**
98     * Returns a unique identifier for this program.
99     *
100     * @return a unique identifier for this program
101     */
102    public final int getUniqueId() {
103        return  (compiledSql != null) ? compiledSql.nStatement : 0;
104    }
105
106    /* package */ String getSqlString() {
107        return mSql;
108    }
109
110    /**
111     * @deprecated use this.compiledStatement.compile instead
112     *
113     * @param sql the SQL string to compile
114     * @param forceCompilation forces the SQL to be recompiled in the event that there is an
115     *  existing compiled SQL program already around
116     */
117    @Deprecated
118    protected void compile(String sql, boolean forceCompilation) {
119        // TODO is there a need for this?
120    }
121
122    /**
123     * Bind a NULL value to this statement. The value remains bound until
124     * {@link #clearBindings} is called.
125     *
126     * @param index The 1-based index to the parameter to bind null to
127     */
128    public void bindNull(int index) {
129        acquireReference();
130        try {
131            native_bind_null(index);
132        } finally {
133            releaseReference();
134        }
135    }
136
137    /**
138     * Bind a long value to this statement. The value remains bound until
139     * {@link #clearBindings} is called.
140     *
141     * @param index The 1-based index to the parameter to bind
142     * @param value The value to bind
143     */
144    public void bindLong(int index, long value) {
145        acquireReference();
146        try {
147            native_bind_long(index, value);
148        } finally {
149            releaseReference();
150        }
151    }
152
153    /**
154     * Bind a double value to this statement. The value remains bound until
155     * {@link #clearBindings} is called.
156     *
157     * @param index The 1-based index to the parameter to bind
158     * @param value The value to bind
159     */
160    public void bindDouble(int index, double value) {
161        acquireReference();
162        try {
163            native_bind_double(index, value);
164        } finally {
165            releaseReference();
166        }
167    }
168
169    /**
170     * Bind a String value to this statement. The value remains bound until
171     * {@link #clearBindings} is called.
172     *
173     * @param index The 1-based index to the parameter to bind
174     * @param value The value to bind
175     */
176    public void bindString(int index, String value) {
177        if (value == null) {
178            throw new IllegalArgumentException("the bind value at index " + index + " is null");
179        }
180        acquireReference();
181        try {
182            native_bind_string(index, value);
183        } finally {
184            releaseReference();
185        }
186    }
187
188    /**
189     * Bind a byte array value to this statement. The value remains bound until
190     * {@link #clearBindings} is called.
191     *
192     * @param index The 1-based index to the parameter to bind
193     * @param value The value to bind
194     */
195    public void bindBlob(int index, byte[] value) {
196        if (value == null) {
197            throw new IllegalArgumentException("the bind value at index " + index + " is null");
198        }
199        acquireReference();
200        try {
201            native_bind_blob(index, value);
202        } finally {
203            releaseReference();
204        }
205    }
206
207    /**
208     * Clears all existing bindings. Unset bindings are treated as NULL.
209     */
210    public void clearBindings() {
211        acquireReference();
212        try {
213            native_clear_bindings();
214        } finally {
215            releaseReference();
216        }
217    }
218
219    /**
220     * Release this program's resources, making it invalid.
221     */
222    public void close() {
223        mDatabase.lock();
224        try {
225            releaseReference();
226        } finally {
227            mDatabase.unlock();
228        }
229    }
230
231    /**
232     * Compiles SQL into a SQLite program.
233     *
234     * <P>The database lock must be held when calling this method.
235     * @param sql The SQL to compile.
236     */
237    @Deprecated
238    protected final native void native_compile(String sql);
239    @Deprecated
240    protected final native void native_finalize();
241
242    protected final native void native_bind_null(int index);
243    protected final native void native_bind_long(int index, long value);
244    protected final native void native_bind_double(int index, double value);
245    protected final native void native_bind_string(int index, String value);
246    protected final native void native_bind_blob(int index, byte[] value);
247    private final native void native_clear_bindings();
248}
249
250