[/
    Copyright (c) 2019-2024 Ruben Perez Hidalgo (rubenperez038 at gmail dot com)
   
    Distributed under the Boost Software License, Version 1.0. (See accompanying
    file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
]

[section:pipeline (Experimental) Pipelines]
[nochunk]

Functions like [refmemunq any_connection execute], [refmemunq any_connection prepare_statement]
and their async counterparts are half-duplex:
they write a single request to the server and wait for its response.
In contrast, pipelines can increase efficiency by coalescing several requests into a single message, saving round-trips to the server.

[warning
    The MySQL client/server protocol doesn't have explicit support for pipelines. [*From the server's point of view,
    a pipeline is just a sequence of unrelated requests]. The server will try to execute all stages
    in each pipeline, regardless of the result of previous stages. Pipelines are considered
    an [*advanced feature]. Please read [link mysql.pipeline.pitfalls the pitfalls section] for more info.
]

[note
    This feature is experimental. Its API may change in subsequent releases.
]

[heading Use cases]

You should use pipelines for lightweight operations, dominated by round-trip time. Typical examples include:

* Running connection setup code, involving operations like [refmemunq any_connection reset_connection],
  [refmemunq any_connection set_character_set] or preparing statements. [reflink connection_pool] uses
  pipelines to clean up connections for re-use.
* Preparing several statements, in batch.
* Executing and closing a statement in a single round-trip.


You should [*avoid] pipelines for the following cases:

* When you can achieve the same functionality using semicolon-separated queries
  (thus using [link mysql.multi_resultset.multi_queries multi-queries] and [link mysql.sql_formatting client-side SQL formatting]).
  Multi-queries will stop after the first error, which is usually what you want. See [link mysql.pipeline.pitfalls this section] for more info.
* When running heavyweight queries, where the gains in round-trip time are not significant.
* When there are dependencies between stages in the pipeline. Lack of protocol support makes this use case impossible.

If you're not sure, don't use this feature.






[heading Pipeline requests and responses]

To run a pipeline, create a [reflink pipeline_request] object describing what should the pipeline do:

[pipeline_request]

We're using [refmemunq pipeline_request add_execute] and [refmemunq pipeline_request add_prepare_statement]
to add stages to our pipeline. You can find all available stage types in the [link mysql.pipeline.reference reference section].

To actually run the pipeline, create a response object and call
[refmem any_connection run_pipeline] or [refmemunq any_connection async_run_pipeline]:

[pipeline_run]

Finally, you can access the statements using [refmem stage_response as_statement]:

[pipeline_results]

If your pipeline contains an execution stage, it will generate a `results` object
that can be accessed using [refmem stage_response as_results].




[heading:error Error handling]

If any of the pipeline stages result in an error, the entire [refmemunq any_connection run_pipeline] operation
is considered failed. This means that [*if `run_pipipeline` completed successfully, all stages succeeded]. Recall that
[*all stages are always run, regardless of the outcome of previous stages]. 

If `run_pipipeline` fails, you can check which stages succeeded and failed by inspecting responses.
[refmem stage_response error] and [refmem stage_response diag] will return error information about failed steps. For instance:

[pipeline_errors]




[heading:pitfalls Potential pitfalls]

All requests in the pipeline are always run, regardless of the outcome of previous requests. As a result, some pipelines can behave non-intuitively:

[pipeline_pitfalls_bad]

Pipelines aren't the best fit here. Instead, you can express the same logic using semicolon-separated queries:

[pipeline_pitfalls_good]

Pipeline stages are run sequentially by the server. If any of the stages involves a heavyweight query,
the server won't process subsequent stages until the query completes.



[heading:reference Pipeline stage reference]

In the table below, the following variables are assumed:

* `req` is a [reflink pipeline_request].
* `stmt` is a valid [reflink statement].
* `result` is a [reflink results] object.
* `conn` is an [reflink any_connection] object.

[table:reference
    [
        [Stage type]
        [Example]
        [When run, equivalent to...]
        [Response type]
    ]
    [
        [
            [*Execute]: behaves like [refmem any_connection execute][br][br]
            [refmem pipeline_request add_execute][br]
            [refmem pipeline_request add_execute_range]
        ]
        [[pipeline_reference_execute]]
        [[pipeline_reference_execute_equivalent]]
        [
            [reflink results] or an error
        ]
    ]
    [
        [
            [*Prepare statement]: behaves like [refmem any_connection prepare_statement][br][br]
            [refmem pipeline_request add_prepare_statement]
            
        ]
        [[pipeline_reference_prepare_statement]]
        [[pipeline_reference_prepare_statement_equivalent]]
        [
            [reflink statement] or an error
        ]
    ]
    [
        [
            [*Close statement]: behaves like [refmem any_connection close_statement][br][br]
            [refmem pipeline_request add_close_statement]
        ]
        [[pipeline_reference_close_statement]]
        [[pipeline_reference_close_statement_equivalent]]
        [
            Possibly empty error
        ]
    ]
    [
        [
            [*Reset connection]: behaves like [refmem any_connection reset_connection][br][br]
            [refmem pipeline_request add_reset_connection]
        ]
        [[pipeline_reference_reset_connection]]
        [[pipeline_reference_reset_connection_equivalent]]
        [
            Possibly empty error
        ]
    ]
    [
        [
            [*Set character set]: behaves like [refmem any_connection set_character_set][br][br]
            [refmem pipeline_request add_set_character_set]
        ]
        [[pipeline_reference_set_character_set]]
        [[pipeline_reference_set_character_set_equivalent]]
        [
            Possibly empty error
        ]
    ]
]


[endsect]