微软ODBC参考手册
这个标准的来历大家都清楚,微软手册的API描述很权威,不再赘述。
SQLSpecialColumns函数定义
它的作用
1、返回最佳的能唯一标识记录的字段,比如:主键、唯一索引 2、返回能伴随记录更新一起变化的字段,比如:序列字段?有默认值的字段?这里拿不准,因为只有插入起作用关于它的参数和返回值手册都有,这里不展开。
2018/11/14补充IBM手册:,关于返回值有更清楚的表述。
PostgreSQL ODBC的实现问题
实际使用中,SQL_BEST_ROWID总是得到oid字段,这是很奇怪的,因为表默认启用行oid是很久远以前的事情了,这里我们竟然取不到主键,更取不到唯一索引。
官网:https://odbc.postgresql.org/
代码:https://git.postgresql.org/gitweb/?p=psqlodbc.git;a=summary
代码实现是函数 PGAPI_SpecialColumns,源文件 info.c,暂时忽略视图部分的处理
if (fColType == SQL_BEST_ROWID) { Int2 the_type = PG_TYPE_OID; int atttypmod = -1; if (relhasoids[0] != '1') { ret = SQL_SUCCESS; goto cleanup; } tuple = QR_AddNew(res); set_tuplefield_int2(&tuple[SPECOLS_SCOPE], SQL_SCOPE_SESSION); set_tuplefield_string(&tuple[SPECOLS_COLUMN_NAME], OID_NAME); set_tuplefield_int2(&tuple[SPECOLS_DATA_TYPE], PGTYPE_ATTR_TO_CONCISE_TYPE(conn, the_type, atttypmod)); set_tuplefield_string(&tuple[SPECOLS_TYPE_NAME], pgtype_attr_to_name(conn, the_type, atttypmod, TRUE)); set_tuplefield_int4(&tuple[SPECOLS_COLUMN_SIZE], PGTYPE_ATTR_COLUMN_SIZE(conn, the_type, atttypmod)); set_tuplefield_int4(&tuple[SPECOLS_BUFFER_LENGTH], PGTYPE_ATTR_BUFFER_LENGTH(conn, the_type, atttypmod)); set_tuplefield_int2(&tuple[SPECOLS_DECIMAL_DIGITS], PGTYPE_ATTR_DECIMAL_DIGITS(conn, the_type, atttypmod)); set_tuplefield_int2(&tuple[SPECOLS_PSEUDO_COLUMN], SQL_PC_PSEUDO); }
并没有检测是否有主键,更没有检测唯一索引,而是直接返回oid,没有WITH OIDS选项则返回空集。
下边的
else if (fColType == SQL_ROWVER)
返回的是 xmin
这里的代码应该是为老版本PG写的,后来一直没有更新过。
如何改变
对于 SQL_BEST_ROWID,我想应该是清楚的,优先返回Primary KEY,如果没有则返回UNIQUE索引,仍然没有才检查是不是有WITH OIDS选项,如果有则返回oid字段。以上全没有,我们还有 ctid,所以无论如何都不会告诉客户端没有唯一识别记录的列。
SQL_ROWVER应该返回什么?这个我想可以参考其他数据库来决定。
是Bug?
不是的,对于一个历史悠久的自由软件来说,这种事情很常见,很多代码完成之后,没有及时跟进更新。
既然我们已经发现,就给它补上。
============================
本文由飞象数据权叔亲手炮制,版权所有。
如有错误实属正常,欢迎阅读,欢迎斧正。 不允许链接,不允许转载。