Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions .release-notes/next-release.md
Original file line number Diff line number Diff line change
Expand Up @@ -203,3 +203,40 @@ actor MyReceiver is ResultReceiver
session.close()
```

## Add equality comparison for Field

`Field` now implements `Equatable`, enabling `==` and `!=` comparisons. A `Field` holds a column name and a typed value. Two fields are equal when they have the same name and the same value — the values must be the same type and compare equal using that type's own equality.

```pony
Field("id", I32(42)) == Field("id", I32(42)) // true
Field("id", I32(42)) == Field("id", I64(42)) // false — different types
Field("id", I32(42)) == Field("name", I32(42)) // false — different names
```

## Add equality comparison for Row

`Row` now implements `Equatable`, enabling `==` and `!=` comparisons. A `Row` holds an ordered sequence of `Field` values representing a single result row. Two rows are equal when they have the same number of fields and each corresponding pair of fields is equal. Field order matters — the same fields in a different order are not equal.

```pony
let r1 = Row(recover val [Field("id", I32(1)); Field("name", "Alice")] end)
let r2 = Row(recover val [Field("id", I32(1)); Field("name", "Alice")] end)
r1 == r2 // true

let r3 = Row(recover val [Field("name", "Alice"); Field("id", I32(1))] end)
r1 == r3 // false — same fields, different order
```

## Add equality comparison for Rows

`Rows` now implements `Equatable`, enabling `==` and `!=` comparisons. A `Rows` holds an ordered collection of `Row` values representing a query result set. Two `Rows` are equal when they have the same number of rows and each corresponding pair of rows is equal. Row order matters — the same rows in a different order are not equal.

```pony
let rs1 = Rows(recover val
[Row(recover val [Field("id", I32(1))] end)]
end)
let rs2 = Rows(recover val
[Row(recover val [Field("id", I32(1))] end)]
end)
rs1 == rs2 // true
```

3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ All notable changes to this project will be documented in this file. This projec
- Add named prepared statement support ([PR #78](https://github.com/ponylang/postgres/pull/78))
- Add SSL/TLS negotiation support ([PR #79](https://github.com/ponylang/postgres/pull/79))
- Enable follow-up queries from ResultReceiver and PrepareReceiver callbacks ([PR #84](https://github.com/ponylang/postgres/pull/84))
- Add equality comparison for Field ([PR #85](https://github.com/ponylang/postgres/pull/85))
- Add equality comparison for Row ([PR #85](https://github.com/ponylang/postgres/pull/85))
- Add equality comparison for Rows ([PR #85](https://github.com/ponylang/postgres/pull/85))

### Changed

Expand Down
9 changes: 7 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,11 @@ Tests live in the main `postgres/` package (private test classes).
- `_TestSSLNegotiationRefused` — mock server responds 'N' to SSLRequest; verifies `pg_session_connection_failed` fires
- `_TestSSLNegotiationJunkResponse` — mock server responds with junk byte to SSLRequest; verifies session shuts down
- `_TestSSLNegotiationSuccess` — mock server responds 'S', both sides upgrade to TLS, sends AuthOk+ReadyForQuery; verifies full SSL→auth flow
- `_TestField*Equality*` / `_TestFieldInequality` — example-based reflexive, structural, symmetric equality and inequality tests for Field
- `_TestRowEquality` / `_TestRowInequality` — example-based equality and inequality tests for Row
- `_TestRowsEquality` / `_TestRowsInequality` — example-based equality and inequality tests for Rows
- `_TestField*Property` — PonyCheck property tests for Field reflexive, structural, and symmetric equality
- `_TestRowReflexiveProperty` / `_TestRowsReflexiveProperty` — PonyCheck property tests for Row/Rows reflexive equality

**Integration tests** (require PostgreSQL, names prefixed `integration/`):
- Connect, ConnectFailure, Authenticate, AuthenticateFailure
Expand All @@ -145,7 +150,6 @@ Test helpers: `_ConnectionTestConfiguration` reads env vars with defaults. Sever

## Known Issues and TODOs in Code

- `rows.pony:43` — TODO: need tests for Rows/Row/Field (requires implementing `eq`)
- `_test_response_parser.pony:6` — TODO: chain-of-messages tests to verify correct buffer advancement across message sequences

## Roadmap
Expand Down Expand Up @@ -293,7 +297,7 @@ Can arrive between any other messages (must always handle):
## File Layout

```
postgres/ # Main package (29 files)
postgres/ # Main package (30 files)
session.pony # Session actor + state machine traits + query sub-state machine
ssl_mode.pony # SSLDisabled, SSLRequired, SSLMode types
simple_query.pony # SimpleQuery class
Expand Down Expand Up @@ -323,6 +327,7 @@ postgres/ # Main package (29 files)
_test_query.pony # Query integration tests
_test_response_parser.pony # Parser unit tests + test message builders
_test_frontend_message.pony # Frontend message unit tests
_test_equality.pony # Equality tests for Field/Row/Rows (example + PonyCheck property)
assets/test-cert.pem # Self-signed test certificate for SSL unit tests
assets/test-key.pem # Private key for SSL unit tests
examples/README.md # Examples overview
Expand Down
15 changes: 15 additions & 0 deletions postgres/_test.pony
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use "cli"
use "collections"
use "files"
use lori = "lori"
use "pony_check"
use "pony_test"
use "ssl/net"

Expand Down Expand Up @@ -87,6 +88,20 @@ actor \nodoc\ Main is TestList
test(_TestSSLAuthenticate)
test(_TestSSLQueryResults)
test(_TestSSLRefused)
test(_TestFieldEqualityReflexive)
test(_TestFieldEqualityStructural)
test(_TestFieldEqualitySymmetric)
test(_TestFieldInequality)
test(_TestRowEquality)
test(_TestRowInequality)
test(_TestRowsEquality)
test(_TestRowsInequality)
test(Property1UnitTest[Field](_TestFieldReflexiveProperty))
test(Property1UnitTest[FieldDataTypes](_TestFieldStructuralProperty))
test(Property1UnitTest[(FieldDataTypes, FieldDataTypes)](
_TestFieldSymmetricProperty))
test(Property1UnitTest[Row](_TestRowReflexiveProperty))
test(Property1UnitTest[Rows](_TestRowsReflexiveProperty))

class \nodoc\ iso _TestAuthenticate is UnitTest
"""
Expand Down
Loading