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