当前位置: 首页 > news >正文

利用postgres_proto和pgproto配合验证测试postgres协议

postgres_proto是一个python编写的模拟接收postgres协议请求的服务器。
pgproto是一个c编写的发送postgres协议请求的客户端。

但是两者的文档都不很详细,源代码中也有错误。通过查看报错信息,修改postgres_proto解析器源码,成功实现了两者对话。修改pgproto源码增加了数据输出函数,不但保证消息的正确性,还能查看消息的内容。

parser.py中注释掉非必须的SQL成分,如果需要测试相应的子句,可以加上。

SelectStmt = namedtuple('SelectStmt', ['columns',  'tables']) #,'cols_aliases', 'where', 'group_by', 'order_by' 'limit', 'offset'])
SelectColumnExpr = namedtuple('SelectColumnExpr', ['name', 'alias'])
FromTableExpr = namedtuple('FromTableExpr', ['name', 'schema', 'alias']) #, 'joins', 'subquery'])

在read.c中添加如下函数,并在数据行的处理中添加调用

void parse_structured_data(const unsigned char* buf, size_t len) {if (len < 2) return;int pos = 0;int is_first_field = 1;// 读取字段数量(2字节,大端序)uint16_t field_count = (buf[0] << 8) | buf[1];pos += 2;//printf("字段数量: %u\n", field_count);for (int i = 0; i < field_count; i++) {if (pos + 4 > len) break; // 检查边界// 读取字段长度(4字节,大端序)uint32_t field_len = (buf[pos] << 24) | (buf[pos+1] << 16) | (buf[pos+2] << 8) | buf[pos+3];pos += 4;if (pos + field_len > len) break; // 检查边界// 输出字段分隔符(除了第一个字段)if (!is_first_field) {fprintf(stderr,"|");}is_first_field = 0;// 输出字段内容for (uint32_t j = 0; j < field_len; j++) {fprintf(stderr,"%c", buf[pos + j]);}pos += field_len;}fprintf(stderr,"\n");
}
...
void read_until_ready_for_query(PGconn *conn, int timeout)
{
...case 'D':	/* Data row */fprintf(stderr, "<= BE DataRow\n");len = read_int32(conn);buf = read_bytes(len - sizeof(int), conn);parse_structured_data(buf, len);pg_free(buf);								//read_and_discard(conn);break;
...

编写pgproto测试命令脚本, 其中Q行语句可以改为"SELECT * FROM table1"以测试静态数据。

#
# Test data example
#
'Q'	"SELECT * FROM csv"
'Y'
'P'	"S1"	"BEGIN"	0
'B'	""	"S1"	0	0	0
'E'	""	0
'C'	'S'	"S1"
'P'	"foo"	"SELECT 1"	0
'B'	"myportal"	"foo"	0	0	0
'E'	"myportal"	0
'P'	"S2"	"COMMIT"	0
'B'	""	"S2"	0	0	0
'E'	""	0
'C'	'S'	"S2"
'S'
'Y'
'X'

测试python代码中的静态数据
服务端,在examples目录下执行命令行,其中PYTHONPATH=..是告诉python3 postgres_proto模块在上一级目录下。这是DeepSeek教我的,否则按照README文档$ python -m postgres_proto.server your_file.MyRequestHandler是不能执行成功的。

/par/postgres-proto/examples# PYTHONPATH=.. python3 static.py
Serving on 127.0.0.1:55432
----------------------------------------
Exception occurred during processing of request from ('127.0.0.1', 41856)

客户端,用.configure和make编译

/par/pgproto# src/pgproto -h 127.0.0.1 -p 55432 -f /par/pgpo.txt
FE=> Query (query="SELECT * FROM table1")
<= BE RowDescription
<= BE DataRow
1|hello world
<= BE DataRow
2|my second row
<= BE CommandComplete(SELECT)
<= BE ReadyForQuery(I)
FE=> Parse(stmt="S1", query="BEGIN")
FE=> Bind(stmt="S1", portal="")
FE=> Execute(portal="")
FE=> Close(stmt="S1")
FE=> Parse(stmt="foo", query="SELECT 1")
FE=> Bind(stmt="foo", portal="myportal")
FE=> Execute(portal="myportal")
FE=> Parse(stmt="S2", query="COMMIT")
FE=> Bind(stmt="S2", portal="")
FE=> Execute(portal="")
FE=> Close(stmt="S2")
FE=> Sync
<= BE ParseComplete
<= BE BindComplete
<= BE CommandComplete(BEGIN)
<= BE CloseComplete
<= BE ParseComplete
<= BE BindComplete
read_it: EOF detect

测试外部csv文件中的数据
服务端

/par/postgres-proto/examples# PYTHONPATH=.. python3 csv_db.py demo.csv
Serving on 127.0.0.1:55432
----------------------------------------
Exception occurred during processing of request from ('127.0.0.1', 44076)

客户端

/par/pgproto# src/pgproto -h 127.0.0.1 -p 55432 -f /par/pgpo.txt
FE=> Query (query="SELECT * FROM csv")
<= BE RowDescription
<= BE DataRow
toto@toto.com|toto|1111
<= BE DataRow
titi@titi.com|titi|2222
<= BE DataRow
tutu@tutu.com|tutu|
<= BE CommandComplete(SELECT)
<= BE ReadyForQuery(I)
FE=> Parse(stmt="S1", query="BEGIN")
FE=> Bind(stmt="S1", portal="")
FE=> Execute(portal="")
FE=> Close(stmt="S1")
FE=> Parse(stmt="foo", query="SELECT 1")
FE=> Bind(stmt="foo", portal="myportal")
FE=> Execute(portal="myportal")
FE=> Parse(stmt="S2", query="COMMIT")
FE=> Bind(stmt="S2", portal="")
FE=> Execute(portal="")
FE=> Close(stmt="S2")
FE=> Sync
<= BE ParseComplete
<= BE BindComplete
<= BE CommandComplete(BEGIN)
<= BE CloseComplete
<= BE ParseComplete
<= BE BindComplete
read_it: EOF detected

协议的字母含义参阅postgresql文档。上述自定义函数的结构来自以下说明。

DataRow (B) 
Byte1('D')
标识消息为数据行。Int32
消息内容(包括自身)的长度(以字节为单位)。Int16
下面跟随着的列值数量(可能为零)。接下来,每列出现以下一对字段Int32
列值的长度,以字节为单位(此计数不包括自身)。可以为零。在特殊情况下,-1 表示 NULL 列值。在 NULL 情况下,不跟随着任何值字节。Byten
列的值,格式由关联的格式代码指示。n 是上面的长度。

暂时只考虑字符串类型。

补记,postgresql的psql客户端也能访问此服务端

/par# psql  -h 127.0.0.1 -p 55432
psql (15.13 (Debian 15.13-0+deb12u1), server 130000)
WARNING: psql major version 15, server major version 130000.Some psql features might not work.
Type "help" for help.root=> select * from table1;id |     title
----+---------------1  | hello world2  | my second row
(2 rows)root=> select * from table2;id |          name
----+-------------------------1  | first row, second table
(1 row)root=> select * from csv;email     | name | phone
---------------+------+-------toto@toto.com | toto | 1111titi@titi.com | titi | 2222tutu@tutu.com | tutu |
(3 rows)

文章转载自:

http://1AhmqzaQ.Ljdhj.cn
http://yeFxwajz.Ljdhj.cn
http://6mhULAEF.Ljdhj.cn
http://zValw6Ja.Ljdhj.cn
http://kN8xFuYx.Ljdhj.cn
http://5OJrqEYA.Ljdhj.cn
http://KdhcCyNE.Ljdhj.cn
http://iZMDRfCf.Ljdhj.cn
http://NKNu3qjG.Ljdhj.cn
http://426kttTo.Ljdhj.cn
http://yphAhbG2.Ljdhj.cn
http://InE88Mve.Ljdhj.cn
http://2tPNEzJc.Ljdhj.cn
http://ZZ51KODm.Ljdhj.cn
http://dPUBsYJT.Ljdhj.cn
http://p1cnjumn.Ljdhj.cn
http://OaLax2tB.Ljdhj.cn
http://PaTQwLus.Ljdhj.cn
http://QopB5X5w.Ljdhj.cn
http://dgvP1EvC.Ljdhj.cn
http://8ESXdI11.Ljdhj.cn
http://EzliWYbM.Ljdhj.cn
http://dP9SuOCV.Ljdhj.cn
http://HMCrCYvj.Ljdhj.cn
http://Rp2jwCzz.Ljdhj.cn
http://ZdVXviaF.Ljdhj.cn
http://lDCQgoGF.Ljdhj.cn
http://y9aTD44s.Ljdhj.cn
http://rn0kEA7v.Ljdhj.cn
http://fJ1uwQNr.Ljdhj.cn
http://www.dtcms.com/a/384919.html

相关文章:

  • 联咏nt98568点亮sensor步骤
  • 大模型操作SQL查询Text2SQL
  • 风力发电乙级资质需要哪些人员配备
  • 【JavaScript】实现一个高精度的定时器
  • 无偏估计-
  • SQL-流程控制函数
  • TNNLS-2015《Linear-Time Subspace Clustering via Bipartite Graph Modeling》
  • 线性代数 · 行列式 | 子式 / 主子式 / 顺序主子式 / 余子式 / 代数余子式
  • LLM的MTP论文阅读
  • 软考-系统架构设计师 软件工程详细讲解
  • MATLAB 实现基于 GMM-HMM的语音识别系统
  • Day24_【深度学习(4)—PyTorch使用—张量的数值计算】
  • 2019年下半年 系统架构设计师 综合知识
  • C++类和对象详解(2);初识类的默认成员函数
  • AI智能体的应用前景
  • 文档驱动的AI协作 (DDAC) 工作流
  • Selenium 与 Playwright 安装及浏览器驱动配置
  • 数字丝绸之路的暗礁,解码“一带一路”与RCEP时代的跨境法治挑战
  • fabric启动节点var/hyperledger/production: permission denied
  • 小型无人机传感器仿真模型MATLAB实现方案
  • 拓扑dp|博弈|正难则反
  • linux时间管理
  • 第2章 语言模型:自然语言处理的基石
  • 汽车电子电气架构 --- 新趋势下的挑战与技术
  • 地铁站电子钟:NTP实时校准时间
  • 【数据集】2025年国家自然科学基金立项名单(经管类)
  • Elastic APM 2025 新特性:Tail-based Sampling 和 GenAI 优化
  • 如何解决 pip install 安装报错 ModuleNotFoundError: No module named ‘sklearn’ 问题
  • 《二战系统分析师》第五章总结
  • 机器学习中的距离总结