/
Store database structure in unit configs [5.3.0-B1]
Store database structure in unit configs [5.3.0-B1]
The database is used for storing majority of user entered data (except user uploaded files). Almost each database table has associated unit, that is responsible for reading/writing data from it.
Following is missing however:
- the unit isn't aware/responsible for the indexes added to associated table
- cross-table relations are not stored anywhere (even in database itself)
- adding new fields to database is not error-prone, because:
- developer needs to switch to DB application (Navicat, Sequel Pro, phpMyAdmin)
- developer needs to enter several values to configure new field (field name, field type, field value size, null/not null, default value)
- developer needs to go to "System Tools" section in Admin Console
- developer needs to type in unit name to see "Fields" array content
- developer needs to copy/paste relevant changed field declarations from there to the unit config in IDE
Solution
- make "
db_type
" field option (in "Fields" array) contain pseudo database type, instead of actual MySQL data type:date - "INT(10) NULL DEFAULT NULL"
money - "DECIMAL(20,6) NULL DEFAULT NULL"
int32 - "INT(10)"
int64 - "BIGINT(20)"
- auto - "INT(10)" + auto-increment
- auto64 - "BIGINT(20)" + auto-increment
- text255 - "VARCHAR(255) NOT NULL DEFAULT ''"
- text - "text NULL DEFAULT NULL"
and so on
- database table columns must be specified in "
Fields
" array first: - only, when "
db_type
" field option is specified for all fields in the table, then auto-adjust that table describe index structure in the new "
Indexes
" unit config option like so (the field specified in "IDField" of unit config is automatically assigned an "auto_increment" db extra and added as primary key):'Indexes' => array( 'IDX_INDEX_NAME' => array( 'columns' => array('DBColumn1', 'DBColumn2'), 'unique' => true, ), ),
- create the "in-portal db:sync" command, that will:
- create missing database tables
- change structure of existing tables to match one from unit config (but won't delete columns/tables, because of performance)
- integrate code, that creates multi-lingual columns (e.g. "
l1_Name
") into this command
- add "OnBeforeTableStructureChange" and "OnAfterTableStructureChange" events, that will:
- be called before/after each column is added/changed
- have "
old_schema
" event parameter, when changing column definition (fragment of ALTER TABLE statement relevant to affected column) - have "
new_schema
" event parameter, when adding/changing column definition (fragment of ALTER TABLE statement relevant to affected column) - have "
column_name
" event parameter - allow developer to write universal code to migrate existing data in the column using PHP code
- replace "
Rebuild Multilingual Fields
" action on "System Tools
" page with "Rebuild Database Structure
" action that would call above created command - run above created command before SQL migrations during deploy
if table column has association with another database table, then define it via new "
foreign_key
" field option (won't be used for now) like so:'Fields' => array( 'ItemResourceId' => array( 'type' => 'int', ..., 'default' => null, 'foreign_key' => 'l:ResourceId' ), ),
Problems
- existing unit configs might be already not in sync with db and attempting to mass convert db based on unit configs might make things worse
- none of unit configs have "
db_type
" and we have lots of tables/fields to populate them automatically - when adding new fields via "OnAfterConfigRead" event there is no way to specify position at which they will be added into the table; specifying position of each field is time consuming