Compare commits

...

1 Commits

Author SHA1 Message Date
Jarred Sumner
adf8868aa5 WIP fix for duplicate columns in bun:sql 2024-07-19 19:55:07 -07:00
3 changed files with 34 additions and 12 deletions

View File

@@ -1,5 +1,8 @@
#include "root.h"
#include "helpers.h"
#include "JavaScriptCore/JSObject.h"
#include "JavaScriptCore/JSGlobalObject.h"
#include <JavaScriptCore/StructureInlines.h>
#include <JavaScriptCore/ObjectPrototype.h>
@@ -266,7 +269,20 @@ extern "C" EncodedJSValue JSC__constructObjectFromDataCell(
extern "C" EncodedJSValue JSC__createStructure(JSC::JSGlobalObject* globalObject, JSC::JSCell* owner, unsigned int inlineCapacity, BunString* names)
{
auto& vm = globalObject->vm();
Structure* structure = globalObject->structureCache().emptyObjectStructureForPrototype(globalObject, globalObject->objectPrototype(), inlineCapacity);
PropertyNameArray propertyNames(vm, PropertyNameMode::Strings, PrivateSymbolMode::Exclude);
unsigned int totalCount = inlineCapacity;
for (unsigned i = 0; i < totalCount; i++) {
auto initialCount = propertyNames.size();
propertyNames.add(Identifier::fromString(vm, names[i].toWTFString()));
// Handle duplicates
if (UNLIKELY(propertyNames.size() == initialCount)) {
names[i].deref();
names[i] = BunStringEmpty;
}
}
Structure* structure = globalObject->structureCache().emptyObjectStructureForPrototype(globalObject, globalObject->objectPrototype(), std::min(static_cast<unsigned>(propertyNames.size()), JSFinalObject::maxInlineCapacity));
if (owner) {
vm.writeBarrier(owner, structure);
} else {
@@ -274,14 +290,10 @@ extern "C" EncodedJSValue JSC__createStructure(JSC::JSGlobalObject* globalObject
}
ensureStillAliveHere(structure);
PropertyNameArray propertyNames(vm, PropertyNameMode::Strings, PrivateSymbolMode::Exclude);
for (unsigned i = 0; i < inlineCapacity; i++) {
propertyNames.add(Identifier::fromString(vm, names[i].toWTFString()));
}
PropertyOffset offset = 0;
for (unsigned i = 0; i < inlineCapacity; i++) {
structure = structure->addPropertyTransition(vm, structure, propertyNames[i], 0, offset);
for (const auto& name : propertyNames) {
structure = structure->addPropertyTransition(vm, structure, name, 0, offset);
}
return JSValue::encode(structure);

View File

@@ -930,6 +930,7 @@ pub const protocol = struct {
table_oid: int4 = 0,
column_index: short = 0,
type_oid: int4 = 0,
is_duplicate_column: bool = false,
pub fn typeTag(this: @This()) types.Tag {
return @enumFromInt(@as(short, @truncate(this.type_oid)));
@@ -969,10 +970,10 @@ pub const protocol = struct {
};
pub const RowDescription = struct {
fields: []const FieldDescription = &[_]FieldDescription{},
fields: []FieldDescription = &[_]FieldDescription{},
pub fn deinit(this: *@This()) void {
for (this.fields) |*field| {
@constCast(field).deinit();
field.deinit();
}
bun.default_allocator.free(this.fields);
@@ -4062,7 +4063,7 @@ pub const PostgresSQLConnection = struct {
pub const PostgresSQLStatement = struct {
cached_structure: JSC.Strong = .{},
ref_count: u32 = 1,
fields: []const protocol.FieldDescription = &[_]protocol.FieldDescription{},
fields: []protocol.FieldDescription = &[_]protocol.FieldDescription{},
parameters: []const int4 = &[_]int4{},
signature: Signature,
status: Status = Status.parsing,
@@ -4107,7 +4108,10 @@ pub const PostgresSQLStatement = struct {
return this.cached_structure.get() orelse {
const names = bun.default_allocator.alloc(bun.String, this.fields.len) catch return .undefined;
defer {
for (names) |*name| {
for (names, this.fields) |*name, *field| {
if (name.isEmpty()) {
field.is_duplicate_column = true;
}
name.deref();
}
bun.default_allocator.free(names);
@@ -4121,6 +4125,7 @@ pub const PostgresSQLStatement = struct {
@truncate(this.fields.len),
names.ptr,
);
this.cached_structure.set(globalObject, structure_);
return structure_;
};

View File

@@ -88,6 +88,11 @@ if (!isCI) {
await sql`drop table test`;
});
test("Duplicate columns", async () => {
const [{ x }] = await sql`select 1 as x, 2 as x`;
expect(x).toBe(1);
});
test("Drop table", async () => {
await sql`create table test(int int)`;
await sql`drop table test`;