Built-in Functions
LeapSQL macros have access to Starlark's standard library plus some LeapSQL-specific functions.
Starlark Standard Library
String Functions
String Methods
python
# Case conversion
"hello".upper() # "HELLO"
"HELLO".lower() # "hello"
"hello".capitalize() # "Hello"
"hello world".title() # "Hello World"
# Whitespace
" hello ".strip() # "hello"
" hello ".lstrip() # "hello "
" hello ".rstrip() # " hello"
# Search
"hello".startswith("he") # True
"hello".endswith("lo") # True
"hello".find("l") # 2 (index of first 'l')
"hello".count("l") # 2
# Replace
"hello".replace("l", "L") # "heLLo"
# Split/Join
"a,b,c".split(",") # ["a", "b", "c"]
",".join(["a", "b", "c"]) # "a,b,c"String Formatting
python
# .format() method
"Hello, {}!".format("World")
# "Hello, World!"
"{} + {} = {}".format(1, 2, 3)
# "1 + 2 = 3"
"Name: {name}, Age: {age}".format(name="Alice", age=30)
# "Name: Alice, Age: 30"
# Repeated placeholder
"{0} {0} {1}".format("hello", "world")
# "hello hello world"String Checks
python
"hello".isalpha() # True (all alphabetic)
"12345".isdigit() # True (all digits)
"hello123".isalnum() # True (alphanumeric)
" ".isspace() # True (all whitespace)List Functions
Creation and Access
python
# Create
my_list = [1, 2, 3]
empty = []
# Access
my_list[0] # 1 (first element)
my_list[-1] # 3 (last element)
my_list[1:3] # [2, 3] (slice)
# Length
len(my_list) # 3List Operations
python
# Concatenation
[1, 2] + [3, 4] # [1, 2, 3, 4]
# Repetition
[1, 2] * 3 # [1, 2, 1, 2, 1, 2]
# Membership
2 in [1, 2, 3] # True
4 in [1, 2, 3] # False
4 not in [1, 2, 3] # TrueList Methods
python
# Note: Lists in Starlark are immutable by default in many contexts
# These operations return new lists
# append (in a mutable context)
my_list = [1, 2]
my_list.append(3) # [1, 2, 3]
# extend
my_list.extend([4, 5]) # [1, 2, 3, 4, 5]
# index
[1, 2, 3].index(2) # 1
# remove
my_list.remove(2) # Removes first occurrence of 2List Comprehensions
python
# Transform
[x * 2 for x in [1, 2, 3]]
# [2, 4, 6]
# Filter
[x for x in [1, 2, 3, 4] if x > 2]
# [3, 4]
# Transform and filter
[x * 2 for x in [1, 2, 3, 4] if x > 2]
# [6, 8]
# Nested
[[i, j] for i in [1, 2] for j in [3, 4]]
# [[1, 3], [1, 4], [2, 3], [2, 4]]Dictionary Functions
Creation and Access
python
# Create
my_dict = {"a": 1, "b": 2}
empty = {}
# Access
my_dict["a"] # 1
my_dict.get("a") # 1
my_dict.get("c", 0) # 0 (with default)
# Check membership
"a" in my_dict # True
"c" in my_dict # FalseDictionary Methods
python
my_dict = {"a": 1, "b": 2}
# Keys, values, items
my_dict.keys() # ["a", "b"]
my_dict.values() # [1, 2]
my_dict.items() # [("a", 1), ("b", 2)]
# Get with default
my_dict.get("c", "default") # "default"
# Update (in mutable context)
my_dict.update({"c": 3})
# Pop
my_dict.pop("a") # Returns 1, removes "a"
my_dict.pop("z", "not found") # Returns "not found"Dictionary Comprehensions
python
# Create from list
{x: x * 2 for x in [1, 2, 3]}
# {1: 2, 2: 4, 3: 6}
# Filter
{k: v for k, v in {"a": 1, "b": 2, "c": 3}.items() if v > 1}
# {"b": 2, "c": 3}
# Transform keys
{k.upper(): v for k, v in {"a": 1, "b": 2}.items()}
# {"A": 1, "B": 2}Built-in Functions
Type Conversion
python
int("42") # 42
int(3.14) # 3
float("3.14") # 3.14
str(42) # "42"
bool(1) # True
bool(0) # False
list("abc") # ["a", "b", "c"]
dict([("a", 1)]) # {"a": 1}Math Functions
python
abs(-5) # 5
min(1, 2, 3) # 1
max(1, 2, 3) # 3
min([1, 2, 3]) # 1 (works with lists too)
sum([1, 2, 3]) # 6Sequence Functions
python
len([1, 2, 3]) # 3
len("hello") # 5
len({"a": 1}) # 1
range(5) # [0, 1, 2, 3, 4]
range(1, 5) # [1, 2, 3, 4]
range(0, 10, 2) # [0, 2, 4, 6, 8]
sorted([3, 1, 2]) # [1, 2, 3]
reversed([1, 2, 3]) # [3, 2, 1]
enumerate(["a", "b"]) # [(0, "a"), (1, "b")]
zip([1, 2], ["a", "b"]) # [(1, "a"), (2, "b")]Boolean Functions
python
all([True, True, True]) # True
all([True, False, True]) # False
any([False, True, False]) # True
any([False, False]) # FalseOther Built-ins
python
type(42) # "int"
type("hello") # "string"
type([1, 2]) # "list"
type({"a": 1}) # "dict"
hasattr(obj, "method") # Check if object has attribute
getattr(obj, "method") # Get attribute value
repr("hello") # "'hello'" (string representation)
hash("hello") # Integer hash valueControl Flow
If Expressions
python
# Ternary-style
result = "yes" if condition else "no"
# In macro
def conditional_sql(include):
return "column" if include else "'redacted'"For Loops
python
def build_columns(cols):
result = []
for col in cols:
result.append(col)
return ", ".join(result)Error Handling
python
def validated(value):
if not value:
fail("Value is required") # Raises error
return valueLeapSQL Built-ins
Global Objects
These are available in the template context:
python
# Environment variables
env.MY_VAR
env.get("MY_VAR", "default")
# Project configuration
config.project_name
config.version
# Current target
target.name
target.schema
# Current model metadata
this.name
this.materialized
this.tags
this.metaUtility Functions
var()
Get a variable with optional default:
python
var("start_date", "2024-01-01")
var("required_param") # Fails if not setfail()
Stop execution with an error:
python
def require_prod():
if target.name != "prod":
fail("This model can only run in production")print()
Debug output (visible in logs):
python
def debug_function(value):
print("Received value:", value)
return valueExample: Using Built-ins in Macros
String Processing
python
def snake_to_camel(name):
"""Convert snake_case to camelCase."""
parts = name.split("_")
return parts[0] + "".join(p.capitalize() for p in parts[1:])
def pluralize(word):
"""Simple English pluralization."""
if word.endswith("s"):
return word + "es"
elif word.endswith("y"):
return word[:-1] + "ies"
else:
return word + "s"List Processing
python
def unique(items):
"""Remove duplicates while preserving order."""
seen = {}
result = []
for item in items:
if item not in seen:
seen[item] = True
result.append(item)
return result
def chunk(items, size):
"""Split list into chunks of given size."""
return [items[i:i+size] for i in range(0, len(items), size)]Dictionary Processing
python
def merge_dicts(*dicts):
"""Merge multiple dictionaries."""
result = {}
for d in dicts:
result.update(d)
return result
def filter_dict(d, keys):
"""Keep only specified keys from dict."""
return {k: v for k, v in d.items() if k in keys}SQL Generation
python
def columns_except(all_cols, exclude):
"""Return columns except those in exclude list."""
return [c for c in all_cols if c not in exclude]
def aliased_columns(cols, prefix):
"""Add prefix alias to columns."""
return ["{} as {}_{}".format(c, prefix, c) for c in cols]
def null_safe_equals(col1, col2):
"""NULL-safe equality comparison."""
return "({0} = {1} OR ({0} IS NULL AND {1} IS NULL))".format(col1, col2)Limitations
Not Available in Starlark
These Python features are NOT available:
python
# No imports
import os # Error!
# No file I/O
open("file.txt") # Error!
# No network
requests.get(...) # Error!
# No exec/eval
exec("code") # Error!
# No classes
class MyClass: # Error!
passStarlark Differences from Python
python
# No while loops
while condition: # Error!
pass
# No try/except
try: # Error!
risky()
except:
pass
# No *args/**kwargs (limited support)
def func(*args): # Limited support
pass
# Integers only (no arbitrary precision)
very_large = 10 ** 100 # May overflow
# Strings are immutable (as in Python, but no mutation methods)Next Steps
- Writing Macros - Create custom macros
- Using Macros - Call macros in models
- Templating - Template syntax