phibble

Expression edge cases

Verification

Scope

Argument rules of row_number() and ntile(); isIn() with dates, datetimes, and times; NaN in coalesce(); one-character pads in str_pad(); parse_date_time() orders without a year; fractional periods; and dates plus clock periods. Results and error conditions on DataFrame, the SQL databases, and Polars.

References

Reference
R 4.6.1 with dplyr 1.2.1, stringr 1.6.0, and lubridate 1.9.5
Versions
R 4.6.1, dplyr 1.2.1, stringr 1.6.0, lubridate 1.9.5, jsonlite 2.0.0, PHP 8.5.10, SQLite 3.45.2, PostgreSQL 17.0 (Laravel Herd), MySQL 8.0.46, php_polars 0.1.0

Data

edge cases
Literal vectors in tests/ExprRTest.php and tests/Polars/PolarsExprRTest.php Source

Method

tests/r/edge_cases.R prints R's result or error for each case. The tests hold those results as expected values and check that phibble gives the same value, or raises where R raises. Fixtures regenerated with the listed R versions on 2026-11-01; output byte-identical to the committed files.

Check
Comparison with a reference implementation
Recorded
2026-11-02, PHP 8.5.10, macOS 27.0.1 (arm64), commit 1abdeb1

Tolerances

exact equality

Applies to: Values and result types

NA in identical positions, datetimes to the microsecond

x: package value; r: reference value.

Results

21 comparisons in 15 cases: 21 pass, 0 fail, 0 skipped.

By case

Results by case
Case Comparisons Status
takes at most one argument in row_number(), as dplyr does 1 pass
takes x and a required n in ntile(), as dplyr does 1 pass
matches dates, datetimes, and times by value in isIn() 1 pass
serializes temporal isIn() lists 1 pass
matches dates and datetimes by value in isIn() 4 pass
skips NaN in coalesce(), as is_na() does 1 pass
skips NaN in coalesce() 4 pass
requires a one-character pad in str_pad(), as stringr does 1 pass
parses orders without a year into year 0, as lubridate does 1 pass
rejects a parse_date_time() order with a day but no month 1 pass
keeps fractional seconds and rejects other fractional periods, as lubridate does 1 pass
gives a datetime for a date plus hours, minutes, or seconds, as lubridate does 1 pass
buckets with ntile(x, n) 1 pass
parses orders without a year into year 0, and rejects a day without a month 1 pass
keeps fractional seconds and gives a datetime for a date plus hours 1 pass

Every comparison

Every comparison
Case Implementation Quantity Status
takes at most one argument in row_number(), as dplyr does DataFrame pass
takes x and a required n in ntile(), as dplyr does DataFrame pass
matches dates, datetimes, and times by value in isIn() DataFrame pass
serializes temporal isIn() lists DataFrame pass
matches dates and datetimes by value in isIn() SQLite pass
PostgreSQL pass
MySQL pass
skips NaN in coalesce(), as is_na() does DataFrame pass
skips NaN in coalesce() SQLite pass
PostgreSQL pass
MySQL pass
requires a one-character pad in str_pad(), as stringr does DataFrame pass
parses orders without a year into year 0, as lubridate does DataFrame pass
rejects a parse_date_time() order with a day but no month DataFrame pass
keeps fractional seconds and rejects other fractional periods, as lubridate does DataFrame pass
gives a datetime for a date plus hours, minutes, or seconds, as lubridate does DataFrame pass
matches dates and datetimes by value in isIn() Polars pass
skips NaN in coalesce() Polars pass
buckets with ntile(x, n) Polars pass
parses orders without a year into year 0, and rejects a day without a month Polars pass
keeps fractional seconds and gives a datetime for a date plus hours Polars pass

Limitations

Exclusions

  • isIn() with temporal lists on SQLite and coalesce() of numbers on PostgreSQL run in memory; the results are compared the same way.

Known differences

  • parse_date_time() with an order that has a day but no month: lubridate returns NA with a warning; phibble raises an error.
  • Errors where R errors: phibble raises an exception with its own message.

Reproduction

From the repository root
Rscript tests/r/edge_cases.R
PHIBBLE_TEST_PGSQL="pgsql:host=127.0.0.1;port=5432;dbname=postgres" PHIBBLE_TEST_PGSQL_USER=postgres PHIBBLE_TEST_MYSQL="mysql:host=127.0.0.1;port=3306" PHIBBLE_TEST_MYSQL_USER=root php vendor/bin/pest tests/ExprRTest.php
php -d extension=php_polars.so php vendor/bin/pest tests/Polars/PolarsExprRTest.php
Raw record
site/verifications/expression-edge-cases.json
Input data
tests/r/edge_cases.R