# Understanding Database Interactions

## Accessing the Tables

Before starting to write to/read from the tables we defined in the `zephyr.toml`, we need to define them in our program.&#x20;

```rust
#[derive(DatabaseDerive, Clone)]
#[with_name("feedback")]
pub struct Feedback {
    pub source: ScVal,
    pub hash: ScVal,
    pub text: ScVal,
    pub votes: ScVal,
}
```

We're defining here the table "feedback" of the one of the `zephyr.toml` as a struct and assigning it the DatabaseDerive macro (more on that later). When using DatabaseDerive we also need to specify the table's name. Moreover, the field names in the structure must be the same as defined in your `zephyr.toml` columns definition.

Now to access (in this case to write) the table from the program we just have to create an instance of the struct, which will represent a row in the table, and call the Environment functions to interact with the database, such as `EnvClient::put()`. More about database operations on the next page.&#x20;

```rust
pub fn write_feedback(env: &EnvClient, feedback: Feedback) {
    env.put(&feedback)
}
```

## DatabaseDerive and Defining Tables Rust-Side

The magic of rust metaprogramming comes into play when working with the database. Assuming you've already read through the quickstart, let's jump to an immediate example. Before the `DatabaseDerive` macro, reading, and writing to the database was done as follows:

```rust
// This snippet is taken from xycLoans' zephyr program code.
env.db_write(
    "xlsupply",
    &["contract", "timestamp", "supply"],
    &[
        contract_id,
        &self.timestamp.to_be_bytes(),
        &supply.to_be_bytes(),
    ],
)
.unwrap()
```

Reading from the database and updating was even worse. This is unsound and non-idiomatic, but more importantly very unsafe. With the `DatabaseDerive` macro, this becomes much better and safer:

```rust
// Snipped from Script3's soroban governor indexer.

#[derive(DatabaseDerive, Clone)]
#[with_name("votes")]
pub struct Votes {
    pub contract: Hash,  // governor contract address
    // other fields ...
}

pub fn write_votes(env: &EnvClient, votes: Votes) {
    env.put(&votes)
}
```

The `DatabaseDerive` macro builds the required trait implementation to construct a code similar to the one used in the xycLoans example under the hood. For this to work, however, you need to make sure that **the field names in the structure are the same as defined in your `zephyr.toml` columns definition**.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.mercurydata.app/zephyr-full-customization/learn/database-interactions/understanding-database-interactions.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
