psycopg2,Redshift和unittest

时间:2015-10-21 01:40:00

标签: python postgresql psycopg2 amazon-redshift python-unittest

我在Python 2.7中,使用psycopg2连接到Amazon Redshift数据库。我有单元测试,在这个测试类的setUp和tearDown方法中,我删除了为此测试目的而创建的表。所以该计划是:

def setUp(self):
    drop_specific_tables()
    create_specific_tables()

def tearDown(self):
    drop_specific_tables()

在setUp以及tearDown中放弃的原因是,如果测试不安全地退出并且跳过tearDown,我们仍然可以知道无论何时它再次运行它仍将以干净的平板开始。

这是drop_specific_tables方法,rcur是指向我们的redshift数据库的psycopg2游标。

def drop_specific_tables(rcur):
    rcur.execute("BEGIN;")
    rcur.execute("SELECT table_name "
                 "  FROM information_schema.tables "
                 "  WHERE table_schema='public' ")
    tables = [row for row, in rcur]
    rcur.execute("DROP TABLE IF EXISTS " + ", ".join(tables) + " CASCADE;")
    rcur.execute("END;")

当运行单个测试时,它会通过。但是当整个类运行时,setUp或tearDown中的某些测试错误(它是非确定性的,测试错误和drop_specific_tables),在drop_specific_tables()中的行

rcur.execute("SELECT table_name "
             "  FROM information_schema.tables "
             "  WHERE table_schema='public' ")

产生错误ProgrammingError: Relation with OID 1454844 does not exist.我打印出'information_schema.tables'的OID,它与错误消息中的OID不同。

为什么会发生这种情况?我理解对于不存在的关系意味着什么,但是这个查询找不到它的关系是什么?为什么它有时不存在,导致查询错误?

更新:我还在删除之前打印出每个表的OID,并且它们都不是错误消息中的OID!

1 个答案:

答案 0 :(得分:1)

您正在使用带有CASCADE选项的DROP。因此,任何具有引用完整性的表的删除也将删除与父表关联的子表。

要解决这是否真的发生了什么,在运行代码之前,请使用其OID拍摄现有表的快照(我认为pg_tables或pg_relations应该包含此信息)。运行代码并使用表名的快照检查错误消息的OID。

编辑:可能是因为如何在PostgreSQL中缓存计划(在Redshift中)以用于函数。这是一个记录在案的bug,直到8.2,所以你可能想要搜索它的修复程序。该计划将根据函数的第一次执行进行缓存,但对于第二次执行,由于重新创建,一些对象将获得新的OID。 http://merlinmoncure.blogspot.ie/2007/09/as-previously-stated-postgresql-8.html

http://www.postgresql.org/message-id/eea51fdb0708170848w77e27daarfc375ad5c7bc1e09@mail.gmail.com