exports.up = knex => Promise.resolve() .then(() => knex.schema.createTable('countries', (table) => { table.string('alpha2', 2) .unique() .primary(); table.string('alpha3', 3) .unique(); table.string('name') .notNullable(); table.string('alias'); table.integer('code', 3); table.string('nationality'); table.integer('priority', 2) .defaultTo(0); })) .then(() => knex.schema.createTable('media', (table) => { table.increments('id', 16); table.string('path'); table.string('thumbnail'); table.integer('index'); table.string('mime'); table.string('hash'); table.integer('size', 12); table.integer('quality', 6); table.integer('width', 6); table.integer('height', 6); table.float('entropy'); table.text('comment'); table.string('scraper', 32); table.string('copyright', 100); table.string('source', 1000); table.unique('hash'); table.unique('source'); table.datetime('created_at') .defaultTo(knex.fn.now()); })) .then(() => knex.schema.createTable('tags_groups', (table) => { table.increments('id', 12); table.string('name', 32); table.text('description'); table.string('slug', 32) .unique(); table.datetime('created_at') .defaultTo(knex.fn.now()); })) .then(() => knex.schema.createTable('tags', (table) => { table.increments('id', 12); table.string('name'); table.text('description'); table.integer('priority', 2) .defaultTo(0); table.integer('group_id', 12) .references('id') .inTable('tags_groups'); table.integer('alias_for', 12) .references('id') .inTable('tags'); table.string('slug', 32) .unique(); table.datetime('created_at') .defaultTo(knex.fn.now()); })) .then(() => knex.schema.createTable('tags_posters', (table) => { table.integer('tag_id', 12) .notNullable() .references('id') .inTable('tags'); table.integer('media_id', 16) .notNullable() .references('id') .inTable('media'); table.unique('tag_id'); })) .then(() => knex.schema.createTable('tags_photos', (table) => { table.integer('tag_id', 12) .notNullable() .references('id') .inTable('tags'); table.integer('media_id', 16) .notNullable() .references('id') .inTable('media'); table.unique(['tag_id', 'media_id']); })) .then(() => knex.schema.createTable('networks', (table) => { table.increments('id', 12); table.string('name'); table.string('url'); table.text('description'); table.json('parameters'); table.integer('parent_id', 12) .references('id') .inTable('networks'); table.string('slug', 32) .unique(); table.datetime('created_at') .defaultTo(knex.fn.now()); })) .then(() => knex.schema.createTable('networks_social', (table) => { table.increments('id', 16); table.string('url'); table.string('platform'); table.integer('network_id', 12) .notNullable() .references('id') .inTable('networks'); table.unique(['url', 'network_id']); table.datetime('created_at') .defaultTo(knex.fn.now()); })) .then(() => knex.schema.createTable('sites', (table) => { table.increments('id', 12); table.integer('network_id', 12) .notNullable() .references('id') .inTable('networks'); table.string('name'); table.string('url'); table.text('description'); table.json('parameters'); table.integer('priority', 3) .defaultTo(0); table.boolean('show') .defaultTo(true); table.boolean('scrape') .defaultTo(true); table.string('slug', 32) .unique(); table.datetime('created_at') .defaultTo(knex.fn.now()); })) .then(() => knex.schema.createTable('sites_tags', (table) => { table.integer('tag_id', 12) .notNullable() .references('id') .inTable('tags'); table.integer('site_id', 12) .notNullable() .references('id') .inTable('sites'); table.boolean('inherit') .defaultTo(false); table.unique(['tag_id', 'site_id']); })) .then(() => knex.schema.createTable('sites_social', (table) => { table.increments('id', 16); table.string('url'); table.string('platform'); table.integer('site_id', 12) .notNullable() .references('id') .inTable('sites'); table.unique(['url', 'site_id']); table.datetime('created_at') .defaultTo(knex.fn.now()); })) .then(() => knex.schema.createTable('studios', (table) => { table.increments('id', 12); table.integer('network_id', 12) .notNullable() .references('id') .inTable('networks'); table.string('name'); table.string('url'); table.text('description'); table.string('slug', 32) .unique(); table.datetime('created_at') .defaultTo(knex.fn.now()); })) .then(() => knex.schema.createTable('actors', (table) => { table.increments('id', 12); table.string('name') .unique() .notNullable(); table.date('birthdate'); table.string('gender', 18); table.text('description'); table.string('birth_city'); table.string('birth_state'); table.string('birth_country_alpha2', 2) .references('alpha2') .inTable('countries'); table.string('residence_city'); table.string('residence_state'); table.string('residence_country_alpha2', 2) .references('alpha2') .inTable('countries'); table.string('ethnicity'); table.string('bust', 10); table.integer('waist', 3); table.integer('hip', 3); table.boolean('natural_boobs'); table.integer('height', 3); table.integer('weight', 3); table.string('eyes'); table.string('hair'); table.boolean('has_tattoos'); table.boolean('has_piercings'); table.string('piercings'); table.string('tattoos'); table.integer('alias_for', 12) .references('id') .inTable('actors'); table.string('slug', 32) .unique(); table.datetime('created_at') .defaultTo(knex.fn.now()); table.datetime('scraped_at'); table.boolean('scrape_success'); })) .then(() => knex.schema.createTable('actors_avatars', (table) => { table.integer('actor_id', 12) .notNullable() .references('id') .inTable('actors'); table.integer('media_id', 16) .notNullable() .references('id') .inTable('media'); table.unique('actor_id'); })) .then(() => knex.schema.createTable('actors_photos', (table) => { table.integer('actor_id', 12) .notNullable() .references('id') .inTable('actors'); table.integer('media_id', 16) .notNullable() .references('id') .inTable('media'); table.unique(['actor_id', 'media_id']); })) .then(() => knex.schema.createTable('actors_social', (table) => { table.increments('id', 16); table.string('url'); table.string('platform'); table.integer('actor_id', 8) .notNullable() .references('id') .inTable('actors'); table.unique(['url', 'actor_id']); table.datetime('created_at') .defaultTo(knex.fn.now()); })) .then(() => knex.schema.createTable('directors', (table) => { table.increments('id', 12); table.string('name'); table.integer('alias_for', 12) .references('id') .inTable('directors'); table.string('slug', 32) .unique(); table.datetime('created_at') .defaultTo(knex.fn.now()); })) .then(() => knex.schema.createTable('releases', (table) => { table.increments('id', 16); table.integer('site_id', 12) .notNullable() .references('id') .inTable('sites'); table.integer('studio_id', 12) .references('id') .inTable('studios'); table.string('type', 10) .defaultTo('scene'); table.string('shoot_id'); table.string('entry_id'); table.unique(['site_id', 'entry_id']); table.string('url', 1000); table.string('title'); table.string('slug'); table.date('date'); table.text('description'); table.integer('duration') .unsigned(); table.integer('parent_id', 16) .references('id') .inTable('releases'); table.boolean('deep'); table.string('deep_url', 1000); table.datetime('created_at') .defaultTo(knex.fn.now()); })) .then(() => knex.schema.createTable('releases_actors', (table) => { table.integer('release_id', 16) .notNullable() .references('id') .inTable('releases'); table.integer('actor_id', 8) .notNullable() .references('id') .inTable('actors'); table.unique(['release_id', 'actor_id']); })) .then(() => knex.schema.createTable('releases_directors', (table) => { table.integer('release_id', 16) .notNullable() .references('id') .inTable('releases'); table.integer('director_id', 8) .notNullable() .references('id') .inTable('directors'); table.unique(['release_id', 'director_id']); })) .then(() => knex.schema.createTable('releases_posters', (table) => { table.integer('release_id', 16) .notNullable() .references('id') .inTable('releases'); table.integer('media_id', 16) .notNullable() .references('id') .inTable('media'); table.unique('release_id'); })) .then(() => knex.schema.createTable('releases_covers', (table) => { table.integer('release_id', 16) .notNullable() .references('id') .inTable('releases'); table.integer('media_id', 16) .notNullable() .references('id') .inTable('media'); table.unique(['release_id', 'media_id']); })) .then(() => knex.schema.createTable('releases_trailers', (table) => { table.integer('release_id', 16) .notNullable() .references('id') .inTable('releases'); table.integer('media_id', 16) .notNullable() .references('id') .inTable('media'); table.unique('release_id'); })) .then(() => knex.schema.createTable('releases_teasers', (table) => { table.integer('release_id', 16) .notNullable() .references('id') .inTable('releases'); table.integer('media_id', 16) .notNullable() .references('id') .inTable('media'); table.unique('release_id'); })) .then(() => knex.schema.createTable('releases_photos', (table) => { table.integer('release_id', 16) .notNullable() .references('id') .inTable('releases'); table.integer('media_id', 16) .notNullable() .references('id') .inTable('media'); table.unique(['release_id', 'media_id']); })) .then(() => knex.schema.createTable('releases_tags', (table) => { table.integer('tag_id', 12) .notNullable() .references('id') .inTable('tags'); table.integer('release_id', 16) .notNullable() .references('id') .inTable('releases'); table.unique(['tag_id', 'release_id']); })) .then(() => knex.raw(` COMMENT ON COLUMN actors.height IS E'@omit read,update,create,delete,all,many'; COMMENT ON COLUMN actors.weight IS E'@omit read,update,create,delete,all,many'; CREATE FUNCTION search_sites(search text) RETURNS SETOF sites AS $$ SELECT * FROM sites WHERE name ILIKE ('%' || search || '%') OR slug ILIKE ('%' || search || '%') OR url ILIKE ('%' || search || '%') $$ LANGUAGE SQL STABLE; /* CREATE VIEW releases_actors_sortable AS SELECT releases_actors.*, actors.gender, actors.name, actors.birthdate FROM releases_actors JOIN actors ON releases_actors.actor_id = actors.id; CREATE VIEW releases_tags_sortable AS SELECT releases_tags.*, tags.name, tags.priority FROM releases_tags JOIN tags ON releases_tags.tag_id = tags.id; CREATE VIEW actors_releases_sortable AS SELECT releases_actors.*, releases.date FROM releases_actors JOIN releases ON releases_actors.release_id = releases.id; COMMENT ON VIEW releases_actors_sortable IS E'@foreignKey (release_id) references releases (id)\n@foreignKey (actor_id) references actors (id)'; COMMENT ON VIEW releases_tags_sortable IS E'@foreignKey (release_id) references releases (id)\n@foreignKey (tag_id) references tags (id)'; COMMENT ON VIEW actors_releases_sortable IS E'@foreignKey (release_id) references releases (id)\n@foreignKey (actor_id) references actors (id)'; /* allow conversion resolver to be added for height and weight */ CREATE FUNCTION releases_by_tag_slugs(slugs text[]) RETURNS setof releases AS $$ SELECT DISTINCT ON (releases.id) releases.* FROM releases JOIN releases_tags ON (releases_tags.release_id = releases.id) JOIN tags ON (releases_tags.tag_id = tags.id) WHERE tags.slug = ANY($1); $$ LANGUAGE sql STABLE; */ `)); exports.down = knex => knex.raw(` DROP FUNCTION IF EXISTS releases_by_tag_slugs; DROP FUNCTION IF EXISTS search_sites; DROP VIEW IF EXISTS releases_actors_view; DROP TABLE IF EXISTS releases_actors CASCADE; DROP TABLE IF EXISTS releases_directors CASCADE; DROP TABLE IF EXISTS releases_posters CASCADE; DROP TABLE IF EXISTS releases_photos CASCADE; DROP TABLE IF EXISTS releases_covers CASCADE; DROP TABLE IF EXISTS releases_trailers CASCADE; DROP TABLE IF EXISTS releases_teasers CASCADE; DROP TABLE IF EXISTS releases_tags CASCADE; DROP TABLE IF EXISTS actors_avatars CASCADE; DROP TABLE IF EXISTS actors_photos CASCADE; DROP TABLE IF EXISTS actors_social CASCADE; DROP TABLE IF EXISTS sites_tags CASCADE; DROP TABLE IF EXISTS sites_social CASCADE; DROP TABLE IF EXISTS networks_social CASCADE; DROP TABLE IF EXISTS tags_posters CASCADE; DROP TABLE IF EXISTS tags_photos CASCADE; DROP TABLE IF EXISTS releases CASCADE; DROP TABLE IF EXISTS actors CASCADE; DROP TABLE IF EXISTS directors CASCADE; DROP TABLE IF EXISTS tags CASCADE; DROP TABLE IF EXISTS tags_groups CASCADE; DROP TABLE IF EXISTS social CASCADE; DROP TABLE IF EXISTS sites CASCADE; DROP TABLE IF EXISTS studios CASCADE; DROP TABLE IF EXISTS media CASCADE; DROP TABLE IF EXISTS countries CASCADE; DROP TABLE IF EXISTS networks CASCADE; `);