Options

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

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?

Comments

  • Options
    Bryan_HBryan_H Vertica Employee Administrator

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

  • Options

    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)
    
  • Options
    edited November 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)
        { }
    };
    
  • Options

    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.

Leave a Comment

BoldItalicStrikethroughOrdered listUnordered list
Emoji
Image
Align leftAlign centerAlign rightToggle HTML viewToggle full pageToggle lights
Drop image/file