I have a need for an auto-incrementing integer field on a data table. Anyone got a nice way of doing that?
I would also very much like one of those. I havenât yet found a reliable way to do it.
EDIT - donât do this - see @meredydd 's answer elsewhere using transactions.
Got a feeling this is not what youâre looking for, but for the sake of typing something âŚ
I have some code somewhere for this, but basically what I did was :
- search, ordered by your id field descending and returning just the [0] record to get the biggest number so far.
- add 1 to that value
- use it in your add_row() call
If your app is seriously multi-user then you may need to lock the table first (store a random number in a lock table and make sure you can read back your number confirming itâs you that has the lock) else you might have a race.
(edit) - my answer doesnât question the reasoning for doing this - see @p.colbert 's answer below for caveats to this method.
Thatâs pretty much what I had in mind, but it felt dirty!!
Iâm sure Anvil Central will have a better way, but it kinda works.
I was also wondering about using a sequence generator, but it would still have to do something similar when the app starts.
If your intent is simply to give each row a unique id, it already has one. See âRow IDsâ in https://anvil.works/doc/#-div-id-data_tables_api-using-data-tables-in-python-div-
Otherwise, a contingency you may want to consider: will you ever have to delete the record that has the largest number? (This need not be part of the design. It could just as easily be due to a bug, or a GDPR request.)
If so, then you will end up reusing a sequence number. This can sometimes be a bad thing (e.g., if that number is referenced from somewhere else).
If itâs a bad thing, then you might use @david.wylieâs lock table approach. E.g., also store your largest sequence number in that table. While you have it locked, you can increment its sequence number, and stamp other record(s) with that new number.
Itâs not just uniqueness that I need, itâs a contiguous sequence of integers.
Iâm looking at holding a ânext sequence numberâ in a separate table, with a lock, so that I donât have to query the entire history each time looking for the max value.
Eek. No need for any of these shenanigans! Just use a transaction:
# Assume there's a table called 'Counter' with a single column ('value')
# and a single row:
@tables.in_transaction
def get_next_value_in_sequence():
row = app_tables.counter.get()
row['value'] += 1
return row['value']
Anvilâs transactions are fully serialisable, and @tables.in_transaction
automatically retries on conflict, so this function will produce a steady continuous sequence.
I knew theyâd have a better way
@meredydd Ha! Iâve just been playing with exactly that to see if it behaves as I was hoping. Youâve saved me a job!
@meredydd - can you move your answer up to underneath the question? Donât want anyone looking at my nonsense before seeing your answer