Skip to content

feat: PostgreSQL extended query protocol (prepared statements) #126

@FumingPower3925

Description

@FumingPower3925

Summary

Implement the PostgreSQL Extended Query protocol, enabling prepared statements with parameter binding. This is required for database/sql's Prepare + Exec/Query pattern and provides SQL injection protection.

Design

Package: driver/postgres/protocol/extended.go

Extended Query Flow

Client → Server:  Parse { name: "s1", query: "SELECT * FROM users WHERE id = $1", paramOIDs: [] }
Client → Server:  Bind { portal: "", statement: "s1", params: ["\x00\x00\x00\x01"], formatCodes: [1] }
Client → Server:  Describe { type: 'P', name: "" }
Client → Server:  Execute { portal: "", maxRows: 0 }
Client → Server:  Sync
Server → Client:  ParseComplete
Server → Client:  BindComplete
Server → Client:  RowDescription { ... }
Server → Client:  DataRow { ... }*
Server → Client:  CommandComplete { ... }
Server → Client:  ReadyForQuery

Messages to Implement

Frontend:

  • Parse: named prepared statement with optional parameter type OIDs
  • Bind: bind parameters to a portal (text or binary format)
  • Describe: request description of statement ('S') or portal ('P')
  • Execute: execute a portal with optional row limit
  • Sync: synchronization point (triggers response pipeline flush)
  • Close: close a named statement or portal

Backend:

  • ParseComplete ('1')
  • BindComplete ('2')
  • ParameterDescription ('t'): parameter type OIDs
  • NoData ('n'): for statements that return no rows

State Machine

type ExtendedQueryState struct {
    phase       extPhase
    prepared    map[string]*PreparedStmt  // named statements
    activeBind  *BindState
}

type PreparedStmt struct {
    Name      string
    Query     string
    ParamOIDs []uint32
    Columns   []ColumnDesc
}

Parameter Format

  • Support both text and binary parameter formats
  • Binary format preferred for performance (avoids text→binary conversion on server)
  • Format codes sent in Bind message

Acceptance Criteria

  • Parse/Bind/Describe/Execute/Sync message serialization
  • Close message for statement and portal cleanup
  • ParseComplete/BindComplete/ParameterDescription/NoData response handling
  • Named prepared statements with reuse across multiple Bind/Execute cycles
  • Text and binary parameter formats
  • Row limit in Execute (for cursor-like behavior)
  • Error handling: ErrorResponse during extended query rolls back to Sync
  • Unit tests with captured extended query exchanges

Dependencies

  • Depends on 125 (simple query — shares RowDescription/DataRow/CommandComplete parsing)

Metadata

Metadata

Labels

area/driverDatabase/cache driver infrastructuredriver/postgresPostgreSQL driver

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions