mirror of
https://github.com/oven-sh/bun
synced 2026-02-10 10:58:56 +00:00
113 lines
3.6 KiB
Zig
113 lines
3.6 KiB
Zig
const Signature = @This();
|
|
|
|
fields: []const int4,
|
|
name: []const u8,
|
|
query: []const u8,
|
|
prepared_statement_name: []const u8,
|
|
|
|
pub fn empty() Signature {
|
|
return Signature{
|
|
.fields = &[_]int4{},
|
|
.name = &[_]u8{},
|
|
.query = &[_]u8{},
|
|
.prepared_statement_name = &[_]u8{},
|
|
};
|
|
}
|
|
|
|
pub fn deinit(this: *Signature) void {
|
|
if (this.prepared_statement_name.len > 0) {
|
|
bun.default_allocator.free(this.prepared_statement_name);
|
|
}
|
|
if (this.name.len > 0) {
|
|
bun.default_allocator.free(this.name);
|
|
}
|
|
if (this.fields.len > 0) {
|
|
bun.default_allocator.free(this.fields);
|
|
}
|
|
if (this.query.len > 0) {
|
|
bun.default_allocator.free(this.query);
|
|
}
|
|
}
|
|
|
|
pub fn hash(this: *const Signature) u64 {
|
|
var hasher = std.hash.Wyhash.init(0);
|
|
hasher.update(this.name);
|
|
hasher.update(std.mem.sliceAsBytes(this.fields));
|
|
return hasher.final();
|
|
}
|
|
|
|
pub fn generate(globalObject: *JSC.JSGlobalObject, query: []const u8, array_value: JSValue, columns: JSValue, prepared_statement_id: u64, unnamed: bool) !Signature {
|
|
var fields = std.ArrayList(int4).init(bun.default_allocator);
|
|
var name = try std.ArrayList(u8).initCapacity(bun.default_allocator, query.len);
|
|
|
|
name.appendSliceAssumeCapacity(query);
|
|
|
|
errdefer {
|
|
fields.deinit();
|
|
name.deinit();
|
|
}
|
|
|
|
var iter = try QueryBindingIterator.init(array_value, columns, globalObject);
|
|
|
|
while (try iter.next()) |value| {
|
|
if (value.isEmptyOrUndefinedOrNull()) {
|
|
// Allow postgres to decide the type
|
|
try fields.append(0);
|
|
try name.appendSlice(".null");
|
|
continue;
|
|
}
|
|
|
|
const tag = try types.Tag.fromJS(globalObject, value);
|
|
|
|
switch (tag) {
|
|
.int8 => try name.appendSlice(".int8"),
|
|
.int4 => try name.appendSlice(".int4"),
|
|
// .int4_array => try name.appendSlice(".int4_array"),
|
|
.int2 => try name.appendSlice(".int2"),
|
|
.float8 => try name.appendSlice(".float8"),
|
|
.float4 => try name.appendSlice(".float4"),
|
|
.numeric => try name.appendSlice(".numeric"),
|
|
.json, .jsonb => try name.appendSlice(".json"),
|
|
.bool => try name.appendSlice(".bool"),
|
|
.timestamp => try name.appendSlice(".timestamp"),
|
|
.timestamptz => try name.appendSlice(".timestamptz"),
|
|
.bytea => try name.appendSlice(".bytea"),
|
|
else => try name.appendSlice(".string"),
|
|
}
|
|
|
|
switch (tag) {
|
|
.bool, .int4, .int8, .float8, .int2, .numeric, .float4, .bytea => {
|
|
// We decide the type
|
|
try fields.append(@intFromEnum(tag));
|
|
},
|
|
else => {
|
|
// Allow postgres to decide the type
|
|
try fields.append(0);
|
|
},
|
|
}
|
|
}
|
|
|
|
if (iter.anyFailed()) {
|
|
return error.InvalidQueryBinding;
|
|
}
|
|
// max u64 length is 20, max prepared_statement_name length is 63
|
|
const prepared_statement_name = if (unnamed) "" else try std.fmt.allocPrint(bun.default_allocator, "P{s}${d}", .{ name.items[0..@min(40, name.items.len)], prepared_statement_id });
|
|
|
|
return Signature{
|
|
.prepared_statement_name = prepared_statement_name,
|
|
.name = name.items,
|
|
.fields = fields.items,
|
|
.query = try bun.default_allocator.dupe(u8, query),
|
|
};
|
|
}
|
|
|
|
const bun = @import("bun");
|
|
const std = @import("std");
|
|
const QueryBindingIterator = @import("./QueryBindingIterator.zig").QueryBindingIterator;
|
|
|
|
const types = @import("./PostgresTypes.zig");
|
|
const int4 = types.int4;
|
|
|
|
const JSC = bun.JSC;
|
|
const JSValue = JSC.JSValue;
|