Bug / Integer primary key conflict should upsert #60
Bug / Integer primary key conflict should upsert #60
Conversation
Need to put a function on here to find this implicit constraint, then feed that back to the InsertHelper. Due to all the static functions I can't easily decouple and make that one pass before this one...
…ry key. Implementation copied across from the workaround I put on CCleaner and hope to soon remove.
… code just introduced
Can one of the admins review this PR? |
final Cursor pragmas = db.rawQuery(String.format(PRGAMA_INDEX_LIST, table), null); | ||
while (pragmas.moveToNext()) { | ||
int isUnique = pragmas.getInt(2); | ||
final Cursor indices = queryIndexListForTable(table, db); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You don't want to fix it in the deprecated version?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's deprecated... so, no? If someone updated the lib to get the fix, they could switch to using the non-deprecated version.
💯 what about adding a demo of an upsert? Another PR to split the noise probably |
@@ -1,2 +1,4 @@ | |||
CREATE TABLE 'parents' (_id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT UNIQUE, description TEXT, latitude REAL, longitude REAL, createdAt INTEGER); | |||
CREATE TABLE 'childs' (_id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, parent_id INTEGER NOT NULL, FOREIGN KEY(parent_id) REFERENCES parent(_id)); | |||
-- This table intentionally has no Foreign Keys, no UNIQUE fields, no indexes, apart from the implicit index from the INTEGER PRIMARY KEY. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
@blundell the demos seem kind of like low-grade tests - i.e. it just runs a bunch of stuff in onCreate while pointing out that no-one should do that, so I figured well expressed tests would demonstrate it better. Ah, admittedly I think it was demo-simple I looked at. Perhaps the other is better. I'd honestly ditch demo-simple in favour of nicely self-documenting tests. I might look at adding a demo to the demo-extended thing, if I can see a meaningful way to show it. But yeah, as you said, another PR... |
List<String> tables = getTables(db); | ||
List<String> foreignTables = new ArrayList<String>(5); | ||
String name; | ||
String tableName; | ||
while (cur.moveToNext()) { | ||
name = cur.getString(cur.getColumnIndexOrThrow("name")); | ||
name = cur.getString(cur.getColumnIndexOrThrow(COLUMN_NAME)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
Looks legit 👍 |
2 👍 = in my book |
Problem
InsertHelper claims it will perform an "upsert" - that is, update if present, insert if not - but this only works for tables with explicitly defined uniqueness constraints that will result in explicit indexes.
There is a common pattern of usage with SQLite to use a synthetic primary key column named
_id
, and for that column to be declared as anINTEGER PRIMARY KEY
. As per theSQLite docs
:When this happens, there will not be an explicit unique index created for this column. None is needed; it is an alias for the
ROWID
, which is inherently unique and faster than any index. In the case that this is the only thing constrained to be unique in a table, the library fails to detect this constraint and thus does not switch to an update. It instead attempts an insert, which fails.Solution
Functionality has been added to DbUtils to detect an
INTEGER PRIMARY KEY
on a table, and if found, to add this to the list of constraints it will find for a table. With the implicit constraint made apparent, the library performs correctly.Tests