You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: AGENTS.md
+5-97Lines changed: 5 additions & 97 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -578,7 +578,7 @@ Named parameters in transactions:
578
578
-**Prevention**: Prevents SQL injection attacks through proper parameter binding
579
579
580
580
**Backward Compatibility:**
581
-
Positional parameters (`?`) still work unchanged. Mix positional and named parameters carefully - SQLite applies them in parameter-order:
581
+
Positional parameters (`?`) still work unchanged:
582
582
583
583
```elixir
584
584
# Positional parameters still work
@@ -589,10 +589,12 @@ Positional parameters (`?`) still work unchanged. Mix positional and named param
589
589
state
590
590
)
591
591
592
-
# Named parameters can coexist with positional in same Elixir codebase
593
-
# (but not in the same query - SQLite doesn't allow mixing syntaxes)
592
+
# Named and positional can coexist in separate queries within the same codebase
594
593
```
595
594
595
+
**Avoiding Mixed Syntax:**
596
+
While SQLite technically permits mixing positional (`?`) and named (`:name`) parameters in a single statement, this is discouraged. Named parameters receive implicit numeric indices which can conflict with positional parameters, leading to unexpected binding order. This adapter's map-based approach naturally avoids this issue—pass a list for positional queries, or a map for named queries, but don't mix within a single statement.
597
+
596
598
#### How Statement Caching Works
597
599
598
600
Prepared statements are now cached internally after preparation:
@@ -1603,100 +1605,6 @@ end
1603
1605
CREATETABLEsessions (...) RANDOM ROWID
1604
1606
```
1605
1607
1606
-
#### STRICT Tables (Type Enforcement)
1607
-
1608
-
STRICT tables enforce strict type checking - columns must be one of the allowed SQLite types. This prevents accidental type mismatches and data corruption:
1609
-
1610
-
```elixir
1611
-
# Create a STRICT table for type safety
1612
-
defmoduleMyApp.Repo.Migrations.CreateUsersdo
1613
-
useEcto.Migration
1614
-
1615
-
defchangedo
1616
-
create table(:users, strict:true) do
1617
-
add :id, :integer, primary_key:true
1618
-
add :name, :string, null:false
1619
-
add :email, :string, null:false
1620
-
add :age, :integer
1621
-
add :balance, :float, default:0.0
1622
-
add :avatar, :binary
1623
-
add :is_active, :boolean, default:true
1624
-
1625
-
timestamps()
1626
-
end
1627
-
1628
-
create unique_index(:users, [:email])
1629
-
end
1630
-
end
1631
-
```
1632
-
1633
-
**Benefits:**
1634
-
-**Type Safety**: Enforces that columns only accept their declared types (TEXT, INTEGER, REAL, BLOB, NULL)
1635
-
-**Data Integrity**: Prevents accidental type coercion that could lead to bugs
1636
-
-**Better Errors**: Clear error messages when incorrect types are inserted
1637
-
-**Performance**: Can enable better query optimisation by knowing exact column types
1638
-
1639
-
**Allowed Types in STRICT Tables:**
1640
-
-`INT`, `INTEGER` - Integer values only
1641
-
-`TEXT` - Text values only
1642
-
-`BLOB` - Binary data only
1643
-
-`REAL` - Floating-point values only
1644
-
-`NULL` - NULL values only (rarely used)
1645
-
1646
-
**Usage Examples:**
1647
-
1648
-
```elixir
1649
-
# STRICT table with various types
1650
-
create table(:products, strict:true) do
1651
-
add :sku, :string, null:false# Must be TEXT
1652
-
add :name, :string, null:false# Must be TEXT
1653
-
add :quantity, :integer, default:0# Must be INTEGER
1654
-
add :price, :float, null:false# Must be REAL
1655
-
add :description, :text# Must be TEXT
1656
-
add :image_data, :binary# Must be BLOB
1657
-
add :published_at, :utc_datetime# Stored as TEXT (ISO8601 format)
1658
-
timestamps()
1659
-
end
1660
-
1661
-
# Combining STRICT with RANDOM ROWID
1662
-
create table(:api_keys, options: [strict:true, random_rowid:true]) do
0 commit comments