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

  • 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)

  • 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)
    
  • edited November 26

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