$TABLE
Thread Safety and Parallelism
$TABLE (and all Grapa datatypes) are fully thread safe by design. All variable and data structure updates are internally synchronized at the C++ level, so you will never encounter crashes or corruption from concurrent access. However, if your program logic allows multiple threads to read and write the same table or field, you may see logical race conditions (unexpected values, overwrites, etc.). This is a design consideration, not a stability issue. Minimize shared mutable state between threads unless intentional.
Only $thread()
objects provide explicit locking and unlocking via lock()
, unlock()
, and trylock()
. To protect access to a shared resource, create a $thread()
lock object and use it to guard access. Calling .lock()
or .unlock()
on a regular variable (like a table, array, or scalar) will return an error.
Canonical Example:
lock_obj = $thread();
lock_obj.lock();
/* ... perform thread-safe operations on shared table or data ... */
lock_obj.unlock();
See Threading and Locking and Function Operators: static and const for details and best practices.
References:
A $TABLE is a hierarchical database with columns, rows, supporting both row store and column store architectures.
Note: - The type GROUP
is used both for hierarchical/grouped databases and for folders/directories in the file system. When navigating a traditional file system, folders/directories will appear as GROUP
in listings and type queries.
Database Types
Row Store (RTABLE_TREE)
- Optimization: Transactional workloads, record-based operations
- Storage: Contiguous data blocks (BYTE_DATA) for each record
- Use Cases: OLTP applications, frequent record updates, small to medium datasets
Column Store (CTABLE_TREE)
- Optimization: Analytical queries, column-based operations
- Storage: Fragmented data storage (FREC_DATA) for efficient sparse data handling
- Use Cases: Data warehousing, analytical workloads, large datasets with many columns
Group Store (GROUP_TREE)
- Optimization: Hierarchical/grouped data, or file system folders/directories
- Storage: GROUP_TREE
- Use Cases: Nested/grouped data, directory navigation, or representing folders in the file system
Type Table
Type | Description/Use Case | Storage Model |
---|---|---|
GROUP | Folder/directory in file system, or hierarchical/grouped database | GROUP_TREE |
ROW | Transactional, record-based, OLTP, point queries | RTABLE_TREE, BYTE_DATA |
COL | Analytical, column-based, sparse/large datasets | CTABLE_TREE, FREC_DATA |
Key Features
- In-Memory and Persistent: Can be stored in memory or on the file system
- Dynamic Schema: Fields can be added and removed at runtime
- Multiple Storage Types: Support for fixed, variable, and partitioned field storage
- Efficient Queries: Optimized for both row-oriented and column-oriented access patterns
Performance Characteristics
Row Store
- Fast record retrieval and updates
- Efficient for point queries on specific records
- Good for transactional workloads
Column Store
- Fast column scans and aggregations
- Efficient for analytical queries across columns
- Better compression for similar data types
- Optimized for sparse data storage
Basic Usage
# Create an in-memory table
f = $file().table()
f.type()
$TABLE
# Basic operations
f.set("test", "value")
f.ls()
[{"$KEY":"test","$TYPE":"ROW","$BYTES":5}]
f.get("test")
value
Field Creation
Field Creation Syntax
The mkfield()
method creates fields in the table with the following syntax:
table.mkfield(field_name, field_type, storage_mode, size)
Field Types
Type | Description | Default Size | Notes |
---|---|---|---|
STR | String | Variable | Use "VAR" mode for variable length |
INT | Integer | 4 bytes | Important: Use without explicit mode for proper integer types |
FLOAT | Floating point | 8 bytes | Use "FIX" mode with size 8 |
TIME | Timestamp | 8 bytes | Unix timestamp format |
BOOL | Boolean | 1 byte | True/false values |
Storage Modes
Mode | Description | Use Case |
---|---|---|
VAR | Variable length storage | Strings, variable data |
FIX | Fixed length storage | Numbers, timestamps |
PAR | Partitioned storage | Large data requiring partial updates |
Field Creation Examples
/* String fields */
table.mkfield("name", "STR", "VAR"); /* Variable length string */
table.mkfield("code", "STR", "FIX", 10); /* Fixed length string (10 chars) */
/* Integer fields - IMPORTANT: Use without explicit mode */
table.mkfield("age", "INT"); /* ✅ Correct: Creates proper integer field */
table.mkfield("id", "INT", "FIX", 4); /* ❌ May create string field instead */
/* Float fields */
table.mkfield("salary", "FLOAT", "FIX", 8); /* 8-byte floating point */
table.mkfield("price", "FLOAT"); /* Default float field */
/* Time fields */
table.mkfield("created", "TIME", "FIX", 8); /* Unix timestamp */
Field Creation Best Practices
- Integer Fields: Use
table.mkfield("field", "INT")
without explicit mode - String Fields: Use
"VAR"
mode for variable length,"FIX"
with size for fixed length - Float Fields: Use
"FIX"
mode with size 8 for consistency - Time Fields: Use
"FIX"
mode with size 8 for timestamps
Storage Architecture
Row Store Architecture
- Data Organization: Records stored contiguously
- Access Pattern: Horizontal (all fields of a record)
- Storage Type: BYTE_DATA for fixed fields
- Best For: Record-based operations
Column Store Architecture
- Data Organization: Columns stored separately
- Access Pattern: Vertical (all values of a field)
- Storage Type: FREC_DATA for fixed fields, SDATA_TREE for variable fields
- Best For: Column-based operations
Field Storage Types
Fixed Fields (STORE_FIX)
- Row Store: Contiguous storage within record
- Column Store: Fragmented storage (FREC_DATA) for efficient sparse data
- Use Case: Small, frequently accessed fields
Variable Fields (STORE_VAR)
- Row Store: Reference to separate data area
- Column Store: Tree-based storage (SDATA_TREE)
- Use Case: Medium-sized variable data
Partitioned Fields (STORE_PAR)
- Row Store: Reference to partitioned data area
- Column Store: Fragmented storage for large data
- Use Case: Large data requiring partial updates
Use Case Examples
Row Store Example (Transactional)
/* Create row store database */
f.mk("orders_db", "ROW");
f.cd("orders_db");
/* Define schema with correct field creation */
f.mkfield("order_id", "INT"); /* Integer field */
f.mkfield("customer_id", "INT"); /* Integer field */
f.mkfield("order_date", "TIME", "FIX", 8); /* Timestamp */
f.mkfield("total_amount", "FLOAT", "FIX", 8); /* Float field */
f.mkfield("status", "STR", "VAR"); /* Variable string */
/* Add records */
f.set("order_001", 1001, "customer_id");
f.set("order_001", 1640995200, "order_date"); /* Unix timestamp */
f.set("order_001", 299.99, "total_amount");
f.set("order_001", "pending", "status");
/* Retrieve complete record */
order = f.get("order_001", "customer_id"); /* Returns integer 1001 */
Column Store Example (Analytical)
/* Create column store database */
f.mk("sales_analytics", "COL");
f.cd("sales_analytics");
/* Define schema with correct field creation */
f.mkfield("date", "TIME", "FIX", 8); /* Timestamp */
f.mkfield("product_id", "INT"); /* Integer field */
f.mkfield("region", "STR", "VAR"); /* Variable string */
f.mkfield("sales_amount", "FLOAT", "FIX", 8); /* Float field */
f.mkfield("quantity", "INT"); /* Integer field */
/* Add data (records created automatically) */
f.set("sale_001", 1640995200, "date");
f.set("sale_001", 1001, "product_id");
f.set("sale_001", "North", "region");
f.set("sale_001", 299.99, "sales_amount");
f.set("sale_001", 2, "quantity");
/* Column-oriented queries are efficient */
/* (In a real implementation, you'd have aggregation functions) */
Data Retrieval and Type Conversion
Retrieving Data with Type Conversion
When retrieving data from tables, use appropriate type conversion methods:
/* Retrieve with type conversion */
name = table.get("user1", "name").str(); /* Convert to string */
age = table.get("user1", "age").int(); /* Convert to integer */
salary = table.get("user1", "salary").float(); /* Convert to float */
Type Conversion Methods
Method | Description | Use Case |
---|---|---|
.str() | Convert to string | Text data, display |
.int() | Convert to integer | Numeric calculations |
.float() | Convert to float | Decimal calculations |
.type() | Get data type | Debugging, type checking |
Performance Optimization
Row Store Optimization
- Use fixed fields for frequently accessed data
- Minimize variable field usage for better performance
- Design for record-based access patterns
Column Store Optimization
- Use appropriate field types for data distribution
- Consider data sparsity when designing schemas
- Design for column-oriented access patterns
Advanced Features
Dynamic Schema
/* Add fields at runtime */
f.mkfield("new_field", "STR", "VAR");
/* Remove fields */
f.rmfield("old_field");
Debug Information
/* Inspect database structure */
f.debug();
Best Practices
Field Creation
- Integer Fields: Always use
table.mkfield("field", "INT")
without explicit mode - String Fields: Use
"VAR"
for variable length,"FIX"
with size for fixed length - Float Fields: Use
"FIX"
mode with size 8 for consistency - Type Conversion: Always use
.str()
,.int()
,.float()
when retrieving data
Choosing Between Row and Column Store
Use Row Store When: - Frequent record updates - Point queries on specific records - Small to medium datasets - Transactional workloads
Use Column Store When: - Analytical queries and aggregations - Column scans across many records - Large datasets with many columns - Sparse data (many NULL values)
Schema Design
Row Store: - Group related fields together - Use fixed fields for primary keys and frequently accessed data - Consider record size for optimal performance
Column Store: - Design for column-oriented access patterns - Use appropriate storage types for data distribution - Consider data sparsity and growth patterns
Technical Details
Storage Implementation
- Row Store: Uses BYTE_DATA for contiguous storage
- Column Store: Uses FREC_DATA for fragmented storage of fixed fields
- Growth Management: Automatic growth parameter setting for optimal performance
- Sparse Data: Efficient handling of NULL and empty values
Data Access Patterns
- Row Store: Optimized for horizontal data access
- Column Store: Optimized for vertical data access
- Cache Efficiency: Different cache utilization patterns for each type