Skip to content

Postgres Keyword SERIAL creates Default But the Default is ignored by Sqlpp23 #59

@SimpleForest

Description

@SimpleForest

Summary

Used DB: psql (17.6 (Ubuntu 17.6-1))

In my first steps I realized that I have to explicitly give an integer value to add_values for a column created with the Keyword SERIAL

serial SERIAL PRIMARY KEY

If I dont give a precomputed serial from cpp I get an error.

I expect this to be unwanted behavior, as the SERIAL has a Default given. In this example it is

serial integer NOT NULL DEFAULT nextval('news.article_serial_seq'::regclass)

Code to Reproduce:

Create Database - not minimal but also not complex:

CREATE SCHEMA IF NOT EXISTS news;

CREATE TABLE IF NOT EXISTS news.author (
	serial SERIAL PRIMARY KEY,
	fullname VARCHAR(255) 
);

CREATE TABLE IF NOT EXISTS  news.publisher (
	serial SERIAL PRIMARY KEY,
	fullname VARCHAR(255) UNIQUE
);

CREATE TABLE IF NOT EXISTS  news.journal (
	serial SERIAL PRIMARY KEY,
	publisher_serial INTEGER NOT NULL,
	FOREIGN KEY (publisher_serial) REFERENCES news_collection.publisher(serial),
	fullname VARCHAR(255) UNIQUE
);

CREATE TABLE IF NOT EXISTS  news.article (
	serial SERIAL PRIMARY KEY,
	summary VARCHAR(2055) UNIQUE,
	author_serial INTEGER NOT NULL,
	journal_serial INTEGER NOT NULL,
   	FOREIGN KEY (author_serial) REFERENCES news_collection.author(serial),
	FOREIGN KEY (journal_serial) REFERENCES news_collection.journal (serial),
	url VARCHAR(255),
	title VARCHAR(255),
	article VARCHAR(10000),
	publish_date date
);

INSERT INTO news.publisher (fullname) VALUES ('Zeitverlag Gerd Bucerius GmbH & Co. KG');
INSERT INTO news.journal (fullname, publisher_serial) VALUES('Die Zeit', 1);
INSERT INTO news.author (fullname, publisher_serial) VALUES('Der Investigative Reporter', 1);

Create the db header file with ddl2cpp

pg_dump -U postgres -h localhost -p 5432 -d searchable_news -W -f ~/searchable_news.sql
./ddl2cpp ~/searchable_news.sql ~/news_dbpp.h news

Cpp code chunk, place into ur hello world:

    auto multi_insert2 = insert_into(table).columns(table.url, table.title, table.summary, table.authorSerial, table.journalSerial);
    multi_insert2.add_values(
                           table.url = "abc1",
                           table.title = "abc1",
                           table.summary = "abc1  asdyxc",
                           table.authorSerial = 1,
                           table.journalSerial = 1);
    multi_insert2.add_values(
        table.url = "abc2",
        table.title = "abc2",
        table.summary = "abc2  asdyxc",
        table.authorSerial = 1,
        table.journalSerial = 1);
    auto& db = sndb::getConnection();
    auto tx = start_transaction(db);
    try
    {
        db(multi_insert2);
        tx.commit();
    }
    catch (...)
    {
        std::cerr << "Something terrible happened here" << std::endl;
        //tx.rollback();
    }
    ```

Error received

/usr/local/include/sqlpp23/core/clause/insert_value_list.h:138: error: static assertion failed: at least one required column is missing in columns()
/usr/local/include/sqlpp23/core/clause/insert_value_list.h:138:19: error: static assertion failed: at least one required column is missing in columns()
  138 |     static_assert(wrong<T...>,
      |                   ^~~~~~~~~~~
/usr/local/include/sqlpp23/core/clause/insert_value_list.h:138:19: note: ‘sqlpp::wrong<>’ evaluates to false

coming from

class assert_all_required_columns_t : public wrapped_static_assert {
 public:
  template <typename... T>
  static void verify(T&&...) {
    static_assert(wrong<T...>,
                        "at least one required column is missing in columns()");
  }
};

Reason

This is because the serial has in the generated header definition

    struct Serial : public ::sqlpp::name_tag_base {
      SQLPP_CREATE_NAME_TAG_FOR_SQL_AND_CPP(serial, serial);
      using data_type = ::sqlpp::integral;
      using has_default = std::true_type;
    };   
    

    using _required_insert_columns = sqlpp::detail::type_set<
               sqlpp::column_t<sqlpp::table_t<NewsArticle_>, Serial>,
               sqlpp::column_t<sqlpp::table_t<NewsArticle_>, AuthorSerial>,
               sqlpp::column_t<sqlpp::table_t<NewsArticle_>, JournalSerial>>;

Solution

  • so using has_default = std::false_type; is set wrongly
  • we also do not want the entry sqlpp::column_t<sqlpp::table_t<NewsArticle_>, Serial>, in the required_insert_columns construction.

I tested the solution manually. I did not dive into adapting the ddl2cpp.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions