Merge pull request #13160 from darthaud/feat/add-support-to-mysql
Feat: Added support to mysql on some raw queries
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
---
|
||||
'@backstage/backend-tasks': patch
|
||||
'@backstage/plugin-catalog-backend': patch
|
||||
---
|
||||
|
||||
Added support to mysql on some raw queries
|
||||
@@ -292,14 +292,21 @@ export class TaskWorker {
|
||||
seconds: dt,
|
||||
})}`,
|
||||
);
|
||||
nextRun = this.knex.client.config.client.includes('sqlite3')
|
||||
? this.knex.raw(
|
||||
`max(datetime(next_run_start_at, ?), datetime('now'))`,
|
||||
[`+${dt} seconds`],
|
||||
)
|
||||
: this.knex.raw(
|
||||
`greatest(next_run_start_at + interval '${dt} seconds', now())`,
|
||||
);
|
||||
|
||||
if (this.knex.client.config.client.includes('sqlite3')) {
|
||||
nextRun = this.knex.raw(
|
||||
`max(datetime(next_run_start_at, ?), datetime('now'))`,
|
||||
[`+${dt} seconds`],
|
||||
);
|
||||
} else if (this.knex.client.config.client.includes('mysql')) {
|
||||
nextRun = this.knex.raw(
|
||||
`greatest(next_run_start_at + interval ${dt} second, now())`,
|
||||
);
|
||||
} else {
|
||||
nextRun = this.knex.raw(
|
||||
`greatest(next_run_start_at + interval '${dt} seconds', now())`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const rows = await this.knex<DbTasksRow>(DB_TASKS_TABLE)
|
||||
|
||||
@@ -14,9 +14,16 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import knexFactory, { Knex } from 'knex';
|
||||
import { Duration } from 'luxon';
|
||||
import { AbortController } from 'node-abort-controller';
|
||||
import { delegateAbortController, sleep, validateId } from './util';
|
||||
import { delegateAbortController, nowPlus, sleep, validateId } from './util';
|
||||
|
||||
class KnexBuilder {
|
||||
public build(client: string): Knex {
|
||||
return knexFactory({ client });
|
||||
}
|
||||
}
|
||||
|
||||
describe('util', () => {
|
||||
describe('validateId', () => {
|
||||
@@ -73,4 +80,35 @@ describe('util', () => {
|
||||
expect(child.signal.aborted).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('nowPlus', () => {
|
||||
describe('without duration', () => {
|
||||
const databases = [
|
||||
{ client: 'sqlite3', expected: 'CURRENT_TIMESTAMP' },
|
||||
{ client: 'mysql2', expected: 'CURRENT_TIMESTAMP' },
|
||||
{ client: 'pg', expected: 'CURRENT_TIMESTAMP' },
|
||||
];
|
||||
|
||||
it.each(databases)('for client $client', ({ client, expected }) => {
|
||||
const knex = new KnexBuilder().build(client);
|
||||
const result = nowPlus(undefined, knex);
|
||||
|
||||
expect(result.toString()).toBe(expected);
|
||||
});
|
||||
});
|
||||
describe('With duration', () => {
|
||||
const databases = [
|
||||
{ client: 'sqlite3', expected: "datetime('now', '20 seconds')" },
|
||||
{ client: 'mysql2', expected: 'now() + interval 20 second' },
|
||||
{ client: 'pg', expected: "now() + interval '20 seconds'" },
|
||||
];
|
||||
it.each(databases)('for client $client', ({ client, expected }) => {
|
||||
const duration = Duration.fromObject({ seconds: 20 });
|
||||
const knex = new KnexBuilder().build(client);
|
||||
const result = nowPlus(duration, knex);
|
||||
|
||||
expect(result.toString()).toBe(expected);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -38,9 +38,16 @@ export function nowPlus(duration: Duration | undefined, knex: Knex) {
|
||||
if (!seconds) {
|
||||
return knex.fn.now();
|
||||
}
|
||||
return knex.client.config.client.includes('sqlite3')
|
||||
? knex.raw(`datetime('now', ?)`, [`${seconds} seconds`])
|
||||
: knex.raw(`now() + interval '${seconds} seconds'`);
|
||||
|
||||
if (knex.client.config.client.includes('sqlite3')) {
|
||||
return knex.raw(`datetime('now', ?)`, [`${seconds} seconds`]);
|
||||
}
|
||||
|
||||
if (knex.client.config.client.includes('mysql')) {
|
||||
return knex.raw(`now() + interval ${seconds} second`);
|
||||
}
|
||||
|
||||
return knex.raw(`now() + interval '${seconds} seconds'`);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -113,7 +113,10 @@ export class DefaultProcessingDatabase implements ProcessingDatabase {
|
||||
|
||||
// Delete old relations
|
||||
let previousRelationRows: DbRelationsRow[];
|
||||
if (tx.client.config.client.includes('sqlite3')) {
|
||||
if (
|
||||
tx.client.config.client.includes('sqlite3') ||
|
||||
tx.client.config.client.includes('mysql')
|
||||
) {
|
||||
previousRelationRows = await tx<DbRelationsRow>('relations')
|
||||
.select('*')
|
||||
.where({ originating_entity_id: id });
|
||||
@@ -201,6 +204,13 @@ export class DefaultProcessingDatabase implements ProcessingDatabase {
|
||||
|
||||
if (toRemove.length) {
|
||||
let removedCount = 0;
|
||||
const rootId = () => {
|
||||
if (tx.client.config.client.includes('mysql')) {
|
||||
return tx.raw('CAST(NULL as UNSIGNED INT)', []);
|
||||
}
|
||||
|
||||
return tx.raw('CAST(NULL as INT)', []);
|
||||
};
|
||||
for (const refs of lodash.chunk(toRemove, 1000)) {
|
||||
/*
|
||||
WITH RECURSIVE
|
||||
@@ -266,7 +276,7 @@ export class DefaultProcessingDatabase implements ProcessingDatabase {
|
||||
.withRecursive('ancestors', function ancestors(outer) {
|
||||
return outer
|
||||
.select({
|
||||
root_id: tx.raw('CAST(NULL as INT)', []),
|
||||
root_id: rootId(),
|
||||
via_entity_ref: 'entity_ref',
|
||||
to_entity_ref: 'entity_ref',
|
||||
})
|
||||
@@ -435,15 +445,26 @@ export class DefaultProcessingDatabase implements ProcessingDatabase {
|
||||
.orderBy('next_update_at', 'asc');
|
||||
|
||||
const interval = this.options.refreshInterval();
|
||||
|
||||
const nextUpdateAt = (refreshInterval: number) => {
|
||||
if (tx.client.config.client.includes('sqlite3')) {
|
||||
return tx.raw(`datetime('now', ?)`, [`${refreshInterval} seconds`]);
|
||||
}
|
||||
|
||||
if (tx.client.config.client.includes('mysql')) {
|
||||
return tx.raw(`now() + interval ${refreshInterval} second`);
|
||||
}
|
||||
|
||||
return tx.raw(`now() + interval '${refreshInterval} seconds'`);
|
||||
};
|
||||
|
||||
await tx<DbRefreshStateRow>('refresh_state')
|
||||
.whereIn(
|
||||
'entity_ref',
|
||||
items.map(i => i.entity_ref),
|
||||
)
|
||||
.update({
|
||||
next_update_at: tx.client.config.client.includes('sqlite3')
|
||||
? tx.raw(`datetime('now', ?)`, [`${interval} seconds`])
|
||||
: tx.raw(`now() + interval '${interval} seconds'`),
|
||||
next_update_at: nextUpdateAt(interval),
|
||||
});
|
||||
|
||||
return {
|
||||
|
||||
Reference in New Issue
Block a user