Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
6fec1b6
fix autonumbering locking
acwhite211 Sep 26, 2025
fe388a8
Merge branch 'main' into issue-6490-1
acwhite211 Oct 6, 2025
ccfed12
Lint code with ESLint and Prettier
acwhite211 Oct 6, 2025
04512f6
Merge branch 'main' into issue-6490-1
acwhite211 Oct 17, 2025
d612278
Lint code with ESLint and Prettier
acwhite211 Oct 17, 2025
e604dec
Merge branch 'main' into issue-6490-1
acwhite211 Oct 22, 2025
a95ad63
Lint code with ESLint and Prettier
acwhite211 Oct 22, 2025
494dcd1
change autonumbering locking naming key to use db_name and table_name
acwhite211 Oct 23, 2025
e222a02
try row level locking with django
acwhite211 Oct 23, 2025
f5160aa
Add missing autonumbering tables to django model
acwhite211 Oct 24, 2025
411ea24
implement lock_ge_range
acwhite211 Oct 24, 2025
f1dddc6
add db indexes to help autonumbering range locking
acwhite211 Oct 24, 2025
719de2f
Merge branch 'main' into issue-6490-1
acwhite211 Nov 3, 2025
bc815be
fix migration after merge
acwhite211 Nov 4, 2025
61ddb00
Merge branch 'main' into issue-6490-1
acwhite211 Nov 18, 2025
359c152
add PR comment links to lock_tables warning note
acwhite211 Nov 20, 2025
3c2437c
remove unneeded autonum tables
acwhite211 Nov 20, 2025
5effe3d
remove unused function get_tables_to_lock_strict
acwhite211 Nov 20, 2025
a47537e
add more composite indexes for autonumbering
acwhite211 Nov 25, 2025
a9a5ea8
fix migration issues
acwhite211 Dec 17, 2025
02ab2c3
Remove duplicate invoicenumber index
acwhite211 Dec 17, 2025
fb28674
Remove duplicate indexes from migration
acwhite211 Dec 17, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,6 @@ const containsSystemTables = (queryFieldSpec: QueryFieldSpec) => {
return Boolean(baseIsBlocked || pathHasBlockedSystem);
};


const hasHierarchyBaseTable = (queryFieldSpec: QueryFieldSpec) =>
Object.keys(schema.domainLevelIds).includes(
queryFieldSpec.baseTable.name.toLowerCase() as 'collection'
Expand Down
30 changes: 30 additions & 0 deletions specifyweb/specify/migrations/0001_initial.py
Original file line number Diff line number Diff line change
Expand Up @@ -5762,6 +5762,36 @@ class Migration(migrations.Migration):
'ordering': (),
},
),
migrations.CreateModel(
name='AutonumschColl',
fields=[
('collectionid', models.ForeignKey(db_column='CollectionID', on_delete=django.db.models.deletion.DO_NOTHING, primary_key=True, serialize=False, to='specify.collection')),
],
options={
'db_table': 'autonumsch_coll',
'managed': False,
},
),
migrations.CreateModel(
name='AutonumschDiv',
fields=[
('divisionid', models.ForeignKey(db_column='DivisionID', on_delete=django.db.models.deletion.DO_NOTHING, primary_key=True, serialize=False, to='specify.division')),
],
options={
'db_table': 'autonumsch_div',
'managed': False,
},
),
migrations.CreateModel(
name='AutonumschDsp',
fields=[
('disciplineid', models.ForeignKey(db_column='DisciplineID', on_delete=django.db.models.deletion.DO_NOTHING, primary_key=True, serialize=False, to='specify.discipline')),
],
options={
'db_table': 'autonumsch_dsp',
'managed': False,
},
),
migrations.CreateModel(
name='Author',
fields=[
Expand Down
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(just a note/consideration)
Very nice, glad we're considering some more indices here! 🏆

I would love to see other indices (like those proposed in Add missing field indexes (#7482)) if the benefit of adding them would outweight the cost, although that could definitely be a future PR.

I will warn that indexes can result in a performance loss for write, insert, and delete operations, as each index on a table needs to be maintained (i.e., the B-Tree or similar data structure updated).

In the case of Specify for example, this could slow down (non-negligibly or perhaps even significantly, depending on the index data structure and data being inserted/updated) WorkBench and BatchEdit operations along with common DataEntry operations.

If this is a fine trade-off (such as the case were there will be overall significantly more reads than write and the index is well-structured for the intended optimization), I say shoot for the stars 🚀

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ya, sounds good. I'm looking through the issue, and creating a separate PR for create those specific indexes. The difference for this PR, is that the indexes are always on two values (scoping_field, autonumbering_field). So far we added these two indexes:

operations = [
    migrations.AddIndex(
        model_name='accession',
        index=models.Index(fields=['division_id', 'accessionnumber'], name='AccScopeAccessionsnumberIDX'),
    ),
    migrations.AddIndex(
        model_name='collectionobject',
        index=models.Index(fields=['collectionmemberid', 'catalognumber'], name='ColObjScopeCatalognumberIDX'),
    ),
]

For this PR, I'm going through all the proposed indexes and picking out the ones that are common for autonumbering. Let me know if there are any specific ones you want to include?

Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
from django.db import migrations, models

class Migration(migrations.Migration):

dependencies = [
('specify', '0041_add_missing_schema_after_reorganization'),
]

operations = [
# accession, accessionnumber, division
migrations.AddIndex(
model_name='accession',
index=models.Index(fields=['division_id', 'accessionnumber'], name='DivAccessionNumberIDX'),
),
# collectionobject, catalognumber, collection
migrations.AddIndex(
model_name='collectionobject',
index=models.Index(fields=['collectionmemberid', 'catalognumber'], name='ColCatalogNumberIDX'),
),
# loan, discipline, loannumber
migrations.AddIndex(
model_name='loan',
index=models.Index(fields=['discipline', 'loannumber'], name='DispLoanNumberIDX'),
),

# borrow, invoicenumber, null
# migrations.AddIndex(
# model_name='borrow',
# index=models.Index(fields=['invoicenumber'], name='BorrowInvoiceNumberIDX'),
# ),

# exchangein, exchangeinnumber, division
migrations.AddIndex(
model_name='exchangein',
index=models.Index(fields=['division', 'exchangeinnumber'], name='DivExcInNumberIDX'),
),

# exchangeout, exchangeoutnumber, division
migrations.AddIndex(
model_name='exchangeout',
index=models.Index(fields=['division', 'exchangeoutnumber'], name='DivExcOutNumberIDX'),
),

# collectingevent, stationfieldnumber, discipline
migrations.AddIndex(
model_name='collectingevent',
index=models.Index(fields=['discipline', 'stationfieldnumber'], name='DispStationFieldNumIDX'),
),

# collection, regnumber, discipline
migrations.AddIndex(
model_name='collection',
index=models.Index(fields=['discipline', 'regnumber'], name='DispColRegNumberIDX'),
),

# collector, ordernumber, division
migrations.AddIndex(
model_name='collector',
index=models.Index(fields=['division', 'ordernumber'], name='DivCollectorOrderNumIDX'),
),

# discipline, regnumber, division
migrations.AddIndex(
model_name='discipline',
index=models.Index(fields=['division', 'regnumber'], name='DivDispRegNumberIDX'),
),

# disposal, disposalnumber, null
# migrations.AddIndex(
# model_name='disposal',
# index=models.Index(fields=['disposalnumber'], name='DisposalNumberIDX'),
# ),

# division, regnumber, institution
migrations.AddIndex(
model_name='division',
index=models.Index(fields=['institution', 'regnumber'], name='InstDivRegNumberIDX'),
),

# exsiccataitem, number, null
migrations.AddIndex(
model_name='exsiccataitem',
index=models.Index(fields=['number'], name='ExsiccataItemNumberIDX'),
),

# fieldnotebookpage, pagenumber, discipline
migrations.AddIndex(
model_name='fieldnotebookpage',
index=models.Index(fields=['discipline', 'pagenumber'], name='DispFNBPageNumIDX'),
),

# fieldnotebookpageset, ordernumber, discipline
migrations.AddIndex(
model_name='fieldnotebookpageset',
index=models.Index(fields=['discipline', 'ordernumber'], name='DispFNBPageSetNumIDX'),
),

# fundingagent, ordernumber, division
migrations.AddIndex(
model_name='fundingagent',
index=models.Index(fields=['division', 'ordernumber'], name='DivFundingAgentOrderNumIDX'),
),

# gift, giftnumber, discipline
migrations.AddIndex(
model_name='gift',
index=models.Index(fields=['discipline', 'giftnumber'], name='DispGiftNumberIDX'),
),

# groupperson, ordernumber, division
migrations.AddIndex(
model_name='groupperson',
index=models.Index(fields=['division', 'ordernumber'], name='DivGroupPersonOrderNumIDX'),
),

# permit, permitnumber, institution
migrations.AddIndex(
model_name='permit',
index=models.Index(fields=['institution', 'permitnumber'], name='InstPermitNumberIDX'),
),

# referencework, librarynumber, institution
migrations.AddIndex(
model_name='referencework',
index=models.Index(fields=['institution', 'librarynumber'], name='InstRefWorkLibNumIDX'),
),

# repositoryagreement, repositoryagreementnumber, division
migrations.AddIndex(
model_name='repositoryagreement',
index=models.Index(fields=['division', 'repositoryagreementnumber'], name='DivRepoAgreeNumIDX'),
),

# shipment, shipmentnumber, discipline
migrations.AddIndex(
model_name='shipment',
index=models.Index(fields=['discipline', 'shipmentnumber'], name='DispShipmentNumberIDX'),
),

# treatmentevent, treatmentnumber, division
migrations.AddIndex(
model_name='treatmentevent',
index=models.Index(fields=['division', 'treatmentnumber'], name='DivTreatmentNumberIDX'),
),
]
Loading