# Athena Client

Execute SQL queries against Amazon Athena with full type safety and runtime validation.

## Methods

| Method                                      | Description                                                |
| ------------------------------------------- | ---------------------------------------------------------- |
| `query<T>(sql, schema, params?, metadata?)` | Execute a SELECT query and return validated, typed results |
| `execute(sql, params?, metadata?)`          | Execute a statement and return affected row count          |

## Usage

### Basic Query with Schema Validation

```typescript
import { api, z, athena } from "@superblocksteam/sdk-api";

// Integration ID from the integrations panel
const PROD_ATHENA = "a1b2c3d4-5678-90ab-cdef-athena000001";

const LogSchema = z.object({
  timestamp: z.string(),
  level: z.string(),
  message: z.string(),
  request_id: z.string(),
});

export default api({
  name: "AthenaExample",
  integrations: {
    athena: athena(PROD_ATHENA),
  },
  input: z.object({
    level: z.string(),
  }),
  output: z.object({
    logs: z.array(LogSchema),
  }),
  async run(ctx, { level }) {
    const logs = await ctx.integrations.athena.query(
      `SELECT timestamp, level, message, request_id
       FROM logs
       WHERE level = ?
       LIMIT 100`,
      LogSchema,
      [level],
    );

    return { logs };
  },
});
```

### Querying S3 Data

```typescript
const EventSchema = z.object({
  event_id: z.string(),
  event_type: z.string(),
  user_id: z.string(),
  created_at: z.string(),
});

const events = await ctx.integrations.athena.query(
  `SELECT event_id, event_type, user_id, created_at
   FROM events
   WHERE date_partition = ?
     AND event_type = ?`,
  EventSchema,
  ["2024-01-15", "purchase"],
);
```

### Aggregation Query

```typescript
const StatsSchema = z.object({
  date: z.string(),
  total_events: z.coerce.number(),
  unique_users: z.coerce.number(),
});

const stats = await ctx.integrations.athena.query(
  `SELECT
    DATE(created_at) as date,
    COUNT(*) as total_events,
    COUNT(DISTINCT user_id) as unique_users
  FROM events
  WHERE created_at >= DATE_ADD('day', -7, CURRENT_DATE)
  GROUP BY DATE(created_at)
  ORDER BY date DESC`,
  StatsSchema,
);
```

## Trace Metadata

All methods accept an optional `metadata` parameter as the last argument for diagnostics labeling. See the [root SDK README](../../../README.md#trace-metadata) for details.

## Common Pitfalls

### Query Execution Time

Athena queries can take time to execute. Consider the data size being scanned.

### BIGINT Values Returned as Strings

```typescript
const schema = z.object({
  count: z.coerce.number(),
});
```

### Schema Parameter is Required

```typescript
// CORRECT - Schema is required
const logs = await ctx.integrations.athena.query(
  "SELECT * FROM logs",
  LogSchema,
);
```

### NULL Handling

```typescript
const schema = z.object({
  message: z.string(),
  metadata: z.string().nullable(),
});
```

### Partition Filters

Always use partition filters when possible to reduce data scanned:

```typescript
// GOOD - Uses partition filter
const logs = await ctx.integrations.athena.query(
  "SELECT * FROM logs WHERE date_partition = ?",
  LogSchema,
  ["2024-01-15"],
);
```

## Error Handling

```typescript
import { QueryValidationError } from "@superblocksteam/sdk-api";

try {
  const logs = await ctx.integrations.athena.query(
    "SELECT * FROM logs",
    LogSchema,
  );
} catch (error) {
  if (error instanceof QueryValidationError) {
    console.error("Row index:", error.details.rowIndex);
    console.error("Validation errors:", error.details.errors);
  }
}
```

## API Reference

- [Amazon Athena Documentation](https://docs.aws.amazon.com/athena/)
- [Athena SQL Reference](https://docs.aws.amazon.com/athena/latest/ug/ddl-sql-reference.html)
- [Athena Data Types](https://docs.aws.amazon.com/athena/latest/ug/data-types.html)
