Name

SPVM::DBI::St - Statement Handle

Description

DBI::St class in SPVM represents a statement handle. This class is a base class for statement handles, and each method is expected to be overridden in child classes like DBI::St::SQLite.

Usage

A statement handle is typically created by calling the prepare method of a database handle (DBI).

# Create a statement handle
my $sth = $dbh->prepare($ctx, "SELECT id, name FROM users WHERE id = ?");

# Execute with bind values
$sth->execute($ctx, [(object)1]);

# Fetch rows
while (my $row = $sth->fetch($ctx)) {
  my $id = $row->[0]->(int);
  my $name = $row->[1]->(string);
}

# Finish explicitly
$sth->finish;

Binary Data:

my $binary_data = "abc\0\1\2";
my $blob = DBI->blob($binary_data);

my $sth_insert = $dbh->prepare($ctx, "INSERT INTO images (data) VALUES (?)");
$sth_insert->execute($ctx, [(object)$blob]);

Fields

Database

has Database : ro DBI;

The database handle that created this statement handle.

Statement

has Statement : ro string;

The SQL statement string.

Instance Methods

NUM_OF_FIELDS

method NUM_OF_FIELDS : int ($ctx : Go::Context);

Returns the number of fields (columns) in the result set.

NAME

method NAME : string[] ($ctx : Go::Context);

Returns an array of column names.

NULLABLE

method NULLABLE : int[] ($ctx : Go::Context);

Returns an array indicating if each column is nullable.

TYPE

method TYPE : int[] ($ctx : Go::Context);

Returns an array of column types.

PRECISION

method PRECISION : int[] ($ctx : Go::Context);

Returns an array of column precision values.

SCALE

method SCALE : int[] ($ctx : Go::Context);

Returns an array of column scale values.

execute

method execute : long ($ctx : Go::Context, $bind_values : object[] = undef);

Executes the prepared statement and return the number of affected rows, or -1 if unknown.

fetch

method fetch : object[] ($ctx : Go::Context);

Fetches the next row of data from the result set as an array of objects.

This is the simplest way to fetch data. It always allocates a new array and new column objects (e.g., Int, string) for each row.

Arguments:

  • $ctx : Go::Context

    The context for execution control and cancellation.

Return Value:

Returns the fetched row as an array of objects (object[]). Returns undef if there are no more rows.

fetch_with_bind_columns

method fetch_with_bind_columns : object[] ($ctx : Go::Context, $bind_columns : object[] = undef, $ret_row : object[] = undef, $create_count_ref : int* = undef, $extended_count_ref : int* = undef);

Fetches the next row efficiently by using bound columns as reusable buffers.

Arguments:

  • $ctx : Go::Context

    The context for execution control and cancellation.

  • $bind_columns : object[] (Optional)

    An array of objects provided as reusable containers for column values. This array is read-only; the driver does not modify its elements.

    • If a slot contains an object of the matching type, the driver reuses that container by updating its value, avoiding new memory allocations.

    • If a slot is undef, or if the existing object's type does not match the type fetched from the database, the driver creates a new column object.

  • $ret_row : object[] (Optional)

    An array to store the result of the current row.

    • The driver fills this array with the objects: either the reused ones from $bind_columns or the newly created ones.

    • If undef, the driver creates and returns a new array for the row result.

    • If an array is provided, the driver fills and returns it. If the provided array does not have enough capacity to store all columns, it is automatically extended.

  • $create_count_ref : int* (Optional)

    A reference to an integer that is incremented whenever a new column object is created. This can be used to detect unintended object creations caused by type mismatches between $bind_columns and the actual database columns.

  • $extended_count_ref : int* (Optional)

    A reference to an integer that is incremented whenever the $ret_row array is extended. This is useful for detecting unintended memory allocations caused by the insufficient size of the provided $ret_row array.

Return Value:

Returns the fetched row as an array of objects.

  • If $ret_row was provided, that same array is returned (potentially extended).

  • If $ret_row was undef, a newly allocated array is returned.

  • The returned array contains objects from $bind_columns where the types matched; otherwise, it contains newly created objects.

  • Returns undef when there are no more rows.

rows

method rows : long ($ctx : Go::Context);

Returns the number of rows affected by the last execute.

finish

method finish : void ();

Indicates that no more data will be fetched from this statement handle before it is prepared again or destroyed.

DESTROY

method DESTROY : void ();

The destructor. Calls "finish" method.

For Driver Authors

Extending DBI::St

The following example shows how to implement a specific database statement handle (DBD) by extending the DBI::St class.

class DBD::MyDriver::St extends DBI::St {
  
  # Overriding the execute method
  method execute : long ($ctx : Go::Context, $bind_values : object[] = undef) {
    
    # Implement the logic to execute the prepared statement.
    # Return the number of affected rows, or -1 if unknown.
    # ...
  }
  
  # Overriding the fetch method
  method fetch : object[] ($ctx : Go::Context, $bind_columns : object[] = undef, $ret_row : object[] = undef) {
    
    # Implement the logic to fetch one row.
    # Use $bind_columns and $ret_row to minimize memory allocations.
    # ...
  }
}

Abstract Methods

The following methods are intended to be overridden in child classes. If a method is not overridden, it throws a DBI::Error::SQLState exception with SQLSTATE "IM001" (Driver does not support this function) to indicate that the driver implementation is missing:

"NUM_OF_FIELDS", "NAME", "NULLABLE", "TYPE", "PRECISION", "SCALE", "execute", "fetch", "rows", "finish".

Overriding Instance Methods

option_names

protected method option_names : string[] ();

Returns the valid option names for this statement handle. Override this method if your statement handle supports specific options. These names are used to validate the options passed to DBI#prepare_common method.

Type Mapping Rules

The mapping depends on the SPVM type and the target database column type. Driver authors must follow these rules to ensure data integrity and consistent behavior.

Bind Values (SPVM to SQL)

The driver must interpret the SPVM objects and convert them to the appropriate C type for the target database column.

  • Byte (unsigned field is a false value)

    The value is treated as a signed 8-bit integer (int8_t).

  • Byte (unsigned field is a true value)

    The value is treated as an unsigned 8-bit integer (uint8_t).

  • Short (unsigned field is a false value)

    The value is treated as a signed 16-bit integer (int16_t).

  • Short (unsigned field is a true value)

    The value is treated as an unsigned 16-bit integer (uint16_t).

  • Int (unsigned field is a false value)

    The value is treated as a signed 32-bit integer (int32_t).

  • Int (unsigned field is a true value)

    The value is treated as an unsigned 32-bit integer (uint32_t).

  • Long (unsigned field is a false value)

    The value is treated as a signed 64-bit integer (int64_t).

  • Long (unsigned field is a true value)

    The value is treated as an unsigned 64-bit integer (uint64_t).

  • Float

    The value is treated as a single-precision floating-point (float).

  • Double

    The value is treated as a double-precision floating-point (double).

  • string

    The value is treated as a string.

    Conventionally, strings are expected to be UTF-8 encoded. However, since the string type represents a raw sequence of bytes, it can also hold strings in any other character encoding (e.g., EUC-JP, Shift_JIS) or any arbitrary byte data.

  • DBI::BindData::Blob

    The value is treated as binary data (BLOB).

  • undef

    The value is treated as a database NULL.

Fetching Rows (SQL to SPVM)

The driver must convert database values into the following SPVM objects.

  • Database 8-bit Signed Integer

    Converts to a Byte object (unsigned field is a false value).

  • Database 8-bit Unsigned Integer

    Converts to a Byte object (unsigned field is a true value).

  • Database 16-bit Signed Integer

    Converts to a Short object (unsigned field is a false value).

  • Database 16-bit Unsigned Integer

    Converts to a Short object (unsigned field is a true value).

  • Database 32-bit Signed Integer

    Converts to an Int object (unsigned field is a false value).

  • Database 32-bit Unsigned Integer

    Converts to an Int object (unsigned field is a true value).

  • Database 64-bit Signed Integer (e.g., BIGINT)

    Converts to a Long object (unsigned field is a false value).

  • Database 64-bit Unsigned Integer (e.g., BIGINT UNSIGNED)

    Converts to a Long object (unsigned field is a true value).

  • Database Single-precision Floating Point

    Converts to a Float object.

  • Database Double-precision Floating Point

    Converts to a Double object.

  • Database Character String (e.g., CHAR, VARCHAR)

    Converts to a string object.

  • Database Binary Data (BLOB)

    Converts to a string object.

  • Date and Time Types (e.g., DATE, TIME, DATETIME, TIMESTAMP)

    Converts to a string object in RFC 3339 format. The specific format depends on the database type:

    • Date: YYYY-MM-DD

    • Time: HH:MM:SS.fffffffff

    • Date and Time: YYYY-MM-DD HH:MM:SS.fffffffff[Z|[+|-]HH:MM]

    The following rules apply to these formats:

    • Separator

      A space is used between the date and time instead of "T" for better readability and compatibility with standard SQL output.

    • Fractional Seconds

      The fractional seconds part (fffffffff) can have up to 9 digits (nanosecond precision). The number of digits depends on the database precision (e.g., 6 digits for microseconds).

    • Time Zone

      If the database provides time zone information, it must be included as Z (for UTC) or a numerical offset (e.g., +09:00). If the database does not provide time zone information, the offset part is omitted to indicate a local or unknown time zone.

  • Database Decimals (e.g., DECIMAL, NUMERIC, and integers exceeding 64-bit)

    Converts to a string object. These values are converted into their exact textual representation (e.g., "12345678901234567890.12345") to preserve full precision that exceeds the capacity of 64-bit integers or floating-point numbers.

  • Database Character Large Object (CLOB)

    Converts to a string object.

  • Database NULL

    Converts to undef.

See Also

DBI, Go::Context

Repository

https://github.com/yuki-kimoto/SPVM-DBI

Author

Yuki Kimoto kimoto.yuki@gmail.com

Copyright & License

Copyright (c) 2026 Yuki Kimoto

MIT License