Skip to main content

How to make AnalyticPartitionWriter produce arbitrary fixed-point numeric data?

  • November 22, 2024
  • 4 replies
  • 9 views

RonCormier

Anyone have any tips for outputing numerics (i.e. with precision and scale) from AnalyticPartitionWriter? It seems there is no setNumeric() method.
https://docs.vertica.com/24.4.x/sdkdocs/CppSDK/class_vertica_1_1_analytic_partition_writer.htm

I'm writing a UDx and it would be very handy to produce VNumerics. Instead I'm using floats which make me nervous. Seems Java has it... why not C++? Is there some other method?

4 replies

Bryan_H
Forum|alt.badge.img+2
  • Participating Frequently
  • November 23, 2024

You should be able to create a VNumeric and pass the pointer in the C++ SDK:
VNumeric * getColPtrForWrite (size_t idx)


RonCormier
  • Author
  • New Participant
  • November 26, 2024

Thanks. I'm struggling to get that function to work though, getting strange values like 1402984621720.88. Probably I'm using it wrong. Do you have an example of how it should be used? Attaching a reproducer.

dbadmin@pc=>with nums as (select 12.5::numeric(8,2) as num) select *, numeric_test(num) over () from nums;
  num  |     ?column?
-------+------------------
 12.50 | 1402984621720.88
(1 row)

RonCormier
  • Author
  • New Participant
  • November 26, 2024

Ok, figured it out with the help of InvertedIndex.cpp example from the SDK.

class numeric_test : public AnalyticFunction
{
    virtual void processPartition(ServerInterface &srvInterface, AnalyticPartitionReader &inputReader,
                                    AnalyticPartitionWriter &outputWriter)
    {   
        const SizedColumnTypes &inTypes = inputReader.getTypeMetaData();
        vector<size_t> argCols;
        inTypes.getArgumentColumns(argCols);

        const SizedColumnTypes &outTypes = outputWriter.getTypeMetaData();
        vector<size_t> outCols;
        outTypes.getArgumentColumns(outCols);

        do {
            const VNumeric* inVal = inputReader.getNumericPtr(argCols.at(0));
            char* buff = new char[64];
            inVal->toString(buff, 64);
            srvInterface.log("string value of inVal: %s", buff);

            VNumeric &outNum = outputWriter.getNumericRef(outCols.at(0));
            outNum.copy(inVal);

            outputWriter.next();
        } while (inputReader.next());
    }

    virtual void setup(ServerInterface &srvInterface, const SizedColumnTypes
                        &argTypes)
    { }

    virtual void destroy(ServerInterface &srvInterface, const SizedColumnTypes
                        &argTypes)
    { }
};

Sergey_Cherepan_1
Forum|alt.badge.img+2

Just to point out, conversions to/from string are outrageously expensive.
I remember solving problem, by creating var of required datatype, for example NUMERIC(10,2). Then, overriding 8-byte array with my value. That performs quite reasonable.