# Databricks Client

Execute SQL queries against Databricks SQL warehouses 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, databricks } from "@superblocksteam/sdk-api";

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

const DataSchema = z.object({
  id: z.number(),
  value: z.string(),
  timestamp: z.string(),
});

export default api({
  name: "DatabricksExample",
  integrations: {
    databricks: databricks(PROD_DATABRICKS),
  },
  input: z.object({
    date: z.string(),
  }),
  output: z.object({
    data: z.array(DataSchema),
  }),
  async run(ctx, { date }) {
    const data = await ctx.integrations.databricks.query(
      "SELECT id, value, timestamp FROM data WHERE date = :PARAM_1",
      DataSchema,
      [date],
    );

    return { data };
  },
});
```

The SDK accepts Databricks parameters as a positional `params` array, but the
SQL text should use `:PARAM_1`, `:PARAM_2`, and so on. The first array value
binds to `:PARAM_1`, the second binds to `:PARAM_2`, and so forth.

### Executing INSERT, UPDATE, DELETE Statements

```typescript
// INSERT
await ctx.integrations.databricks.execute(
  "INSERT INTO metrics (name, value) VALUES (:PARAM_1, :PARAM_2)",
  ["cpu_usage", "75.5"],
);

// UPDATE
const updateResult = await ctx.integrations.databricks.execute(
  "UPDATE metrics SET value = :PARAM_1 WHERE name = :PARAM_2",
  ["80.0", "cpu_usage"],
);
console.log(`Updated ${updateResult.rowCount} rows`);

// DELETE
const deleteResult = await ctx.integrations.databricks.execute(
  "DELETE FROM metrics WHERE timestamp < :PARAM_1",
  ["2024-01-01"],
);
console.log(`Deleted ${deleteResult.rowCount} rows`);
```

### Analytics Query with Delta Lake

```typescript
const AnalyticsSchema = z.object({
  date: z.string(),
  total_revenue: z.string(),
  order_count: z.coerce.number(),
});

const analytics = await ctx.integrations.databricks.query(
  `SELECT
    date,
    SUM(revenue) as total_revenue,
    COUNT(*) as order_count
  FROM orders
  WHERE date >= DATE_SUB(CURRENT_DATE(), 30)
  GROUP BY date
  ORDER BY date DESC`,
  AnalyticsSchema,
);
```

## 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

### Parameter Placeholders Must Match the SDK Contract

Pass parameter values as an array, but write the SQL with `:PARAM_n`
placeholders:

```typescript
// WRONG - Positional question marks are not the placeholder syntax this SDK emits
await ctx.integrations.databricks.query(
  "SELECT * FROM data WHERE date = ?",
  DataSchema,
  ["2024-01-01"],
);

// CORRECT - Use Databricks placeholders with positional params
await ctx.integrations.databricks.query(
  "SELECT * FROM data WHERE date = :PARAM_1",
  DataSchema,
  ["2024-01-01"],
);
```

### BIGINT/LONG Values Returned as Strings

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

### DECIMAL Values Returned as Strings

```typescript
const schema = z.object({
  amount: z.string().transform((val) => parseFloat(val)),
});
```

### Schema Parameter is Required

```typescript
// CORRECT - Schema is required
const data = await ctx.integrations.databricks.query(
  "SELECT * FROM data",
  DataSchema,
);
```

### NULL Handling

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

## Error Handling

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

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

## API Reference

- [Databricks SQL Documentation](https://docs.databricks.com/sql/index.html)
- [Databricks SQL Reference](https://docs.databricks.com/sql/language-manual/index.html)
- [Databricks Data Types](https://docs.databricks.com/sql/language-manual/sql-ref-datatypes.html)
