Quiero almacenar datos de la organización en la base de datos PostgreSQL usando Enums. Dado que los nombres de las organizaciones a veces cambian, a veces necesito actualizar los valores de Enum, y quiero automatizar esto usando Python con sqlalchemy
y psycopg2
. Sin embargo, después de modificar el Enum, no se pueden insertar nuevos valores.
Sospecho que esto se debe al método de check()
de psycopg2
, ya que la base de datos acepta el nuevo valor. ¿Conoces un método para actualizar los tipos conocidos por psycopg2
?
Aquí están mis pruebas para este script:
class DbconTestCase(unittest.TestCase): def setUp(self): self.engine, self.meta = db.get_connection('test_user', 'test_pass', 'testdb') # Create test table, which will be deleted later self.test_table = Table('test_table', self.meta, Column('id', Integer, primary_key=True), Column('type', Enum('number', 'text', 'image', name='type'), nullable=False), Column('text', String(32))) self.meta.create_all() def test_add_enum_value(self): try: # Add new value to enum named 'type' db.add_enum_value(self.engine, 'type', 'object') except Exception as exp: self.assertTrue(False, msg=exp.__cause__) else: self.assertTrue(True) def test_bulk_copy(self): types = ['number', 'text', 'image', 'object'] objects = [{'id': idx, 'type': types[idx % len(types)], 'text': 'random text to insert'} for idx in range(10000)] try: db.bulk_copy(self.engine, str(self.test_table.name), objects) except Exception as exp: self.assertTrue(False, msg=exp.__cause__) else: self.assertTrue(True) def tearDown(self): self.meta.drop_all()
Y una pequeña explicación: básicamente creo una tabla de prueba en una base de datos de prueba y luego extiendo un tipo de enumeración con un nuevo valor. Luego trato de insertar una gran cantidad de datos, con el nuevo valor de la enumeración entre ellos. Tuve el siguiente error:
psycopg2.DataError: invalid input value for enum type: "object"
También enfrenté este problema, y luego lo resolví con la actualización del valor de enumeración de PostgreSQL directamente siguiendo estas respuestas , también podemos seguir esta respuesta para actualizar la enumeración en PostgreSQL directamente.
El valor de enumeración en la base de datos debe actualizarse (si no desea usar la migración, etc.), el siguiente código sql lo ayuda
ALTER TYPE type ADD VALUE 'object';