Skip to content

QB Extention - #2

Open
enlivenapp wants to merge 1 commit into
KnifeLemon:masterfrom
enlivenapp:master
Open

enlivenapp wants to merge 1 commit into
KnifeLemon:masterfrom
enlivenapp:master

Conversation

@enlivenapp

Copy link
Copy Markdown

Alrighty... what a minefield. lol

As we discussed in #1 here's what I've done as I understand what you were interested in seeing and wanted, if I missed anywhere, please let me know and I'll get it fixed. I parked the CHANGELOG list in Unreleased so I'm not guessing.

Select / aggregates

  • selectSum(), selectAvg(), selectMin(), selectMax(), selectCount() with optional alias
  • distinct()
  • selectSubquery(Builder, $alias = '') and fromSubquery(Builder, $alias) (alias required) with correctly ordered parameters

Conditions

  • whereIn(), orWhereIn(), whereNotIn(), orWhereNotIn(): accept an array or a subquery Builder
  • like(), orLike(), notLike(), orNotLike(): value is bound (LIKE ?), wildcards escaped, explicit ESCAPE '!'; positions both / before / after / none. Existing ['LIKE', ...] array form is untouched.
  • groupStart(), orGroupStart(), notGroupStart(), groupEnd(): balanced, helpful error on unbalanced
  • having(), orHaving()

Joins / unions

  • rightJoin()
  • union(), unionAll()

Writes

  • insertBatch(), upsertBatch(), updateBatch(), deleteBatch()

Builder

  • when(), whenNot()
  • build(bool $reset = false): opt-in reset (default behavior unchanged)
  • orderBy($column, ?string $direction = null): second form validates the column with safeIdentifier() and restricts direction to ASC/DESC; the existing single-argument expression form still works. Multiple calls replace (same for both forms).

Misc

Things I ran across while building this that you might want to lay eyes on and decide if you want to do anything with. I've left all of it alone.

  1. getParams() is unchanged. It still returns only WHERE-bound parameters and does not include the new-feature params (data, HAVING, select-subqueries, UNION). The full list is always in build()['params']. I left it as-is for BC rather than change its return value; if you'd rather it match build()['params'], that's a separate change.
  2. clearAll() still preserves the action. The new build(true) clears then resets the action to SELECT as an extra step, so the opt-in reset is fully reusable. Documented in the README plus a dedicated test.
  3. QueryLogger / Tracy panel: the logged where remains array<string> and the panel rendering is unchanged, for BC. Consequence: grouped conditions (groupStart() etc.) render imperfectly in the debug panel (implode(' AND ') over ( ... )). Debug only, no SQL impact.
  4. upsertBatch() emits VALUES(col), matching the existing onDuplicateKeyUpdate() docs. That form is deprecated in MySQL 8.0.20+ in favor of row aliases, so switch it if you want the newer syntax.
  5. insertBatch() / upsertBatch() require every row to have identical columns in the same order (rejects ambiguity rather than silently reordering).

Internal changes (no output change for existing usage)

  • WHERE conditions are stored as structured parts ({join, sql}) to support nesting and HAVING; parameter assembly is centralized so SELECT subquery/FROM/HAVING/UNION params stay in SQL order.
  • buildSQL() now shares the SELECT compiler (compileSelect()) with build(); identical output for pre-existing inputs, plus DISTINCT/HAVING/subqueries when those features are used.
  • QueryLogger gained a null-coalescing metric-key guard so the new batch actions don't warn on unknown keys.

Testing

  • composer test: 175 tests(+36), 345 assertions(+85), 1 environment-skipped (the "logging disabled" panel branch needs Tracy absent).
  • composer phpstan: at level-max.
  • Coverage: overall 99.02% lines; Builder 99.10%, BuilderRaw 100%, QueryLogger 100%, QueryPanel 98.26%. I've pulled coverage up as high as reasonably possible.
  • Targets PHP 7.4 (no PHP 8-only syntax). Tested on PHP 8.3.

…, groups, HAVING, unions, batch writes, BC compat preserved.

Added:
- selectSum/selectAvg/selectMin/selectMax/selectCount with optional alias
- distinct()
- selectSubquery()/fromSubquery() with correctly ordered parameters
- whereIn/orWhereIn/whereNotIn/orWhereNotIn (array or subquery Builder)
- like/orLike/notLike/orNotLike (value bound as LIKE ?, wildcards escaped, explicit ESCAPE '!', positions both/before/after/none)
- groupStart/orGroupStart/notGroupStart/groupEnd with unbalanced-group error
- having()/orHaving()
- rightJoin()
- union()/unionAll()
- insertBatch()/upsertBatch()/updateBatch()/deleteBatch()
- when()/whenNot()
- build(bool $reset = false) opt-in reset
- orderBy($column, ?string $direction = null) validated second form (safeIdentifier + ASC/DESC)
- tests/BuilderExtensionsTest.php, tests/QueryLoggerTest.php, tests/QueryPanelTest.php, BuilderRaw::__toString coverage

Fixed:
- count() no longer leaks select-subquery params into COUNT (placeholder/param mismatch)
- count() emits JOIN clauses again (restore original behavior)
- delete() no longer uses fromSubquery (was emitting invalid DELETE FROM (subquery) and dropping params)
- QueryLogger metric-key guard so new batch actions don't warn on unknown keys
- updateBatch() missing-WHERE-column test now exercises the intended check

Changed:
- WHERE conditions stored as structured {join, sql} parts to support groups and HAVING
- buildSQL() now shares compileSelect() with build()
- clearAll() clears the new builder state (selectParams/fromParams/having/unions/distinct/fromSubquery/batch)

See CHANGELOG.md and README.md for more details.
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