Loading core/java/android/database/DatabaseUtils.java +65 −5 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import android.compat.annotation.UnsupportedAppUsage; import android.content.ContentValues; import android.content.Context; import android.content.OperationApplicationException; import android.database.sqlite.Flags; import android.database.sqlite.SQLiteAbortException; import android.database.sqlite.SQLiteConstraintException; import android.database.sqlite.SQLiteDatabase; Loading Loading @@ -1609,7 +1610,7 @@ public class DatabaseUtils { * Comments either start with "--" and run to the end of the line or are C-style block * comments. The function returns null if a prefix could not be found. */ private static String getSqlStatementPrefixExtended(String sql) { private static String getSqlStatementPrefixExtendedRegex(String sql) { Matcher m = sPrefixPattern.matcher(sql); if (m.lookingAt()) { return m.group(PREFIX_GROUP_NUM).toUpperCase(Locale.ROOT); Loading @@ -1618,6 +1619,61 @@ public class DatabaseUtils { } } /** * Return the index of the first character past comments and whitespace. -1 is returned if * a comment is malformed. */ private static int getSqlStatementPrefixOffset(String s) { final int limit = s.length() - 2; if (limit < 0) return -1; int i = 0; while (i < limit) { final char c = s.charAt(i); if (c <= ' ') { // This behavior conforms to String.trim(), which is used by the legacy Android // SQL prefix logic. This test is not unicode-aware. Notice that it accepts the // null character as whitespace even though the null character will terminate the // SQL string in native code. i++; } else if (c == '-') { if (s.charAt(i+1) != '-') return i; i = s.indexOf('\n', i+2); if (i < 0) return -1; i++; } else if (c == '/') { if (s.charAt(i+1) != '*') return i; i++; do { i = s.indexOf('*', i+1); if (i < 0) return -1; i++; } while (s.charAt(i) != '/'); i++; } else { return i; } } return -1; } /** * Scan past leading comments without using the Java regex routines. */ private static String getSqlStatementPrefixExtendedNoRegex(String sql) { int n = getSqlStatementPrefixOffset(sql); if (n < 0) { // Bad comment syntax. return null; } final int end = sql.length(); if (n > end) { // Bad scanning. This indicates a programming error. return null; } final int eos = Math.min(n+3, end); return sql.substring(n, eos); } /** * Return the extended statement type for the SQL statement. This is not a public API and it * can return values that are not publicly visible. Loading Loading @@ -1663,12 +1719,16 @@ public class DatabaseUtils { * @hide */ public static int getSqlStatementTypeExtended(@NonNull String sql) { if (Flags.simpleSqlCommentScanner()) { return categorizeStatement(getSqlStatementPrefixExtendedNoRegex(sql), sql); } else { int type = categorizeStatement(getSqlStatementPrefixSimple(sql), sql); if (type == STATEMENT_COMMENT) { type = categorizeStatement(getSqlStatementPrefixExtended(sql), sql); type = categorizeStatement(getSqlStatementPrefixExtendedRegex(sql), sql); } return type; } } /** * Convert an extended statement type to a public SQL statement type value. Loading core/java/android/database/sqlite/flags.aconfig +8 −0 Original line number Diff line number Diff line Loading @@ -17,3 +17,11 @@ flag { description: "Permit updates to TEMP tables in read-only transactions" bug: "317993835" } flag { name: "simple_sql_comment_scanner" namespace: "system_performance" is_fixed_read_only: true description: "Scan SQL comments by hand instead of with a regex" bug: "329118560" } core/tests/coretests/src/android/database/DatabaseUtilsTest.java +5 −1 Original line number Diff line number Diff line Loading @@ -78,7 +78,8 @@ public class DatabaseUtilsTest { final int sel = STATEMENT_SELECT; assertEquals(sel, getSqlStatementType("SELECT")); assertEquals(sel, getSqlStatementType(" SELECT")); assertEquals(sel, getSqlStatementType(" \n SELECT")); assertEquals(sel, getSqlStatementType(" \n\r\f\t SELECT")); assertEquals(sel, getSqlStatementType(" \n\r\f\t SEL")); final int upd = STATEMENT_UPDATE; assertEquals(upd, getSqlStatementType("UPDATE")); Loading @@ -95,6 +96,9 @@ public class DatabaseUtilsTest { assertEquals(othr, getSqlStatementType("SE LECT")); assertEquals(othr, getSqlStatementType("-- cmt\n SE")); assertEquals(othr, getSqlStatementType("WITH")); assertEquals(othr, getSqlStatementType("-")); assertEquals(othr, getSqlStatementType("--")); assertEquals(othr, getSqlStatementType("*/* foo */ SEL")); // Verify that leading line-comments are skipped. assertEquals(sel, getSqlStatementType("-- cmt\n SELECT")); Loading Loading
core/java/android/database/DatabaseUtils.java +65 −5 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import android.compat.annotation.UnsupportedAppUsage; import android.content.ContentValues; import android.content.Context; import android.content.OperationApplicationException; import android.database.sqlite.Flags; import android.database.sqlite.SQLiteAbortException; import android.database.sqlite.SQLiteConstraintException; import android.database.sqlite.SQLiteDatabase; Loading Loading @@ -1609,7 +1610,7 @@ public class DatabaseUtils { * Comments either start with "--" and run to the end of the line or are C-style block * comments. The function returns null if a prefix could not be found. */ private static String getSqlStatementPrefixExtended(String sql) { private static String getSqlStatementPrefixExtendedRegex(String sql) { Matcher m = sPrefixPattern.matcher(sql); if (m.lookingAt()) { return m.group(PREFIX_GROUP_NUM).toUpperCase(Locale.ROOT); Loading @@ -1618,6 +1619,61 @@ public class DatabaseUtils { } } /** * Return the index of the first character past comments and whitespace. -1 is returned if * a comment is malformed. */ private static int getSqlStatementPrefixOffset(String s) { final int limit = s.length() - 2; if (limit < 0) return -1; int i = 0; while (i < limit) { final char c = s.charAt(i); if (c <= ' ') { // This behavior conforms to String.trim(), which is used by the legacy Android // SQL prefix logic. This test is not unicode-aware. Notice that it accepts the // null character as whitespace even though the null character will terminate the // SQL string in native code. i++; } else if (c == '-') { if (s.charAt(i+1) != '-') return i; i = s.indexOf('\n', i+2); if (i < 0) return -1; i++; } else if (c == '/') { if (s.charAt(i+1) != '*') return i; i++; do { i = s.indexOf('*', i+1); if (i < 0) return -1; i++; } while (s.charAt(i) != '/'); i++; } else { return i; } } return -1; } /** * Scan past leading comments without using the Java regex routines. */ private static String getSqlStatementPrefixExtendedNoRegex(String sql) { int n = getSqlStatementPrefixOffset(sql); if (n < 0) { // Bad comment syntax. return null; } final int end = sql.length(); if (n > end) { // Bad scanning. This indicates a programming error. return null; } final int eos = Math.min(n+3, end); return sql.substring(n, eos); } /** * Return the extended statement type for the SQL statement. This is not a public API and it * can return values that are not publicly visible. Loading Loading @@ -1663,12 +1719,16 @@ public class DatabaseUtils { * @hide */ public static int getSqlStatementTypeExtended(@NonNull String sql) { if (Flags.simpleSqlCommentScanner()) { return categorizeStatement(getSqlStatementPrefixExtendedNoRegex(sql), sql); } else { int type = categorizeStatement(getSqlStatementPrefixSimple(sql), sql); if (type == STATEMENT_COMMENT) { type = categorizeStatement(getSqlStatementPrefixExtended(sql), sql); type = categorizeStatement(getSqlStatementPrefixExtendedRegex(sql), sql); } return type; } } /** * Convert an extended statement type to a public SQL statement type value. Loading
core/java/android/database/sqlite/flags.aconfig +8 −0 Original line number Diff line number Diff line Loading @@ -17,3 +17,11 @@ flag { description: "Permit updates to TEMP tables in read-only transactions" bug: "317993835" } flag { name: "simple_sql_comment_scanner" namespace: "system_performance" is_fixed_read_only: true description: "Scan SQL comments by hand instead of with a regex" bug: "329118560" }
core/tests/coretests/src/android/database/DatabaseUtilsTest.java +5 −1 Original line number Diff line number Diff line Loading @@ -78,7 +78,8 @@ public class DatabaseUtilsTest { final int sel = STATEMENT_SELECT; assertEquals(sel, getSqlStatementType("SELECT")); assertEquals(sel, getSqlStatementType(" SELECT")); assertEquals(sel, getSqlStatementType(" \n SELECT")); assertEquals(sel, getSqlStatementType(" \n\r\f\t SELECT")); assertEquals(sel, getSqlStatementType(" \n\r\f\t SEL")); final int upd = STATEMENT_UPDATE; assertEquals(upd, getSqlStatementType("UPDATE")); Loading @@ -95,6 +96,9 @@ public class DatabaseUtilsTest { assertEquals(othr, getSqlStatementType("SE LECT")); assertEquals(othr, getSqlStatementType("-- cmt\n SE")); assertEquals(othr, getSqlStatementType("WITH")); assertEquals(othr, getSqlStatementType("-")); assertEquals(othr, getSqlStatementType("--")); assertEquals(othr, getSqlStatementType("*/* foo */ SEL")); // Verify that leading line-comments are skipped. assertEquals(sel, getSqlStatementType("-- cmt\n SELECT")); Loading