mirror of
https://github.com/oven-sh/bun
synced 2026-02-02 15:08:46 +00:00
empty commit to trigger formatting ci (#20378)
Co-authored-by: nektro <5464072+nektro@users.noreply.github.com>
This commit is contained in:
32
packages/bun-types/sqlite.d.ts
vendored
32
packages/bun-types/sqlite.d.ts
vendored
@@ -767,36 +767,36 @@ declare module "bun:sqlite" {
|
||||
/**
|
||||
* The actual SQLite column types from the first row of the result set.
|
||||
* Useful for expressions and computed columns, which are not covered by `declaredTypes`
|
||||
*
|
||||
*
|
||||
* Returns an array of SQLite type constants as uppercase strings:
|
||||
* - `"INTEGER"` for integer values
|
||||
* - `"FLOAT"` for floating-point values
|
||||
* - `"FLOAT"` for floating-point values
|
||||
* - `"TEXT"` for text values
|
||||
* - `"BLOB"` for binary data
|
||||
* - `"NULL"` for null values
|
||||
* - `null` for unknown/unsupported types
|
||||
*
|
||||
*
|
||||
* **Requirements:**
|
||||
* - Only available for read-only statements (SELECT queries)
|
||||
* - For non-read-only statements, throws an error
|
||||
*
|
||||
*
|
||||
* **Behavior:**
|
||||
* - Uses `sqlite3_column_type()` to get actual data types from the first row
|
||||
* - Returns `null` for columns with unknown SQLite type constants
|
||||
*
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* const stmt = db.prepare("SELECT id, name, age FROM users WHERE id = 1");
|
||||
*
|
||||
*
|
||||
* console.log(stmt.columnTypes);
|
||||
* // => ["INTEGER", "TEXT", "INTEGER"]
|
||||
*
|
||||
*
|
||||
* // For expressions:
|
||||
* const exprStmt = db.prepare("SELECT length('bun') AS str_length");
|
||||
* console.log(exprStmt.columnTypes);
|
||||
* // => ["INTEGER"]
|
||||
* ```
|
||||
*
|
||||
*
|
||||
* @throws Error if statement is not read-only (INSERT, UPDATE, DELETE, etc.)
|
||||
* @since Bun v1.2.13
|
||||
*/
|
||||
@@ -804,19 +804,19 @@ declare module "bun:sqlite" {
|
||||
|
||||
/**
|
||||
* The declared column types from the table schema.
|
||||
*
|
||||
*
|
||||
* Returns an array of declared type strings from `sqlite3_column_decltype()`:
|
||||
* - Raw type strings as declared in the CREATE TABLE statement
|
||||
* - `null` for columns without declared types (e.g., expressions, computed columns)
|
||||
*
|
||||
*
|
||||
* **Requirements:**
|
||||
* - Statement must be executed at least once before accessing this property
|
||||
* - Available for both read-only and read-write statements
|
||||
*
|
||||
*
|
||||
* **Behavior:**
|
||||
* - Uses `sqlite3_column_decltype()` to get schema-declared types
|
||||
* - Returns the exact type string from the table definition
|
||||
*
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* // For table columns:
|
||||
@@ -824,14 +824,14 @@ declare module "bun:sqlite" {
|
||||
* stmt.get();
|
||||
* console.log(stmt.declaredTypes);
|
||||
* // => ["INTEGER", "TEXT", "REAL"]
|
||||
*
|
||||
*
|
||||
* // For expressions (no declared types):
|
||||
* const exprStmt = db.prepare("SELECT length('bun') AS str_length");
|
||||
* exprStmt.get();
|
||||
* console.log(exprStmt.declaredTypes);
|
||||
* // => [null]
|
||||
* ```
|
||||
*
|
||||
*
|
||||
* @throws Error if statement hasn't been executed
|
||||
* @since Bun v1.2.13
|
||||
*/
|
||||
@@ -913,10 +913,10 @@ declare module "bun:sqlite" {
|
||||
* Native object representing the underlying `sqlite3_stmt`
|
||||
*
|
||||
* This is left untyped because the ABI of the native bindings may change at any time.
|
||||
*
|
||||
*
|
||||
* For stable, typed access to statement metadata, use the typed properties on the Statement class:
|
||||
* - {@link columnNames} for column names
|
||||
* - {@link paramsCount} for parameter count
|
||||
* - {@link paramsCount} for parameter count
|
||||
* - {@link columnTypes} for actual data types from the first row
|
||||
* - {@link declaredTypes} for schema-declared column types
|
||||
*/
|
||||
|
||||
@@ -2375,22 +2375,22 @@ JSC_DEFINE_CUSTOM_GETTER(jsSqlStatementGetColumnTypes, (JSGlobalObject * lexical
|
||||
CHECK_PREPARED
|
||||
|
||||
int count = sqlite3_column_count(castedThis->stmt);
|
||||
|
||||
|
||||
// We need to reset and step the statement to get fresh types,
|
||||
// but only do this for read-only statements to avoid side effects
|
||||
bool isReadOnly = sqlite3_stmt_readonly(castedThis->stmt) != 0;
|
||||
|
||||
if (! isReadOnly) {
|
||||
// For non-read-only statements, throw an error since column types don't make sense
|
||||
throwException(lexicalGlobalObject, scope, createError(lexicalGlobalObject, "columnTypes is not available for non-read-only statements (INSERT, UPDATE, DELETE, etc.)"_s));
|
||||
return { };
|
||||
if (!isReadOnly) {
|
||||
// For non-read-only statements, throw an error since column types don't make sense
|
||||
throwException(lexicalGlobalObject, scope, createError(lexicalGlobalObject, "columnTypes is not available for non-read-only statements (INSERT, UPDATE, DELETE, etc.)"_s));
|
||||
return {};
|
||||
}
|
||||
|
||||
// Reset the statement (safe for read-only statements)
|
||||
int resetStatus = sqlite3_reset(castedThis->stmt);
|
||||
if (resetStatus != SQLITE_OK) {
|
||||
throwException(lexicalGlobalObject, scope, createSQLiteError(lexicalGlobalObject, castedThis->version_db->db));
|
||||
return { };
|
||||
return {};
|
||||
}
|
||||
|
||||
MarkedArgumentBuffer args;
|
||||
@@ -2439,7 +2439,7 @@ JSC_DEFINE_CUSTOM_GETTER(jsSqlStatementGetColumnTypes, (JSGlobalObject * lexical
|
||||
// If there was an error stepping, throw it
|
||||
throwException(lexicalGlobalObject, scope, createSQLiteError(lexicalGlobalObject, castedThis->version_db->db));
|
||||
sqlite3_reset(castedThis->stmt);
|
||||
return { };
|
||||
return {};
|
||||
}
|
||||
|
||||
// Reset the statement back to its original state
|
||||
@@ -2462,7 +2462,7 @@ JSC_DEFINE_CUSTOM_GETTER(jsSqlStatementGetColumnDeclaredTypes, (JSGlobalObject *
|
||||
// Ensure the statement has been executed at least once
|
||||
if (!castedThis->hasExecuted) {
|
||||
throwException(lexicalGlobalObject, scope, createError(lexicalGlobalObject, "Statement must be executed before accessing declaredTypes"_s));
|
||||
return { };
|
||||
return {};
|
||||
}
|
||||
|
||||
int count = sqlite3_column_count(castedThis->stmt);
|
||||
@@ -2472,7 +2472,7 @@ JSC_DEFINE_CUSTOM_GETTER(jsSqlStatementGetColumnDeclaredTypes, (JSGlobalObject *
|
||||
for (int i = 0; i < count; i++) {
|
||||
const char* declType = sqlite3_column_decltype(castedThis->stmt, i);
|
||||
JSC::JSValue typeValue;
|
||||
|
||||
|
||||
if (declType != nullptr) {
|
||||
String typeStr = String::fromUTF8(declType);
|
||||
typeValue = JSC::jsNontrivialString(vm, typeStr);
|
||||
@@ -2480,10 +2480,10 @@ JSC_DEFINE_CUSTOM_GETTER(jsSqlStatementGetColumnDeclaredTypes, (JSGlobalObject *
|
||||
// If no declared type (e.g., for expressions or results of functions)
|
||||
typeValue = JSC::jsNull();
|
||||
}
|
||||
|
||||
|
||||
array->putDirectIndex(lexicalGlobalObject, i, typeValue);
|
||||
}
|
||||
|
||||
|
||||
RELEASE_AND_RETURN(scope, JSC::JSValue::encode(array));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { describe, it, expect } from "bun:test";
|
||||
import { Database } from "bun:sqlite";
|
||||
import { describe, expect, it } from "bun:test";
|
||||
|
||||
describe("SQLite Statement column types", () => {
|
||||
it("reports correct column types for a variety of data types", () => {
|
||||
@@ -25,25 +25,25 @@ describe("SQLite Statement column types", () => {
|
||||
|
||||
// Prepare a statement that selects all columns
|
||||
const stmt = db.prepare("SELECT * FROM test_types");
|
||||
|
||||
|
||||
// Execute the statement to get column types
|
||||
const row = stmt.get();
|
||||
|
||||
// Verify column metadata
|
||||
expect(stmt.native.columns).toEqual(["id", "name", "weight", "image", "is_active"]);
|
||||
expect(stmt.native.columnsCount).toBe(5);
|
||||
|
||||
|
||||
// Test the columnTypes property (uses actual data types from sqlite3_column_type)
|
||||
expect(stmt.columnTypes).toBeDefined();
|
||||
expect(Array.isArray(stmt.columnTypes)).toBe(true);
|
||||
expect(stmt.columnTypes.length).toBe(5);
|
||||
expect(stmt.columnTypes).toEqual(['INTEGER', 'TEXT', 'FLOAT', 'BLOB', 'INTEGER']);
|
||||
|
||||
expect(stmt.columnTypes).toEqual(["INTEGER", "TEXT", "FLOAT", "BLOB", "INTEGER"]);
|
||||
|
||||
// Test the declaredTypes property (uses declared types from sqlite3_column_decltype)
|
||||
expect(stmt.declaredTypes).toBeDefined();
|
||||
expect(Array.isArray(stmt.declaredTypes)).toBe(true);
|
||||
expect(stmt.declaredTypes.length).toBe(5);
|
||||
expect(stmt.declaredTypes).toEqual(['INTEGER', 'TEXT', 'REAL', 'BLOB', 'INTEGER']);
|
||||
expect(stmt.declaredTypes).toEqual(["INTEGER", "TEXT", "REAL", "BLOB", "INTEGER"]);
|
||||
});
|
||||
|
||||
it("handles NULL values correctly", () => {
|
||||
@@ -59,15 +59,15 @@ describe("SQLite Statement column types", () => {
|
||||
db.run(`INSERT INTO nulls_test (id, nullable) VALUES (1, NULL)`);
|
||||
|
||||
const stmt = db.prepare("SELECT * FROM nulls_test");
|
||||
|
||||
|
||||
// Execute the statement to get column types
|
||||
const row = stmt.get();
|
||||
|
||||
// columnTypes now returns actual data types - NULL values are reported as 'NULL'
|
||||
expect(stmt.columnTypes).toEqual(['INTEGER', 'NULL']);
|
||||
|
||||
expect(stmt.columnTypes).toEqual(["INTEGER", "NULL"]);
|
||||
|
||||
// declaredTypes still shows the declared table schema
|
||||
expect(stmt.declaredTypes).toEqual(['INTEGER', 'TEXT']);
|
||||
expect(stmt.declaredTypes).toEqual(["INTEGER", "TEXT"]);
|
||||
});
|
||||
|
||||
it("reports actual column types based on data values", () => {
|
||||
@@ -82,24 +82,24 @@ describe("SQLite Statement column types", () => {
|
||||
|
||||
// SQLite can store various types in the same column
|
||||
db.run(`INSERT INTO dynamic_types VALUES (1, 42)`);
|
||||
|
||||
|
||||
let stmt = db.prepare("SELECT * FROM dynamic_types");
|
||||
|
||||
|
||||
// Execute the statement to get column types
|
||||
let row = stmt.get();
|
||||
|
||||
|
||||
// We should get the actual type of the value (integer)
|
||||
expect(stmt.columnTypes).toEqual(['INTEGER', 'INTEGER']);
|
||||
|
||||
expect(stmt.columnTypes).toEqual(["INTEGER", "INTEGER"]);
|
||||
|
||||
// Update to a text value
|
||||
db.run(`UPDATE dynamic_types SET value = 'text' WHERE id = 1`);
|
||||
|
||||
|
||||
// Re-prepare to get fresh column type information
|
||||
stmt = db.prepare("SELECT * FROM dynamic_types");
|
||||
row = stmt.get();
|
||||
|
||||
|
||||
// We should get the actual type of the value (text)
|
||||
expect(stmt.columnTypes).toEqual(['INTEGER', 'TEXT']);
|
||||
expect(stmt.columnTypes).toEqual(["INTEGER", "TEXT"]);
|
||||
|
||||
// Update to a float value
|
||||
db.run(`UPDATE dynamic_types SET value = 3.14 WHERE id = 1`);
|
||||
@@ -109,7 +109,7 @@ describe("SQLite Statement column types", () => {
|
||||
row = stmt.get();
|
||||
|
||||
// We should get the actual type of the value (float)
|
||||
expect(stmt.columnTypes).toEqual(['INTEGER', 'FLOAT']);
|
||||
expect(stmt.columnTypes).toEqual(["INTEGER", "FLOAT"]);
|
||||
});
|
||||
|
||||
it("reports actual types for columns from expressions", () => {
|
||||
@@ -124,14 +124,14 @@ describe("SQLite Statement column types", () => {
|
||||
expect(row).toEqual({
|
||||
str_length: 3,
|
||||
magic_number: 42,
|
||||
greeting: "hello"
|
||||
greeting: "hello",
|
||||
});
|
||||
|
||||
// Check columns are correctly identified
|
||||
expect(stmt.native.columns).toEqual(['str_length', 'magic_number', 'greeting']);
|
||||
|
||||
expect(stmt.native.columns).toEqual(["str_length", "magic_number", "greeting"]);
|
||||
|
||||
// For expressions, expect the actual data types
|
||||
expect(stmt.columnTypes).toEqual(['INTEGER', 'INTEGER', 'TEXT']);
|
||||
expect(stmt.columnTypes).toEqual(["INTEGER", "INTEGER", "TEXT"]);
|
||||
});
|
||||
|
||||
it("handles multiple different expressions and functions", () => {
|
||||
@@ -148,33 +148,31 @@ describe("SQLite Statement column types", () => {
|
||||
length('bun') AS func_result,
|
||||
CURRENT_TIMESTAMP AS timestamp
|
||||
`);
|
||||
|
||||
|
||||
const row = stmt.get();
|
||||
|
||||
// Verify we have the expected columns
|
||||
expect(stmt.native.columns).toEqual([
|
||||
'int_val',
|
||||
'float_val',
|
||||
'text_val',
|
||||
'blob_val',
|
||||
'null_val',
|
||||
'func_result',
|
||||
'timestamp'
|
||||
"int_val",
|
||||
"float_val",
|
||||
"text_val",
|
||||
"blob_val",
|
||||
"null_val",
|
||||
"func_result",
|
||||
"timestamp",
|
||||
]);
|
||||
|
||||
// Expression columns should be reported with their actual types
|
||||
expect(stmt.columnTypes).toEqual([
|
||||
'INTEGER', 'FLOAT', 'TEXT', 'BLOB', 'NULL', 'INTEGER', 'TEXT'
|
||||
]);
|
||||
expect(stmt.columnTypes).toEqual(["INTEGER", "FLOAT", "TEXT", "BLOB", "NULL", "INTEGER", "TEXT"]);
|
||||
|
||||
// Verify data types were correctly identified at runtime
|
||||
expect(typeof row.int_val).toBe('number');
|
||||
expect(typeof row.float_val).toBe('number');
|
||||
expect(typeof row.text_val).toBe('string');
|
||||
expect(typeof row.int_val).toBe("number");
|
||||
expect(typeof row.float_val).toBe("number");
|
||||
expect(typeof row.text_val).toBe("string");
|
||||
expect(row.blob_val instanceof Uint8Array).toBe(true);
|
||||
expect(row.null_val).toBe(null);
|
||||
expect(typeof row.func_result).toBe('number');
|
||||
expect(typeof row.timestamp).toBe('string');
|
||||
expect(typeof row.func_result).toBe("number");
|
||||
expect(typeof row.timestamp).toBe("string");
|
||||
});
|
||||
|
||||
it("shows difference between columnTypes and declaredTypes for expressions", () => {
|
||||
@@ -185,8 +183,8 @@ describe("SQLite Statement column types", () => {
|
||||
const row = stmt.get();
|
||||
|
||||
// columnTypes shows actual data types based on the values
|
||||
expect(stmt.columnTypes).toEqual(['INTEGER', 'INTEGER', 'TEXT']);
|
||||
|
||||
expect(stmt.columnTypes).toEqual(["INTEGER", "INTEGER", "TEXT"]);
|
||||
|
||||
// declaredTypes shows declared types (which are null for expressions without explicit declarations)
|
||||
expect(stmt.declaredTypes).toEqual([null, null, null]);
|
||||
});
|
||||
@@ -203,27 +201,27 @@ describe("SQLite Statement column types", () => {
|
||||
|
||||
// Insert an integer value
|
||||
db.run(`INSERT INTO dynamic_types VALUES (1, 42)`);
|
||||
|
||||
|
||||
let stmt = db.prepare("SELECT * FROM dynamic_types");
|
||||
let row = stmt.get();
|
||||
|
||||
|
||||
// columnTypes shows actual type (integer) for the current value
|
||||
expect(stmt.columnTypes).toEqual(['INTEGER', 'INTEGER']);
|
||||
|
||||
expect(stmt.columnTypes).toEqual(["INTEGER", "INTEGER"]);
|
||||
|
||||
// declaredTypes shows the declared table schema
|
||||
expect(stmt.declaredTypes).toEqual(['INTEGER', 'ANY']);
|
||||
|
||||
expect(stmt.declaredTypes).toEqual(["INTEGER", "ANY"]);
|
||||
|
||||
// Update to a text value
|
||||
db.run(`UPDATE dynamic_types SET value = 'text' WHERE id = 1`);
|
||||
|
||||
|
||||
stmt = db.prepare("SELECT * FROM dynamic_types");
|
||||
row = stmt.get();
|
||||
|
||||
|
||||
// columnTypes now shows text for the current value
|
||||
expect(stmt.columnTypes).toEqual(['INTEGER', 'TEXT']);
|
||||
|
||||
expect(stmt.columnTypes).toEqual(["INTEGER", "TEXT"]);
|
||||
|
||||
// declaredTypes still shows the declared table schema
|
||||
expect(stmt.declaredTypes).toEqual(['INTEGER', 'ANY']);
|
||||
expect(stmt.declaredTypes).toEqual(["INTEGER", "ANY"]);
|
||||
});
|
||||
|
||||
it("throws an error when accessing columnTypes before statement execution", () => {
|
||||
@@ -235,7 +233,7 @@ describe("SQLite Statement column types", () => {
|
||||
|
||||
// Accessing columnTypes before executing is fine (implicitly executes the statement)
|
||||
expect(stmt.columnTypes).toBeArray();
|
||||
|
||||
|
||||
// Accessing declaredTypes before executing should throw
|
||||
expect(() => {
|
||||
stmt.declaredTypes;
|
||||
|
||||
Reference in New Issue
Block a user