11package com .j256 .ormlite .android ;
22
3- import java .lang .reflect .Array ;
3+ import java .lang .reflect .InvocationTargetException ;
44import java .lang .reflect .Method ;
55import java .sql .SQLException ;
66import java .util .ArrayList ;
@@ -33,6 +33,8 @@ public class AndroidCompiledStatement implements CompiledStatement {
3333 private static final String [] NO_STRING_ARGS = new String [0 ];
3434 private static final ApiCompatibility apiCompatibility = ApiCompatibilityUtils .getCompatibility ();
3535
36+ private static Method hiddenExecSqlMethod ;
37+
3638 private final String sql ;
3739 private final SQLiteDatabase db ;
3840 private final StatementType type ;
@@ -44,6 +46,10 @@ public class AndroidCompiledStatement implements CompiledStatement {
4446 private Integer max ;
4547 private CancellationHook cancellationHook ;
4648
49+ static {
50+ hiddenExecSqlMethod = hiddenExecSqlMethod ();
51+ }
52+
4753 public AndroidCompiledStatement (String sql , SQLiteDatabase db , StatementType type , boolean cancelQueriesEnabled ,
4854 boolean cacheStore ) {
4955 this .sql = sql ;
@@ -215,17 +221,18 @@ public String toString() {
215221 * Execute some SQL on the database and return the number of rows changed.
216222 */
217223 static int execSql (SQLiteDatabase db , String label , String finalSql , Object [] argArray ) throws SQLException {
218- int result = -1 ;
219224 try {
220- result = exeSqlCompatibly (db , finalSql , argArray );
225+ Integer result = execSqlCompatibly (db , finalSql , argArray );
226+ // reflection sql method returns will >= 0, public API will return null
227+ if (result != null && result >= 0 ) {
228+ logger .trace ("executing statement using reflection {} changed {} rows: {}" , label , result , finalSql );
229+ return result ;
230+ }
221231 } catch (android .database .SQLException e ) {
222232 throw new SQLException ("Problems executing " + label + " Android statement: " + finalSql , e );
223233 }
224234
225- // reflected sql method returns will >= 0
226- if (result >= 0 ) {
227- return result ;
228- }
235+ int result ;
229236
230237 SQLiteStatement stmt = null ;
231238 try {
@@ -248,32 +255,35 @@ static int execSql(SQLiteDatabase db, String label, String finalSql, Object[] ar
248255 * Use reflection first, when reflection error, use origin method without return code
249256 * @return modified rows count
250257 */
251- private static int exeSqlCompatibly (SQLiteDatabase db , String sql , Object [] bindArgs ) {
258+ private static Integer execSqlCompatibly (SQLiteDatabase db , String sql , Object [] bindArgs ) {
252259 try {
253- int result = invokeExecSqlMethod (db , sql , bindArgs );
254- return result ;
260+ return invokeHiddenExecSqlMethod (db , sql , bindArgs );
255261 } catch (android .database .SQLException e ) {
262+ logger .trace (e , "reflection failed, call origin method, sql {}" , sql );
256263 db .execSQL (sql , bindArgs );
257- return - 1 ;
264+ return null ;
258265 }
259266 }
260267
261- private static int invokeExecSqlMethod (SQLiteDatabase db , String sql , Object [] bindArgs ) throws android .database .SQLException {
268+ private static int invokeHiddenExecSqlMethod (SQLiteDatabase db , String sql , Object [] bindArgs ) throws android .database .SQLException {
262269 try {
263- Object result = hiddenExecSqlMethod ().invoke (db , sql , bindArgs );
264- logger .trace ("invokeExecSqlMethod result: {}" , result );
265- return (int ) result ;
266- } catch (Exception e ) {
267- throw new android .database .SQLException ("reflect error" , e );
270+ if (hiddenExecSqlMethod != null ) {
271+ Object result = hiddenExecSqlMethod .invoke (db , sql , bindArgs );
272+ logger .trace ("invoke hidden execSql method result: {}" , result );
273+ return (int ) result ;
274+ } else {
275+ throw new android .database .SQLException ("reflection get method error" );
276+ }
277+ } catch (InvocationTargetException | IllegalAccessException e ) {
278+ // reflection cannot work, set method null, no need invoke anymore
279+ hiddenExecSqlMethod = null ;
280+ throw new android .database .SQLException ("reflection invoke error" , e );
268281 }
269282 }
270283
271284 private static Method hiddenExecSqlMethod () {
272- Class <SQLiteDatabase > clz = SQLiteDatabase .class ;
273- Class <?> objArrClass = Array .newInstance (Object .class , 0 ).getClass ();
274285 try {
275- Method executeSqlMethod = clz .getMethod ("executeSql" , String .class , objArrClass );
276- return executeSqlMethod ;
286+ return SQLiteDatabase .class .getMethod ("executeSql" , String .class , Object [].class );
277287 } catch (NoSuchMethodException e ) {
278288 return null ;
279289 }
0 commit comments