---
title: "Column Types & Modifiers"
description: "All available column helpers and the chainable modifiers used to configure them."
canonical_url: "https://docs.ctrl-neo.dev/en/tauri-sqlite-orm/core-concepts/column-types-and-modifiers"
---
# Column Types & Modifiers

> All available column helpers and the chainable modifiers used to configure them.

This page serves as a reference guide for all available column helpers and the chainable modifiers used to configure them.

## Column Types

These functions define the data type of your column.

<table>
<thead>
  <tr>
    <th>
      Function
    </th>
    
    <th>
      SQLite Type
    </th>
    
    <th>
      Default TS Type
    </th>
    
    <th>
      Modes & Special Usage
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        text(name, config?)
      </code>
    </td>
    
    <td>
      <code>
        TEXT
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        mode: 'json'
      </code>
      
      : The column is serialized/deserialized as JSON, and the TS type becomes <code>
        any
      </code>
      
      . <br />
      
      <code>
        enum: [...]
      </code>
      
      : Constrains values to a TypeScript union type (e.g., `'active'
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        integer(name, config?)
      </code>
    </td>
    
    <td>
      <code>
        INTEGER
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        mode: 'timestamp'
      </code>
      
      : Treats the value as a UNIX epoch <strong>
        second
      </strong>
      
       and maps to a <code>
        Date
      </code>
      
       object. <br />
      
      <code>
        mode: 'timestamp_ms'
      </code>
      
      : Treats the value as a UNIX epoch <strong>
        millisecond
      </strong>
      
       and maps to a <code>
        Date
      </code>
      
       object. <br />
      
      <code>
        mode: 'boolean'
      </code>
      
      : Maps <code>
        0
      </code>
      
       and <code>
        1
      </code>
      
       to <code>
        false
      </code>
      
       and <code>
        true
      </code>
      
      .
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        real(name)
      </code>
    </td>
    
    <td>
      <code>
        REAL
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      Used for floating-point numbers.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        blob(name, config?)
      </code>
    </td>
    
    <td>
      <code>
        BLOB
      </code>
    </td>
    
    <td>
      <code>
        Uint8Array
      </code>
    </td>
    
    <td>
      <code>
        mode: 'json'
      </code>
      
      : Stores JSON as a binary blob, maps to <code>
        any
      </code>
      
      . <br />
      
      <code>
        mode: 'bigint'
      </code>
      
      : Maps the value to a <code>
        bigint
      </code>
      
      .
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        boolean(name)
      </code>
    </td>
    
    <td>
      <code>
        BOOLEAN
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      An alias for <code>
        integer(name, { mode: 'boolean' })
      </code>
      
      .
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        numeric(name, config?)
      </code>
    </td>
    
    <td>
      <code>
        NUMERIC
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      A flexible type that can store various numeric formats. <br />
      
      <code>
        mode: 'bigint'
      </code>
      
      : Maps the value to a <code>
        bigint
      </code>
      
      .
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        enumType(name, vals)
      </code>
    </td>
    
    <td>
      <code>
        TEXT
      </code>
    </td>
    
    <td>
      <code>
        vals[number]
      </code>
    </td>
    
    <td>
      A convenient shortcut for <code>
        text(name, { enum: vals })
      </code>
      
      .
    </td>
  </tr>
</tbody>
</table>

## Column Modifiers

These chainable methods add constraints and behaviors to your column definitions.

<table>
<thead>
  <tr>
    <th>
      Modifier
    </th>
    
    <th>
      Description
    </th>
    
    <th>
      Example
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        .primaryKey()
      </code>
    </td>
    
    <td>
      Marks the column as the primary key. Automatically implies <code>
        .notNull()
      </code>
      
      .
    </td>
    
    <td>
      <code>
        integer('id').primaryKey()
      </code>
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        .autoincrement()
      </code>
    </td>
    
    <td>
      When used on an <code>
        integer
      </code>
      
       primary key, makes it auto-incrementing.
    </td>
    
    <td>
      <code>
        integer('id').primaryKey().autoincrement()
      </code>
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        .notNull()
      </code>
    </td>
    
    <td>
      Adds a <code>
        NOT NULL
      </code>
      
       constraint. Inserts must provide a value for this column unless a default is set.
    </td>
    
    <td>
      <code>
        text('email').notNull()
      </code>
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        .unique()
      </code>
    </td>
    
    <td>
      Adds a <code>
        UNIQUE
      </code>
      
       constraint, ensuring all values in this column are unique across the table.
    </td>
    
    <td>
      <code>
        text('session_token').unique()
      </code>
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        .default(value)
      </code>
    </td>
    
    <td>
      Provides a static default value for the column if one is not provided on insert.
    </td>
    
    <td>
      <code>
        integer('status').default(0)
      </code>
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        .$defaultFn(() => value)
      </code>
    </td>
    
    <td>
      Provides a dynamic default value, evaluated at the time of insertion. Perfect for timestamps or UUIDs.
    </td>
    
    <td>
      <code>
        text('id').$defaultFn(() => crypto.randomUUID())
      </code>
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        .$onUpdateFn(() => value)
      </code>
    </td>
    
    <td>
      Sets a dynamic value that is evaluated every time a row is updated.
    </td>
    
    <td>
      <code>
        integer('updated_at').$onUpdateFn(() => new Date())
      </code>
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        .references(() => table._.columns.column, options?)
      </code>
    </td>
    
    <td>
      Creates a foreign key via a lazy getter (Drizzle-style). Enables self-references and forward refs. Use <code>
        table._.columns.id
      </code>
      
       to avoid name clashes.
    </td>
    
    <td>
      <code>
        integer('author_id').references(() => users._.columns.id, { onDelete: 'cascade' })
      </code>
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        .$type<T>()
      </code>
    </td>
    
    <td>
      <strong>
        Advanced
      </strong>
      
      : Overrides TypeScript's inferred type for the column. Useful for custom data transformations that the ORM doesn't handle natively.
    </td>
    
    <td>
      <code>
        text('metadata').$type<MyCustomMetadataType>()
      </code>
    </td>
  </tr>
</tbody>
</table>

## Important Notes

### `.default()` vs `.$defaultFn()`

Understanding the difference between these two is crucial:

- **.default(value)** → Creates a SQL `DEFAULT value` clause in the table schema. The value must be a **simple literal** (number, string, boolean). This is evaluated by SQLite at INSERT time.
- **.$defaultFn(fn)** → Calls the function in your **application code** when you INSERT a row. Use this for complex values like `Date` objects or `crypto.randomUUID()`.

```ts
// ✅ CORRECT
export const users = sqliteTable('users', {
  id: text('id').primaryKey().$defaultFn(() => crypto.randomUUID()),
  status: integer('status').default(0),  // Simple value - OK for .default()
  createdAt: integer('created_at', { mode: 'timestamp' })
    .$defaultFn(() => new Date()),  // Date object - must use $defaultFn()
});

// ❌ WRONG - Will cause SQL syntax error!
export const users = sqliteTable('users', {
  id: text('id').primaryKey()
    .default(crypto.randomUUID())  // ❌ Function call in .default()
    .$defaultFn(() => crypto.randomUUID()),
  createdAt: integer('created_at', { mode: 'timestamp' })
    .default(new Date())  // ❌ Date object in .default()
    .$defaultFn(() => new Date()),
});
```

**Rule of thumb:**

- Simple values (`0`, `'active'`, `false`) → use `.default()`
- Complex values (`new Date()`, `crypto.randomUUID()`, computed values) → use `.$defaultFn()`
- **Never use both on the same column**

### Accessing Columns in Code

When referencing columns in queries, always use the `table._.columns.columnName` syntax:

```ts
// ✅ CORRECT
eq(users._.columns.id, 1)
eq(users._.columns.email, 'john@example.com')
users._.columns.createdAt

// ❌ WRONG - This doesn't work
eq(users.id, 1)
eq(users.email, 'john@example.com')
users.createdAt
```

The `._` property contains the table's metadata, including all column definitions.


## Sitemap

See the full [sitemap](https://docs.ctrl-neo.dev/sitemap.md) for all pages.
