Skip to content

database/sql: documentation: ambiguity with contexts and Rows.Next #76752

@kevin-matthew

Description

@kevin-matthew

Rows.Next is the query equivalent of a stream's Read(...) in the fact that these functions make external API calls that would normally require a context be supplied, but instead implicitly use the context supplied in the method that established the stream (ie, QueryContext and Listen respectively).

This implicit behavior is not documented on QueryContext nor Next. So without diving into driver code, one wouldn't know if canceling the context passed into the QueryContext would actually effect Next. Some drivers may download 100% of the result rows before Query is returned, others may download parts at a time in the background, and others may only download rows only when Next is called.

This causes the problem when it comes to streaming results while also processing them by other means that require contexts.

type RowProcessor interface {
    // OpenProcessor will execute the query and will read row-by-row every time
    // ProcessRow is called.
    OpenProcessor(ctx context.Context, sql string, args ...any) (err error)

    // ProcessRow will read the next row from the query, execute some other
    // queries to process it, and return non-nil when the next row is ready to
    // processed.
    ProcessRow(ctx context.Context) (err error)
}

In the above example, OpenProcessor uses a context to execute the original query, and ProcessRow must take a context to execute auxiliary queries/api calls with. But what is confusing is that ProcessRow is still affected by the context passed into OpenProcessor. If the user cancels the context used for OpenProcessor, that may have ProcessRow fail in subsequent calls. Problems arise because OpenProcessor may have a tight deadline to perform its basic operations, whereas a longer deadline is appropriate for each call to ProcessRow, so that first tight deadline may expire well before all the rows have been processed. Thus, the context used for OpenProcessor must be valid for the entire processing duration. This will cause problems, as that overall context is expected to be minutes long, so if OpenProcessor hangs, the user would have to wait those same minutes.

In conclusion, I think Next() should have a NextContext(context.Context) alternative. This will allow the original context used for QueryContext to be cancelled before the results are fully processed. It provides a way to utilize a context exclusively for initializing a row stream rather than linger around for the entirety of the steam.

Metadata

Metadata

Assignees

No one assigned

    Labels

    DocumentationIssues describing a change to documentation.LibraryProposalIssues describing a requested change to the Go standard library or x/ libraries, but not to a toolNeedsInvestigationSomeone must examine and confirm this is a valid issue and not a duplicate of an existing one.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions