Open-source software for Joomla, Gitea, and web platforms. Home of MokoSuite, MokoGitea, and MokoCLI.
Tennessee
architecture/joomla-database-conventions.-
Joomla Database Conventions
Database schema standards for MokoSuite extensions.
Table Naming
#__mokosuitebackup_profiles # Backup profiles
#__mokosuitebackup_records # Backup history records
#__mokosuitecross_posts # Cross-post queue
#__mokosuitecross_services # Configured services
#__mokosuitecross_templates # Message templates
#__mokosuitecommunity_profiles # User profiles
#__mokosuitecommunity_connections # Friend connections
#__mokosuitecommunity_activities # Activity stream
#__mokoog_tags # OG meta tag records
Pattern: #__{extensionname}_{entity} — the extension name has no separators, entity is plural.
Standard Columns
Every table should include these Joomla-standard columns where applicable:
| Column | Type | Purpose |
|---|---|---|
id |
INT UNSIGNED AUTO_INCREMENT |
Primary key |
published |
TINYINT(1) DEFAULT 1 |
Publication state (1=published, 0=unpublished, -2=trashed) |
ordering |
INT DEFAULT 0 |
Manual sort order |
checked_out |
INT UNSIGNED DEFAULT NULL |
Record locking (user ID) |
checked_out_time |
DATETIME DEFAULT NULL |
Record lock timestamp |
created_by |
INT DEFAULT 0 |
Creator user ID |
created_at |
DATETIME DEFAULT CURRENT_TIMESTAMP |
Creation timestamp |
modified_by |
INT DEFAULT 0 |
Last modifier user ID |
modified_at |
DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP |
Last modified |
params |
TEXT |
JSON configuration blob |
SQL Install Script
sql/install.mysql.sql — creates all tables:
CREATE TABLE IF NOT EXISTS `#__mokosuitebackup_profiles` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`title` VARCHAR(255) NOT NULL DEFAULT '',
`description` TEXT,
`backup_type` VARCHAR(50) NOT NULL DEFAULT 'full',
`config` TEXT COMMENT 'JSON profile configuration',
`filters` TEXT COMMENT 'JSON exclude filters',
`published` TINYINT(1) NOT NULL DEFAULT 1,
`ordering` INT NOT NULL DEFAULT 0,
`checked_out` INT UNSIGNED DEFAULT NULL,
`checked_out_time` DATETIME DEFAULT NULL,
`created_by` INT NOT NULL DEFAULT 0,
`created_at` DATETIME DEFAULT CURRENT_TIMESTAMP,
`modified_at` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `idx_mokosuitebackup_profiles_published` (`published`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS `#__mokosuitebackup_records` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`profile_id` INT UNSIGNED NOT NULL DEFAULT 0,
`status` VARCHAR(50) NOT NULL DEFAULT 'pending',
`backup_type` VARCHAR(50) NOT NULL DEFAULT 'full',
`archive_path` VARCHAR(1024) DEFAULT NULL,
`archive_size` BIGINT UNSIGNED DEFAULT 0,
`db_size` BIGINT UNSIGNED DEFAULT 0,
`files_count` INT UNSIGNED DEFAULT 0,
`checksum` VARCHAR(64) DEFAULT NULL COMMENT 'SHA-256',
`duration_seconds` INT UNSIGNED DEFAULT 0,
`error_message` TEXT,
`created_at` DATETIME DEFAULT CURRENT_TIMESTAMP,
`completed_at` DATETIME DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `idx_mokosuitebackup_records_profile` (`profile_id`),
KEY `idx_mokosuitebackup_records_status` (`status`),
KEY `idx_mokosuitebackup_records_created` (`created_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_unicode_ci;
Update Scripts
Versioned migrations in sql/updates/mysql/{version}.sql:
-- sql/updates/mysql/01.01.00.sql
-- Add encryption support
ALTER TABLE `#__mokosuitebackup_profiles`
ADD COLUMN `encryption_enabled` TINYINT(1) NOT NULL DEFAULT 0 AFTER `filters`,
ADD COLUMN `encryption_key_hash` VARCHAR(128) DEFAULT NULL AFTER `encryption_enabled`;
ALTER TABLE `#__mokosuitebackup_records`
ADD COLUMN `encrypted` TINYINT(1) NOT NULL DEFAULT 0 AFTER `checksum`;
Rules for update scripts:
- One file per version, named exactly matching the manifest version
- Only contains the delta from the previous version
- Use
ALTER TABLEfor schema changes - Use
INSERT/UPDATEfor data migrations - Never drop columns in minor versions (only major)
- Always test upgrade path: fresh install AND upgrade from previous version
Composite Keys
For content-type lookups (like OG tags), use composite keys:
CREATE TABLE `#__mokoog_tags` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`content_type` VARCHAR(100) NOT NULL,
`content_id` INT UNSIGNED NOT NULL,
`og_title` VARCHAR(255) DEFAULT NULL,
`og_description` TEXT,
`og_image` VARCHAR(1024) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `unq_mokoog_tags_content` (`content_type`, `content_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_unicode_ci;
Uninstall Script
sql/uninstall.mysql.sql — drops tables in reverse dependency order:
DROP TABLE IF EXISTS `#__mokosuitebackup_records`;
DROP TABLE IF EXISTS `#__mokosuitebackup_profiles`;
Pages