Using DuckDB as an in-process analytical SQL engine for SwiftUI applications, enabling SQL queries over CSV, Parquet, and SQLite files.
Enables SQL queries on CSV, Parquet, and SQLite files directly within SwiftUI applications using DuckDB.
npx claudepluginhub arustydev/aiThis skill inherits all available tools. When active, it can use any tool Claude has access to.
Using DuckDB as an in-process analytical SQL engine for SwiftUI applications, enabling SQL queries over CSV, Parquet, and SQLite files.
// Package.swift
dependencies: [
.package(url: "https://github.com/duckdb/duckdb-swift", from: "1.0.0")
]
import DuckDB
// In-memory database
let database = try Database(store: .inMemory)
let connection = try database.connect()
// File-backed database
let database = try Database(store: .file(at: "analytics.duckdb"))
// Execute SQL
try connection.execute("CREATE TABLE items (id INTEGER, name VARCHAR, price DECIMAL)")
// Insert data
try connection.execute("""
INSERT INTO items VALUES
(1, 'Widget', 9.99),
(2, 'Gadget', 19.99)
""")
// Query with results
let result = try connection.query("SELECT * FROM items WHERE price > 10")
// Iterate rows
for row in result {
let id: Int32 = row[0]!
let name: String = row[1]!
let price: Double = row[2]!
print("\(id): \(name) - $\(price)")
}
// Column access
let names = result[1].cast(to: String.self)
for name in names {
print(name ?? "NULL")
}
// Query CSV directly
let result = try connection.query("""
SELECT * FROM read_csv('data.csv')
WHERE category = 'Electronics'
ORDER BY price DESC
LIMIT 10
""")
// With options
let result = try connection.query("""
SELECT * FROM read_csv('data.csv',
header = true,
delim = ',',
columns = {'id': 'INTEGER', 'name': 'VARCHAR', 'price': 'DECIMAL'}
)
""")
// Query Parquet directly
let result = try connection.query("""
SELECT
date_trunc('month', timestamp) as month,
SUM(amount) as total
FROM read_parquet('transactions.parquet')
GROUP BY 1
ORDER BY 1
""")
// Filter pushdown (efficient)
let result = try connection.query("""
SELECT * FROM read_parquet('large_file.parquet')
WHERE year = 2024 AND region = 'US'
""")
// Attach SQLite database
try connection.execute("INSTALL sqlite; LOAD sqlite;")
try connection.execute("ATTACH 'existing.sqlite' AS sqlite_db (TYPE sqlite)")
// Query SQLite tables
let result = try connection.query("""
SELECT * FROM sqlite_db.users
WHERE created_at > '2024-01-01'
""")
import SwiftUI
import DuckDB
@Observable
final class AnalyticsViewModel {
var results: [[String: Any]] = []
var isLoading = false
var error: Error?
private let database: Database
private let connection: Connection
init() throws {
database = try Database(store: .inMemory)
connection = try database.connect()
}
func executeQuery(_ sql: String) async {
isLoading = true
defer { isLoading = false }
do {
let result = try connection.query(sql)
results = result.map { row in
var dict: [String: Any] = [:]
for (index, column) in result.columns.enumerated() {
dict[column.name] = row[index]
}
return dict
}
error = nil
} catch {
self.error = error
results = []
}
}
func loadCSV(from url: URL) async throws {
try connection.execute("""
CREATE OR REPLACE TABLE data AS
SELECT * FROM read_csv('\(url.path)')
""")
}
}
struct QueryResultsView: View {
let results: [[String: Any]]
let columns: [String]
var body: some View {
Table(results, columns: columns) { result in
TableRow(result) { columnName in
Text(String(describing: result[columnName] ?? "NULL"))
}
}
}
}
struct SQLEditorView: View {
@State private var viewModel: AnalyticsViewModel
@State private var query = "SELECT * FROM data LIMIT 100"
var body: some View {
VSplitView {
// Query editor
TextEditor(text: $query)
.font(.system(.body, design: .monospaced))
.frame(minHeight: 100)
// Results
if viewModel.isLoading {
ProgressView()
} else if let error = viewModel.error {
Text(error.localizedDescription)
.foregroundStyle(.red)
} else {
ResultsTableView(results: viewModel.results)
}
}
.toolbar {
Button("Run") {
Task {
await viewModel.executeQuery(query)
}
}
.keyboardShortcut(.return, modifiers: .command)
}
}
}
let result = try connection.query("""
SELECT
date,
value,
AVG(value) OVER (
ORDER BY date
ROWS BETWEEN 6 PRECEDING AND CURRENT ROW
) as moving_avg_7d
FROM time_series
""")
let result = try connection.query("""
WITH daily_totals AS (
SELECT
DATE_TRUNC('day', timestamp) as day,
SUM(amount) as total
FROM transactions
GROUP BY 1
),
running_totals AS (
SELECT
day,
total,
SUM(total) OVER (ORDER BY day) as cumulative
FROM daily_totals
)
SELECT * FROM running_totals
""")
let result = try connection.query("""
SELECT
category,
COUNT(*) as count,
AVG(price) as avg_price,
PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY price) as median_price,
STDDEV(price) as price_stddev
FROM products
GROUP BY category
HAVING COUNT(*) > 10
ORDER BY avg_price DESC
""")
.file() store for large datasetsimport TabularData
extension DataFrame {
init(duckDBResult: ResultSet) {
var columns: [AnyColumn] = []
for (index, column) in duckDBResult.columns.enumerated() {
switch column.type {
case .integer:
let values = duckDBResult.map { $0[index] as Int64? }
columns.append(Column<Int64?>(name: column.name, contents: values).eraseToAnyColumn())
case .varchar:
let values = duckDBResult.map { $0[index] as String? }
columns.append(Column<String?>(name: column.name, contents: values).eraseToAnyColumn())
case .double:
let values = duckDBResult.map { $0[index] as Double? }
columns.append(Column<Double?>(name: column.name, contents: values).eraseToAnyColumn())
default:
break
}
}
self.init(columns: columns)
}
}
Activates when the user asks about AI prompts, needs prompt templates, wants to search for prompts, or mentions prompts.chat. Use for discovering, retrieving, and improving prompts.
Search, retrieve, and install Agent Skills from the prompts.chat registry using MCP tools. Use when the user asks to find skills, browse skill catalogs, install a skill for Claude, or extend Claude's capabilities with reusable AI agent components.
This skill should be used when the user asks to "create an agent", "add an agent", "write a subagent", "agent frontmatter", "when to use description", "agent examples", "agent tools", "agent colors", "autonomous agent", or needs guidance on agent structure, system prompts, triggering conditions, or agent development best practices for Claude Code plugins.