Documentation
¶
Overview ¶
Package writer provides small streaming helpers for exporting Spanner rows using spanvalue formatters.
DelimitedWriter is the primary writer for CSV-style delimited text. NewCSVWriter is a thin helper for the common comma-delimited CSV case, while NewDelimitedWriter accepts an explicit delimiter for TSV and other delimited output. DelimitedWriter and JSONLWriter preserve explicit duplicate column names. Their UnnamedFieldNamer only fills empty column names, and generated names avoid collisions with existing names. DelimitedWriter buffers through encoding/csv, so callers must call Flush after the final write.
Quoted delimited text vs raw tab-separated ¶
DelimitedWriter uses encoding/csv rules: fields that contain the delimiter, double quotes, or newlines are quoted and inner quotes are doubled (RFC 4180-style). NewDelimitedWriter with delimiter '\t' produces quoted TSV, not a raw join of formatted column strings with tab characters only.
Downstream tools that must preserve legacy TAB output (for example tab-separated CLI export without CSV escaping) can implement Writer and format each column with spanvalue, then join with '\t'. For WriteRowIterator, implement RowIteratorWriter (FlushWriter plus RowIteratorWriter.PrepareRowType); Flusher.Flush may be a no-op when no header is needed.
Writer streams *spanner.Row values; concrete writers also offer WriteValues, WriteGCVs, and WriteStructValues. FlushWriter adds Flush (required for buffered DelimitedWriter). Flush does not close the underlying io.Writer.
Constructors ¶
NewDelimitedWriter, NewCSVWriter, NewJSONLWriter, and NewSQLInsertWriter accept WithFormatter and schema options below. WithSQLInsertKind selects the INSERT prefix (see Spanner INSERT DML syntax). WithSQLDialect selects identifier quoting for table and column names in SQL INSERT output (GoogleSQL by default). WithSQLBatchSize groups rows into multi-row INSERT statements. When batching, call SQLInsertWriter.Flush after the final row to close a partial batch; Flush is safe to call unconditionally (including when the last batch closed on a size boundary).
After any write error from SQLInsertWriter.WriteRow, SQLInsertWriter.WriteGCVs, SQLInsertWriter.WriteValues, or SQLInsertWriter.WriteStructValues, discard the writer and do not retry writes (same convention as encoding/csv.Writer after Error). RowData, FormatDelimitedRow, and FormatJSONLRow format a single row without a writer.
Column names and field types ¶
Each write API either supplies schema on every call or expects it in the writer:
- WriteRow, WriteValues: column names and GCV types per call; no registration.
- WriteGCVs: register column names before the first row; types from each GCV.
- WriteStructValues: register column names and field types before the first row.
Pre-register at construction with With* or later with Prepare* on the concrete writer. Names only: WithColumnNames, PrepareColumnNames. Names and types: WithRowType, WithMetadata, PrepareRowType. WithMetadata uses metadata.GetRowType(); from a cloud.google.com/go/spanner.RowIterator, Metadata is set after the first Next. The first [WriteRow] or [WriteValues] call can also register column names from a row. DelimitedWriter.Prepare, JSONLWriter.Prepare, and SQLInsertWriter.Prepare are deprecated.
Registered schema vs missing schema ¶
Writers distinguish schema that was never registered from a registered schema with zero column names (len(names) == 0):
- Not registered: no Prepare*, With*, or row has supplied names yet. DelimitedWriter.WriteHeader, DelimitedWriter.Flush (with WithHeader(true)), and DelimitedWriter.WriteGCVs without prior registration return ErrMissingColumnNames.
- Registered empty: [PrepareRowType] or WithRowType with a nil row type or a row type whose fields slice is empty (for example DML without THEN RETURN: zero rows and zero columns). DelimitedWriter.Flush succeeds and writes no output; DelimitedWriter.WriteHeader is a no-op because there are no column names. A later [WriteRow] still initializes names from the row if one arrives.
- [PrepareColumnNames] requires at least one column name and returns ErrMissingColumnNames for an empty list. Do not use it when metadata has zero columns; use [PrepareRowType] or WithRowType with nil or an empty fields slice instead (for example DML without THEN RETURN).
- WithColumnNames with an empty name list is ignored at construction (the writer stays unregistered); it does not return an error because options cannot report one (#95 tracks error-returning options). Prefer [PrepareRowType] for zero-column metadata.
WithMetadata registers the same names and types as WithRowType; call one or the other, not both. Use it when metadata is already available (not iter.Metadata from a cloud.google.com/go/spanner.RowIterator before the first Next). For streaming, call [PrepareRowType] with iter.Metadata.GetRowType() after the first Next when the result may be empty but still has columns (including when Next returns iterator.Done); call DelimitedWriter.Flush after the loop and propagate its error (do not defer Flush—it returns an error). RunRowIterator and WriteRowIterator run that loop, call Finish (Flush for writers), and return metadata and stats (including for zero-row results). When every query returns at least one row, [WriteRow] registers names from the first row.
DelimitedWriter defaults to a CSV/TSV header once column names are known (WithHeader): before the first data row, or on DelimitedWriter.Flush when no data row was written (including zero-row SELECT when names were registered). WithHeader(false) omits the header. DelimitedWriter.WriteHeader forces the header earlier.
Delimited, JSONL, and SQL encodings differ after spanvalue formats each column.
Compatibility constructors ¶
NewDelimitedWriterWithOptions, NewJSONLWriterWithOptions, and NewSQLInsertWriterWithOptions forward to the primary constructors above.
Index ¶
- Constants
- Variables
- func FormatDelimitedRow(fc *spanvalue.FormatConfig, row *spanner.Row, delimiter rune) (string, error)
- func FormatDelimitedValues(fc *spanvalue.FormatConfig, columnNames []string, ...) (string, error)
- func FormatJSONLRow(fc *spanvalue.FormatConfig, row *spanner.Row, ...) (string, error)
- func FormatJSONLValues(fc *spanvalue.FormatConfig, columnNames []string, ...) (string, error)
- func RowData(row *spanner.Row) ([]string, []spanner.GenericColumnValue, error)
- type DelimitedOption
- type DelimitedWriter
- func (w *DelimitedWriter) Flush() error
- func (w *DelimitedWriter) Prepare(metadata *sppb.ResultSetMetadata) errordeprecated
- func (w *DelimitedWriter) PrepareColumnNames(names []string) error
- func (w *DelimitedWriter) PrepareRowType(rowType *sppb.StructType) error
- func (w *DelimitedWriter) WriteGCVs(values []spanner.GenericColumnValue) error
- func (w *DelimitedWriter) WriteHeader() error
- func (w *DelimitedWriter) WriteRow(row *spanner.Row) error
- func (w *DelimitedWriter) WriteStructValues(values []*structpb.Value) error
- func (w *DelimitedWriter) WriteValues(columnNames []string, values []spanner.GenericColumnValue) error
- type FlushWriter
- type Flusher
- type JSONLOption
- type JSONLWriter
- func (w *JSONLWriter) Flush() error
- func (w *JSONLWriter) Prepare(metadata *sppb.ResultSetMetadata) errordeprecated
- func (w *JSONLWriter) PrepareColumnNames(names []string) error
- func (w *JSONLWriter) PrepareRowType(rowType *sppb.StructType) error
- func (w *JSONLWriter) WriteGCVs(values []spanner.GenericColumnValue) error
- func (w *JSONLWriter) WriteRow(row *spanner.Row) error
- func (w *JSONLWriter) WriteStructValues(values []*structpb.Value) error
- func (w *JSONLWriter) WriteValues(columnNames []string, values []spanner.GenericColumnValue) error
- type NameOption
- type Option
- type RowIteratorHooks
- type RowIteratorResult
- type RowIteratorStats
- type RowIteratorWriter
- type SQLInsertKind
- type SQLInsertOption
- type SQLInsertWriter
- func (w *SQLInsertWriter) Flush() error
- func (w *SQLInsertWriter) Prepare(metadata *sppb.ResultSetMetadata) errordeprecated
- func (w *SQLInsertWriter) PrepareColumnNames(names []string) error
- func (w *SQLInsertWriter) PrepareRowType(rowType *sppb.StructType) error
- func (w *SQLInsertWriter) WriteGCVs(values []spanner.GenericColumnValue) error
- func (w *SQLInsertWriter) WriteRow(row *spanner.Row) error
- func (w *SQLInsertWriter) WriteStructValues(values []*structpb.Value) error
- func (w *SQLInsertWriter) WriteValues(columnNames []string, values []spanner.GenericColumnValue) error
- type Writer
Constants ¶
const ( // Comma is the standard CSV field delimiter. Pass Comma to // NewDelimitedWriter for CSV output. Comma rune = ',' )
Variables ¶
var ( // ErrEmptyTableName reports that SQLInsertWriter.Table is empty. ErrEmptyTableName = errors.New("empty table name") // ErrEmptyColumnName reports that a SQL writer received an empty column name. ErrEmptyColumnName = errors.New("empty column name") // ErrNilOutputWriter reports that a writer was constructed without an output. ErrNilOutputWriter = errors.New("nil output writer") // ErrNilRow reports that WriteRow was called with a nil row. ErrNilRow = spanvalue.ErrNilRow // ErrMissingColumnNames reports that an operation requires a registered column schema // when none was registered yet, or column names/types are insufficient for the write // (for example values without names). It is not returned for a registered zero-column // schema (see package doc "Registered schema vs missing schema"). [PrepareColumnNames] // with an empty name list returns this error; [WithColumnNames] with an empty list is // ignored (writer stays unregistered). Use [PrepareRowType] for zero-column result sets. ErrMissingColumnNames = errors.New("missing column names") // ErrColumnNamesMismatch reports that provided column names differ from initialized schema. ErrColumnNamesMismatch = errors.New("column names mismatch") // ErrHeaderAfterData reports that DelimitedWriter.WriteHeader was called after data rows were emitted. ErrHeaderAfterData = errors.New("header after data") // ErrInvalidDelimiter reports that DelimitedWriter received an invalid delimiter. ErrInvalidDelimiter = errors.New("invalid delimiter") // ErrMissingFieldTypes reports that WriteStructValues requires registered field types. ErrMissingFieldTypes = errors.New("missing field types schema") // ErrMismatchedStructValueCount reports that WriteStructValues value count does not match the schema. ErrMismatchedStructValueCount = errors.New("mismatched struct value count") // ErrInvalidSQLInsertKindForDialect reports that [WithSQLInsertKind] selected INSERT OR IGNORE // or INSERT OR UPDATE with a PostgreSQL dialect. Those prefixes are GoogleSQL-only; use plain // [SQLInsert] with [WithSQLDialect](databasepb.DatabaseDialect_POSTGRESQL) instead. ErrInvalidSQLInsertKindForDialect = errors.New("INSERT OR IGNORE/UPDATE not supported for PostgreSQL dialect") )
var ErrNilRowIterator = errors.New("nil row iterator")
ErrNilRowIterator reports that RunRowIterator or WriteRowIterator was called with a nil iterator.
var ErrNilWriter = errors.New("nil row iterator writer")
ErrNilWriter reports that WriteRowIterator was called with a nil writer.
Functions ¶
func FormatDelimitedRow ¶ added in v0.3.2
func FormatDelimitedRow(fc *spanvalue.FormatConfig, row *spanner.Row, delimiter rune) (string, error)
FormatDelimitedRow formats one row as a CSV-style delimited record without a trailing newline. Pass Comma for CSV output.
func FormatDelimitedValues ¶ added in v0.3.2
func FormatDelimitedValues(fc *spanvalue.FormatConfig, columnNames []string, values []spanner.GenericColumnValue, delimiter rune) (string, error)
FormatDelimitedValues formats one row represented as column names plus GCV values as a CSV-style delimited record without a trailing newline. Pass Comma for CSV output.
func FormatJSONLRow ¶ added in v0.3.2
func FormatJSONLRow(fc *spanvalue.FormatConfig, row *spanner.Row, namer spanvalue.UnnamedFieldNamer) (string, error)
FormatJSONLRow formats one row as a JSON object string without a trailing newline. Callers writing JSONL streams should add the newline at the stream boundary.
func FormatJSONLValues ¶ added in v0.3.2
func FormatJSONLValues(fc *spanvalue.FormatConfig, columnNames []string, values []spanner.GenericColumnValue, namer spanvalue.UnnamedFieldNamer) (string, error)
FormatJSONLValues formats one row represented as column names plus GCV values as a JSON object string without a trailing newline. Callers writing JSONL streams should add the newline at the stream boundary.
Types ¶
type DelimitedOption ¶ added in v0.3.2
type DelimitedOption interface {
// contains filtered or unexported methods
}
DelimitedOption configures a DelimitedWriter created by NewDelimitedWriter or NewCSVWriter.
func WithHeader ¶ added in v0.3.2
func WithHeader(header bool) DelimitedOption
WithHeader sets whether DelimitedWriter emits a CSV/TSV header (default true). The header is written before the first data row, or on DelimitedWriter.Flush if only names were registered. See DelimitedWriter.WriteHeader to emit it earlier.
type DelimitedWriter ¶ added in v0.3.2
type DelimitedWriter struct {
Formatter *spanvalue.FormatConfig
// Header enables a header line before the first data row when true (default).
// See [WithHeader].
Header bool
// Set before the first write. Once names have been resolved for the current
// schema, later changes do not retroactively rewrite cached header names.
UnnamedFieldNamer spanvalue.UnnamedFieldNamer
// contains filtered or unexported fields
}
DelimitedWriter writes rows as CSV-style delimited text. Call Flush after the final write. Header controls automatic header output; see WithHeader and DelimitedWriter.WriteHeader.
func NewCSVWriter ¶
func NewCSVWriter(out io.Writer, opts ...DelimitedOption) *DelimitedWriter
NewCSVWriter returns a comma-delimited CSV writer configured by options. It is a thin helper for NewDelimitedWriter(out, Comma, opts...).
func NewDelimitedWriter ¶ added in v0.3.1
func NewDelimitedWriter(out io.Writer, delimiter rune, options ...DelimitedOption) *DelimitedWriter
NewDelimitedWriter returns a CSV-style writer using delimiter as the field delimiter and configured by options.
It supports CSV (delimiter Comma), quoted TSV (delimiter '\t'), or other single-rune delimiters. Output follows encoding/csv quoting rules, not raw field joins. Delimiter must be non-zero and a valid encoding/csv delimiter. See the package-level section "Quoted delimited text vs raw tab-separated".
func NewDelimitedWriterWithOptions
deprecated
added in
v0.3.2
func NewDelimitedWriterWithOptions(out io.Writer, delimiter rune, options ...DelimitedOption) *DelimitedWriter
NewDelimitedWriterWithOptions forwards to NewDelimitedWriter.
Deprecated: Use NewDelimitedWriter instead.
func (*DelimitedWriter) Flush ¶ added in v0.3.2
func (w *DelimitedWriter) Flush() error
Flush flushes buffered delimited data to the underlying writer. When DelimitedWriter.Header is true, a schema is registered, len(column names) > 0, and no header was written yet, Flush writes the header first (including zero-row SELECT exports). With a registered zero-column schema, Flush succeeds without writing. With no registered schema and DelimitedWriter.Header true, Flush returns ErrMissingColumnNames. Flush does not close the underlying writer.
func (*DelimitedWriter) Prepare
deprecated
added in
v0.3.2
func (w *DelimitedWriter) Prepare(metadata *sppb.ResultSetMetadata) error
Prepare initializes the delimited schema from result-set metadata before the first row is written.
Deprecated: Use DelimitedWriter.PrepareRowType or DelimitedWriter.PrepareColumnNames.
func (*DelimitedWriter) PrepareColumnNames ¶ added in v0.4.1
func (w *DelimitedWriter) PrepareColumnNames(names []string) error
PrepareColumnNames registers column names only; same as WithColumnNames for non-empty names. Unlike WithColumnNames, an empty names slice returns ErrMissingColumnNames; for zero-column result sets use DelimitedWriter.PrepareRowType instead.
func (*DelimitedWriter) PrepareRowType ¶ added in v0.4.1
func (w *DelimitedWriter) PrepareRowType(rowType *sppb.StructType) error
PrepareRowType registers column names and field types; same as WithRowType. Nil rowType and a row type with no fields both register an empty schema (see package doc).
func (*DelimitedWriter) WriteGCVs ¶ added in v0.3.2
func (w *DelimitedWriter) WriteGCVs(values []spanner.GenericColumnValue) error
WriteGCVs writes one row from GCVs; see package doc "Column names and field types".
func (*DelimitedWriter) WriteHeader ¶ added in v0.3.2
func (w *DelimitedWriter) WriteHeader() error
WriteHeader writes the CSV/TSV header once; a column schema must already be registered. With zero registered column names (empty row type), WriteHeader succeeds without writing. With no registered schema, it returns ErrMissingColumnNames. When DelimitedWriter.Header is true, DelimitedWriter.Flush also writes a pending header.
func (*DelimitedWriter) WriteRow ¶ added in v0.3.2
func (w *DelimitedWriter) WriteRow(row *spanner.Row) error
WriteRow writes one delimited row; see package doc "Column names and field types".
func (*DelimitedWriter) WriteStructValues ¶ added in v0.4.1
func (w *DelimitedWriter) WriteStructValues(values []*structpb.Value) error
WriteStructValues writes one row from []*structpb.Value; see package doc "Column names and field types".
func (*DelimitedWriter) WriteValues ¶ added in v0.3.2
func (w *DelimitedWriter) WriteValues(columnNames []string, values []spanner.GenericColumnValue) error
WriteValues writes one row from column names and GCVs.
type FlushWriter ¶ added in v0.3.2
FlushWriter streams Spanner rows and finalizes any buffered output.
type Flusher ¶ added in v0.3.1
type Flusher interface {
Flush() error
}
Flusher finalizes any buffered output. Flush does not close the underlying io.Writer. DelimitedWriter uses Flush to forward buffered CSV-style data; JSONLWriter implements Flush as a no-op. SQLInsertWriter.Flush closes a partial multi-row INSERT when WithSQLBatchSize is greater than 1.
type JSONLOption ¶ added in v0.3.2
type JSONLOption interface {
// contains filtered or unexported methods
}
JSONLOption configures a JSONLWriter created by NewJSONLWriter.
type JSONLWriter ¶
type JSONLWriter struct {
Formatter *spanvalue.FormatConfig
// Set before the first write. Once names have been resolved for the current
// schema, later changes do not retroactively rewrite cached object keys.
UnnamedFieldNamer spanvalue.UnnamedFieldNamer
// contains filtered or unexported fields
}
JSONLWriter writes one JSON object per line.
func NewJSONLWriter ¶
func NewJSONLWriter(out io.Writer, options ...JSONLOption) *JSONLWriter
NewJSONLWriter returns a JSONL writer configured by options.
func NewJSONLWriterWithOptions
deprecated
added in
v0.3.2
func NewJSONLWriterWithOptions(out io.Writer, options ...JSONLOption) *JSONLWriter
NewJSONLWriterWithOptions forwards to NewJSONLWriter.
Deprecated: Use NewJSONLWriter instead.
func (*JSONLWriter) Flush ¶ added in v0.3.1
func (w *JSONLWriter) Flush() error
Flush finalizes JSONL output. JSONLWriter is unbuffered, so this is a no-op.
func (*JSONLWriter) Prepare
deprecated
added in
v0.3.2
func (w *JSONLWriter) Prepare(metadata *sppb.ResultSetMetadata) error
Prepare initializes the JSONL schema from result-set metadata before the first row is written. If a schema is already initialized, Prepare verifies that the metadata column names match the existing schema.
Deprecated: Use JSONLWriter.PrepareRowType, JSONLWriter.PrepareColumnNames, WithRowType, WithColumnNames, or WithMetadata.
func (*JSONLWriter) PrepareColumnNames ¶ added in v0.4.1
func (w *JSONLWriter) PrepareColumnNames(names []string) error
PrepareColumnNames registers column names; see DelimitedWriter.PrepareColumnNames.
func (*JSONLWriter) PrepareRowType ¶ added in v0.4.1
func (w *JSONLWriter) PrepareRowType(rowType *sppb.StructType) error
PrepareRowType registers names and field types; see DelimitedWriter.PrepareRowType. Nil rowType registers an empty schema.
func (*JSONLWriter) WriteGCVs ¶
func (w *JSONLWriter) WriteGCVs(values []spanner.GenericColumnValue) error
WriteGCVs writes one row; see DelimitedWriter.WriteGCVs.
func (*JSONLWriter) WriteRow ¶
func (w *JSONLWriter) WriteRow(row *spanner.Row) error
WriteRow writes one JSONL row. Does not require With* or Prepare*; see DelimitedWriter.WriteRow.
func (*JSONLWriter) WriteStructValues ¶ added in v0.4.1
func (w *JSONLWriter) WriteStructValues(values []*structpb.Value) error
WriteStructValues writes one row; see DelimitedWriter.WriteStructValues.
func (*JSONLWriter) WriteValues ¶
func (w *JSONLWriter) WriteValues(columnNames []string, values []spanner.GenericColumnValue) error
WriteValues writes one row; see DelimitedWriter.WriteValues.
type NameOption ¶ added in v0.3.2
type NameOption interface {
DelimitedOption
JSONLOption
}
NameOption configures field-name handling for delimited and JSONL writers.
func WithUnnamedFieldNamer ¶ added in v0.3.2
func WithUnnamedFieldNamer(namer spanvalue.UnnamedFieldNamer) NameOption
WithUnnamedFieldNamer sets the unnamed-field naming policy for delimited and JSONL writers.
type Option ¶ added in v0.3.2
type Option interface {
DelimitedOption
JSONLOption
SQLInsertOption
}
Option configures any writer type created by a writer constructor.
func WithColumnNames ¶ added in v0.4.1
WithColumnNames registers column names only and clears any registered field types. An empty names slice is ignored (the writer stays unregistered); use WithRowType for a zero-column result set.
func WithFormatter ¶ added in v0.3.2
func WithFormatter(formatter *spanvalue.FormatConfig) Option
WithFormatter sets the FormatConfig used by a writer.
func WithMetadata ¶ added in v0.3.2
func WithMetadata(metadata *sppb.ResultSetMetadata) Option
WithMetadata registers names and types from metadata.GetRowType(); same as WithRowType. Other metadata fields are ignored.
func WithRowType ¶ added in v0.4.1
func WithRowType(rowType *sppb.StructType) Option
WithRowType registers column names and field types at construction. Nil rowType registers an empty schema (see package doc).
type RowIteratorHooks ¶ added in v0.4.2
type RowIteratorHooks struct {
PrepareMetadata func(*sppb.ResultSetMetadata) error
WriteRow func(*spanner.Row) error
Finish func(*RowIteratorResult) error
}
RowIteratorHooks drives RunRowIterator. Nil function fields are skipped.
PrepareMetadata runs once after the first spanner.RowIterator.Next, with whatever cloud.google.com/go/spanner.RowIterator.Metadata holds at that point (including nil for DML or stats-only iterators, and including when the only result is iterator.Done). It is not called when the first Next returns a query error other than iterator.Done.
Finish runs only after all rows are consumed without error. If PrepareMetadata or WriteRow returns an error, the loop aborts and Finish is not called. The returned RowIteratorResult is still populated with whatever iter.Metadata and stats are available at the abort point. Stats is fully populated when Finish runs successfully. QueryPlan and QueryStats require QueryWithStats. Finish may read Metadata again for end-of-stream processing.
func RowIteratorHooksFromWriter ¶ added in v0.4.2
func RowIteratorHooksFromWriter(w RowIteratorWriter) RowIteratorHooks
RowIteratorHooksFromWriter returns hooks that register metadata via RowIteratorWriter.PrepareRowType, write each row, and call Flusher.Flush in Finish. Flush is not called when PrepareRowType or WriteRow returns an error. A nil writer returns empty hooks.
type RowIteratorResult ¶ added in v0.4.2
type RowIteratorResult struct {
Metadata *sppb.ResultSetMetadata
Stats RowIteratorStats
}
RowIteratorResult is the metadata and stats available from a cloud.google.com/go/spanner.RowIterator after RunRowIterator returns. On the error path, stats fields reflect whatever the iterator had populated at the abort point and may be zero until iterator.Done (QueryStats and RowCount are only fully populated after a successful run).
func RunRowIterator ¶ added in v0.4.2
func RunRowIterator(iter *spanner.RowIterator, hooks RowIteratorHooks) (*RowIteratorResult, error)
RunRowIterator streams all rows from iter using hooks. It always calls spanner.RowIterator.Stop on return.
The returned RowIteratorResult reflects iter.Metadata and iter stats fields after Stop and the loop (including when no data rows were written). When hooks.Finish is set, it receives the same pointer that is returned.
func WriteRowIterator ¶ added in v0.4.2
func WriteRowIterator(iter *spanner.RowIterator, w RowIteratorWriter) (*RowIteratorResult, error)
WriteRowIterator streams all rows from iter into w using RowIteratorHooksFromWriter. See RunRowIterator for iterator metadata, stats, and zero-row behavior.
type RowIteratorStats ¶ added in v0.4.2
RowIteratorStats holds execution information populated on a cloud.google.com/go/spanner.RowIterator after iteration completes. QueryPlan and QueryStats are set when the query used QueryWithStats. RowCount is set for DML after iterator.Done.
type RowIteratorWriter ¶ added in v0.4.2
type RowIteratorWriter interface {
FlushWriter
PrepareRowType(*sppb.StructType) error
}
RowIteratorWriter streams rows from a cloud.google.com/go/spanner.RowIterator through WriteRowIterator. DelimitedWriter, JSONLWriter, and SQLInsertWriter implement it.
type SQLInsertKind ¶ added in v0.4.0
type SQLInsertKind int
SQLInsertKind selects the INSERT statement prefix written by SQLInsertWriter.
Variants follow Spanner GoogleSQL DML: INSERT OR IGNORE skips rows whose primary key already exists; INSERT OR UPDATE inserts or updates by primary key. They cannot be combined with ON CONFLICT in the same statement, and INSERT is not supported in Partitioned DML. See https://cloud.google.com/spanner/docs/reference/standard-sql/dml-syntax .
SQLInsertOrIgnore and SQLInsertOrUpdate are invalid with WithSQLDialect(databasepb.DatabaseDialect_POSTGRESQL); NewSQLInsertWriter rejects that combination via ErrInvalidSQLInsertKindForDialect on the first write.
const ( // SQLInsert writes plain INSERT INTO statements. SQLInsert SQLInsertKind = iota // SQLInsertOrIgnore writes INSERT OR IGNORE INTO statements. SQLInsertOrIgnore // SQLInsertOrUpdate writes INSERT OR UPDATE INTO statements. SQLInsertOrUpdate )
func (SQLInsertKind) String ¶ added in v0.4.0
func (k SQLInsertKind) String() string
type SQLInsertOption ¶ added in v0.3.2
type SQLInsertOption interface {
// contains filtered or unexported methods
}
SQLInsertOption configures a SQLInsertWriter created by NewSQLInsertWriter.
func WithSQLBatchSize ¶ added in v0.5.0
func WithSQLBatchSize(n int) SQLInsertOption
WithSQLBatchSize sets how many rows SQLInsertWriter combines into one INSERT statement. Values 0 or 1 keep the default of one row per statement. Values greater than 1 emit multi-row INSERT ... VALUES (...), (...); up to n rows per statement. Call SQLInsertWriter.Flush after the final row to close a partial batch (Flush is also safe when the last batch closed exactly on a size boundary).
Batching applies the same SQLInsertKind prefix once per batched statement. Multi-row INSERT OR IGNORE and INSERT OR UPDATE follow Spanner GoogleSQL DML rules and require GoogleSQL dialect; PostgreSQL rejects those prefixes (ErrInvalidSQLInsertKindForDialect). Identifier quoting follows WithSQLDialect; value literals still use WithFormatter.
func WithSQLDialect ¶ added in v0.5.0
func WithSQLDialect(dialect databasepb.DatabaseDialect) SQLInsertOption
WithSQLDialect sets identifier quoting for table and column names in SQL INSERT output. It does not change INSERT statement prefixes (WithSQLInsertKind) or value literal formatting (WithFormatter). The default is GoogleSQL (databasepb.DatabaseDialect_GOOGLE_STANDARD_SQL).
PostgreSQL dialect does not support SQLInsertOrIgnore or SQLInsertOrUpdate prefixes; combining them returns ErrInvalidSQLInsertKindForDialect on write.
func WithSQLInsertKind ¶ added in v0.4.0
func WithSQLInsertKind(kind SQLInsertKind) SQLInsertOption
WithSQLInsertKind sets the INSERT statement variant for a SQLInsertWriter.
type SQLInsertWriter ¶
type SQLInsertWriter struct {
// Table is the qualified table name used in INSERT statements.
//
// Deprecated: Set only via [NewSQLInsertWriter]. Do not mutate Table after the
// first write; the field will be unexported in a future minor release.
Table string
// Formatter formats value literals in INSERT statements.
//
// Deprecated: Set only via [NewSQLInsertWriter] or [WithFormatter]. Do not mutate
// Formatter after the first write; the field will be unexported in a future minor release.
Formatter *spanvalue.FormatConfig
// contains filtered or unexported fields
}
SQLInsertWriter writes rows as SQL INSERT statements with dialect-aware identifier quoting.
After any error from SQLInsertWriter.WriteRow, SQLInsertWriter.WriteGCVs, SQLInsertWriter.WriteValues, or SQLInsertWriter.WriteStructValues, discard the writer; partial batched INSERT output may be unrecoverable on retry.
func NewSQLInsertWriter ¶
func NewSQLInsertWriter(out io.Writer, table string, options ...SQLInsertOption) *SQLInsertWriter
NewSQLInsertWriter returns a SQL INSERT writer configured by options.
func NewSQLInsertWriterWithOptions
deprecated
added in
v0.3.2
func NewSQLInsertWriterWithOptions(out io.Writer, table string, options ...SQLInsertOption) *SQLInsertWriter
NewSQLInsertWriterWithOptions forwards to NewSQLInsertWriter.
Deprecated: Use NewSQLInsertWriter instead.
func (*SQLInsertWriter) Flush ¶ added in v0.3.1
func (w *SQLInsertWriter) Flush() error
Flush finalizes a partial multi-row INSERT batch started by WithSQLBatchSize. When batch size is 0 or 1, or when the last batch closed on a size boundary, Flush is a no-op. Flush is safe to call unconditionally after the final row.
func (*SQLInsertWriter) Prepare
deprecated
added in
v0.3.2
func (w *SQLInsertWriter) Prepare(metadata *sppb.ResultSetMetadata) error
Prepare initializes the SQL INSERT schema from result-set metadata before the first row is written. If a schema is already initialized, Prepare verifies that the metadata column names match the existing schema.
Deprecated: Use SQLInsertWriter.PrepareRowType, SQLInsertWriter.PrepareColumnNames, WithRowType, WithColumnNames, or WithMetadata.
func (*SQLInsertWriter) PrepareColumnNames ¶ added in v0.4.1
func (w *SQLInsertWriter) PrepareColumnNames(names []string) error
PrepareColumnNames initializes the SQL INSERT schema from column names before the first row is written. See DelimitedWriter.PrepareColumnNames for empty-name behavior.
func (*SQLInsertWriter) PrepareRowType ¶ added in v0.4.1
func (w *SQLInsertWriter) PrepareRowType(rowType *sppb.StructType) error
PrepareRowType initializes the SQL INSERT schema from a row type before the first row is written. When the row type comes from a cloud.google.com/go/spanner.RowIterator, use RunRowIterator or [PrepareRowType] with iter.Metadata.GetRowType() after the first Next. Nil rowType registers an empty schema; SQLInsertWriter.WriteGCVs still requires at least one column to emit SQL.
func (*SQLInsertWriter) WriteGCVs ¶
func (w *SQLInsertWriter) WriteGCVs(values []spanner.GenericColumnValue) error
func (*SQLInsertWriter) WriteStructValues ¶ added in v0.4.1
func (w *SQLInsertWriter) WriteStructValues(values []*structpb.Value) error
WriteStructValues writes one row from structpb values using the field-type schema registered by WithRowType, WithMetadata, or [PrepareRowType].
func (*SQLInsertWriter) WriteValues ¶
func (w *SQLInsertWriter) WriteValues(columnNames []string, values []spanner.GenericColumnValue) error
type Writer ¶
Writer writes Spanner rows to an output stream.
WriteRow supplies column names and values on each call; see package doc "Column names and field types". Writer intentionally models row streaming only. Some concrete writers also implement Flusher; callers that own the full write lifecycle must call Flush after the final row when it is available. Factories that may return a buffered writer should return a concrete type or FlushWriter, not Writer alone.