<commit_before>const debug = require('@tryghost/debug')('test:dbUtils');

// Utility Packages
const fs = require('fs-extra');
const Promise = require('bluebird');
const KnexMigrator = require('knex-migrator');
const knexMigrator = new KnexMigrator();
const DatabaseInfo = require('@tryghost/database-info');

// Ghost Internals
const config = require('../../core/shared/config');
const db = require('../../core/server/data/db');
const schema = require('../../core/server/data/schema').tables;
const schemaTables = Object.keys(schema);

// Other Test Utilities
const urlServiceUtils = require('./url-service-utils');

const dbHash = Date.now();

module.exports.isMySQL = () => {
    return DatabaseInfo.isMySQL(db.knex);
};

module.exports.isSQLite = () => {
    return DatabaseInfo.isSQLite(db.knex);
};

module.exports.reset = async ({truncate} = {truncate: false}) => {
    // Only run this copy in CI until it gets fleshed out
    if (process.env.CI && module.exports.isSQLite()) {
        const filename = config.get('database:connection:filename');
        const filenameOrig = `${filename}.${dbHash}-orig`;

        const dbExists = await fs.pathExists(filenameOrig);

        if (dbExists) {
            await db.knex.destroy();
            await fs.copyFile(filenameOrig, filename);
        } else {
            await knexMigrator.reset({force: true});

            // Do a full database initialisation
            await knexMigrator.init();

            await fs.copyFile(filename, filenameOrig);
        }
    } else {
        if (truncate) {
            // Perform a fast reset by tearing down all the tables and
            // inserting the fixtures
            await module.exports.teardown();
            await knexMigrator.init({only: 2});
        } else {
            // Do a full database reset + initialisation
            await knexMigrator.reset({force: true});
            await knexMigrator.init();
        }
    }
};

module.exports.initData = async () => {
    await knexMigrator.init();
    await urlServiceUtils.reset();
    await urlServiceUtils.init();
    await urlServiceUtils.isFinished();
};

module.exports.truncate = async (tableName) => {
    if (module.exports.isSQLite()) {
        const [foreignKeysEnabled] = await db.knex.raw('PRAGMA foreign_keys;');
        if (foreignKeysEnabled.foreign_keys) {
            await db.knex.raw('PRAGMA foreign_keys = OFF;');
        }
        await db.knex(tableName).truncate();
        if (foreignKeysEnabled.foreign_keys) {
            await db.knex.raw('PRAGMA foreign_keys = ON;');
        }
        return;
    }

    await db.knex.raw('SET FOREIGN_KEY_CHECKS=0;');
    await db.knex(tableName).truncate();
    await db.knex.raw('SET FOREIGN_KEY_CHECKS=1;');
};

// we must always try to delete all tables
module.exports.clearData = async () => {
    debug('Database reset');
    await knexMigrator.reset({force: true});
    urlServiceUtils.reset();
};

/**
 * Has to run in a transaction for MySQL, otherwise the foreign key check does not work.
 * Sqlite3 has no truncate command.
 */
module.exports.teardown = () => {
    debug('Database teardown');
    urlServiceUtils.reset();

    const tables = schemaTables.concat(['migrations']);

    if (module.exports.isSQLite()) {
        return Promise
            .mapSeries(tables, function createTable(table) {
                return (async function () {
                    const [foreignKeysEnabled] = await db.knex.raw('PRAGMA foreign_keys;');
                    if (foreignKeysEnabled.foreign_keys) {
                        await db.knex.raw('PRAGMA foreign_keys = OFF;');
                    }
                    await db.knex.raw('DELETE FROM ' + table + ';');
                    if (foreignKeysEnabled.foreign_keys) {
                        await db.knex.raw('PRAGMA foreign_keys = ON;');
                    }
                })();
            })
            .catch(function (err) {
                // CASE: table does not exist
                if (err.errno === 1) {
                    return Promise.resolve();
                }

                throw err;
            })
            .finally(() => {
                debug('Database teardown end');
            });
    }

    return db.knex.transaction(function (trx) {
        return db.knex.raw('SET FOREIGN_KEY_CHECKS=0;').transacting(trx)
            .then(function () {
                return Promise
                    .each(tables, function createTable(table) {
                        return db.knex.raw('TRUNCATE ' + table + ';').transacting(trx);
                    });
            })
            .then(function () {
                return db.knex.raw('SET FOREIGN_KEY_CHECKS=1;').transacting(trx);
            })
            .catch(function (err) {
                // CASE: table does not exist
                if (err.errno === 1146) {
                    return Promise.resolve();
                }

                throw err;
            });
    });
};<commit_msg>Fixed error handling on db truncate in tests<commit_after>const debug = require('@tryghost/debug')('test:dbUtils');

// Utility Packages
const fs = require('fs-extra');
const Promise = require('bluebird');
const KnexMigrator = require('knex-migrator');
const knexMigrator = new KnexMigrator();
const DatabaseInfo = require('@tryghost/database-info');

// Ghost Internals
const config = require('../../core/shared/config');
const db = require('../../core/server/data/db');
const schema = require('../../core/server/data/schema').tables;
const schemaTables = Object.keys(schema);

// Other Test Utilities
const urlServiceUtils = require('./url-service-utils');

const dbHash = Date.now();

module.exports.isMySQL = () => {
    return DatabaseInfo.isMySQL(db.knex);
};

module.exports.isSQLite = () => {
    return DatabaseInfo.isSQLite(db.knex);
};

module.exports.reset = async ({truncate} = {truncate: false}) => {
    // Only run this copy in CI until it gets fleshed out
    if (process.env.CI && module.exports.isSQLite()) {
        const filename = config.get('database:connection:filename');
        const filenameOrig = `${filename}.${dbHash}-orig`;

        const dbExists = await fs.pathExists(filenameOrig);

        if (dbExists) {
            await db.knex.destroy();
            await fs.copyFile(filenameOrig, filename);
        } else {
            await knexMigrator.reset({force: true});

            // Do a full database initialisation
            await knexMigrator.init();

            await fs.copyFile(filename, filenameOrig);
        }
    } else {
        if (truncate) {
            // Perform a fast reset by tearing down all the tables and inserting the fixtures
            try {
                await module.exports.teardown();
                await knexMigrator.init({only: 2});
            } catch (err) {
                // If it fails, try a normal restore
                await knexMigrator.reset({force: true});
                await knexMigrator.init();
            }
        } else {
            // Do a full database reset + initialisation
            await knexMigrator.reset({force: true});
            await knexMigrator.init();
        }
    }
};

module.exports.initData = async () => {
    await knexMigrator.init();
    await urlServiceUtils.reset();
    await urlServiceUtils.init();
    await urlServiceUtils.isFinished();
};

module.exports.truncate = async (tableName) => {
    if (module.exports.isSQLite()) {
        const [foreignKeysEnabled] = await db.knex.raw('PRAGMA foreign_keys;');
        if (foreignKeysEnabled.foreign_keys) {
            await db.knex.raw('PRAGMA foreign_keys = OFF;');
        }
        await db.knex(tableName).truncate();
        if (foreignKeysEnabled.foreign_keys) {
            await db.knex.raw('PRAGMA foreign_keys = ON;');
        }
        return;
    }

    await db.knex.raw('SET FOREIGN_KEY_CHECKS=0;');
    await db.knex(tableName).truncate();
    await db.knex.raw('SET FOREIGN_KEY_CHECKS=1;');
};

// we must always try to delete all tables
module.exports.clearData = async () => {
    debug('Database reset');
    await knexMigrator.reset({force: true});
    urlServiceUtils.reset();
};

/**
 * Has to run in a transaction for MySQL, otherwise the foreign key check does not work.
 * Sqlite3 has no truncate command.
 */
module.exports.teardown = () => {
    debug('Database teardown');
    urlServiceUtils.reset();

    const tables = schemaTables.concat(['migrations']);

    if (module.exports.isSQLite()) {
        return Promise
            .mapSeries(tables, function createTable(table) {
                return (async function () {
                    const [foreignKeysEnabled] = await db.knex.raw('PRAGMA foreign_keys;');
                    if (foreignKeysEnabled.foreign_keys) {
                        await db.knex.raw('PRAGMA foreign_keys = OFF;');
                    }
                    await db.knex.raw('DELETE FROM ' + table + ';');
                    if (foreignKeysEnabled.foreign_keys) {
                        await db.knex.raw('PRAGMA foreign_keys = ON;');
                    }
                })();
            })
            .catch(function (err) {
                // CASE: table does not exist
                if (err.errno === 1) {
                    return Promise.resolve();
                }

                throw err;
            })
            .finally(() => {
                debug('Database teardown end');
            });
    }

    return db.knex.transaction(function (trx) {
        return db.knex.raw('SET FOREIGN_KEY_CHECKS=0;').transacting(trx)
            .then(function () {
                return Promise
                    .each(tables, function createTable(table) {
                        return db.knex.raw('TRUNCATE ' + table + ';').transacting(trx);
                    });
            })
            .then(function () {
                return db.knex.raw('SET FOREIGN_KEY_CHECKS=1;').transacting(trx);
            })
            .catch(function (err) {
                // CASE: table does not exist || DB does not exist
                // If the table or DB are not present, we can safely ignore
                if (err.errno === 1146 || err.errno === 1049) {
                    return Promise.resolve();
                }

                throw err;
            })
            .finally(() => {
                debug('Database teardown end');
            });
    })
        .catch(function (err) {
            // CASE: table does not exist || DB does not exist
            // If the table or DB are not present, we can safely ignore
            if (err.errno === 1146 || err.errno === 1049) {
                return Promise.resolve();
            }

            throw err;
        });
};
{'fraction_non_alphanumeric': 0.1318342974435529, 'fraction_numerical': 0.003172233625676432, 'mean_word_length': 1.9151482186565134, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 20, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7212099', 'n_tokens_mistral': 3109, 'n_tokens_neox': 3005, 'n_words': 684}