Je cherche à écrire une chaîne de migration pour ajouter une nouvelle chaîne au type de colonne enum. J'essaie d'ajouter gamma
à la colonne service
.
J'ai essayé avec ce code ci-dessous. Cela entre en collision car la table et la colonne existent déjà.
const table = 'user_associations'
export function up (knex, Promise) {
return knex.schema.table(table, function (table) {
table.enu('service', ['alpha', 'beta', 'gamma']).notNullable()
})
}
export function down (knex, Promise) {
return knex.schema.table(table, function (table) {
table.enu('service', ['alpha', 'beta']).notNullable()
})
}
C'est bon, un moyen d'utiliser l'API alter
?
les enums sont actuellement effectués avec des contraintes de vérification et .alter()
n'a pas de traitement spécial pour eux...
Un problème est que .alter()
ne sait pas quel est le type d'origine de la colonne et c'est pourquoi il ne sait pas s'il doit supprimer l'ancienne contrainte de vérification d'enum.
Pour autant que je sache actuellement, on ne peut modifier les valeurs d'énumération autorisées qu'avec knex.raw
en supprimant l'ancienne et en créant une nouvelle contrainte de vérification ...
Je pense que cela pourrait être implémenté par quelque drop old constraint if exist
, puis en créer un nouveau si le type modifié de la colonne est enum.
J'aimerais voir cette fonctionnalité être implémentée.
@elhigu J'ai écrit une requête d'énumération personnalisée pour pouvoir utiliser les énumérations Postgres, mais il y a un débat dans la communauté Postgres sur les conditions de vérification par rapport aux énumérations
Juste pour tous ceux qui veulent savoir à quoi le code _pourrait_ ressembler dans Postgres 9
const formatAlterTableEnumSql = (
tableName,
columnName,
enums,
) => {
const constraintName = `${tableName}_${columnName}_check`;
return [
`ALTER TABLE ${tableName} DROP CONSTRAINT IF EXISTS ${constraintName};`,
`ALTER TABLE ${tableName} ADD CONSTRAINT ${constraintName} CHECK (${columnName} = ANY (ARRAY['${enums.join(
"'::text, '"
)}'::text]));`,
].join('\n');
};
exports.up = async function up(knex) {
await knex.raw(
formatAlterTableEnumSql('myTableName', 'myColumnName', [
'enum1',
'enum2',
'enum3',
])
);
};
exports.down = async function down(knex) {
await knex.raw(
formatAlterTableEnumSql('myTableName', 'myColumnName', [
'enum1',
'enum2',
])
);
};
@holloway Merci pour l'exemple de code de migration. Exactement ce que je cherchais. Je rencontre cependant un problème. 'myColumnName' génère une erreur lors de la migration. Le message dit "la colonne 'mycolumnname' n'existe pas". Notez que le camelCase est maintenant manquant. Des idées sur la façon de contourner cela?
@Jordan24 Pouvez-vous partager votre code ?
'use strict';
const formatAlterTableEnumSql = (tableName, columnName, enums) => {
const constraintName = `${tableName}_${columnName}_check`;
return [
`ALTER TABLE ${tableName} DROP CONSTRAINT IF EXISTS ${constraintName};`,
`ALTER TABLE ${tableName} ADD CONSTRAINT ${constraintName} CHECK (${columnName} = ANY (ARRAY['${enums.join(
`'::text, '`
)}'::text]));`
].join('\n');
};
exports.up = async function up(knex) {
await knex.raw(
formatAlterTableEnumSql('item_messages', 'sentMethod', [
'Web App', 'Email', 'Text Message', 'Log Conversation'
])
);
};
exports.down = async function down(knex) {
await knex.raw(
formatAlterTableEnumSql('item_messages', 'sentMethod', [
'Web App', 'Email', 'Text Message'
])
);
};
Si j'enveloppe le columnName dans des guillemets doubles, j'obtiens une erreur de syntaxe car les guillemets simples ne sont pas supprimés dans le code brut.
Je pense que je pourrais laisser tomber la fonction et écrire le code brut deux fois.
@ Jordan24 Sans les guillemets, PostgreSQL plie tous les identifiants en minuscules.
Tout codé en dur sauf le « enum » pour le contourner. Merci pour le conseil @kibertoad !
Commentaire le plus utile
Juste pour tous ceux qui veulent savoir à quoi le code _pourrait_ ressembler dans Postgres 9