Inputs
Inputs are typed parameters that clients provide when calling queries. Hyperterse validates inputs, applies defaults for optional fields, and safely injects them into SQL statements. They serve three purposes:
- Validation — Ensure data types match before execution
- Documentation — Generate OpenAPI schemas and LLM descriptions
- Security — Properly escape values to prevent SQL injection
Defining inputs
Section titled “Defining inputs”queries: search-users: use: main_db description: "Search users by name and role" statement: | SELECT id, name, email, role FROM users WHERE name LIKE {{ inputs.searchTerm }} AND role = {{ inputs.role }} LIMIT {{ inputs.limit }} inputs: searchTerm: type: string description: "Search term (supports % wildcards)" role: type: string description: "User role to filter by" optional: true default: "user" limit: type: int description: "Maximum results to return" optional: true default: "20"query search-users { use: main_db description: "Search users by name and role" statement: "SELECT id, name FROM users WHERE name LIKE {{ inputs.searchTerm }}" inputs: { searchTerm: { type: string description: "Search term" } }}Input properties
Section titled “Input properties”| Property | Required | Description |
|---|---|---|
type | Yes | Data type (see below) |
description | Yes | Human-readable description |
optional | No | Whether the input is optional (default: false) |
default | No | Default value for optional inputs |
Supported types
Section titled “Supported types”| Type | Description | Example Value |
|---|---|---|
string | Text values | "hello world" |
int | Integer numbers (64-bit) | 42, -100 |
float | Floating-point numbers | 3.14, -0.5 |
boolean | True/false values | true, false |
uuid | UUID strings | "550e8400-e29b-41d4-a716-446655440000" |
datetime | ISO 8601 datetime (RFC3339) | "2024-01-15T10:30:00Z" |
Using inputs in statements
Section titled “Using inputs in statements”Reference inputs in SQL statements using the template syntax:
{{ inputs.fieldName }}Basic usage
Section titled “Basic usage”statement: | SELECT * FROM users WHERE id = {{ inputs.userId }}inputs: userId: type: int description: 'User ID'When called with {"userId": 123}, the statement becomes:
SELECT * FROM users WHERE id = 123String values
Section titled “String values”String values are automatically quoted and escaped:
statement: | SELECT * FROM users WHERE email = {{ inputs.email }}inputs: email: type: string description: 'Email address'When called with {"email": "alice@example.com"}:
SELECT * FROM users WHERE email = 'alice@example.com'Multiple inputs
Section titled “Multiple inputs”statement: | SELECT * FROM products WHERE category = {{ inputs.category }} AND price BETWEEN {{ inputs.minPrice }} AND {{ inputs.maxPrice }} AND in_stock = {{ inputs.inStock }} ORDER BY price ASCinputs: category: type: string description: 'Product category' minPrice: type: float description: 'Minimum price' maxPrice: type: float description: 'Maximum price' inStock: type: boolean description: 'Only show in-stock items'Date/Time values
Section titled “Date/Time values”statement: | SELECT * FROM events WHERE created_at >= {{ inputs.startDate }} AND created_at <= {{ inputs.endDate }}inputs: startDate: type: datetime description: 'Start of date range' endDate: type: datetime description: 'End of date range'Call with ISO 8601 format:
{ "startDate": "2024-01-01T00:00:00Z", "endDate": "2024-01-31T23:59:59Z"}Optional inputs and defaults
Section titled “Optional inputs and defaults”Mark inputs as optional and provide default values:
inputs: limit: type: int description: 'Number of results' optional: true default: '20'
sortOrder: type: string description: 'Sort direction (asc or desc)' optional: true default: 'desc'Optional input examples
Section titled “Optional input examples”queries: list-users: use: main_db description: 'List users with optional pagination' statement: | SELECT id, name, email FROM users ORDER BY created_at DESC LIMIT {{ inputs.limit }} OFFSET {{ inputs.offset }} inputs: limit: type: int description: 'Page size' optional: true default: '20' offset: type: int description: 'Number of items to skip' optional: true default: '0'This can be called with no inputs:
curl -X POST http://localhost:8080/query/list-users \ -H "Content-Type: application/json" \ -d '{}'Or with specific values:
curl -X POST http://localhost:8080/query/list-users \ -H "Content-Type: application/json" \ -d '{"limit": 50, "offset": 100}'Validation
Section titled “Validation”Hyperterse validates all inputs before executing queries:
Type validation
Section titled “Type validation”Inputs must match their declared types:
// Valid for type: int{"userId": 123}
// Invalid - string provided for int{"userId": "abc"}Required input validation
Section titled “Required input validation”Missing required inputs return an error:
{ "success": false, "error": "validation error for field 'userId': required input 'userId' is missing", "results": []}Unknown input rejection
Section titled “Unknown input rejection”Extra inputs not defined in the schema are rejected:
{ "success": false, "error": "validation error: unknown input field 'unknownField' provided", "results": []}Security considerations
Section titled “Security considerations”Hyperterse protects against SQL injection through:
- Type enforcement — Only valid types are accepted
- String escaping — Single quotes are escaped in string values
- Template validation — All
{{ inputs.x }}references must be defined
Best practices
Section titled “Best practices”Descriptive names
Section titled “Descriptive names”Use clear, descriptive input names:
# Goodinputs: userId: type: int emailAddress: type: string createdAfter: type: datetime
# Less clearinputs: id: type: int str: type: string dt: type: datetimeHelpful descriptions
Section titled “Helpful descriptions”Write descriptions that help API consumers understand what to provide:
inputs: searchTerm: type: string description: 'Search term to match against user names. Use % as wildcard.' limit: type: int description: 'Maximum number of results (1-100)' optional: true default: '20'Sensible defaults
Section titled “Sensible defaults”Choose defaults that make sense for most use cases:
inputs: limit: type: int default: '20' # Reasonable page size sortOrder: type: string default: 'desc' # Most recent first