> ## Documentation Index
> Fetch the complete documentation index at: https://docs.activeviam.com/llms.txt
> Use this file to discover all available pages before exploring further.

# How to configure the database

> How to define an in-memory database schema with the Atoti Configuration API using `IModelConfigurer` and `IDatabaseConfigurator`, including creating tables with `StoreDescription`, defining joins with `ReferenceDescription`, and customizing existing tables via `ITableConfigurator`

The database configuration defines an in-memory data model including tables, fields, and joins, using the `IModelConfigurer` interface.

## What is the IModelConfigurer interface?

Configuration is handled through a Spring bean that implements the `IModelConfigurer` interface.

The `configureDatabase()` method receives an `IDatabaseConfigurator` that defines tables and joins. See the Javadoc for the complete list of available methods.

```java theme={"languages":{"custom":["/engine/python-sdk/6.2/languages/pycon.tmLanguage.json"]}}
public interface IModelConfigurer {
  /**
   * Configures the database using the provided object.
   *
   * @param database the object used to configure the database
   */
  void configureDatabase(IDatabaseConfigurator database);
  /**
   * Configures the cubes using the provided object.
   *
   * @apiNote This method is called after {@link #configureDatabase(IDatabaseConfigurator)}
   * @param cubeManager the object used to configure the cubes
   * @param schema the schema of its underlying database
   */
  void configureCubes(ICubeManagerConfigurator cubeManager, IDatabaseSchema schema);
}
```

## How to create an in-memory table

* Use `IDatabaseConfigurator.addTable()` with a `StoreDescription` to create a table.
* Use `asKeyField()` to mark fields as part of the primary key.

The following example creates a table with three fields:

```java theme={"languages":{"custom":["/engine/python-sdk/6.2/languages/pycon.tmLanguage.json"]}}
databaseConfigurator.addTable(
    StoreDescription.builder()
        .withStoreName("MyStore")
        .withField("key", ILiteralType.INT)
        .asKeyField()
        .withField("city", ILiteralType.STRING)
        .withField("value", ILiteralType.DOUBLE)
        .build());
```

## How to add a join between tables

Use `IDatabaseConfigurator.addJoin()` with a `ReferenceDescription` to define a join between tables. The following example creates a join from MyStore to Country:

```java theme={"languages":{"custom":["/engine/python-sdk/6.2/languages/pycon.tmLanguage.json"]}}
databaseConfigurator.addJoin(
    ReferenceDescription.builder()
        .fromStore("MyStore")
        .toStore("Country")
        .withName("toCountry")
        .withMapping("city", "city")
        .build());
```

## How to customize an existing database

Applications with a predefined database schema can customize tables and joins using the `IDatabaseConfigurator` interface.

### How to edit a table

Use `IDatabaseConfigurator.table()` to get an `ITableConfigurator` for modifying an existing table.
An existing table can be modified in several ways:

#### How to add a field

Add a new field to an existing table:

```java theme={"languages":{"custom":["/engine/python-sdk/6.2/languages/pycon.tmLanguage.json"]}}
ITableConfigurator tableConfigurator = databaseConfigurator.table("MyStore");
// Add a new field
tableConfigurator.addField(
    FieldDescription.builder().name("NewField").dataType(ILiteralType.STRING).build());
```

#### How to change a field type

Change the type of a field and provide a transformation function:

```java theme={"languages":{"custom":["/engine/python-sdk/6.2/languages/pycon.tmLanguage.json"]}}
ITableConfigurator tableConfigurator = databaseConfigurator.table("MyStore");
tableConfigurator.changeFieldType(
    "myField",
    ILiteralType.LONG,
    (fact, buffer) -> {
      int value = fact.readInt();
      buffer.writeLong(value);
    });
```

#### How to change a default value

Change the default value of a field:

```java theme={"languages":{"custom":["/engine/python-sdk/6.2/languages/pycon.tmLanguage.json"]}}
tableConfigurator.withDefaultValue("myField", "newDefaultValue");
```

#### How to configure partitioning

Configure or remove partitioning on a table:

```java theme={"languages":{"custom":["/engine/python-sdk/6.2/languages/pycon.tmLanguage.json"]}}
// Add partitioning
tableConfigurator.inMemoryOptions().withPartitioning(partitioningDescription);
// Or remove partitioning
tableConfigurator.inMemoryOptions().withPartitioning(null);
```

#### How to add or remove a secondary index

Modify secondary indexes on a table:

```java theme={"languages":{"custom":["/engine/python-sdk/6.2/languages/pycon.tmLanguage.json"]}}
// Add
tableConfigurator.inMemoryOptions().addSecondaryIndex("field1", "field2");
// Remove
tableConfigurator.inMemoryOptions().removeSecondaryIndex("field1", "field2");
```

#### How to set the chunk size

Set the chunk size for a new table. The value is rounded up to the next power of 2:

```java theme={"languages":{"custom":["/engine/python-sdk/6.2/languages/pycon.tmLanguage.json"]}}
tableConfigurator.inMemoryOptions().withChunkSize(4096);
```

#### How to set a duplicate key handler

Configure how duplicate keys are handled during data loading:

```java theme={"languages":{"custom":["/engine/python-sdk/6.2/languages/pycon.tmLanguage.json"]}}
tableConfigurator.inMemoryOptions().withDuplicateKeyHandler(customHandler);
```

#### How to set the remove unknown key behavior

Configure the behavior when removing a record with a key that does not exist:

```java theme={"languages":{"custom":["/engine/python-sdk/6.2/languages/pycon.tmLanguage.json"]}}
tableConfigurator.inMemoryOptions().withRemoveUnknownKeyBehavior(customListener);
```

#### How to enable update only if different

Enable this option to skip updating records when the new values are identical to the existing ones:

```java theme={"languages":{"custom":["/engine/python-sdk/6.2/languages/pycon.tmLanguage.json"]}}
tableConfigurator.inMemoryOptions().withUpdateOnlyIfDifferent(true);
```

#### How to enable index compression

Enable index compression to reduce memory usage at the cost of additional computation for decompression:

```java theme={"languages":{"custom":["/engine/python-sdk/6.2/languages/pycon.tmLanguage.json"]}}
tableConfigurator.inMemoryOptions().withCompressIndexes(true);
```

#### How to set the NUMA selector description

Configure the NUMA selector description:

```java theme={"languages":{"custom":["/engine/python-sdk/6.2/languages/pycon.tmLanguage.json"]}}
tableConfigurator.inMemoryOptions().withNumaSelector(customNumaSelector);
```

#### How to change vector fields properties

Change the default properties of a vector field:

* size
* blockSize
* delimiter
* swapping

```java theme={"languages":{"custom":["/engine/python-sdk/6.2/languages/pycon.tmLanguage.json"]}}
tableConfigurator
    .inMemoryOptions()
    .vectorField("field")
    .ofSize(42)
    .withBlockSize(8) // Block size should be defined after size
    .withDelimiter(';');
```

#### How to change vector fields swapping

Change the default swapping of a vector field:

```java theme={"languages":{"custom":["/engine/python-sdk/6.2/languages/pycon.tmLanguage.json"]}}
// Swap with default directory
tableConfigurator.inMemoryOptions().vectorField("field").swap(true);
// Swap with custom directory
tableConfigurator.inMemoryOptions().vectorField("field").swap("swap/directory/");
```

## Related pages

* [Configure cubes](./cube/overview): cube, dimension, and measure configuration
