Data Types
Introduction
Velocity provides a unified type system that abstracts database-specific data types into a consistent set of portable types. This abstraction allows you to write Schemas once and deploy them across any supported database without modification.
Philosophy: Schema-First Development
The Velocity Approach:
Instead of thinking in terms of database-specific types like VARCHAR2, NVARCHAR, BIGINT, or NUMBER(19), you define your schema using Velocity's portable data types. Velocity automatically translates these to the optimal native type for each database.
// Schema-first: Define once, deploy anywhere
Table productsTable = schema.CreateTable("products");
productsTable.AddColumn("product_id", DataType.Long, autoGenerate: true, notNull: true);
productsTable.AddColumn("product_name", DataType.VarChar, size: 200, notNull: true);
productsTable.AddColumn("price", DataType.Decimal, precision: 10, scale: 2);
productsTable.AddColumn("created_at", DataType.DateTime);
This same schema deploys correctly to SQL Server (as BIGINT, NVARCHAR(200), DECIMAL(10,2), DATETIME2), PostgreSQL (as BIGINT, VARCHAR(200), DECIMAL(10,2), TIMESTAMP), MySQL, Oracle, and all other supported databases—each using its native optimal types.
Benefits:
- Write Once, Deploy Anywhere - No database-specific schema code
- Type Safety - Consistent behavior across all databases
- Maintainability - Single source of truth for your data model
- Future-Proof - Easy migration between database vendors
- No Vendor Lock-in - Change databases without changing schemas
Golden Rule: Define your schemas using Velocity data types and let Velocity handle the database-specific translation. Don't worry about the underlying database types—Velocity optimizes them for you.
Velocity Data Types
Velocity provides 20 DataTypes organized into several categories:
Numeric Types
| Type | .NET Type | Description | Range/Precision |
|---|---|---|---|
Byte |
byte |
8-bit unsigned integer | 0 to 255 |
Short |
short |
16-bit signed integer | -32,768 to 32,767 |
Integer |
int |
32-bit signed integer | -2,147,483,648 to 2,147,483,647 |
Long |
long |
64-bit signed integer | -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807 |
Float |
float |
Single-precision floating-point (32-bit) | ~7 digits precision |
Double |
double |
Double-precision floating-point (64-bit) | ~15-16 digits precision |
Decimal |
decimal |
Fixed-precision decimal number | Exact precision, configurable scale |
Boolean |
bool |
Logical true/false value | true or false |
String Types
| Type | .NET Type | Description | Size |
|---|---|---|---|
Char |
string |
Fixed-length character string | Specify size (e.g., 10) |
VarChar |
string |
Variable-length character string | Specify maximum size |
Clob |
string |
Character Large Object for long text | Unlimited |
Date/Time Types
| Type | .NET Type | Description | Precision |
|---|---|---|---|
Date |
DateOnly |
Date only (no time component) | Year, month, day |
DateTime |
DateTime |
Date and time without timezone | Year to millisecond |
Interval |
TimeSpan |
Duration of time (not anchored to a date) | Days, hours, minutes, seconds |
Time |
TimeOnly |
Time of day without date component | Hour, minute, second |
Timestamp |
DateTimeOffset |
Date and time with timezone offset | Year to millisecond with timezone |
Binary and Large Object Types
| Type | .NET Type | Description | Use Cases |
|---|---|---|---|
Blob |
byte[] |
Binary Large Object | Images, files, binary data |
Geospatial Types
| Type | .NET Type | Description | Coordinate System |
|---|---|---|---|
Geometry |
NetTopologySuite.Geometries.Geometry |
Planar/Cartesian spatial data | Flat plane coordinates |
Geography |
YndigoBlue.Velocity.Model.Geography |
Geodetic/Spherical spatial data | Earth surface (latitude/longitude) |
Special Types
These types are used internally by Velocity and are not typically specified in schema definitions:
| Type | Description | Usage |
|---|---|---|
String |
Generic string type from queries | Internal use for query results |
Query |
Subquery result value | Internal use for subquery values |
Expression |
Computed expression value | Internal use for calculated columns |
Guid |
Globally Unique Identifier | Data binding context only |
Unsupported |
Vendor-specific unsupported type | Appears when loading schemas with unsupported types |
Type Mappings by Database
The following tables show how Velocity data types map to native database types. You should never need to reference these mappings when writing schemas—Velocity handles the translation automatically.
DB2 Type Mappings
| Velocity Type | DB2 Native Type | Notes |
|---|---|---|
Blob |
BLOB |
Binary Large Object |
Boolean |
BOOLEAN |
Native boolean support |
Byte |
SMALLINT |
16-bit integer |
Char |
CHAR(size) |
Fixed-length |
Clob |
CLOB |
Character Large Object |
Date |
DATE |
Date only |
DateTime |
TIMESTAMP |
With microsecond precision |
Decimal |
DECIMAL(p,s) |
Fixed precision |
Double |
DOUBLE |
64-bit float |
Float |
REAL |
32-bit float |
Geometry |
DB2GSE.ST_GEOMETRY |
DB2 Spatial Extender |
Geography |
DB2GSE.ST_GEOMETRY |
Treated as ST_GEOMETRY |
Integer |
INT |
32-bit integer |
Interval |
BIGINT |
Stored as ticks (100-nanosecond units) |
Long |
BIGINT |
64-bit integer |
Short |
SMALLINT |
16-bit integer |
Time |
TIME |
Time of day |
Timestamp |
TIMESTAMP |
With microsecond precision |
VarChar |
VARCHAR(size) |
Variable-length |
MySQL Type Mappings
| Velocity Type | MySQL Native Type | Notes |
|---|---|---|
Blob |
LONGBLOB |
Up to 4GB |
Boolean |
BOOL |
Alias for TINYINT(1) |
Byte |
TINYINT UNSIGNED |
0-255 |
Char |
CHAR(size) |
Fixed-length |
Clob |
LONGTEXT |
Up to 4GB text |
Date |
DATE |
YYYY-MM-DD |
DateTime |
DATETIME |
Precision to microseconds |
Decimal |
DECIMAL(p,s) |
Fixed precision |
Double |
DOUBLE |
64-bit float |
Float |
FLOAT |
32-bit float |
Geometry |
GEOMETRY |
MySQL spatial |
Geography |
GEOMETRY |
Treated as GEOMETRY |
Integer |
INT |
32-bit integer |
Interval |
BIGINT |
Stored as ticks (100-nanosecond units) |
Long |
BIGINT |
64-bit integer |
Short |
SMALLINT |
16-bit integer |
Time |
TIME |
Time of day |
Timestamp |
TIMESTAMP |
With automatic timezone handling |
VarChar |
VARCHAR(size) |
Variable-length |
Oracle Type Mappings
| Velocity Type | Oracle Native Type | Notes |
|---|---|---|
Blob |
BLOB |
Binary Large Object |
Boolean |
BOOLEAN |
NUMBER(1) can be used for Oracle 19 |
Byte |
NUMBER(3) |
0-255 range |
Char |
CHAR(size) |
Fixed-length |
Clob |
CLOB |
Character Large Object |
Date |
DATE |
Includes time component |
DateTime |
TIMESTAMP |
Default precision 6 |
Decimal |
DECIMAL(p,s) |
Fixed precision |
Double |
BINARY_DOUBLE |
64-bit IEEE 754 |
Float |
BINARY_FLOAT |
32-bit IEEE 754 |
Geometry |
SDO_GEOMETRY |
Oracle Spatial |
Geography |
SDO_GEOMETRY |
Treated as SDO_GEOMETRY |
Integer |
NUMBER(10) |
32-bit range |
Interval |
INTERVAL DAY(3) TO SECOND(6) |
Native interval; up to 999 days with microsecond precision |
Long |
NUMBER(18) |
64-bit range |
Short |
NUMBER(5) |
16-bit range |
Time |
INTERVAL DAY(0) TO SECOND |
Oracle has no native TIME type; stored as a zero-day interval |
Timestamp |
TIMESTAMP WITH TIME ZONE |
With timezone support |
VarChar |
VARCHAR2(size) |
Variable-length |
PostgreSQL Type Mappings
| Velocity Type | PostgreSQL Native Type | Notes |
|---|---|---|
Blob |
BYTEA |
Variable-length binary |
Boolean |
BOOLEAN |
Native boolean support |
Byte |
SMALLINT |
PostgreSQL has no 8-bit type |
Char |
CHAR(size) |
Fixed-length |
Clob |
TEXT |
Unlimited length |
Date |
DATE |
Date only |
DateTime |
TIMESTAMP |
Without timezone |
Decimal |
DECIMAL(p,s) |
Arbitrary precision |
Double |
DOUBLE PRECISION |
64-bit float |
Float |
REAL |
32-bit float |
Geometry |
GEOMETRY |
PostGIS extension |
Geography |
GEOGRAPHY |
PostGIS geodetic type |
Integer |
INTEGER |
32-bit integer |
Interval |
INTERVAL |
Native interval type; maps directly to TimeSpan |
Long |
BIGINT |
64-bit integer |
Short |
SMALLINT |
16-bit integer |
Time |
TIME |
Time of day |
Timestamp |
TIMESTAMP WITH TIME ZONE |
With timezone |
VarChar |
VARCHAR(size) |
Variable-length |
SQL Server Type Mappings
| Velocity Type | SQL Server Native Type | Notes |
|---|---|---|
Blob |
VARBINARY(MAX) |
Maximum 2GB |
Boolean |
BIT |
0 or 1 |
Byte |
TINYINT |
0-255 |
Char |
NCHAR(size) |
Unicode fixed-length |
Clob |
NVARCHAR(MAX) |
Unicode CLOB type |
Date |
DATE |
YYYY-MM-DD |
DateTime |
DATETIME2 |
Precision to 100 nanoseconds |
Decimal |
DECIMAL(p,s) |
p = precision, s = scale |
Double |
FLOAT(53) |
64-bit float |
Float |
REAL |
32-bit float |
Geometry |
GEOMETRY |
SQL Server spatial |
Geography |
GEOGRAPHY |
SQL Server geodetic spatial |
Integer |
INT |
32-bit integer |
Interval |
BIGINT |
Stored as ticks (100-nanosecond units) |
Long |
BIGINT |
64-bit integer |
Short |
SMALLINT |
16-bit integer |
Time |
TIME |
Time of day, precision to 100 nanoseconds |
Timestamp |
DATETIMEOFFSET |
With timezone offset |
VarChar |
NVARCHAR(size) |
Unicode variable-length |
SQLite Type Mappings
| Velocity Type | SQLite Native Type | Notes |
|---|---|---|
Blob |
BLOB |
Dynamic typing |
Boolean |
BOOLEAN |
Stored as 0/1 |
Byte |
SMALLINT |
Stored as INTEGER |
Char |
CHAR(size) |
Stored as TEXT |
Clob |
CLOB |
Stored as TEXT |
Date |
DATE |
Stored as TEXT |
DateTime |
DATETIME |
Stored as TEXT |
Decimal |
DECIMAL(p,s) |
Stored as REAL |
Double |
DOUBLE |
Stored as REAL |
Float |
FLOAT |
Stored as REAL |
Geometry |
BLOB |
WKB format in BLOB |
Geography |
BLOB |
WKB format in BLOB |
Integer |
INTEGER |
Native integer |
Interval |
BIGINT |
Stored as ticks (100-nanosecond units) |
Long |
LONG |
Stored as INTEGER |
Short |
SMALLINT |
Stored as INTEGER |
Time |
TIME |
Stored as TEXT |
Timestamp |
TIMESTAMP |
Stored as TEXT |
VarChar |
VARCHAR(size) |
Stored as TEXT |
Note: SQLite uses dynamic typing with storage classes (INTEGER, REAL, TEXT, BLOB). Type names are advisory and enforce type affinity.
Teradata Type Mappings
| Velocity Type | Teradata Native Type | Notes |
|---|---|---|
Blob |
BLOB |
Binary Large Object |
Boolean |
BYTEINT |
Teradata has no native boolean |
Byte |
SMALLINT |
16-bit integer |
Char |
CHAR(size) |
Fixed-length |
Clob |
CLOB |
Character Large Object |
Date |
DATE |
Date only |
DateTime |
TIMESTAMP |
Default precision 6 |
Decimal |
DECIMAL(p,s) |
Fixed precision |
Double |
DOUBLE PRECISION |
64-bit float |
Float |
FLOAT |
Configurable precision |
Geometry |
ST_GEOMETRY |
Teradata Geospatial |
Geography |
ST_GEOMETRY |
Treated as ST_GEOMETRY |
Integer |
INTEGER |
32-bit integer |
Interval |
BIGINT |
Stored as ticks (100-nanosecond units) |
Long |
BIGINT |
64-bit integer |
Short |
SMALLINT |
16-bit integer |
Time |
TIME |
Time of day |
Timestamp |
TIMESTAMP WITH TIME ZONE |
With timezone support |
VarChar |
VARCHAR(size) |
Variable-length |
Choosing the Right Data Type
When designing your Schema, select Velocity data types based on your data requirements, not the target database:
Numeric Data
// Counting, IDs, quantities - use integers
table.AddColumn("quantity", DataType.Integer);
table.AddColumn("user_id", DataType.Long, autoGenerate: true);
// Financial calculations - use Decimal for exact precision
table.AddColumn("price", DataType.Decimal, precision: 10, scale: 2);
table.AddColumn("tax_rate", DataType.Decimal, precision: 5, scale: 4);
// Scientific/measurements - use Float or Double
table.AddColumn("temperature", DataType.Float);
table.AddColumn("latitude", DataType.Double);
String Data
// Fixed-length codes, abbreviations
table.AddColumn("country_code", DataType.Char, size: 2); // "US", "CA", "UK"
table.AddColumn("status", DataType.Char, size: 10); // "ACTIVE ", "INACTIVE "
// Variable-length text with known maximum
table.AddColumn("username", DataType.VarChar, size: 50);
table.AddColumn("email", DataType.VarChar, size: 100);
table.AddColumn("title", DataType.VarChar, size: 200);
// Long text without size limit
table.AddColumn("description", DataType.Clob);
table.AddColumn("article_content", DataType.Clob);
table.AddColumn("user_bio", DataType.Clob);
Date and Time
// Date only (birthdate, hire date)
table.AddColumn("birth_date", DataType.Date);
table.AddColumn("invoice_date", DataType.Date);
// Time of day only (business hours, recurring schedules)
table.AddColumn("opening_time", DataType.Time);
table.AddColumn("shift_start", DataType.Time);
// Duration / elapsed time (task duration, response time, SLA window)
table.AddColumn("task_duration", DataType.Interval);
table.AddColumn("response_time", DataType.Interval);
// Date and time without timezone (events in local time)
table.AddColumn("meeting_time", DataType.DateTime);
table.AddColumn("created_at", DataType.DateTime);
// Date and time with timezone (global events, audit trails)
table.AddColumn("transaction_timestamp", DataType.Timestamp);
table.AddColumn("last_login_utc", DataType.Timestamp);
Binary Data
// Images, documents, files
table.AddColumn("profile_picture", DataType.Blob);
table.AddColumn("pdf_document", DataType.Blob);
table.AddColumn("encrypted_data", DataType.Blob);
Geospatial Data
// Geometry - planar coordinates (building layouts, game maps)
table.AddColumn("building_footprint", DataType.Geometry);
// Geography - Earth surface coordinates (real-world locations)
table.AddColumn("store_location", DataType.Geography);
table.AddColumn("delivery_route", DataType.Geography);
Complete Example: E-Commerce Schema
Here's a complete example showing how to use CreateTable, AddColumn, and the Manager to build a multi-table e-commerce schema:
using YndigoBlue.Velocity.Model;
using YndigoBlue.Velocity.Engine;
using YndigoBlue.Velocity.Enums;
// Create schema using portable Velocity data types
Schema ecommerceSchema = Schema.NewSchema("ecommerce");
// Customers table
Table customersTable = ecommerceSchema.CreateTable("customers");
customersTable.AddColumn("customer_id", DataType.Long, autoGenerate: true, notNull: true);
customersTable.AddColumn("email", DataType.VarChar, size: 100, notNull: true);
customersTable.AddColumn("first_name", DataType.VarChar, size: 50);
customersTable.AddColumn("last_name", DataType.VarChar, size: 50);
customersTable.AddColumn("phone", DataType.VarChar, size: 20);
customersTable.AddColumn("created_at", DataType.Timestamp, notNull: true);
customersTable.AddColumn("is_active", DataType.Boolean, notNull: true);
customersTable.CreatePrimaryKey("pk_customers", "customer_id");
customersTable.CreateUniqueConstraint("uq_customer_email", "email");
// Products table
Table productsTable = ecommerceSchema.CreateTable("products");
productsTable.AddColumn("product_id", DataType.Long, autoGenerate: true, notNull: true);
productsTable.AddColumn("sku", DataType.VarChar, size: 50, notNull: true);
productsTable.AddColumn("name", DataType.VarChar, size: 200, notNull: true);
productsTable.AddColumn("description", DataType.Clob);
productsTable.AddColumn("price", DataType.Decimal, precision: 10, scale: 2, notNull: true);
productsTable.AddColumn("weight_kg", DataType.Float);
productsTable.AddColumn("stock_quantity", DataType.Integer, notNull: true);
productsTable.AddColumn("created_at", DataType.DateTime);
productsTable.CreatePrimaryKey("pk_products", "product_id");
productsTable.CreateUniqueConstraint("uq_product_sku", "sku");
// Orders table
Table ordersTable = ecommerceSchema.CreateTable("orders");
ordersTable.AddColumn("order_id", DataType.Long, autoGenerate: true, notNull: true);
ordersTable.AddColumn("customer_id", DataType.Long, notNull: true);
ordersTable.AddColumn("order_date", DataType.Timestamp, notNull: true);
ordersTable.AddColumn("subtotal", DataType.Decimal, precision: 12, scale: 2, notNull: true);
ordersTable.AddColumn("tax_amount", DataType.Decimal, precision: 10, scale: 2);
ordersTable.AddColumn("total_amount", DataType.Decimal, precision: 12, scale: 2, notNull: true);
ordersTable.AddColumn("status", DataType.VarChar, size: 20, notNull: true);
ordersTable.AddColumn("shipped_at", DataType.Timestamp);
ordersTable.CreatePrimaryKey("pk_orders", "order_id");
ordersTable.CreateForeignKey(
"fk_orders_customers",
"customer_id",
"ecommerce",
"customers",
"customer_id"
);
// Deploy to any database - SQL Server, PostgreSQL, MySQL, Oracle, etc.
// Each database gets optimal native types automatically
using (var manager = new Manager(connection))
{
manager.BuildSchema(ecommerceSchema, overwrite: true);
}
This exact Schema deploys identically to all supported databases with appropriate native type mappings—no changes required.
Best Practices
1. Always Use Velocity Data Types in Schemas
Always use DataType when defining Table Columns:
Good:
table.AddColumn("user_id", DataType.Long, autoGenerate: true);
table.AddColumn("username", DataType.VarChar, size: 50);
Avoid:
// Don't think in database-specific terms
// "I need a BIGINT and NVARCHAR(50)"
2. Choose Types Based on Data Requirements
// For money: always use Decimal for exact precision
table.AddColumn("price", DataType.Decimal, precision: 10, scale: 2);
// For measurements: Float or Double are appropriate
table.AddColumn("temperature_celsius", DataType.Float);
// For IDs: Long provides ample range
table.AddColumn("record_id", DataType.Long, autoGenerate: true);
3. Use Boolean for True/False Data
// Clear, portable boolean type
table.AddColumn("is_active", DataType.Boolean, notNull: true);
table.AddColumn("email_verified", DataType.Boolean);
// Avoid using integers (0/1) for booleans
4. Select Appropriate Date/Time Types
// Date only - for birthdates, anniversaries
table.AddColumn("birth_date", DataType.Date);
// Time only - for time-of-day values without a date (store hours, schedules)
table.AddColumn("opening_time", DataType.Time);
// Interval - for durations (elapsed time, SLA windows, task length)
table.AddColumn("task_duration", DataType.Interval);
// DateTime - for application events in local time
table.AddColumn("created_at", DataType.DateTime);
// Timestamp - for global events, distributed systems
table.AddColumn("transaction_time", DataType.Timestamp);
5. Don't Worry About Database-Specific Optimizations
Velocity already chooses optimal native types for each database:
// This becomes NVARCHAR(200) in SQL Server, VARCHAR(200) in PostgreSQL,
// VARCHAR2(200) in Oracle, etc. - all optimized appropriately
table.AddColumn("product_name", DataType.VarChar, size: 200);
6. Trust Velocity's Type Mapping
You don't need to know that:
- SQL Server uses
DATETIME2forDataType.DateTime - PostgreSQL uses
TIMESTAMPforDataType.DateTime - Oracle uses
TIMESTAMP(6)forDataType.DateTime
Velocity handles all of this automatically and ensures consistent behavior.
7. Test Across Databases
The beauty of Velocity's type system is that your Schema works identically everywhere:
// Same schema definition
Schema schema = manager.ReadSchemaFromFile("schema.json", ConfigType.Json);
// Test on SQL Server
using (var sqlManager = new Manager(sqlServerConnection))
{
sqlManager.BuildSchema(schema);
// Automatic: BIGINT, NVARCHAR, DATETIME2, etc.
}
// Test on PostgreSQL
using (var pgManager = new Manager(postgresConnection))
{
pgManager.BuildSchema(schema);
// Automatic: BIGINT, VARCHAR, TIMESTAMP, etc.
}
// Test on MySQL
using (var mysqlManager = new Manager(mysqlConnection))
{
mysqlManager.BuildSchema(schema);
// Automatic: BIGINT, VARCHAR, DATETIME, etc.
}
Summary
Velocity's data type system provides:
- Portability - Write schemas once, deploy anywhere
- Simplicity - 20 types cover all common scenarios
- Consistency - Same behavior across all databases
- Abstraction - No need to learn database-specific types
- Optimization - Automatic selection of optimal native types
- Type Safety - Strong typing throughout your application
Remember: Focus on your data requirements, choose the appropriate Velocity data type, and let Velocity handle the database-specific details. This is the essence of schema-first development with Velocity.