sequelize alter existing table with "ON DELETE CASCADE" - sqlite

I have existing tables with column 'endpointId' with "ON DELETE NO ACTION" and I want to alter column to change this to "ON DELETE CASCADE"
What I have tried is to do:
module.exports = {
up: async (queryInterface, Sequelize) => {
await queryInterface.sequelize.query("ALTER TABLE `Analyses` ALTER COLUMN `endpointId` INTEGER NOT NULL REFERENCES `Endpoints` (`id`) ON DELETE CASCADE ON UPDATE CASCADE");
},
down: async (queryInterface, Sequelize) => {
await queryInterface.sequelize.query("ALTER TABLE `Analyses` ALTER COLUMN `endpointId` INTEGER NOT NULL REFERENCES `Endpoints` (`id`) ON DELETE NO ACTION ON UPDATE CASCADE");
}
};
but getting error:
ERROR: SQLITE_ERROR: near "ALTER": syntax error
It seems I need to remove Constraint first, but I can't find any for the table. Is there a way to check constraint?
await queryInterface.removeConstraint('Analyses', '???');

Related

Why is this query forming an incorrect foreign key constraint in Knex/SQLite3?

The Goal
I am trying to make two tables, `users` and `clients`, wherein `clients` has a foreign key called `userId` that references the `id` primary key of `users`.
Shows the desired relationship between the tables users and clients
The Migrations
Users
exports.up = function(knex) {
return knex.schema
.createTable('users', function (table) {
table.increments().primary();
table.string('username').unique().notNullable();
table.string('email').unique().notNullable();
table.string('password').notNullable();
table.boolean('admin').notNullable().defaultTo(false);
});
};
Clients
I have tried a variety of different variations of this, which I will show here along with their results:
exports.up = function(knex) {
return knex.schema
.createTable('clients', function (table) {
table.increments().primary();
table.string('name').notNullable();
table.string('secret').notNullable();
table.integer('userId').unsigned().references("id").inTable("users").onDelete("CASCADE");
});
};
This resulted the successful creation of the database, however, the SQLite Viewer indicated that clients.id was somehow referencing a users.userId, as shown in the following image.
exports.up = function(knex) {
return knex.schema
.createTable('clients', function (table) {
table.increments().primary();
table.string('name').notNullable();
table.integer('userId').unsigned();
table.string('secret').notNullable();
table.foreign('userId').references("users.id").onDelete("CASCADE");
});
};
This produced the exact same result as the previous code.
What am I doing wrong?
Edit: An Additional Complicating Factor
I have tried swapping `userId` and `id` in the first attempt at making the clients table. While this did appear to work for the clients table, when I tried to do the same for a `codes` table, I encountered an error that seemed to indicate swapping the two wasn't doing what I hoped it would do. This is consistent with what I've seen in tutorials. I'm inclined to think I was closer to the correct answer at the beginning.
exports.up = function(knex) {
return knex.schema
.createTable('codes', function (table) {
table.string('value').notNullable();
table.string('redirectUri').notNullable();
table.integer('userId').unsigned();
table.integer('clientId').notNullable();
table.foreign('id').references("userId").inTable("users").onDelete("CASCADE");
});
};
Error: create table codes (value varchar(255) not null, redirectUri varchar(255) not null, userId integer, clientId integer not null, foreign key(id) references users(userId) on delete CASCADE) - SQLITE_ERROR: unknown column "id" in foreign key definition

DyamoDB put item with ConditionExpression instead of key

Since email is not the primary key, I need to check the uniqueness of a record based on the email field. It does not work. The user gets saved. Does DynamoDB not allow conditionExpression on another field instead of a key?
const params = {
TableName: process.env.tableName,
Item: user.toItem(),
ConditionExpression: "#email <> :email",
ExpressionAttributeNames: {
"#email": "email",
},
ExpressionAttributeValues: {
":email": body.email,
},
};
await docClient.put(params).promise();
The condition is valid, but what conditional puts prevent is overwriting records with the same primary key:
The PutItem operation overwrites an item with the same key (if it exists). If you want to avoid this, use a condition expression. This allows the write to proceed only if the item in question does not already have the same key.
To prevent duplicate emails, make it part of your table's primary key or manually check for uniquenes before writing to DynamoDB.

How to write this conditional request correctly MariaDB

I need to check if a book rating for specific book from specific person exists.
If it does update it, if it doesnt create it.
I am getting a whole bunch of wrong errors for 9th 10th.... 12th parameter missing while I count only 8
My mariaDB version is 10.5.8-MariaDB.
My code:
const createBookRate = async (userId, bookId, rate) => {
const sql = `
SELECT IF(EXISTS( SELECT * from rates WHERE rates.users_id=? AND rates.books_id=? ),
UPDATE rates SET rates.rate=? WHERE rates.users_id=? AND rates.books_id=?,
INSERT INTO rates(users_id, books_id, rate))
VALUE (?,?,?,?,?,?,?,?);
`
const { insertId } = await pool.query(sql, [userId, bookId, rate, userId, bookId, userId, bookId, rate])
const rateEntry = await getBookRate(insertId)
return rateEntry
}
You cannot perform an UPDATE or an INSERT inside the IF clause of a SELECT statement, those must be performed separately.
To perform this in a safe manner, use a transaction and first lock the selected row with SELECT ... FOR UPDATE, then either UPDATE or INSERT it and finally COMMIT the transaction.
If the table has a primary key, you can use INSERT ... ON DUPLICATE KEY UPDATE to either insert the row or update it, depending on whether it exists or not. This allows everything to be done in one step without having to first select the affected rows.

Can "PRAGMA foreign_keys=OFF" SQLite statement be used inside a TypeORM migration?

I'm using TypeORM (v0.2.18) with Node.js (v12.7.0) to perform migrations in my SQLite database.
This is my situation: I have a table named country and a table named workflow. I want to remove one of the columns, named name, of country but workflow references country through this column.
Playing with DB Browser for SQLite I could remove the column successfully with these statements:
PRAGMA foreign_keys=OFF;
CREATE TEMPORARY TABLE country_backup(id, createdAt, updatedAt, enabled, codeIso2);
INSERT INTO country_backup SELECT id, createdAt, updatedAt, enabled, codeIso2 FROM country;
DROP TABLE country;
CREATE TABLE country(id, createdAt, updatedAt, enabled, codeIso2);
INSERT INTO country SELECT id, createdAt, updatedAt, enabled, codeIso2 FROM country_backup;
DROP TABLE country_backup;
PRAGMA foreign_keys=ON;
Which I used in a TypeORM migration like this:
...
public async up(queryRunner: QueryRunner): Promise<any> {
await queryRunner.query("PRAGMA foreign_keys=OFF");
await queryRunner.query("CREATE TEMPORARY TABLE country_backup(id, createdAt, updatedAt, enabled, codeIso2)");
await queryRunner.query("INSERT INTO country_backup SELECT id, createdAt, updatedAt, enabled, codeIso2 FROM country");
await queryRunner.query("DROP TABLE country");
await queryRunner.query("CREATE TABLE country(id, createdAt, updatedAt, enabled, codeIso2)");
await queryRunner.query("INSERT INTO country SELECT id, createdAt, updatedAt, enabled, codeIso2 FROM country_backup");
await queryRunner.query("DROP TABLE country_backup");
await queryRunner.query("PRAGMA foreign_keys=ON");
}
...
But I get this error:
Error during migration run:
QueryFailedError: SQLITE_CONSTRAINT: FOREIGN KEY constraint failed
at new QueryFailedError (/.../api/src/error/QueryFailedError.ts:9:9)
at Statement.handler (/.../src/driver/sqlite/SqliteQueryRunner.ts:53:26)
at Statement.replacement (/.../api/node_modules/sqlite3/lib/trace.js:19:31)
at Statement.replacement (/.../api/node_modules/sqlite3/lib/trace.js:19:31) {
message: 'SQLITE_CONSTRAINT: FOREIGN KEY constraint failed',
errno: 19,
code: 'SQLITE_CONSTRAINT',
name: 'QueryFailedError',
query: 'DROP TABLE country',
parameters: []
}
Why did it work in DB Browser for SQLite but not with TypeORM? It's like it ignored the PRAGMA statement.
Based on this, I tried with both PRAGMA foreign_keys and PRAGMA legacy_alter_table (setting them OFF and ON (before any action) and ON and OFF (after any action), respectively).
I tried using the PRAGMA's both inside the up() function and outside it. Outside it means I put the statements before and after await typeOrmConnection.runMigrations() in my main.ts file, like await typeOrmConnection.query("PRAGMA foreign_keys=OFF").
The sqlite docs say that you can't set PRAGMA foreign_keys=off while executing multiple statements, so I tried this and got it work by separating the PRAGMA statements from the others.
A transaction has been started already for the query runner instance passed to the up() function. Therefore, end the existing transaction immediately, then use an outside-of-transaction query to turn off the checks, and then start another transaction.
Write the rest of your non-PRAGMA code within the new transaction.
Right before the end of the function, commit the inner transaction, then use a regular single-statement query to turn the key checks back on, and then start another transaction (so that there will be something to automatically close after up() runs, otherwise you get an error).
public async up(queryRunner: QueryRunner): Promise<any> {
await queryRunner.commitTransaction();
await queryRunner.query('PRAGMA foreign_keys=off');
await queryRunner.startTransaction();
// the rest of your queries
await queryRunner.commitTransaction();
await queryRunner.query('PRAGMA foreign_keys=on');
await queryRunner.startTransaction();
}

Ionic3 and SQLite - create table using property as table name inside query

I'm making an app using Ionic 3 and SQLite. I tried to create a table using a property as table name inside the query but it returns this error:
'sqlite3_prepare_v2 failure: near "(": syntax error'
Here's the code that I used:
onCreateTb() {
this.database.executeSql('CREATE TABLE IF NOT EXISTS (?) (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, skill TEXT, yearsOfExperience INTEGER)', [this.tableName])
.then(() => console.log('Ok'))
.catch(error => console.log(error));
}
In various articles about SQLite I saw the (?) marker on INSERT queries but never on CREATE TABLE queries.
How can I use a property as a table name?

Resources