Skip to content

Commit

Permalink
numerics without bounds get converted to double, properly detect and …
Browse files Browse the repository at this point in the history
…propagate this information
  • Loading branch information
Tishj committed May 6, 2024
1 parent 8bf0eba commit fcec38e
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 8 deletions.
2 changes: 1 addition & 1 deletion include/quack/quack_types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ extern "C" {
}

namespace quack {
duckdb::LogicalType ConvertPostgresToDuckColumnType(Oid type);
duckdb::LogicalType ConvertPostgresToDuckColumnType(Oid type, int32_t typmod);
void ConvertPostgresToDuckValue(Datum value, duckdb::Vector &result, idx_t offset);
void ConvertDuckToPostgresValue(TupleTableSlot *slot, duckdb::Value &value, idx_t col);
void InsertTupleIntoChunk(duckdb::DataChunk &output, TupleDesc tuple, HeapTupleData *slot, idx_t offset);
Expand Down
5 changes: 3 additions & 2 deletions src/quack_heap_scan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ PostgresHeapScanFunctionData::~PostgresHeapScanFunctionData() {

PostgresHeapScanGlobalState::PostgresHeapScanGlobalState(PostgresHeapSeqScan &relation) {
relation.InitParallelScanState();
elog(DEBUG3, "-- (DuckDB/PostgresHeapScanGlobalState) Running %lu threads -- ", MaxThreads());
elog(DEBUG3, "-- (DuckDB/PostgresHeapScanGlobalState) Running %llu threads -- ", MaxThreads());
}

PostgresHeapScanGlobalState::~PostgresHeapScanGlobalState() {
Expand Down Expand Up @@ -79,8 +79,9 @@ PostgresHeapScanFunction::PostgresHeapBind(duckdb::ClientContext &context, duckd
for (int i = 0; i < tupleDesc->natts; i++) {
Form_pg_attribute attr = &tupleDesc->attrs[i];
Oid type_oid = attr->atttypid;
auto typmod = attr->atttypmod;
auto col_name = duckdb::string(NameStr(attr->attname));
auto duck_type = ConvertPostgresToDuckColumnType(type_oid);
auto duck_type = ConvertPostgresToDuckColumnType(type_oid, typmod);
return_types.push_back(duck_type);
names.push_back(col_name);
/* Log column name and type */
Expand Down
50 changes: 45 additions & 5 deletions src/quack_types.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "duckdb.hpp"
#include "duckdb/common/extra_type_info.hpp"

extern "C" {
#include "postgres.h"
Expand Down Expand Up @@ -71,8 +72,26 @@ ConvertDuckToPostgresValue(TupleTableSlot *slot, duckdb::Value &value, idx_t col
}
}

static inline int
numeric_typmod_precision(int32 typmod)
{
return ((typmod - VARHDRSZ) >> 16) & 0xffff;
}

static inline int
numeric_typmod_scale(int32 typmod)
{
return (((typmod - VARHDRSZ) & 0x7ff) ^ 1024) - 1024;
}

struct NumericAsDouble : public duckdb::ExtraTypeInfo {
// Dummy struct to indicate at conversion that the source is a Numeric
public:
NumericAsDouble() : ExtraTypeInfo(duckdb::ExtraTypeInfoType::INVALID_TYPE_INFO) {}
};

duckdb::LogicalType
ConvertPostgresToDuckColumnType(Oid type) {
ConvertPostgresToDuckColumnType(Oid type, int32_t typmod) {
switch (type) {
case BOOLOID:
return duckdb::LogicalTypeId::BOOLEAN;
Expand All @@ -92,8 +111,19 @@ ConvertPostgresToDuckColumnType(Oid type) {
return duckdb::LogicalTypeId::DATE;
case TIMESTAMPOID:
return duckdb::LogicalTypeId::TIMESTAMP;
case FLOAT8OID:
return duckdb::LogicalTypeId::DOUBLE;
case NUMERICOID: {
if (typmod == -1) {
auto extra_type_info = duckdb::make_shared<NumericAsDouble>();
return duckdb::LogicalType(duckdb::LogicalTypeId::DOUBLE, std::move(extra_type_info));
}
auto precision = numeric_typmod_precision(typmod);
auto scale = numeric_typmod_scale(typmod);
return duckdb::LogicalType::DECIMAL(precision, scale);
}
default:
elog(ERROR, "Unsupported quack type: %d", type);
elog(ERROR, "Unsupported quack (Postgres) type: %d", type);
}
}

Expand All @@ -116,8 +146,8 @@ AppendString(duckdb::Vector &result, Datum value, idx_t offset) {

void
ConvertPostgresToDuckValue(Datum value, duckdb::Vector &result, idx_t offset) {

switch (result.GetType().id()) {
auto &type = result.GetType();
switch (type.id()) {
case duckdb::LogicalTypeId::BOOLEAN:
Append<bool>(result, DatumGetBool(value), offset);
break;
Expand All @@ -143,8 +173,18 @@ ConvertPostgresToDuckValue(Datum value, duckdb::Vector &result, idx_t offset) {
Append<duckdb::dtime_t>(result, duckdb::dtime_t(static_cast<int64_t>(value + QUACK_DUCK_TIMESTAMP_OFFSET)),
offset);
break;
case duckdb::LogicalTypeId::DOUBLE: {
auto aux_info = type.GetAuxInfoShrPtr();
if (aux_info && dynamic_cast<NumericAsDouble *>(aux_info.get())) {
elog(ERROR, "NUMERIC AS DOUBLE");
}
Append<double>(result, DatumGetFloat8(value), offset);
break;
}
case duckdb::LogicalTypeId::DECIMAL:
elog(ERROR, "DECIMAL TYPE");
default:
elog(ERROR, "Unsupported quack type: %d", static_cast<int>(result.GetType().id()));
elog(ERROR, "Unsupported quack (DuckDB) type: %d", static_cast<int>(result.GetType().id()));
break;
}
}
Expand Down

0 comments on commit fcec38e

Please sign in to comment.