4D is a relational DBMS that is integrated with an IDE and a proprietary programming language. It allows users to create custom graphical interfaces to work with their database, which can then be run on Windows or Mac OS systems to edit a locally stored database file. 4D can run as a server so that multiple clients can manage a single database. A companion product, "4D for iOS Preview", creates a customizable iOS app for viewing database contents.
4D was originally developed under the name "Silver Surfer" in the 1980s as a DBMS for the Macintosh platform. Apple canceled the project after receiving pressure from 3rd party software developers who feared the product would have an unfair competitive advantage if Apple released it. The project lead, Laurent Ribardière, left Apple and continued to develop the DBMS, ultimately releasing it under the name 4th Dimension. The product gained popularity for its user-friendly interface and ability to handle large amounts of data. 4D later added features like SQL support and a web server to keep up with newer systems. The product is still under active development and used by many companies.
Every modification to the data file since the last backup is recorded in the associated log file. If the database file is corrupted, 4D will restore the most recent backup and replay the changes in the log. When a new backup is created, the log file is cleared. Backups can be triggered manually or on a schedule. The database cannot be edited while a backup is running.
4D requires users to explicitly lock/unlock records and avoid deadlocks. For every user/process, each table in the database is given a read-only or read/write status. If a table is in the read-only state for a given user, all existing records loaded from the table are considered locked and cannot be modified. Any user can append new records to a table, even if it is read-only. If a table is in the read/write state, records will load as unlocked for the first user to load them. To modify a record that is already locked, a user can repeatedly load the record until it unlocks. A user unloads a record to make it available again to other users/processes.
A user can change a table from read-only to read/write or back at any time, but this only affects future load requests made by that user. If a read/write command is executed on a locked record, the command will either be ignored, display an error, or skip the record (if the command targets multiple records). Skipped records are added to the LockedSet of the requesting process to alert it of the error.
Queries can be grouped into transactions to ensure that changes occur atomically, but there is no deadlock prevention/detection. While a transaction is running, changes are saved into a temporary buffer and any modified records are locked.
4D supports one-to-one, many-to-one, and many-to-many relations between tables. Relations are classified as either automatic or non-automatic. Automatic relations cause foreign records to be loaded with records that reference them, while non-automatic relations do not. Automatic relations should avoid cyclic table references.
B+Tree Inverted Index (Full Text)
Indices can use a B+Tree or clustered B+Tree. 4D supports composite indices (indices on pairs of values). It also supports keyword indices (indices mapping individual words to records containing them).
Transactions lock records they modify or create, preventing other transactions from interfering with them. Unrepeatable reads may occur since transactions do not lock records they read. Table entries can be added while a transaction is running, creating invalid aggregation results (phantom problem). Transactions store all modifications in a temporary buffer, so uncommitted data can't affect other transactions.
Isolations levels for 4D transactions are not mentioned in the product documentation, but the behavior is consistent with the Read Committed isolation level.
Nested Loop Join Hash Join Index Nested Loop Join
Queries involving joins are invoked with the "query" and "query by formula" commands in the 4D language. If an index is available, 4D will perform an index nested loop join or an ordinary nested loop join, depending on which is faster given the table sizes. If no index is present, the documentation states that 4D uses the join algorithm used by its SQL engine (presumably Hash Join). The "relate one" and "relate many" commands are also similar to a join on a primary key. They fetch records directly using the primary key, if possible.
When a new data file is created, 4D automatically generates a log file for it with the ".journal" extension. The log file contains a record of all modifications since the last database backup. Entries describe the change that was performed as well as the user and time of the modification. The log also records when a user opens/closes the database.
The 4D query command outputs a selection (subset) of records from a single table. The selection is the set of records that satisfy the query parameters. If the table has any automatic relations, fields from related tables can be referenced in the filtering criteria. The selection can be stored as a named set or combined with other sets using union/intersection commands. Since each set is fully generated before further processing, this is best classified as a materialized model.
4D provides a graphical interface for managing data in a 4D database. Developers can customize the interface using the proprietary 4D programming language to provide additional buttons/forms for data manipulation. The language has syntax for control flow, variable creation, and database queries.
4D includes a SQL engine and the language supports inline SQL queries, though any SQL functionality can be replicated using the 4D language.
N-ary Storage Model (Row/Record)
A 4D database primarily consists of a structure file (for storing the schema), a data file (records stored in a row store format), and a log file for crash recovery. The database also has preferences folder and a resources folder with images/assets used for custom UI. Indices are stored in an index file.