SQLALCHEMY 中查询一直返回空的问题
2016-07-16 19:54
344 查看
问题描述
HabitQuestion表有个last_answer_time字段,默认是null,就是要做它的筛选过滤。一开始使用代码如下:
base_query = base_query.filter(HabitQuestion.last_answer_time.isnot(None)).order_by(HabitQuestion.last_answer_time.desc()))
其中last_answer_time是个默认值是None的参数,运行测试用例的时候报错,说 isnot方法在datetime.datetime里面没找到。可这完全是参考官方文档写的代码。于是改成如下代码,可以运行了。
base_query = base_query.filter(HabitQuestion.last_answer_time != None).order_by(desc(text("last_answer_time")))
但有意思的是,2个测试用例代码,1个测试用例中last_answer_time字段全设置为None,另一个测试用例中last_answer_time字段全设置为有效值,单独运行的时候,都pass了,当合在一起运行的时候,出错,返回什么也没有查到!(每个测试用例都会在执行前做清空数据库的操作,所以不会是脏数据造成),通过str(base_query)打印执行sql命令,发现,单独执行的时候,生成的sql语句where那块正常,但合并执行的时候,那个语句的过滤变成了
WHERE 0 = 1
这明明是根本什么都不选择的意思呀!!!
猜测1:是否是对None的支持不好
于是改数据库字段,last_answer_time变成一个time的int值,默认是0,再次查询,发现打印的sql语句中还是有 0 = 1,所以不是。猜测2: 原sqlalchemy语句写法有误,让SqlAlchemy引擎认为where查询无效,变为 0 = 1 的查询语句
直觉上否定了这个,因为用例单独执行的时候是ok的,否则,应该一直出错。猜测3:之前的操作对数据库的查询还是存在影响?
时间冲突?资源未释放?
用例执行之前,加了2秒的等待,问题依旧。否认这个方向。执行冲突,有顺序依赖?
通过tests = unittest.TestLoader().discover('tests', pattern="test_*questions.py") unittest.TextTestRunner(verbosity=2).run(tests)
将命令拆成两组,1个是test_get_answered_questions.py, 另一个是 test_get_questions.py,发现,如果 test_get_answered_questions.py 先执行,就会有 WHERE 0 = 1 的语句出现,但如果顺序倒过来,所有用例pass。
看来,是某个用例的执行的确对之后的用例产生了影响,那为什么会有影响?
后来通过查看代码,对 last_answer_time 有一个赋值不对。应该是
question.last_answer_time = datetime.datetime.now()
结果写成了
HabitQuestion.last_answer_time = datetime.datetime.now()
那为什么这样会让SQL的语句变为 WHERE 0 = 1 呢?原因是,原来 last_answer_time 的定义是
last_answer_time = db.Column(db.DateTime)
这是一个数据库Column。执行了赋值之后,对于SQLAlchemy而言,HabitQuestion.last_answer_time 不再是有效的数据库表column,无法针对其进行过滤,所以,返回不了任何有效数据,就采用 WHERE 0 = 1,表示没有任何数据可以返回。
后记
属于活久见的测试bug,和以前写linux下ide硬盘驱动,堆栈溢出导致系统会重启到window ce上一个德行。在查找这个问题上,花费的时间比写功能代码还要多。不过还是有收获的。在一开始 HabitQuestion.last_answer_time.isnot(None) 不可用,其实就是因为 HabitQuestion.last_answer_time 被重新赋值为datetime类型,所以找不到 isnot() 的方法,这个预警自己没有注意。问题修正后,改成isnot的方式使用,完全正常。
其实,对于SqlAlchemy而言,当filter的字段明显不是有效db.Column的情况下,是否直接返回异常更好?毕竟,还是有可能用户手贱写错,然后发现任何和这个字段有关的查询,返回都是空。这种恶心的问题,代码扫描都很难发现。这次算是领教了。
相关文章推荐
- java和scala实现oracle lpad\rpad函数
- 分布式中使用Redis实现Session共享
- MySQL索引分析
- MySql 64位 windows下环境配置
- 【读书笔记】ORACLE 内存管理
- Ubuntu下MySQL的安装及配置
- 从无到有——简单的个人博客(一)
- Linux 安装 Oracle 11g——手工建库(RAC)
- win10 64位安装mysql-5.7.13-winx64
- excel数据导入mysql
- mysql查询更新时的锁表机制分析(只介绍了MYISAM)
- mysql数据库引擎MyISAM和InnoDB的比较和使用场合
- redis3.0.0 集群安装详细步骤
- sqlalchemy操作
- Web开发中的PostgreSQL错误汇总
- mac系统安装php redis扩展
- Ubuntu 14.04数据库服务器--mysql的安装和配置
- MySQL索引类型总结
- oracle SQL语句(转)
- 数据库-FMDB简单实用