Array
Arrays let you work with collections of values. Hamelin arrays work much like SQL arrays, but they integrate seamlessly with structs to handle complex nested data.
Creating arrays
You create arrays using square brackets with elements separated by commas.
SET event_types = ["login", "logout", "purchase"]
SET user_ids = [1001, 1002, 1003, 1004]
SET timestamps = [ts('2024-01-15T10:00:00'), ts('2024-01-15T10:15:00'), ts('2024-01-15T10:30:00')]
Arrays can contain any type of value, including numbers, strings, timestamps, and even structs.
Arrays of structs
Arrays become especially useful when they contain structs, as Hamelin automatically handles differences between struct fields.
SET user_events = [
{user_id: 1001, event: "login", timestamp: ts('2024-01-15T09:00:00')},
{user_id: 1001, event: "purchase", timestamp: ts('2024-01-15T09:15:00'), amount: 49.99},
{user_id: 1001, event: "logout", timestamp: ts('2024-01-15T09:30:00')}
]
Notice how the second struct has an amount field that the others don't have. Hamelin automatically creates a combined type that includes all fields, setting missing fields to NULL where needed.
Accessing array elements
Use square brackets with zero-based indexing to access individual elements.
FROM events
| SELECT
first_tag = tags[0],
second_tag = tags[1],
last_tag = tags[-1]
Negative indices count from the end of the array, so [-1] gives you the last element.
Array operations with mixed structs
When you combine arrays containing structs with different fields, Hamelin merges the struct types intelligently.
SET login_events = [
{event_type: "login", user_id: 100, timestamp: ts('2024-01-15T09:00:00')},
{event_type: "login", user_id: 101, timestamp: ts('2024-01-15T09:05:00')}
]
SET purchase_events = [
{event_type: "purchase", user_id: 100, amount: 25.99, timestamp: ts('2024-01-15T09:10:00')}
]
// Combining these creates an array with all fields: event_type, user_id, timestamp, amount
The resulting combined array contains structs where each element has all the fields that appear in any struct, with NULL values where fields are missing.
Field ordering in combined structs
When Hamelin combines structs with different fields, it maintains the field order from the first struct encountered, then appends any new fields in the order they first appear.
SET events = [
{id: 1, type: "login", user_id: 100}, // Order: id, type, user_id
{status: "success", id: 2, type: "logout"} // New field 'status' gets appended
]
// Result order: id, type, user_id, status
Type compatibility
Arrays can only contain elements that can be coerced to a common type. Hamelin will combine compatible types automatically, but incompatible types will cause an error.
// This works - numbers can be in the same array
SET mixed_numbers = [1, 2.5, 3]
// This works - structs with compatible fields
SET compatible_structs = [
{name: "Alice", age: 30},
{name: "Bob", age: 25, city: "Seattle"}
]
// This would fail - structs with same field name but different types
// {name: "Alice", count: 5} and {name: "Bob", count: "many"}
Practical examples
Arrays work well for collecting related values and organizing repeated data.
// Collecting user actions over time
FROM user_logs
| SELECT
user_id,
user_session = {
daily_events: [
{action: "login", time: login_time},
{action: "view_page", time: page_view_time, page: page_name},
{action: "logout", time: logout_time}
],
session_duration: logout_time - login_time
}
This creates structured output where each user's session contains an array of different event types, each with their own specific fields.
Working with nested arrays
Arrays can contain structs that themselves contain arrays, creating complex nested structures.
FROM dns_logs
| SELECT dns_response = {
query: query_name,
answers: [
{name: answer1_name, type: answer1_type, ttl: answer1_ttl},
{name: answer2_name, type: answer2_type, ttl: answer2_ttl}
],
response_time: query_duration
}
This organizes DNS response data where each query can have multiple answers, and each answer has its own set of fields.