# How to Add Custom Value Processors for Database-Specific Data Types in Chat2DB

> Learn to add custom value processors for database-specific data types in Chat2DB. Implement IValueProcessor and register your new processor in the dialect factory for enhanced data handling.

- Repository: [OtterMind/Chat2DB](https://github.com/OtterMind/Chat2DB)
- Tags: how-to-guide
- Published: 2026-07-28

---

**To add custom value processors in Chat2DB, implement the `IValueProcessor` interface (or extend `DefaultValueProcessor`), override the conversion methods for your specific data type, and register the new processor in the appropriate dialect factory such as `MysqlValueProcessorFactory` or `PostgreSQLValueProcessorFactory`.**

Chat2DB renders query results and generates DML statements using a pluggable value-processing framework that isolates database-specific logic per dialect. By implementing custom value processors, you can extend support for vendor-specific types like PostgreSQL's `JSONB` or MySQL's `GEOMETRY` without affecting other database modules. This guide walks through the exact implementation steps using the Chat2DB source code structure.

## Understanding the Value Processing Framework

The core contract for value processing is defined in [`IValueProcessor`](https://github.com/OtterMind/Chat2DB/blob/main/chat2db-community-server/chat2db-community-spi/src/main/java/ai/chat2db/spi/IValueProcessor.java) located in the SPI module. Each database dialect provides its own implementation of this interface to handle type-specific conversions.

A value processor has four responsibilities:

- **`getSqlValueString(SQLDataValue)`** — Produces a SQL literal that can be embedded directly in INSERT or UPDATE statements.
- **`getJdbcValue(JDBCDataValue)`** — Converts a raw JDBC value into a user-readable string for the UI without additional quoting.
- **`getJdbcSqlValueString(JDBCDataValue)`** — Converts a JDBC value into a SQL literal for reuse in DML operations when copying result-set values.
- **`isStringDataType(String)`** — Indicates whether a column type should be treated as a string, affecting how the SQL builder applies quoting and comparison logic.

Most implementations extend [`DefaultValueProcessor`](https://github.com/OtterMind/Chat2DB/blob/main/chat2db-community-server/chat2db-community-spi/src/main/java/ai/chat2db/spi/DefaultValueProcessor.java) and override only the necessary methods rather than implementing the full interface.

## Step-by-Step Implementation Guide

### Create a Custom Processor Class

Create a new class that extends `DefaultValueProcessor` and resides in your dialect's value package. Override the methods that correspond to how your data type should display in the UI and serialize to SQL.

For example, to handle PostgreSQL's `JSONB` type:

```java
package ai.chat2db.plugin.postgresql.value.sub;

import ai.chat2db.spi.DefaultValueProcessor;
import ai.chat2db.community.domain.api.model.value.SQLDataValue;
import ai.chat2db.spi.model.value.JDBCDataValue;

/** Processor for PostgreSQL JSONB columns. */
public class PostgresJsonbProcessor extends DefaultValueProcessor {

    @Override
    public String getSqlValueString(SQLDataValue dataValue) {
        // JSONB literals are written as a string with ::jsonb cast
        String json = dataValue.getValue().toString().replace("'", "''");
        return "'" + json + "'::jsonb";
    }

    @Override
    public String getJdbcValue(JDBCDataValue dataValue) {
        // Display the JSON text without additional quoting
        return dataValue.getValue().toString();
    }

    @Override
    public boolean isStringDataType(String dataType) {
        // Treat JSONB as a string for comparison purposes
        return true;
    }
}

```

### Register the Processor in the Dialect Factory

Each dialect maintains a factory that maps type names to processor instances. For PostgreSQL, modify [`PostgreSQLValueProcessorFactory`](https://github.com/OtterMind/Chat2DB/blob/main/chat2db-community-server/chat2db-community-plugins/chat2db-community-postgresql/src/main/java/ai/chat2db/plugin/postgresql/value/factory/PostgreSQLValueProcessorFactory.java) to include your new mapping in the static initialization block.

If the factory uses an immutable map (as seen in the MySQL implementation), add a new entry to the map:

```java
static {
    PROCESSOR_MAP = Map.ofEntries(
        // ... existing entries ...
        Map.entry("JSONB", new PostgresJsonbProcessor())
    );
}

```

For dialects using mutable maps, simply add the entry during static initialization. The framework automatically resolves type names to processors when rendering result sets or generating DML.

### Verify the Integration

Once registered, any query returning a column of type `JSONB` will automatically invoke `PostgresJsonbProcessor`. The processor handles:

- **UI display** via `getJdbcValue()`
- **INSERT/UPDATE generation** via `getSqlValueString()`
- **Copy-to-clipboard SQL literals** via `getJdbcSqlValueString()`

No additional code changes are required in the core application.

## Key Source Files and Architecture

Understanding the repository structure helps locate the correct extension points:

- **[`chat2db-community-server/chat2db-community-spi/src/main/java/ai/chat2db/spi/IValueProcessor.java`](https://github.com/OtterMind/Chat2DB/blob/main/chat2db-community-server/chat2db-community-spi/src/main/java/ai/chat2db/spi/IValueProcessor.java)** — Core interface defining the four conversion methods.
- **[`chat2db-community-server/chat2db-community-spi/src/main/java/ai/chat2db/spi/DefaultValueProcessor.java`](https://github.com/OtterMind/Chat2DB/blob/main/chat2db-community-server/chat2db-community-spi/src/main/java/ai/chat2db/spi/DefaultValueProcessor.java)** — Base class providing default implementations.
- **[`chat2db-community-server/chat2db-community-plugins/chat2db-community-mysql/src/main/java/ai/chat2db/plugin/mysql/value/factory/MysqlValueProcessorFactory.java`](https://github.com/OtterMind/Chat2DB/blob/main/chat2db-community-server/chat2db-community-plugins/chat2db-community-mysql/src/main/java/ai/chat2db/plugin/mysql/value/factory/MysqlValueProcessorFactory.java)** — MySQL's processor registry.
- **[`chat2db-community-server/chat2db-community-plugins/chat2db-community-postgresql/src/main/java/ai/chat2db/plugin/postgresql/value/factory/PostgreSQLValueProcessorFactory.java`](https://github.com/OtterMind/Chat2DB/blob/main/chat2db-community-server/chat2db-community-plugins/chat2db-community-postgresql/src/main/java/ai/chat2db/plugin/postgresql/value/factory/PostgreSQLValueProcessorFactory.java)** — PostgreSQL's processor registry.

The framework isolates processors per dialect, allowing you to add support for third-party or custom database extensions without impacting other modules.

## Summary

- **Implement `IValueProcessor`** by extending `DefaultValueProcessor` and overriding specific conversion methods for your data type.
- **Register the processor** in the appropriate dialect factory (e.g., `PostgreSQLValueProcessorFactory`) by mapping the type name to your implementation.
- **Handle three contexts**: SQL literals for DML generation, raw display strings for the UI, and type classification for proper quoting.
- **Maintain isolation**: Changes to one dialect's value processors do not affect other databases in the Chat2DB ecosystem.

## Frequently Asked Questions

### What is the difference between `getSqlValueString` and `getJdbcSqlValueString`?

Use `getSqlValueString(SQLDataValue)` when generating SQL from user input or metadata, as it accepts the higher-level `SQLDataValue` object. Use `getJdbcSqlValueString(JDBCDataValue)` when converting values retrieved from a JDBC result set back into SQL literals, such as when users copy cell values from query results to reuse in DML statements.

### Do I need to implement all four methods of `IValueProcessor`?

No. Extend `DefaultValueProcessor` and override only the methods relevant to your data type. The base class provides safe defaults: it returns the string value of the data for display methods and `false` for `isStringDataType`. Override only when you need custom serialization or specific string-type handling.

### Which Chat2DB module contains the dialect-specific factories?

Dialect factories reside in the plugin modules under `chat2db-community-plugins/chat2db-community-[dialect]`. For example, MySQL processors are registered in `chat2db-community-mysql`, while PostgreSQL processors live in `chat2db-community-postgresql`. Each factory maintains a static map of type names to processor instances.

### How does the `isStringDataType` method affect SQL generation?

When `isStringDataType(String)` returns `true`, Chat2DB's SQL builder treats the column as a string type, applying single quotes around literals and using string comparison operators. Returning `false` indicates numeric or binary handling, which affects quoting behavior in generated INSERT and UPDATE statements.