0
Fork 0
mirror of https://github.com/withastro/astro.git synced 2025-04-07 23:41:43 -05:00

fix: correctly respect primary key on INSERT INTO

This commit is contained in:
bholmesdev 2024-02-07 18:15:21 -05:00
parent 92d7d84e6b
commit 3850637e19
2 changed files with 76 additions and 5 deletions

View file

@ -158,17 +158,17 @@ export async function getCollectionChangeQueries({
confirmations.push(reasonMsgs[reason]);
}
const addedPrimaryKey = Object.entries(added).find(([, field]) => hasPrimaryKey(field));
const droppedPrimaryKey = Object.entries(dropped).find(([, field]) => hasPrimaryKey(field));
const updatedPrimaryKey = Object.entries(updated).find(
([, field]) => hasPrimaryKey(field.old) || hasPrimaryKey(field.new)
const primaryKeyExists = Object.entries(newCollection.fields).find(([, field]) =>
hasPrimaryKey(field)
);
const droppedPrimaryKey = Object.entries(dropped).find(([, field]) => hasPrimaryKey(field));
const recreateTableQueries = getRecreateTableQueries({
collectionName,
newCollection,
added,
hasDataLoss: dataLossCheck.dataLoss,
migrateHiddenPrimaryKey: !addedPrimaryKey && !droppedPrimaryKey && !updatedPrimaryKey,
migrateHiddenPrimaryKey: !primaryKeyExists && !droppedPrimaryKey,
});
queries.push(...recreateTableQueries, ...getCreateIndexQueries(collectionName, newCollection));
return { queries, confirmations };

View file

@ -112,6 +112,35 @@ describe('field queries', () => {
expect(queries).to.deep.equal([]);
});
it('should respect user primary key without adding a hidden id', async () => {
const user = collectionSchema.parse({
...userInitial,
fields: {
...userInitial.fields,
id: field.number({ primaryKey: true }),
},
});
const userFinal = collectionSchema.parse({
...user,
fields: {
...user.fields,
name: field.text({ unique: true, optional: true }),
},
});
const { queries } = await userChangeQueries(user, userFinal);
expect(queries[0]).to.not.be.undefined;
const tempTableName = getTempTableName(queries[0]);
expect(queries).to.deep.equal([
`CREATE TABLE \"${tempTableName}\" (\"name\" text UNIQUE, \"age\" integer NOT NULL, \"email\" text NOT NULL UNIQUE, \"mi\" text, \"id\" integer PRIMARY KEY)`,
`INSERT INTO \"${tempTableName}\" (\"name\", \"age\", \"email\", \"mi\", \"id\") SELECT \"name\", \"age\", \"email\", \"mi\", \"id\" FROM \"Users\"`,
'DROP TABLE "Users"',
`ALTER TABLE "${tempTableName}" RENAME TO "Users"`,
]);
});
describe('ALTER RENAME COLUMN', () => {
it('when renaming a field', async () => {
const userFinal = {
@ -170,6 +199,48 @@ describe('field queries', () => {
});
describe('Lossless table recreate', () => {
it('when adding a primary key', async () => {
const userFinal = {
...userInitial,
fields: {
...userInitial.fields,
id: field.number({ primaryKey: true }),
},
};
const { queries } = await userChangeQueries(userInitial, userFinal);
expect(queries[0]).to.not.be.undefined;
const tempTableName = getTempTableName(queries[0]);
expect(queries).to.deep.equal([
`CREATE TABLE \"${tempTableName}\" (\"name\" text NOT NULL, \"age\" integer NOT NULL, \"email\" text NOT NULL UNIQUE, \"mi\" text, \"id\" integer PRIMARY KEY)`,
`INSERT INTO \"${tempTableName}\" (\"name\", \"age\", \"email\", \"mi\") SELECT \"name\", \"age\", \"email\", \"mi\" FROM \"Users\"`,
'DROP TABLE "Users"',
`ALTER TABLE "${tempTableName}" RENAME TO "Users"`,
]);
});
it('when dropping a primary key', async () => {
const user = {
...userInitial,
fields: {
...userInitial.fields,
id: field.number({ primaryKey: true }),
},
};
const { queries } = await userChangeQueries(user, userInitial);
expect(queries[0]).to.not.be.undefined;
const tempTableName = getTempTableName(queries[0]);
expect(queries).to.deep.equal([
`CREATE TABLE \"${tempTableName}\" (_id INTEGER PRIMARY KEY, \"name\" text NOT NULL, \"age\" integer NOT NULL, \"email\" text NOT NULL UNIQUE, \"mi\" text)`,
`INSERT INTO \"${tempTableName}\" (\"name\", \"age\", \"email\", \"mi\") SELECT \"name\", \"age\", \"email\", \"mi\" FROM \"Users\"`,
'DROP TABLE "Users"',
`ALTER TABLE "${tempTableName}" RENAME TO "Users"`,
]);
});
it('when adding an optional unique field', async () => {
const userFinal = {
...userInitial,