Writing Data with PormG: Overview

This section covers all data manipulation operations in PormG, including creating, updating, and deleting records. PormG provides both single-record and bulk operations for efficient data management.

Every write on this page is gated on `change_data`

change_data defaults to false, so a connection cannot write until you enable it under the config: block of the active environment in connection.yml. Until then the first create, update, delete, bulk call or ManyToMany mutator raises WritesDisabledError before any SQL is generated. See Creating Records for the exact YAML and the two ways it commonly goes wrong.

Async-First Philosophy

PormG is designed as Async-First. All database operations must utilize non-blocking I/O where possible. Synchronous APIs (like create(), update(), delete()) are strictly wrappers around an asynchronous core. This ensures that even synchronous code yields to the Julia scheduler, preventing the blocking of the event loop—essential for integration with web frameworks like Genie.jl.

Section Contents

  • Creating Records: Learn how to insert individual records and handle relationships.
  • Updating Records: Update existing data using filters and efficient F-expressions.
  • Deleting Records: Safely remove records with cascading support.
  • Bulk Operations: Efficiently handle large datasets with bulk_insert, bulk_copy, and bulk_update.

Performance Overview

OperationBest ForSpeedProtocol
create()Single rowsStandardSQL INSERT
get_or_create()Fetch-or-insert, keep existingStandardSELECT + INSERT ON CONFLICT
update_or_create()Insert-or-update (upsert)StandardINSERT ON CONFLICT DO UPDATE
row.save()Persisting one fetched rowStandardSQL UPDATE
row.delete()Deleting one fetched rowStandardSQL DELETE (+ cascade)
bulk_insert()Medium datasets (< 10k rows)FastMulti-row INSERT
bulk_copy()Massive datasetsUltra-FastPostgres COPY
update()Selective updatesStandardSQL UPDATE
bulk_update()Modifying many rowsFastMulti-row UPDATE

PostgreSQL Only: bulk_copy() uses PostgreSQL's native COPY FROM STDIN protocol and is not available for SQLite. For SQLite, use bulk_insert() instead.