NAME

DBIO::SQLMaker::ClassicExtensions - Class containing generic enhancements to SQL::Abstract

VERSION

version 0.900004

DESCRIPTION

This module is not intended to be used standalone. Instead it represents a quasi-role, that one would "mix in" via classic @ISA inheritance into a DBIO::SQLMaker-like provider. See "connect_call_rebase_sqlmaker" in DBIO::Storage::DBI for more info.

Currently the enhancements over SQL::Abstract are:

  • Support for JOIN statements (via extended table/from support)

  • Support of functions in SELECT lists

  • GROUP BY/HAVING support (via extensions to the order_by parameter)

  • A rudimentary multicolumn IN operator

  • Support of ...FOR UPDATE type of select statement modifiers

METHODS

_quoting_enabled

_quote_chars

belch

puke

_quote

_where_op_NEST

select

_assemble_binds

_lock_select

insert

_upsert_attempted_sql

my $sql = $sqlmaker->_upsert_attempted_sql('updated_at');
# EXCLUDED."updated_at"   -- PostgreSQL
# excluded."updated_at"   -- SQLite

Renders core's engine-neutral { -attempted => $column } marker — the value the statement tried to insert — as the engine's own reference to that pseudo-row. The one engine-specific piece of an upsert condition, and the only thing "_upsert_condition_sql" is parameterized over.

Core has no default. ADR 0036 pins the split: core stays abstract about the token and the driver SQLMaker renders it, so there is nothing generic to fall back on here and guessing one engine's spelling for another is worse than throwing. The throw is a developer-facing guard for a driver that declared supports_upsert without spelling its token; it is not reachable from the public API, because core never routes an on_conflict structure to a SQLMaker whose storage has not declared the capability.

A driver implements it once and uses it for both places the marker can appear — the set list and the conditional branch — so the two halves of the same statement can never spell it differently.

_upsert_condition_sql

my ($sql, @bind) = $sqlmaker->_upsert_condition_sql(\%cond, $table);

Renders the condition of an upsert's conditional conflict branch — update_where, ADR 0036 section 1. Returns the bare condition without the WHERE keyword, like _recurse_where does, plus its bind values; the driver's own conflict builder splices both in where its grammar wants them.

$table is the target table the statement inserts into. Pass it and every bare (stored-side) column in the condition is qualified with it (see below); it is optional, and omitting it renders the pre-k205 unqualified condition.

Two vocabularies, both engine-neutral:

  • an unqualified column is the stored row — the row the statement collided with. In an ON CONFLICT DO UPDATE branch that row shares the scope with the attempted-values pseudo-row (EXCLUDED / excluded), so a bare column is ambiguous to the engine — PostgreSQL rejects it outright ("column reference is ambiguous"). Given $table, every bare (single-part) column is therefore qualified with the target table, at any depth. An already-qualified column (it carries its own table part) and the { -attempted } marker are left exactly as they are.

  • { -attempted => $column } is the value the statement tried to insert, rendered by "_upsert_attempted_sql". Unlike in the set list, where it is only ever a top-level value, here it may appear at any depth.

# with $table = 'artist':
{ updated_at => { '<' => { -attempted => 'updated_at' } } }
# "artist"."updated_at" < EXCLUDED."updated_at"   -- the last-write-wins guard

A literal (\'excluded.rank > artist.rank' or \[ $sql, @bind ]) passes through untouched, for conditions the abstract form cannot express.

_recurse_fields

_parse_rs_attrs

_order_by

_split_order_chunk

_table

_generate_join_clause

_recurse_from

_gen_from_blocks

_from_chunk_to_sql

_join_condition

_where_op_multicolumn_in

apply_limit

$sql = $self->apply_limit($sql, $rs_attrs, $rows, $offset);

Applies LIMIT/OFFSET to a SELECT statement. The default implementation uses the SQL standard LIMIT ? OFFSET ? syntax supported by PostgreSQL, SQLite, and most modern databases.

Database drivers override this method to provide their own syntax. For example, MySQL uses LIMIT ?, ? (offset-first), Oracle uses ROWNUM, and SQL Server uses ROW_NUMBER() OVER().

_rno_default_order

_SkipFirst

_FirstSkip

_RowNum

_prep_for_skimming_limit

_Top

_FetchFirst

_GenericSubQ

_subqueried_limit_attrs

_unqualify_colname

AUTHOR

DBIO & DBIx::Class Authors

COPYRIGHT AND LICENSE

Copyright (C) 2026 DBIO Authors Portions Copyright (C) 2005-2025 DBIx::Class Authors Based on DBIx::Class, heavily modified.

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.