【问题标题】:After updating Enum with a new value, that value cannot be inserted with psycopg2使用新值更新 Enum 后,无法使用 psycopg2 插入该值
【发布时间】:2017-09-17 01:29:57
【问题描述】:

我想使用 Enums 将组织数据存储在 PostgreSQL 数据库中。由于组织名称有时会更改,因此我有时需要更新 Enum 值,并且我想使用 Python 和 sqlalchemypsycopg2 自动执行此操作。但是修改 Enum 后,就无法插入新值了。

我怀疑这是由于psycopg2 的内部check() 方法,因为数据库确实接受了新值。你知道更新psycopg2已知类型的方法吗?

这是我对此脚本的测试:

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()

还有一点解释:基本上我在测试数据库中创建一个测试表,然后用一个新值扩展一个枚举类型。然后我尝试插入大量数据,其中包含枚举的新值。我收到以下错误:

psycopg2.DataError: invalid input value for enum type: "object"

【问题讨论】:

  • psycopg2 不会跟踪它知道的枚举值。我怀疑你的测试用例失败了,因为test_add_enum_value 不能保证在test_bulk_copy 之前执行。
  • 我明白了,但如果执行顺序因运行而异,在某些情况下我会得到绿色运行,但每次运行都会失败。
  • 这是一个错误的假设。如果执行顺序不保证,那么这两个函数可以按任意顺序运行;他们不必必须按所有可能的顺序运行。换句话说,顺序可以是任意但稳定的。
  • 我刚刚意识到 setUp 和 tearDown 在每次测试之前运行,直到现在我一直认为 setUp 运行一次,然后运行测试用例中的所有测试,然后调用 tearDown 。所以基本上问题是,一个完全不同的表对象被用来插入,而不是我想的那个。

标签: python postgresql enums sqlalchemy psycopg2


【解决方案1】:

我也遇到了这个问题,然后我解决了直接在this answers之后从PostgreSQL更新枚举值,我们也可以关注this answer更新PostgreSQL 直接。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-04-04
    • 2014-02-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-26
    • 2020-09-14
    相关资源
    最近更新 更多