Model

Modelは、jsonスキーマまたはyaml形式で記述されたテーブル定義からデータベーステーブルを自動生成し、SQLAlchemyでORマップしてmodel共通コンテキストにエントリするサービスです。ATOMサービスから生成されるテーブルオブジェクトも本サービスを内部的に利用しています。
プラグイン開発者がテーブルスキーマを記述して本サービスを直接利用することが可能ですが、ATOMサービスを利用してデータベースモデルを生成する方が圧倒的に単純です。

モデルが保有する属性

  • name: モデルの名前をユニークに指定します。データベースのテーブル名となります。ATOMから生成される場合は、ATOMのクラス名が使用されます。

Caution

データベースにPostgreSQLを利用する場合に先頭大文字の名前で生成すると生のSQL文で操作しにくくなりますので注意してください。テーブル名をクォーテートで括るなどする必要が出てきます。

  • category: テーブルのカテゴリを指定します。カテゴリには特別な役割はありません。シンプルなラベルです。

  • schema jsonschemaまたはyamlを使用してテーブルのカラム定義を記述します。

  • constraints テーブル属性の制約を指定します。

    primary key
    テーブルの主キーを指定します。
    unique key
    テーブルのユニークキーを指定します。
    unique key list
    テーブルの複合ユニークキーを指定します。
    foreign key
    テーブルの外部キーを指定します。
  • scenario auto generate mode テーブルのCRUDシナリオを自動的に生成するためのモードを指定します。ATOMの利用を推奨している為、将来的には廃止される予定です。デフォルトはFalseです。

  • base path: シナリオ自動生成モードがTrueの場合に生成されるAPIの基底パスを指定できます。scenario auto generate mode同様に現在は非推奨としています。


カラム定義について

列定義は、次のパラメーターを指定します。

type
JSONの型表現でデータベースの列型を指定します。SQLAlchemyタイプへの変換ルールは次のとおりです。
json type database type
integer sqlalchemy.types.Integer
number sqlalchemy.types.Float
boolean sqlalchemy.types.Boolean
string sqlalchemy.types.String
object sqlalchemy.types.Text
array sqlalchemy.types.Text


dbtype
charsmallintなどを使用したい場合は、データベース特化した型の指定は、dbtypeを使用します。
length
列の桁数を指定します。typeがstringで、長さが64に指定されている場合、それはsqlalchemy.types.String(64)に変換されます。指定しない場合、デフォルトの長さは、Textタイプの場合は65535Stringタイプの場合は255です。
default
列のPythonレイヤのデフォルト値を指定します。CREATE TABLEステートメントには影響しません。
server_default
列のデータベースレイヤのデフォルト値を指定します。CREATE TABLEステートメントに影響します。integerなどの数値型を指定するときは注意してください。SQLAlchemy仕様では、server_default:0は許可されておらず、server_default:"0"として指定する必要があります。
func
SQLAlchemyの組込み関数を指定します。関数名はsqlalchemy.funcの下に存在する必要があります。指定された関数は、列defaultに設定されます。

Note

Not NULL制約は、jsonschemaのrequiredで制御されます。

Example

# Please upload this yaml file from Frontal model list.
category: example
scenario_auto_generation_mode: false
model:
  name: countrylanguage
  schema:
    type: object
    properties:
      CountryCode:
        type: string
        dbtype: CHAR
        length: 3
      Language:
        type: string
        dbtype: CHAR
        length: 30
      IsOfficial:
        type: boolean
        server_default: 'false'
      Percentage:
        type: number
        default: 0
    required:
      - CountryCode
      - Language
      - IsOfficial
  constraints:
    primary_key: CountryCode
# Database terminal
mysql> desc countrylanguage;
+-------------+------------+------+-----+---------+-------+
| Field       | Type       | Null | Key | Default | Extra |
+-------------+------------+------+-----+---------+-------+
| CountryCode | char(3)    | NO   | PRI | NULL    |       |
| Language    | char(30)   | NO   |     | NULL    |       |
| IsOfficial  | tinyint(1) | NO   |     | 0       |       |
| Percentage  | float      | YES  |     | NULL    |       |
+-------------+------------+------+-----+---------+-------+
4 rows in set (0.00 sec)
# interactive shell
>>> async with model.aiodb() as conn:↵
...     await conn.execute(model.countrylanguage.insert().values(CountryCode="ABW", Language="English", Percentage=9.5))↵
... ↵
... async with model.aiodb() as conn:↵
...     cursor = await conn.execute(model.countrylanguage.select())↵
...     rows = await cursor.fetchall()↵
...     [print(row) for row in rows]↵
... ↵
('ABW', 'English', False, 9.5)↵
↵
# Please upload this yaml file from Frontal model list.
category: example
scenario_auto_generation_mode: false
model:
  name: country
  schema:
    type: object
    properties:
      Code:
        type: string
        dbtype: CHAR
        length: 3
      Name:
        type: string
        dbtype: CHAR
        length: 52
      Continent:
        type: string
      Region:
        type: string
        dbtype: CHAR
        length: 26
        default: Asia
      SurfaceArea:
        type: number
        default: 0
      IndepYear:
        type: integer
        dbtype: SMALLINT
      Population:
        type: integer
      LifeExpectancy:
        type: number
      GNP:
        type: number
      LocalName:
        type: string
        dbtype: CHAR
        length: 45
      GovernmentForm:
        type: string
        dbtype: CHAR
        length: 45
      HeadOfState:
        type: string
        dbtype: CHAR
        length: 60
      Capital:
        type: integer
    required:
      - Code
      - Name
      - Continent
      - Region
      - SurfaceArea
      - Population
      - LocalName
      - GovernmentForm
  constraints:
    primary_key: Code
    unique_keys:
      - Name
# Database terminal
mysql> desc country;
+----------------+--------------+------+-----+---------+-------+
| Field          | Type         | Null | Key | Default | Extra |
+----------------+--------------+------+-----+---------+-------+
| Code           | char(3)      | NO   | PRI | NULL    |       |
| Name           | char(52)     | NO   | UNI | NULL    |       |
| Continent      | varchar(255) | NO   |     | NULL    |       |
| Region         | char(26)     | NO   |     | NULL    |       |
| SurfaceArea    | float        | NO   |     | NULL    |       |
| IndepYear      | smallint(6)  | YES  |     | NULL    |       |
| Population     | int(11)      | NO   |     | NULL    |       |
| LifeExpectancy | float        | YES  |     | NULL    |       |
| GNP            | float        | YES  |     | NULL    |       |
| LocalName      | char(45)     | NO   |     | NULL    |       |
| GovernmentForm | char(45)     | NO   |     | NULL    |       |
| HeadOfState    | char(60)     | YES  |     | NULL    |       |
| Capital        | int(11)      | YES  |     | NULL    |       |
+----------------+--------------+------+-----+---------+-------+
13 rows in set (0.00 sec)
# interactive shell
>>> async with model.aiodb() as conn:↵
...     await conn.execute(model.country.insert().values(Code="AFG", Name="Afghanistan", Region="Southern and Central Asia", Continent="Asia",↵
... SurfaceArea=652090.00, Population=22720000, LocalName="Afganistan/Afqanestan", GovernmentForm="Islamic Emirate"))↵
... ↵
... async with model.aiodb() as conn:↵
...     cursor = await conn.execute(model.country.select())↵
...     rows = await cursor.fetchall()↵
...     [print(row) for row in rows]↵
... ↵
('AFG', 'Afghanistan', 'Asia', 'Southern and Central Asia', 652090.0, None, 22720000, None, None, 'Afganistan/Afqanestan', 'Islamic Emirate', None, None)↵
↵
# Please upload this yaml file from Frontal model list.
category: example
scenario_auto_generation_mode: false
model:
  name: city
  schema:
    type: object
    properties:
      ID:
        type: integer
      Name:
        type: string
        dbtype: CHAR
        length: 35
      CountryCode:
        type: string
        dbtype: CHAR
        length: 3
      District:
        type: string
        dbtype: CHAR
        length: 20
      Population:
        type: integer
        default: 0
    required:
      - ID
      - Name
      - CountryCode
      - District
  constraints:
    primary_key: ID
    unique_keys:
      - Name
    foreign_keys:
      - table: country
        column: Code
        key: CountryCode
# Database terminal
mysql> desc city;
+-------------+----------+------+-----+---------+----------------+
| Field       | Type     | Null | Key | Default | Extra          |
+-------------+----------+------+-----+---------+----------------+
| ID          | int(11)  | NO   | PRI | NULL    | auto_increment |
| Name        | char(35) | NO   | UNI | NULL    |                |
| CountryCode | char(3)  | NO   | MUL | NULL    |                |
| District    | char(20) | NO   |     | NULL    |                |
| Population  | int(11)  | YES  |     | NULL    |                |
+-------------+----------+------+-----+---------+----------------+
5 rows in set (0.00 sec)
# interactive shell
>>> async with model.aiodb() as conn:↵
...     await conn.execute(model.city.insert().values(Name="Kabul", CountryCode="AFG", District="Kabol", Population=1780000))↵
... ↵
... async with model.aiodb() as conn:↵
...     cursor = await conn.execute(model.city.select())↵
...     rows = await cursor.fetchall()↵
...     [print(row) for row in rows]↵
... ↵
(1, 'Kabul', 'AFG', 'Kabol', 1780000)↵
↵