Quieting the SQL Syntax Warnings

val db: SQLiteDatabase = TODO("open a database")val st = db.compileStatement("ATTACH DATABASE ? AS plaintext KEY ''")

By default, Android Studio does not like this SQL statement. It puts ared undersquiggle below KEY, complaining that it is expecting a ; instead.

According to SQLite, Android Studio is correct.

This error is coming from a SQL ���language injection���. Rebecca Franks wrotea great blog postabout language injections a few weeks ago. There is a ���SQLiteDatabase methods���language injection set up in my Android Studio 4.1.2 installation, and I assume thatit shipped with Studio itself.

However, in my case, I���m right, and Android Studio is wrong.

That is becausein this code I am not using plain SQLite ��� I am using SQLCipher for Android.SQLCipher for Android has an extended form of ATTACH DATABASE that takes a KEYoption to supply a passphrase (shown here as the empty string '').

It is unclear why a language injection for android.database.sqlite.SQLiteDatabaseis affecting calls to net.sqlcipher.database.SQLiteDatabase. Perhaps it is becausenet.sqlcipher.database.SQLiteDatabase implements androidx.sqlite.db.SupportSQLiteDatabase, the SQLite indirection API that allows you to use things like SQLCipher for Androidwith Room and SQLDelight. Or maybe this is a limitation of the scoping rules forlanguage injections, and anything named SQLiteDatabase will be affected.

Regardless, the red undersquiggle was annoying me.

I could disable that language injection, but then I lose syntax highlighting andvalidation everywhere else. Instead, I want to be able to mark certain statementsas being correct and suppress the warning, akin to how @SuppressLint() works.However, this is not a Lint check, so @SuppressLint itself does not help here.

Rebecca���s post gave me an idea, though, which turns out to work, in a couple of different ways.

In her post, she shows that you can use a //language= comment to cause a particularlanguage injection to be applied in a spot it might not normally be applied.So, while this would result in no errors:

private const val ATTACH_THIS = "ATTACH DATABASE ? AS plaintext KEY ''"

���this would complain about KEY:

//language=sqlprivate const val ATTACH_THIS = "ATTACH DATABASE ? AS plaintext KEY ''"

In the first snippet, the IDE has no idea that this string is a SQL statement andso does not apply any language injections. In the second, we teach it that thisstatement contains SQL, so the IDE applies the appropriate language injection.

So, one workaround is to pull the offending SQL out of the SQLiteDatabase calls:

val db: SQLiteDatabase = TODO("open a database")val st = db.compileStatement(ATTACH_THIS)

If we skip the //language=sql comment on the ATTACH_THIS declaration, thenwe will not get any complaints about KEY.

Another workaround is to override the language injection at the call site:

val db: SQLiteDatabase = TODO("open a database")//language=textval st = db.compileStatement("ATTACH DATABASE ? AS plaintext KEY ''")

Here, we tell the IDE ���Treat this as plain text. Yes, yes, I know, it looks likeit should be SQL. And, yeah, I do not really know if you know what ���plain text��� is.Just skip any syntax validation on the string, please.���

(fortunately, the comment is shorter)

At least for now, these workarounds give you fine-grained ability to suppress SQL syntax warnings,in cases where Android Studio���s SQL parser either has bugs or is confused by extendedSQL syntax.

 •  0 comments  •  flag
Share on Twitter
Published on February 11, 2021 05:16
No comments have been added yet.