Revision history for DBIx-Squirrel

Unreleased

v3.0.2 2026-11-14

    Version 3: a statement is a source for Ekorn::Pipeline, and a sink
    given last turns it into a result.

    An iterator is a source for Ekorn::Pipeline, reading only as many
    rows as it needs, with Ekorn's | and @{}, and saying how its run
    ended (roadmap 2026-0014). Its stages' Context, pluck and as_hash
    work wherever a statement is read (roadmap 2026-0015). A call
    taking stages, the Sugar's statements included, gives a sink's
    result when a sink is last, and otherwise an iterator, and the
    select methods take stages too (roadmap 2026-0016). first is new,
    and single and all give what's left of a run. DBIx::Squirrel uses
    Ekorn::Pipeline as it is, so its own Pipeline and Pipes modules
    are no longer shipped (roadmap 2026-0017), and a Sugar statement's
    definition can name Ekorn's named pipelines (roadmap 2026-0018).
    DBIx::Squirrel::Stages::Flow passes on five more of Ekorn's
    stages, and a gather has a flush and an end.
    DBIx::Squirrel::Tooling exports every stage, sink and word a
    caller uses, from one module (roadmap 2026-0025). Rows are fetched
    in batches that grow, as in version 1, so reading one row of wide
    rows is about 20 times quicker (roadmap 2026-0014), and next is
    about 17% quicker (roadmap 2026-0022). An object given as a bind
    value is bound as a value. The how-to is rewritten as a user guide
    (roadmap 2026-0021), and the reference for version 3 (roadmap
    2026-0023).

    Most code written for 2.x runs as it did. It breaks where it uses
    count, reads all for a count, relies on single croaking at a
    second result or running the statement again, takes a stage for a
    code reference, reads a Sugar statement given stages as a list or
    a count, or uses DBIx::Squirrel::Pipeline, or DBIx::Squirrel::Stop
    as a class. "Upgrading from 2.x", in
    DBIx::Squirrel::Manual::Reference, lists each change and how to
    move. To stay on 2.x, install its last version:
    cpanm DBIx::Squirrel@2.1.0.

    - DBIx::Squirrel::Tooling, new: everything a caller uses to do
      work, from one module, by Ekorn::Pipeline::Tooling's tags, :core,
      :flow, :batch, :taps, :stages, :sources, :sinks, :json
      (from_json, from_jsonl, to_json, to_jsonl, from
      Ekorn::Pipeline::JSON), :words and :all, with :rows (pluck,
      as_hash) and :context (iterator, result_number, result_original)
      besides, :stages including :rows. It exports nothing by default.
      Where DBIx::Squirrel and Ekorn::Pipeline both export a name, it's
      DBIx::Squirrel's, which today is the same sub. The README, the
      reference and the user guide import from it, so their examples
      carry no imports of their own, and each has a section on it
      (roadmap 2026-0025).
    - An iterator is a source, which a pipeline of Ekorn::Pipeline's can
      read, passing on the statement's columns as the run's context. Its
      stages are run by Ekorn::Pipeline.
    - Rows are fetched 2 at first, then twice as many each time a fetch
      fills its batch, up to 64, as in version 1, rather than 100 at a
      time. Reading one row of wide rows is about 20 times quicker.
    - first, new: the next result, or undef, finishing the statement.
    - ended, new: how the last run ended, done, stopped or died.
    - | and @{}, new, as Ekorn::Pipeline's sources have them, where
      use Ekorn::Pipeline::Operators is in scope: $it | keep_all gives
      an array reference of the results, $it | count_items a number,
      and @$it every result. | always gives one value. Each use runs
      the statement afresh, as the iterator's own run.
    - iterate and results, on either handle, give a sink's result when
      the last stage is one of Ekorn::Pipeline::Sinks' sinks:
      keep_all a list, or an array reference for one value;
      count_items, keep_first, keep_last and keep_single their value.
      result_number counts in the stages before the sink, as it does
      for all.
    - A Sugar statement, or a database's function, given stages gives
      an iterator, or, with a sink last, the sink's result, in place of
      every result, or how many in scalar context.
    - The select methods take stages after the bind values, and push
      what the DBI gives through them: every value that comes out, or,
      for one value, a sink's result, or how many. selectall_array
      pushes each row.
    - DBIx::Squirrel::Pipeline is no longer shipped: make a pipeline
      with Ekorn::Pipeline->new. DBIx::Squirrel::Pipes is no longer
      shipped: the handles take pipe and tap from
      Ekorn::Pipeline::Pipes. Installing never removes a file, so a
      copy that 2.x installed still loads until it's deleted, and code
      using it runs as it did.
    - DBIx::Squirrel::Stop still exports Stop, but is no longer a
      class: throw with Ekorn::Pipeline::Stop->throw, and subclass
      Ekorn::Pipeline::Stop.
    - A Sugar statement's definition can give a pipeline's name, as
      Ekorn::Pipeline's named names them, among its stages, looked up
      as the statement is defined, in the package defining it. A
      string given when the statement is called is a bind value, as
      before. Its message for anything else is now "Expected only
      stages after the statement for %s: code references, pipelines or
      their names, or objects offering a stage's role method".
    - The README, the user guide, the reference and the modules' POD
      are swept, as Ekorn::Pipeline's were for its v0.3.0: the
      reference names every function the modules document, older
      terms are gone, paragraphs are filled to 70 columns, examples
      give a pipeline a stage to a line, and the reference has a
      section for developers, Making each kind of part, with worked
      examples of a stage for rows and a sink into a table.
    - The reference is rewritten for version 3, in the user guide's
      order, with every example run, the protocols other code can rely
      on, the run's context among them, and upgrading from 2.x
      (roadmap 2026-0023).
    - The README describes version 3: sinks given last, first,
      take_if, |, a Sugar statement giving an iterator, and upgrading
      from 2.x.
    - The how-to is rewritten as a user guide, DBIx::Squirrel's
      layers from the DBI up, with recipes that print what their
      comments say, comparisons with the alternatives, and answers to
      the questions people ask first, speed included (roadmap
      2026-0021).
    - pluck, as_hash and result_original work in any run reading a
      statement: through |, or in a pipeline of your own, as well as
      in an iterator's own stages. result_number and iterator are
      undef there, as only an iterator's own stages are counted.
    - next is about 17% quicker, and a stage or a sink 4 to 6%, as
      less is done around each row (roadmap 2026-0022).
    - single gives the next result, or undef, and finishes the
      statement. At a second result, it warns "Expected only one item,
      but there were more", and gives the first, rather than croak. It
      no longer executes the statement again: reset first for that.
    - all, asked for one value, gives an array reference of the
      results, not how many there were.
    - count is gone.
    - take_first, take_last and take_single, from
      DBIx::Squirrel::Stages::Flow on request: each passes on what the
      sink of the same name, keep_first, keep_last or keep_single,
      would give, so the stages after it go on. take_single warns at a
      second value, for a SELECT that forgot LIMIT 1. They're
      Ekorn::Pipeline's, which must have them.
    - take_if and drop_if, from DBIx::Squirrel::Stages::Flow on
      request: each passes on the values its block is true, or false,
      of, testing every one, as grep does. They're Ekorn::Pipeline's.
    - A gather's block returns the stage, and optionally a flush and an
      end, as Ekorn::Pipeline v0.3.0 has them. The flush is what was
      called the end function. The end, new, is called once the run has
      ended, told how: done, stopped or died. A block returning
      anything else croaks "Expected stage #%s, made with gather, to
      return a code reference or a pipeline, and optionally a flush and
      an end".
    - A stage made with gather is an object that can go wherever a
      stage can, and no longer a code reference.
    - A gather's block can return its parts by name, as one hash
      reference with the keys step, flush and end, giving only those
      it has, as Ekorn::Pipeline v0.3.0 allows.
    - An object given as a bind value is a value, as the DBI binds it,
      whatever it's made of. A blessed hash first, such as a DateTime,
      was taken for the attributes, so nothing was bound and the query
      quietly found nothing; a blessed array was unwrapped as a list of
      values; and a blessed scalar croaked "Expected a reference to a
      HASH or ARRAY". In a Sugar statement's definition, an object
      straight after the SQL is no longer taken for the attributes: one
      that isn't a stage croaks, as anything else there does.
    - Two of Ekorn::Pipeline's messages, which DBIx::Squirrel passes
      on, say what a stage and a source are, as of Ekorn::Pipeline
      v0.3.0: "Expected stage #%d to be a stage: a code reference, a
      pipeline, or an object offering a stage's role method", for what
      isn't a stage, and "Expected a source: a code reference, or an
      object offering EKORN_SOURCE", from a pipeline's iterator. Code
      matching the old wording needs updating.
    - Three messages say what their conditions test: the iterator's
      "Expected a DBIx::Squirrel statement handle", not "Expected a
      statement handle"; pluck's and as_hash's "Expected a statement to
      read, for the column names", not "Expected an iterator, ..."; and
      the Sugar's "Expected a database named %s", not "Expected a
      database defined as %s". Code matching the old wording needs
      updating.
    - Requires Ekorn::Pipeline v0.3.0 or later, below v0.4.0, for its
      Tooling, a gather's flush and end, and the two messages' wording.

v2.1.0 2026-11-10

    A pipeline goes wherever a stage goes, and the docs read plainly.

    A pipeline can go wherever a stage goes (roadmap 2026-0004), and
    the messages for a bad stage say so. The docs are rewritten in
    plainer, shorter sentences (roadmap 2026-0005), and the manuals
    link to Ekorn::Pipeline's by module name (roadmap 2026-0002).
    Every claim in the reference now has a test (roadmap 2026-0007),
    and the how-to is rebuilt to answer a newcomer's questions (roadmap
    2026-0008).

    - iterate, results, an iterator's reset, and Sugar's statements and
      functions take a pipeline among their stages. Before, they took
      only code references, and a pipeline there was taken for a bind
      value. Its stages run in its place, in the same run, so a take(2)
      inside it gives two results in all (roadmap 2026-0004).
    - A gather block can return a pipeline as its stage.
    - Error messages name a stage inside a pipeline by its place, such
      as #2.3 for the third stage of a pipeline given as the second.
    - Sugar's message for something other than a stage after a
      statement's definition says what a stage is: "Expected only code
      references or pipelines after the statement for %s", not
      "Expected only stages after the statement for %s".
    - Two of Ekorn::Pipeline's messages, which DBIx::Squirrel passes on,
      say a stage can be a pipeline, as of Ekorn::Pipeline v0.2.0:
      "Expected stage #%d to be a code reference or a pipeline", and
      "Expected stage #%s, made with gather, to return a code reference
      or a pipeline, and optionally an end function". Code matching the
      old wording needs updating.
    - The README, the POD and the reference are rewritten in plainer,
      shorter sentences. What they say is unchanged, and so are their
      examples and DIAGNOSTICS entries (roadmap 2026-0005).
    - The reference and the how-to, as POD manuals, link to
      Ekorn::Pipeline's manuals by module name, not to GitHub, so a
      reader on MetaCPAN or in perldoc stays there (roadmap 2026-0002).
    - The reference says where a pipeline can be given, that a stage of
      your own can be one, and where a stage belongs. Each claim it
      makes has a test, in t/23-documented.t (roadmap 2026-0007).
    - The how-to is rebuilt by task: it says who each part is for, and
      has a tested recipe for every topic in the reference, from
      transactions and handle classes of your own to moving from 1.x
      and writing stages for others (roadmap 2026-0008).
    - Requires Ekorn::Pipeline v0.2.0 or later, below v0.3.0: v0.1.3
      for is_stage and a pipeline among its stages, and v0.2.0 for the
      two messages' wording.

v2.0.5 2026-11-08

    The successor to 1.6.5: a rewrite in modern Perl.

    The reference and the how-to ship as POD manuals, so MetaCPAN and
    perldoc have them with the modules (roadmap 2026-0001).

    Code written for 1.x needs changes to run. "Upgrading from 1.x", in
    DBIx::Squirrel::Manual::Reference, lists them. To stay on 1.x, which
    supports older Perls, install its last version:
    cpanm DBIx::Squirrel@1.6.5. Its code is archived at
    https://github.com/nukopian/DBIx-Squirrel-1.

    - Requires Perl 5.36 or later. Compress::Bzip2, Crypt::CBC, Dotenv,
      JSON::Syck and YAML::Syck are no longer dependencies, and loading
      the module no longer reads a .env file.
    - Placeholders in the styles ?, ?1, :1, $1, :name and $name, one
      style to a statement, each rewritten as ? for the DBI. Quoted
      strings and identifiers, comments, casts and PostgreSQL's
      dollar-quoted bodies are left alone, read by the database's rules;
      the ekorn_dialect attribute names the database behind DBD::ODBC
      or DBD::Proxy. DBD::Pg's placeholder options are followed.
      Comments are passed on to the database, where 1.x removed them.
    - A numbered or named placeholder takes one value wherever it
      appears. Numbers are written in the digits 0-9: a digit of another
      script is part of a name, there and in get_column, pluck and
      bind_param, rather than read as 0. Named values come as pairs or
      in a hash reference, with or without the sigil, and an array
      reference stands for the values in it. Values that don't match
      the placeholders croak, and so does executing a statement with
      some left unbound.
    - A placeholder with "..." before it, such as ...:ids or ...?, takes
      a list, written as a ? for each of its values, for IN and anywhere
      else SQL takes a list. The statement is prepared with its values,
      by do, the select methods, iterate, results and Sugar's functions;
      prepare and prepare_cached croak given one, and so do an empty
      list and a list holding a reference. To a statement whose one
      value is a list, a single array reference is the list. An
      iterator's reset prepares the statement again for a list of
      another length.
    - A statement can be a string, lines in an array reference, a code
      reference returning either, or a statement handle.
    - do and the select methods take bind values without the
      attributes in front. do returns what the DBI's do returns, in any
      context: 1.x also returned the statement handle in list context.
    - connect and prepare croak if they fail, whatever RaiseError says.
      connect clones a database handle given in place of a data source.
    - Errors, and the DBI's warnings, are reported at the line that
      called DBIx::Squirrel, naming the method called, as plain DBI
      reports them.
    - iterate returns a DBIx::Squirrel::Iterator, replacing
      DBIx::Squirrel::it, with next, all, single, reset, count, column_names and
      sth, and no aliases. next no longer sets $_, and single croaks on a
      second result, where 1.x warned. Rows are fetched 100 at a time,
      in the shape the ekorn_slice attribute gives, replacing slice,
      cache_size and their defaults; all, without stages, fetches the
      rest at once, close to the DBI's own speed. column_names gives the
      statement's column names, read when it's executed, as DBD::mysql
      gives none once the last row is fetched.
    - Stages, 1.x's transformations, follow the bind values. Each takes
      a value as its argument and in $_, and returns nothing to drop it,
      one value, or several. Stop, from DBIx::Squirrel::Stop, ends a
      pipeline early, and DBIx::Squirrel::Context gives a stage its
      iterator, result_number and result_original.
    - DBIx::Squirrel::Pipeline runs any values through stages, and pipe
      and tap run a database or statement handle through them.
      A pipeline's stages method returns its stages, to give wherever
      stages go, with more after them.
    - Once a stage dies, an iterator or result set has ended: next and
      all return nothing more, and the statement is finished; reset
      runs it again from the start.
    - gather, from DBIx::Squirrel::Gather, makes a stage afresh for each
      run of its pipeline, from a block returning the stage and,
      optionally, a function called once the values run out, whose
      values go through the rest of the stages. A stage can batch rows,
      make one value from all of them, or keep a count that starts
      again on each execution.
    - Canned stages, each module exporting its usual ones:
      DBIx::Squirrel::Stages::Flow's take and drop, with take_while and
      drop_while on request; DBIx::Squirrel::Stages::Rows's pluck and
      as_hash, for rows of any shape; DBIx::Squirrel::Stages::Batch's
      batch and collect, passing values on in batches, or all at once;
      and DBIx::Squirrel::Stages::Taps's peek and count_into, with
      dump_to on request, looking at values as they go by.
    - The pipeline is Ekorn::Pipeline, a distribution of its own, which
      began here, and which DBIx::Squirrel requires, from v0.1.1 up to,
      but not including, v0.2.0. DBIx::Squirrel::Pipeline, Stop, Gather
      and Pipes, and the stages in DBIx::Squirrel::Stages::Flow, Batch
      and Taps, are DBIx::Squirrel's names for its modules, and stay:
      each is a subclass of Ekorn's, or exports Ekorn's functions, from
      a list of its own. A stage that catches errors throws a stop on if
      it isa Ekorn::Pipeline::Stop, which every stop is, including those
      the canned stages throw.
    - results returns a DBIx::Squirrel::Results, replacing
      DBIx::Squirrel::rs, whose rows are DBIx::Squirrel::Result objects,
      replacing DBIx::Squirrel::rc: one class for each list of column
      names, with a method for each column, in lower case. get_column
      takes a name or a position, and the ekorn_result_class attribute
      sets the rows' base class.
    - DBIx::Squirrel::Sugar replaces database_entities: a function for
      each database, connected when it's first used, and for each
      statement, with stages of its own.
    - prepare_cached keeps apart statements rewritten the same, such as
      SELECT :a, :b and SELECT :b, :a, and never hands out a handle an
      iterator is part way through.
    - The ekorn_finish_active attribute finishes a statement still
      active before executing it again.
    - Attributes starting ekorn_ aren't passed on to the DBI. Given to
      connect, they're the defaults for every statement the handle
      prepares.
    - use DBIx::Squirrel takes the names the DBI exports, such as
      :sql_types, as use DBI does.
    - The reference and the how-to ship as POD,
      DBIx::Squirrel::Manual::Reference and DBIx::Squirrel::Manual::HowTo,
      made from their Markdown, so MetaCPAN and perldoc have them with
      the modules (roadmap 2026-0001).
    - SECURITY.md says how to report a vulnerability, privately, and
      CONTRIBUTING.md how to report a bug or ask for a feature; the
      distribution takes issues, not pull requests.
    - Gone, as out of scope: DBIx::Squirrel::Crypt::Fernet, the
      DBIx::Squirrel::Transform modules for JSON and YAML, load_tuples,
      and the file and encoding helpers in DBIx::Squirrel::util. Those
      for Data::Dumper and IO give way to dump_to and peek.
