Skip to content

merge dev to main (v3.4.6)#2478

Merged
ymc9 merged 5 commits intomainfrom
dev
Mar 11, 2026
Merged

merge dev to main (v3.4.6)#2478
ymc9 merged 5 commits intomainfrom
dev

Conversation

@ymc9
Copy link
Copy Markdown
Member

@ymc9 ymc9 commented Mar 11, 2026

Summary by CodeRabbit

  • Bug Fixes

    • Fixed JSON equality filtering to properly handle undefined and null values
    • Enhanced the "now" function to support database-specific SQL implementations
    • Improved "not: null" filter handling for better query results
  • Tests

    • Added tests for not-null shorthand filtering behavior
    • Added tests validating "now" function in policy scenarios
    • Added regression test for "not: null" filtering

Version: 3.4.6

ymc9 and others added 5 commits March 8, 2026 23:11
- Fill now() default in evalGenerator so createdAt fields are populated
  before policy checks, preventing DefaultInsertValueNode from being
  treated as null during pre-create policy evaluation.
- Fix now() SQL function to produce ISO 8601 format matching each
  dialect's DateTime storage format (SQLite: strftime, MySQL:
  DATE_FORMAT with trimmed microseconds), ensuring correct comparisons
  in policy expressions.
- Add e2e tests for now() in create, read, update, and delete policies.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: ymc9 <104139426+ymc9@users.noreply.github.com>
@claude
Copy link
Copy Markdown
Contributor

claude bot commented Mar 11, 2026

Claude finished @ymc9's task —— View job


PR Review: merge dev to main (v3.4.6)

I'll review this pull request focusing on code quality, potential bugs, performance considerations, security concerns, and test coverage.

Todo List:

  • Analyze the substantive code changes (beyond version bumps)
  • Review ORM package changes in base-dialect.ts, postgresql.ts, and functions.ts
  • Examine new test files and regression tests
  • Check for potential bugs, security issues, and performance problems
  • Provide comprehensive feedback

Review Summary

This is a release PR containing 3 main bug fixes and version bumps. The changes look solid overall, with good test coverage for the fixes.

🔧 Code Changes Analysis

1. Null Comparison Fix (Issue #2472)

File: packages/orm/src/client/crud/dialects/base-dialect.ts:770-774

Good:

  • Correctly uses SQL IS operator for null comparisons instead of =
  • Proper separation of undefined (no-op) vs null (IS NULL) handling
  • Comprehensive test coverage in both regression and E2E tests

Minor Concern:
The function was renamed from buildLiteralFilter to buildValueFilter - this is a good improvement for clarity, but ensure this isn't a breaking change for any extending dialects.

2. Now() Function Policy Support

Files: packages/orm/src/client/functions.ts:112-124, packages/orm/src/client/crud/operations/base.ts:1108

Excellent:

  • Database-specific ISO 8601 format handling for different dialects:
    • SQLite: strftime('%Y-%m-%dT%H:%M:%fZ')
    • MySQL: Complex format concatenation for 3-digit milliseconds
    • PostgreSQL: Native CURRENT_TIMESTAMP
  • Proper default value generation in evalGenerator for policy evaluation
  • Comprehensive test coverage across all CRUD operations

Performance Note:
The MySQL implementation uses CONCAT(SUBSTRING(...)) which is acceptable but slightly complex. Consider monitoring query performance if this becomes a bottleneck.

3. Webpack Bundler Warning Fix

File: packages/orm/src/client/crud/dialects/postgresql.ts:40

Good:

  • Simple addition of webpackIgnore: true magic comment
  • Prevents bundler analysis warnings for optional pg dependency
  • No functional impact, purely build-time optimization

🧪 Test Coverage - Excellent

Strong points:

  • New regression test specifically for issue Filtering by not: null not working #2472 with multiple field types
  • Comprehensive now() function tests covering all CRUD operations
  • Tests include edge cases like auth + now() combinations
  • Both positive and negative test cases included

🔒 Security Assessment - No Issues

  • No new attack vectors introduced
  • Null handling improvements actually improve security by preventing SQL injection edge cases
  • Time function changes use database-native functions, not user input

🚀 Performance Considerations

Potential optimizations:

  • The MySQL now() implementation is complex but necessary for format compatibility
  • New IS NULL comparisons may perform slightly better than = NULL (which always returns NULL)

📋 Recommendations

  1. Consider adding JSDoc comments for the new buildValueFilter method explaining the null vs undefined handling
  2. Monitor MySQL performance with the complex now() concatenation in production
  3. Version bumps look correct - all packages consistently bumped to 3.4.6

Overall Assessment

Excellent release PR with:

  • Well-tested bug fixes
  • Proper SQL standard compliance (IS NULL vs = NULL)
  • Database-specific optimizations
  • No breaking changes
  • Good documentation in commit messages

Ready for merge - no blocking issues identified.


@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 11, 2026

📝 Walkthrough

Walkthrough

This PR bumps the monorepo version to 3.4.6 across all packages, enhances ORM JSON filtering to handle undefined and null values explicitly, introduces dialect-specific now() function implementations for SQLite, MySQL, and PostgreSQL, and adds test coverage for not-null filtering and policy-based now() scenarios.

Changes

Cohort / File(s) Summary
Package Version Bumps
package.json, packages/auth-adapters/better-auth/package.json, packages/cli/package.json, packages/clients/*/package.json, packages/common-helpers/package.json, packages/config/*/package.json, packages/create-zenstack/package.json, packages/ide/vscode/package.json, packages/language/package.json, packages/orm/package.json, packages/plugins/policy/package.json, packages/schema/package.json, packages/sdk/package.json, packages/server/package.json, packages/testtools/package.json, packages/zod/package.json, samples/orm/package.json, tests/e2e/package.json, tests/regression/package.json, tests/runtimes/*/package.json
Updated all package versions from 3.4.5 to 3.4.6 across the monorepo.
ORM JSON Filtering Enhancement
packages/orm/src/client/crud/dialects/base-dialect.ts
Replaced literal-filter calls with value-filter logic to handle undefined/null RHS cases; undefined yields no-op true, null yields IS NULL check, otherwise uses standard equality.
PostgreSQL Bundler Configuration
packages/orm/src/client/crud/dialects/postgresql.ts
Added webpackIgnore directive to dynamic pg module import to suppress bundler analysis warnings.
Generator and Function Enhancements
packages/orm/src/client/crud/operations/base.ts, packages/orm/src/client/functions.ts
Added support for "now" generated value function; implemented dialect-aware now() with SQL-specific constructs (ISO timestamps via CURRENT_TIMESTAMP, DATETIME, or NOW()).
Not-Null Filtering Tests
tests/e2e/orm/client-api/filter.test.ts, tests/regression/test/issue-2472.test.ts
Adds test cases validating not: null shorthand filter for string and numeric fields; includes regression tests for nullable field filtering with findMany queries.
Policy Now-Function Tests
tests/e2e/orm/policy/now-function.test.ts
New test suite validating now() function behavior across create, update, read, and delete policy scenarios with authentication checks.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • #2462: Modifies the same packages/orm/src/client/crud/dialects/base-dialect.ts file with related filtering and existence logic changes.

Poem

🐰 Version three-point-four-point-six now hops around,
With filters that handle null without a sound,
The now() function speaks each dialect's tongue,
From SQLite to Postgres, the improvements are sung!
Tests ensure our not-nulls dance just right. 🐇✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title clearly describes the main change: merging development branch to main with version bump to 3.4.6, which matches the extensive version updates across all package.json files and the functional enhancements in the changeset.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch dev

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/orm/src/client/crud/operations/base.ts (1)

1085-1109: ⚠️ Potential issue | 🟠 Major

Use one clock source for @default(now()) and policy now().

This new branch stamps defaults with new Date(), but policy now() in packages/orm/src/client/functions.ts:112-124 is evaluated in SQL. On deployments where the app host and database clocks drift, rules like @@allow('create', createdAt <= now()) can reject freshly created rows intermittently. Please route both paths through the same database-side timestamp source.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/orm/src/client/crud/operations/base.ts` around lines 1085 - 1109,
The evalGenerator currently returns a JS Date for the 'now' default which
mismatches the policy now() (evaluated in SQL); update the 'now' branch inside
evalGenerator in base.ts to produce the same DB-side timestamp expression used
by the policy (use the same SQL-now helper/function used by
packages/orm/src/client/functions.ts: now()), and pass that SQL-now expression
into formatGeneratedValue instead of new Date() so both `@default`(now()) and
policy now() use the identical database clock source.
🧹 Nitpick comments (3)
tests/regression/test/issue-2472.test.ts (1)

16-16: Disconnect the regression test clients.

Both cases allocate a fresh client and never close it. That can leave open handles on PostgreSQL/MySQL runs; adding afterEach or try/finally cleanup keeps this consistent with the other test suites.

Also applies to: 35-41

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/regression/test/issue-2472.test.ts` at line 16, The test allocates
database clients via createTestClient but never closes them; modify the test to
ensure each created client is disconnected after use by either wrapping uses of
createTestClient in a try/finally that calls client.disconnect() (or the
appropriate close method) or by storing the client in a variable and adding an
afterEach hook that disconnects any non-null client; update both places where
createTestClient is called (the occurrence around the earlier call and the
second block covering lines ~35-41) and reference the created client variable
name so the disconnect/cleanup targets the same client instance.
tests/e2e/orm/policy/now-function.test.ts (1)

6-16: Disconnect each policy test client.

Every case creates a new policy client but none is closed. Please add afterEach or try/finally cleanup so this suite doesn't leak connections across provider runs.

Also applies to: 25-35, 51-61, 77-87, 101-116

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/e2e/orm/policy/now-function.test.ts` around lines 6 - 16, The policy
tests create DB clients via createPolicyTestClient but never close them; add
cleanup to avoid leaked connections by either (A) storing the returned client in
a variable and wrapping each test body in try/finally where you call
client.disconnect() in finally, or (B) push each created client into an array
and add an afterEach hook that iterates and calls disconnect() (or close() if
different) on each client; update all usages of createPolicyTestClient in this
file (the blocks that create Post models) to follow one of these patterns so
clients are reliably disconnected after each test.
packages/orm/src/client/functions.ts (1)

112-124: Avoid sql.raw in the shared now() helper.

These branches bake vendor SQL strings directly into the ORM layer. Prefer Kysely builders or push the provider-specific expression down into the dialects so the SQL stays behind the dialect abstraction.

As per coding guidelines, **/*.{ts,tsx}: Use Kysely query builder as escape hatch instead of raw SQL in ORM operations.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/orm/src/client/functions.ts` around lines 112 - 124, The now
ZModelFunction currently embeds vendor SQL via sql.raw in the 'sqlite', 'mysql',
and 'postgresql' match branches; replace this by either using Kysely expression
builders or delegating provider-specific SQL generation into the dialect layer
(i.e., move the sqlite/mysql/postgresql expressions out of
packages/orm/src/client/functions.ts and call a dialect method like
dialect.nowExpression() or use Kysely's function/expression helpers instead of
sql.raw) so the ORM layer no longer contains raw SQL strings and each branch
(sqlite, mysql, postgresql) returns a Kysely-compatible expression or calls the
dialect API.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/orm/src/client/crud/dialects/base-dialect.ts`:
- Around line 759-775: The MySQL override of buildJsonEqualityFilter still emits
JSON_CONTAINS for all cases and must honor the null/undefined fast-path; update
the mysql implementation of buildJsonEqualityFilter (the override in the MySQL
dialect) to reuse the base logic by either calling this.buildValueFilter(lhs,
'Json', rhs) or delegating to super.buildJsonEqualityFilter(lhs, rhs) so that
rhs === undefined returns this.true(), rhs === null returns this.eb(lhs, 'is',
null), and only otherwise emits the JSON_CONTAINS/equals expression; ensure you
reference the existing buildValueFilter/transformInput/eb helpers so behavior
matches the base-dialect fast-path.

---

Outside diff comments:
In `@packages/orm/src/client/crud/operations/base.ts`:
- Around line 1085-1109: The evalGenerator currently returns a JS Date for the
'now' default which mismatches the policy now() (evaluated in SQL); update the
'now' branch inside evalGenerator in base.ts to produce the same DB-side
timestamp expression used by the policy (use the same SQL-now helper/function
used by packages/orm/src/client/functions.ts: now()), and pass that SQL-now
expression into formatGeneratedValue instead of new Date() so both
`@default`(now()) and policy now() use the identical database clock source.

---

Nitpick comments:
In `@packages/orm/src/client/functions.ts`:
- Around line 112-124: The now ZModelFunction currently embeds vendor SQL via
sql.raw in the 'sqlite', 'mysql', and 'postgresql' match branches; replace this
by either using Kysely expression builders or delegating provider-specific SQL
generation into the dialect layer (i.e., move the sqlite/mysql/postgresql
expressions out of packages/orm/src/client/functions.ts and call a dialect
method like dialect.nowExpression() or use Kysely's function/expression helpers
instead of sql.raw) so the ORM layer no longer contains raw SQL strings and each
branch (sqlite, mysql, postgresql) returns a Kysely-compatible expression or
calls the dialect API.

In `@tests/e2e/orm/policy/now-function.test.ts`:
- Around line 6-16: The policy tests create DB clients via
createPolicyTestClient but never close them; add cleanup to avoid leaked
connections by either (A) storing the returned client in a variable and wrapping
each test body in try/finally where you call client.disconnect() in finally, or
(B) push each created client into an array and add an afterEach hook that
iterates and calls disconnect() (or close() if different) on each client; update
all usages of createPolicyTestClient in this file (the blocks that create Post
models) to follow one of these patterns so clients are reliably disconnected
after each test.

In `@tests/regression/test/issue-2472.test.ts`:
- Line 16: The test allocates database clients via createTestClient but never
closes them; modify the test to ensure each created client is disconnected after
use by either wrapping uses of createTestClient in a try/finally that calls
client.disconnect() (or the appropriate close method) or by storing the client
in a variable and adding an afterEach hook that disconnects any non-null client;
update both places where createTestClient is called (the occurrence around the
earlier call and the second block covering lines ~35-41) and reference the
created client variable name so the disconnect/cleanup targets the same client
instance.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: d948b428-0836-4f6c-8fc0-1a86a04d85c8

📥 Commits

Reviewing files that changed from the base of the PR and between 266106c and d4fbb38.

📒 Files selected for processing (31)
  • package.json
  • packages/auth-adapters/better-auth/package.json
  • packages/cli/package.json
  • packages/clients/client-helpers/package.json
  • packages/clients/tanstack-query/package.json
  • packages/common-helpers/package.json
  • packages/config/eslint-config/package.json
  • packages/config/typescript-config/package.json
  • packages/config/vitest-config/package.json
  • packages/create-zenstack/package.json
  • packages/ide/vscode/package.json
  • packages/language/package.json
  • packages/orm/package.json
  • packages/orm/src/client/crud/dialects/base-dialect.ts
  • packages/orm/src/client/crud/dialects/postgresql.ts
  • packages/orm/src/client/crud/operations/base.ts
  • packages/orm/src/client/functions.ts
  • packages/plugins/policy/package.json
  • packages/schema/package.json
  • packages/sdk/package.json
  • packages/server/package.json
  • packages/testtools/package.json
  • packages/zod/package.json
  • samples/orm/package.json
  • tests/e2e/orm/client-api/filter.test.ts
  • tests/e2e/orm/policy/now-function.test.ts
  • tests/e2e/package.json
  • tests/regression/package.json
  • tests/regression/test/issue-2472.test.ts
  • tests/runtimes/bun/package.json
  • tests/runtimes/edge-runtime/package.json

@ymc9 ymc9 merged commit 6ae3bcb into main Mar 11, 2026
15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant