admin管理员组

文章数量:1123509

I'm trying to create an ODB class for following PostgreSQL Database table:

CREATE TABLE person
(name          VARCHAR(10)   NOT NULL,
 birthday      DATE          NOT NULL,
 street        VARCHAR(200)  NOT NULL,
 house_number  NUMERIC(3)    NOT NULL,
 zip           CHAR(5)       NOT NULL,
 city          VARCHAR(100)  NOT NULL,
 CONSTRAINT person_pk        PRIMARY KEY (name, birthday)
);

The equivalent ODB class I've created is following:

class person {
    public:
        person() = default;

        person(const PersonId& id, const string& street, int house_number, const string& zip, const string& city)
            : id_(id), street_(street), house_number_(house_number), zip_(zip), city_(city) {}

        const PersonId& id() const { return id_; }
        void id(const PersonId& id) { id_ = id; }

        const string& street() const { return street_; }
        void street(const string& street) { street_ = street; }

        int house_number() const { return house_number_; }        
        void house_number(int house_number) {house_number_ = house_number; }

        const string& zip() const { return zip_; }
        void zip(const string& zip) { zip_ = zip; }

        const string& city() const { return city_; }
        void city(const string& city) { city_ = city; }

    private:
        #pragma db column("")
        #pragma db id
        PersonId id_;
        
        string street_;

        #pragma db type("NUMERIC(3)")
        int house_number_;

        string zip_;
        string city_;

};

In the ODB documentation is stated that the used PostgreSQL datatype "Numeric" for house_number "is limited to providing a binary buffer containing the binary representation of the value." Aka it cannot be mapped directly to a C++ int. Instead I have to create a value_trait specialization that implements the conversion between PostgreSQL Numeric and a C++ int. Therefore I tried to implement following value_trait:

namespace odb {
    namespace pgsql {
        template <>
        struct value_traits<int, id_numeric>
        {
            using image_type = details::buffer;

            using query_type = int;

            static void set_image(image_type& image, std::size_t& size, bool& is_null, const int& value)
            {
                is_null = false;

                std::string s = std::to_string(value);
                size = sizeof(int);

                std::cout << size << std::endl;

                if (size > image.capacity()) {
                    image.capacity(size);
                }
                
                std::memcpy(image.data(), &value, size);
            }

            static void set_value(int& value, const image_type& image, std::size_t size, bool is_null)
            {
                if (is_null)
                {
                    value = 0; // Default for null values
                    return;
                }

                try
                {
                    std::memcpy(&value, image.data(), size);
                }
                catch (const std::exception&)
                {
                    throw std::runtime_error("Failed to convert NUMERIC to int");
                }
            }
        };
    }
}

However, when trying to add a person object to the database with "db->persist(new_person) I get following error:

08P01: ERROR: insufficient data left in message CONTEXT: unnamed portal parameter $4

Parameter $4 refers to house_number. Does anyone know what be the issue here? Thanks for help already in advance!

When printing the value of image in the set_image() function to the console, the correct value gets printed.

本文标签: ODB Type Mapping PostgreSQL Numeric to C int with valuetraits specializationStack Overflow