Repository navigation
sql-storage-adapter v0.7.16
·
153 commits
to master
since this release
Fixed
SupabaseAdapterwithenableCache()on never answers a row as it stood before one of its own writes.getandallkept each answer by statement and parameters, and no write cleared them, so a row read, then changed throughrun,exec,transactionorbatchWrite, came back from the cache unchanged. They also kept the answer of a statement that writes:get('INSERT ... RETURNING id', params)ran once, and the second call answered the first row without inserting, andget('SELECT bump(?)', params), whose function writes, did the same. The cache now holds the answers ofSELECTs alone (a statement whose first word, past white space and comments, isSELECT), and of those only the ones that wrote nothing: aSELECTthe cache does not hold runs once, in a transaction of its own, and its answer is kept only when PostgreSQL gave that transaction no ID, which PostgreSQL gives a transaction when it first writes. That check readspg_current_xact_id_if_assigned(), so the cache needs PostgreSQL 13 or later. Every statement that writes and every transaction clears the cache when it ends, and a read that a write orclearCache()overtook keeps nothing. A string of several statements counts as a write: aCOMMITin it ended the cache's transaction, and anUPDATEafter it committed in one of its own, which the check could not see. The key of an answer names its call, sogetandallof one statement no longer answer each other's row or list, and it writes each parameter as pg binds it. It wrote them as JSON: a bigint parameter threw (JSON.stringifycannot write one) before the statement reached the database, a statement bound to NaN answered the row kept for null, one bound to a Date, from this realm or another, answered the row kept for the Date's ISO text, which pg binds as other text (local time with its offset), one bound to bytes and one bound to an object JSON writes alike ({ type: 'Buffer', data: [1] }) answered each other's row, two objects that pg binds through their owntoPostgresshared a key whenever JSON wrote them alike, as it writes any two whose state is private, and text spelling a Date's key (U+0000, then the Date's tag and time), which PostgreSQL refuses, answered the row kept for that Date. ASELECTbound to an object with atoPostgresof its own, or to text holding U+0000, now runs each time it is asked. A hit answered the kept row or list itself, and the first caller got it too, so a caller that changed what it was given changed what the cache answered next; the cache now keeps a copy and answers a copy, with each Date and Buffer copied as itself, and keeps no answer holding a value with no faithful copy, such as an interval, which pg parses to an object of its own. A write through another adapter, pool or process, an effect that writes no row, such aspg_notify()or an advisory lock, and aSELECTwhose answer changes from one call to the next by itself, such as one that callsrandom(),now()ornextval(), can still answer from the cache untilclearCache(); run a statement wanted for its effect throughrun, or begin it with a word other thanSELECT, such asVALUES (nextval('ids')).S3StorageProvider.list(#64) answers every key under the prefix: it sendsListObjectsV2again with each page'sNextContinuationTokenuntil a page is not truncated. It answered the first page alone.