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, $bind_columns : object[] = undef, $ret_row : object[] = undef)

Fetches the next row of data from the result set.

Arguments:

  • $ctx : Go::Context

    The context for goroutine-like execution and cancellation.

  • $bind_columns : object[] (Optional)

    An array of objects used as persistent buffers for column values.

    • If a slot is undef, the driver creates a new object (e.g., Int, String) and stores it in this array.

    • If a slot already contains an object, the driver reuses it by updating its value (mutable update), which avoids new memory allocations.

  • $ret_row : object[] (Optional)

    An array to store the result of the current row (the pointers to objects in $bind_columns or undef for NULL).

    • If this argument is undef, the driver creates a new array for the row.

    • If an array is provided, the driver fills it and returns it.

Return Value:

Returns the fetched row as an array of objects.

  • If $ret_row was provided, that same array is returned (with updated values).

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

  • 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

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 Matrix

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 cast the SPVM value to the appropriate C type according to the target database column.

  • SPVM byte (signed 8-bit)

    • To 8-bit Signed Column --> Cast to int8_t

    • To 8-bit Unsigned Column --> Cast to uint8_t

    • To 16-bit Signed Column --> Cast to int16_t

    • To 16-bit Unsigned Column --> Cast to uint16_t

    • To 32-bit Signed Column --> Cast to int32_t

    • To 32-bit Unsigned Column --> Cast to uint32_t

    • To 64-bit Signed Column --> Cast to int64_t

    • To 64-bit Unsigned Column --> Cast to uint64_t

  • SPVM short (signed 16-bit)

    • To 8-bit Signed Column --> Cast to int8_t

    • To 8-bit Unsigned Column --> Cast to uint8_t

    • To 16-bit Signed Column --> Cast to int16_t

    • To 16-bit Unsigned Column --> Cast to uint16_t

    • To 32-bit Signed Column --> Cast to int32_t

    • To 32-bit Unsigned Column --> Cast to uint32_t

    • To 64-bit Signed Column --> Cast to int64_t

    • To 64-bit Unsigned Column --> Cast to uint64_t

  • SPVM int (signed 32-bit)

    • To 8-bit Signed Column --> Cast to int8_t

    • To 8-bit Unsigned Column --> Cast to uint8_t

    • To 16-bit Signed Column --> Cast to int16_t

    • To 16-bit Unsigned Column --> Cast to uint16_t

    • To 32-bit Signed Column --> Cast to int32_t

    • To 32-bit Unsigned Column --> Cast to uint32_t

    • To 64-bit Signed Column --> Cast to int64_t

    • To 64-bit Unsigned Column --> Cast to uint64_t

  • SPVM long (signed 64-bit)

    • To 8-bit Signed Column --> Cast to int8_t

    • To 8-bit Unsigned Column --> Cast to uint8_t

    • To 16-bit Signed Column --> Cast to int16_t

    • To 16-bit Unsigned Column --> Cast to uint16_t

    • To 32-bit Signed Column --> Cast to int32_t

    • To 32-bit Unsigned Column --> Cast to uint32_t

    • To 64-bit Signed Column --> Cast to int64_t

    • To 64-bit Unsigned Column --> Cast to uint64_t

  • SPVM float / double

    • To Floating Point Column --> Cast to float or double

    • To Integer Column --> Standard C casting to the target integer type

  • Other SPVM Types

    For these types, if the target database column type is different from the expected type, the conversion behavior (automatic casting or raising an error) depends on the database implementation.

    • string --> UTF-8 Character string

    • DBI::Data (TYPE_ID_BLOB) --> Binary data

    • DBI::Data (TYPE_ID_BIG_INT) --> Arbitrary precision integer string

    • DBI::Data (TYPE_ID_BIG_FLOAT) --> Arbitrary precision decimal string

    • undef --> Database NULL

---

Fetching Rows (SQL to SPVM)

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

  • Database 8/16/32-bit Integer (Signed/Unsigned)

    • --> Int object (via int32_t cast)

  • Database 64-bit Integer (Signed/Unsigned)

    • --> Long object (via int64_t cast)

  • Database Floating Point

    • Single-precision --> Float object

    • Double-precision --> Double object

  • Database High-Precision Numbers (NUMERIC, DECIMAL, etc.)

    • Exact Integers --> DBI::Data (TYPE_ID_BIG_INT) as string

    • Exact Decimals --> DBI::Data (TYPE_ID_BIG_FLOAT) as string

  • Database String / Binary / NULL

    • Character string --> string object

    • Binary data --> DBI::Data (TYPE_ID_BLOB)

    • NULL --> undef

Technical Note on 64-bit Casts

When casting between uint64_t (database) and int64_t (SPVM long):

  • Range <= 2^63 - 1:

    The value is preserved perfectly during casting. This covers the vast majority of use cases, such as auto-increment IDs that haven't reached the halfway point of the 64-bit range.

  • Range 2^63 - 1>:

    The bit pattern is preserved, but the value will be interpreted as a negative number in SPVM. Since no bits are lost, the original unsigned value can be recovered or compared using bitwise operations if necessary.

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