-
-
Notifications
You must be signed in to change notification settings - Fork 13
Description
Hi! Hopefully there's a good answer to this. I put in as much information as I could to be easy to replicate.
Summary
If our database is responsible for setting the value of a column, we do not want to set that column via SQLAlchemy; instead, we would like the database to handle it via trigger. We do not want the model generated to set the value to None.
This is especially useful in cases where we want timestamps, and we wish them to be handled by the database.
Setup (3 files)
1: openapi.yml
openapi: '3.0.2'
info:
title: 'Null Value issue'
version: '1.0.1'
servers:
- url: https://api.server.test/v1
paths: {}
components:
schemas:
Pet:
type: object
x-tablename: pets
required:
- name
properties:
id:
type: integer
format: int64
x-primary-key: true
x-autoincrement: true
name:
type: string
created_at:
type: string
format: date-time
nullable: false2: main.py
from pathlib import Path
from open_alchemy import init_yaml
from open_alchemy import models
import sqlalchemy
from sqlalchemy import MetaData
from sqlalchemy import orm
OPENAPI_SPEC_FILE = Path("./openapi.yml")
SQLITE_PATH = 'sqlite:///petstore.db'
def main():
"""Define the main entrypoint of the program."""
# Load the models.
init_yaml(OPENAPI_SPEC_FILE)
# Connect to the database.
db = sqlalchemy.create_engine(SQLITE_PATH)
db_session = orm.scoped_session(orm.sessionmaker(bind=db))
metadata = MetaData()
metadata.reflect(bind=db)
# create a Pet
pet = models.Pet(name="Rover")
db_session.add(pet)
# After the following line, Pet will attempt to be added to the database.
# and an error will occur.
db_session.commit()
if __name__ == "__main__":
main()3: A sqlite database: petstore.db
eheiberg:~/dev/scratch/oa-issue$ sqlite3 oa_issue/petstore.db
SQLite version 3.28.0 2019-04-15 14:49:49
Enter ".help" for usage hints.
sqlite> .fullschema
CREATE TABLE pets (
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
name VARCHAR(64),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL
);
/* No STAT tables available */
sqlite>To setup the project...
poetry config virtualenvs.in-project true --local
poetry new oa_issue
cd oa_issue
poetry add SQLAlchemy OpenAlchemyCopy all 3 files above into the main oa_issue folder. Then run the script.
poetry run python main.pyResults
You receive an error from the database.
sqlalchemy.exc.IntegrityError: (sqlite3.IntegrityError)
NOT NULL constraint failed: pets.created_at
[SQL: INSERT INTO pets (name, created_at) VALUES (?, ?)]
[parameters: ('Rover', None)]
(Background on this error at: http://sqlalche.me/e/13/gkpj)
The error happens because the model is setting the created_at column to None explicitly. We don't get the same error on the id column, of course, because OpenAlchemy understands that this is auto-generated by the database, and sets the internal flag of x-generated on that attribute.
Just before the commit, looking in a debugger,
open_alchemy.models.Pet(id=None, name='Rover', created_at=None)Ideally, we'd like the same thing for the created_at column.
Question
Is there any way to get around this, while still keeping the created_at
column in the openapi.yml file?