API Reference

Overview

PormG provides a Django-inspired ORM for Julia with an async-first architecture. This page serves as a comprehensive reference for all exported functions, types, and the query builder API. For topic-specific guides, see the Reading and Writing sections.


Query Builder: Functor API

PormG uses a Django-style, object-oriented query builder. All database operations start from Model.objects and are chained using methods that either modify the query or execute it.

# The general pattern
results = M.Driver.objects
    .filter("nationality" => "Brazilian")
    .values("forename", "surname")
    .order_by("surname")
    .limit(10)
    .list()

Chainable Methods

These methods modify the query builder and return the handler for further chaining:

MethodDescriptionExample
.filter(key => value, ...)Add WHERE conditions (AND). Multiple pairs are ANDed..filter("nationality" => "British")
.values("field1", "field2", ...)Select specific columns. Use "*" for all main-table columns..values("*", "driverId__surname")
.order_by("field", "-field")Sort results. Prefix with - for descending..order_by("-points", "surname")
.limit(n)Limit the number of returned rows..limit(10)
.offset(n)Skip the first n rows..offset(20)
.db("key")Route the query to a different connection pool..db("tenant_42")
.on("path", key => value)Add predicates to the ON clause of an existing join path..on("driverId", "nationality" => "British")

See also: cjoin() for custom join definitions and with() for CTEs.

[!IMPORTANT] Queries that use cjoin() must call .values(...) explicitly before execution. A bare SELECT * across joined tables causes DataFrames.jl to crash with ArgumentError: Duplicate variable names. PormG throws a clear error if you forget. Use .values("*", "joined_model__field") to quickly select all main-table columns plus specific fields from the joined table.

Terminal Methods

These methods finalize the query and execute it against the database:

MethodReturn TypeDescription
.list()Vector{Dict{Symbol, Any}}Returns all matching rows as dictionaries.
.all()Vector{Dict}Alias for .list().
query |> DataFrameDataFramePipe to DataFrame for tabular output.
.count()IntRuns SELECT COUNT(*) and returns the count.
.exists()BoolReturns true if at least one row matches.
.first()Dict or nothingReturns the first matching record or nothing.
.list_json()StringReturns results as a JSON string.
.create(key => value, ...)DictInserts a single record and returns it.
.update(key => value, ...)Updates all matching records.
.delete()Deletes all matching records.

Example:

# Full query chain with DataFrame output
df = M.Result.objects
    .filter("driverId__nationality" => "Brazilian", "positionOrder" => 1)
    .values("driverId__forename", "driverId__surname", "raceId__year")
    .order_by("-raceId__year") |> DataFrame

# Count and existence checks
n = M.Driver.objects.filter("nationality" => "British").count()
has_british = M.Driver.objects.filter("nationality" => "British").exists()

Query Inspection & Debugging

show_query

An integrated switch available on all terminal methods to toggle between execution and inspection.

ModeDescription
:executeDefault. Executes the query and returns results.
:sqlReturns the SQL string only. Minimal overhead for benchmarking.
:dictReturns full metadata dictionary (sql, parameters, dialect, model, operation, etc.).
:paramsReturns the parameters array only.
:noneReturns nothing. Zero-overhead mode for benchmarking the builder itself.
query = M.Driver.objects.filter("nationality" => "British")

# Get just the SQL string
sql = query.list(show_query=:sql)

# Benchmark the builder without execution overhead
@time query.list(show_query=:none)

# Get full metadata
meta = query.list(show_query=:dict)

inspect_query

Dedicated API for comprehensive query inspection without executing. Features a heuristic intent detector that guesses the operation type (select, insert, update) based on the object state.

query = M.Driver.objects.filter("nationality" => "Brazilian").order_by("surname")
inspection = query |> inspect_query()

println(inspection[:sql])        # The generated SQL
println(inspection[:parameters]) # Bound parameters
println(inspection[:operation])  # Automatically detects :select
println(inspection[:dialect])    # :postgresql or :sqlite

[!NOTE] LIMIT and OFFSET values are rendered as literal integers in the SQL string. They do not appear in inspection[:parameter_buckets] or inspection[:parameters]. This is by design.


Filter Operators

PormG uses __@ suffixes for lookup operators and field transforms:

Comparison Operators

OperatorSQL EquivalentExample
field= value"nationality" => "British"
field__@gt> value"points__@gt" => 10
field__@gte>= value"points__@gte" => 10
field__@lt< value"positionOrder__@lt" => 3
field__@lte<= value"positionOrder__@lte" => 10
field__@ne<> value"status__@ne" => "Retired"
field__@inIN (...)"nationality__@in" => ["British", "French"]
field__@ninNOT IN (...)"nationality__@nin" => ["British", "German"]
field__@rangeBETWEEN a AND b"driverId__@range" => [1, 50]
field__@isnullIS NULL / IS NOT NULL"dob__@isnull" => true
field__@containsLIKE '%val%'"name__@contains" => "Monaco"
field__@icontainsILIKE '%val%'"name__@icontains" => "monaco"

Transform Functions

TransformDescriptionExample
field__@yearExtract year from date"dob__@year" => 1960
field__@monthExtract month from date"dob__@month" => 3
field__@dayExtract day from date"dob__@day" => 21
field__@quarterExtract quarter (1-4)"date__@quarter" => 1
field__@dateExtract date from datetime"created_at__@date" => Date(2025, 1, 1)
field__@roundRound numeric value"points__@round" => 0
field__@floorFloor numeric value"points__@floor" => 0
field__@ceilCeiling numeric value"points__@ceil" => 0

For the full list of operators and transforms, see Filters and Aggregates.


F-Expressions

F() enables database-side field references and arithmetic. Use it for field-to-field comparisons and computed expressions.

using PormG: F, Sum, Count

# Field-to-field comparison
M.Result.objects.filter(F("grid") == F("positionOrder"))

# Arithmetic in projections
M.Result.objects.values(
    "driverId__surname",
    "bonus" => F("points") * 0.1
)

# Aggregate ratios
M.Result.objects.values(
    "driverId__surname",
    "avg_pts" => Sum("points") / Count("resultId")
)

# Atomic update (no read-modify-write race)
M.Result.objects.filter("resultId" => 1).update("points" => F("points") + 10)

See Field Expressions for the full reference.


Q Objects: Complex Boolean Logic

Q() and Qor() enable complex boolean predicates with AND/OR logic:

using PormG: Q, Qor

# AND logic (Q contains AND by default)
M.Driver.objects.filter(Q("nationality" => "Brazilian", "code" => "SEN"))

# OR logic
M.Driver.objects.filter(Qor("nationality" => "Brazilian", "nationality" => "French"))

# Nested AND/OR
M.Driver.objects.filter(
    Q("nationality" => "Brazilian", Qor("forename" => "Ayrton", "forename" => "Nelson"))
)

See Q Objects for the full reference.


Aggregate Functions

All aggregate functions can be used in .values() for grouping or combined with F-expressions:

FunctionSQLExample
Count("field")COUNT(field)"total" => Count("resultId")
Sum("field")SUM(field)"total_pts" => Sum("points")
Avg("field")AVG(field)"avg_pts" => Avg("points")
Max("field")MAX(field)"best" => Max("points")
Min("field")MIN(field)"worst" => Min("points")

When aggregate values appear in values(), PormG automatically groups by the non-aggregated columns. Aggregate-based filters are promoted to HAVING.

# Wins per constructor with HAVING filter
df = M.Result.objects.values(
    "constructorId__name",
    "wins" => Count("resultId")
).filter(
    "positionOrder" => 1,
    "wins__@gt" => 50
).order_by("-wins") |> DataFrame

SQL Functions

PormG exports a comprehensive set of SQL functions:

String Functions

FunctionDescriptionExample
Lower("field")Convert to lowercase"name_lower" => Lower("surname")
Upper("field")Convert to uppercase"name_upper" => Upper("surname")
Length("field")String length"name_len" => Length("surname")
Concat(args...)Concatenate values"full" => Concat("forename", Value(" "), "surname")
Trim("field")Trim whitespace"clean" => Trim("name")
LTrim("field")Left trim"clean" => LTrim("name")
RTrim("field")Right trim"clean" => RTrim("name")
Replace("field", old, new)Replace substring"fixed" => Replace("name", "-", " ")

Numeric Functions

FunctionDescription
Abs("field")Absolute value
Round("field", precision)Round to precision
Floor("field")Floor
Ceil("field")Ceiling
Sqrt("field")Square root
Exp("field")Exponential
Ln("field")Natural logarithm
Power("field", n)Raise to power
Mod("field", n)Modulo

Conditional & Utility Functions

FunctionDescriptionExample
Value(x)Literal value in SQLValue("hello")
Coalesce(args...)First non-null valueCoalesce("nickname", "forename")
NullIf("field", value)Returns NULL if equalNullIf("code", "")
Greatest(args...)Maximum of valuesGreatest("points", Value(0))
Least(args...)Minimum of valuesLeast("points", Value(100))
Cast("field", type)Type castingCast("points", "INTEGER")
Extract("part", "field")Extract date/time partExtract("year", "dob")
To_char("field", fmt)Format to stringTo_char("dob", "YYYY-MM")

Case Expressions

Case(
    ("positionOrder" => 1) => Value("Winner"),
    ("positionOrder__@lte" => 3) => Value("Podium"),
    default=Value("Other")
)

See Functions and Dates for more details.


Custom Joins

cjoin()

Defines custom join conditions at query time. Useful for legacy databases, non-FK joins, and multi-tenant systems.

using PormG: cjoin, Q, Qor

query = M.Result.objects
cjoin(query, "driverId" => "Driver",
    filters=[Q("nationality" => "Brazilian", Qor("forename" => "Ayrton", "forename" => "Nelson"))],
    join_type="INNER"
)
query.values("driverId__forename", "driverId__surname", "points")
df = query |> DataFrame

Parameters:

ArgumentTypeDescription
queryhandlerThe query object to add the join to.
main_joinPair{String,String}"field" => "TargetModel" — the join path.
filtersVectorON-clause predicates. Supports Pair, Q(), Qor(), F expressions.
join_typeString"LEFT" (default), "INNER", "RIGHT", or "FULL".
fieldPormGFieldOptional custom field definition for non-FK joins.
warnBoolSuppress auto-discovery warnings (default: true).

See Custom Joins for the full documentation.

on()

Adds ON-clause predicates to existing join paths (including reverse joins) without redefining them:

query = M.Result.objects
query.on("driverId", "nationality" => "Brazilian", "code" => "SEN")
query.values("resultId", "driverId__surname", "points")

Bulk Operations

bulk_insert

Inserts multiple records in a single operation. Returns the inserted rows.

df = DataFrame([
    Dict("forename" => "Ayrton", "surname" => "Senna", "nationality" => "Brazilian"),
    Dict("forename" => "Alain",  "surname" => "Prost", "nationality" => "French"),
])
result = bulk_insert(M.Driver, df)

bulk_update

Updates multiple records in a single operation.

bulk_update(M.Driver.objects, df_with_changes)

bulk_copy

PostgreSQL Only. Uses PostgreSQL's native COPY FROM STDIN protocol for ultra-fast bulk loading.

bulk_copy(M.Driver.objects, df)
FunctionBest ForSpeedProtocol
create()Single rowsStandardSQL INSERT
bulk_insert()Medium datasets (< 10k rows)FastMulti-row INSERT
bulk_copy()Massive datasetsUltra-FastPostgres COPY
bulk_update()Modifying many rowsFastMulti-row UPDATE

Transactions

run_in_transaction

Executes a block inside a database transaction with automatic commit/rollback:

PormG.run_in_transaction("db") do
    M.Result.objects.create("raceId" => 1, "driverId" => 1, "points" => 25)
    M.Driver.objects.filter("driverId" => 1).update("code" => "WIN")
    # If any exception is raised, both operations are rolled back
end

Key features:

  • Async context propagation — spawned @async tasks inherit the transaction
  • Connection sharing — all queries in the block use the same connection
  • Automatic rollback on error

See Transactions for the full reference including savepoints and multithreaded patterns.


Async Execution

fetch_async

Execute a query asynchronously, returning a FetchTask:

task = fetch_async(M.Driver.objects.filter("nationality" => "Brazilian"))
# ... do other work ...
result = await_result(task)

Configuration API

Configuration.load(path; env=nothing)

Loads a database configuration folder. Use env to explicitly set the environment instead of relying on ENV["PORMG_ENV"].

PormG.Configuration.load("db"; env="prod")

Configuration.load_many(paths; env=nothing)

Bootstraps multiple database folders in one call:

PormG.Configuration.load_many(["db", "db_analytics"]; env="prod")

Configuration.is_loaded(path_or_key)

Returns true if PormG has registered settings for the given folder/key. Does not open connections.

Configuration.ping(path_or_key)

Tests actual database reachability. Returns Bool.

Configuration.status(path_or_key)

Returns a rich status payload:

s = PormG.Configuration.status("db")
# (key="db", loaded=true, reachable=true, adapter="PostgreSQL", app_env="prod")

For the full configuration guide, see Configuration.


Advisory Locks

with_advisory_lock

Acquires a PostgreSQL advisory lock for distributed coordination:

PormG.with_advisory_lock("db", "migration_lock"; wait=true, timeout_ms=10000) do
    # Critical section — only one process at a time
    PormG.Migrations.migrate("db")
end

Strategies:

  • :poll (default) — Client-side polling with interval
  • :block — Server-side blocking via pg_advisory_lock

SQLite: No-op (executes the block without locking).

See Advisory Locks for the full reference.


Password Utilities

make_password(raw_password)

Hashes a password using the default algorithm (PBKDF2-SHA256, 720,000 iterations):

hash = make_password("Champion_1988!")
# "pbkdf2_sha256$720000$salt$hash..."

check_password(raw_password, encoded_hash)

Verifies a password against its stored hash with constant-time comparison:

if check_password("Champion_1988!", stored_hash)
    println("Welcome!")
end

password_needs_upgrade(encoded_hash)

Returns true if the hash should be re-calculated with stronger settings:

if password_needs_upgrade(stored_hash)
    new_hash = make_password(raw_password)
end

validate_password(password; kwargs...)

Validates password complexity. Returns a ValidationResult with .valid and .errors.

result = validate_password("weak", min_length=10)
if !result.valid
    println(result.errors)
end

See Passwords for algorithms, custom encoders, i18n, and Django/Spring compatibility.


Terminal Dashboard

tui(db_path; models_module=nothing, fps=30)

Launches an interactive terminal dashboard for migration review and query inspection. Requires Tachikoma.jl.

using Tachikoma
PormG.tui("db"; models_module=M)

See Migrations: Terminal Dashboard for details.


Abstract Types

PormG's type hierarchy provides the foundation for the query builder and model system:

TypeDescription
PormGAbstractTypeBase abstract type for all PormG types.
SQLConnRepresents a database connection (subtypes: PormGPostgres, PormGSQLite).
SQLObjectBase for objects that can be stored in the database.
SQLObjectHandlerHandles operations on SQL objects (the query builder).
SQLTableAliasManages table aliases in SQL queries.
SQLInstructionRepresents an instruction to build a SQL query.
SQLTypeBase for SQL-related expression types.
SQLTypeFieldRepresents a field expression in queries.
SQLTypeQQ-expression type (AND logic).
SQLTypeQorQor-expression type (OR logic).
SQLTypeFF-expression type (field references).
SQLTypeFunctionSQL function type.
SQLTypeCTECommon Table Expression type.
PormGModelBase for model types.
PormGFieldBase for field type definitions.

Exported Symbols

The following symbols are exported by PormG and available after using PormG:

Query Builder

object, Q, Qor, F, show_query, inspect_query

Aggregate Functions

Sum, Avg, Count, Max, Min

SQL Functions

Case, Cast, Concat, Extract, To_char, Value, Coalesce, Greatest, Least, Lower, Upper, Length, Abs, Round, NullIf, Replace, Trim, LTrim, RTrim, Floor, Ceil, Sqrt, Exp, Ln, Power, Mod

Bulk Operations

bulk_insert, bulk_update, bulk_copy

Async API

fetch_async, await_result, FetchTask

Transactions

run_in_transaction, with_tx_context, in_transaction_context

Locking

with_advisory_lock

Passwords

make_password, check_password, password_needs_upgrade, validate_password, ValidationResult, PasswordValidator

Utilities

setup, tui, @import_models, @models_module


Auto-Generated API Docs

The following section contains auto-generated documentation from docstrings in the source code:

PormG.setupFunction
setup(path::String = DB_PATH)

Interactively setup the connection.yml file for PormG. This will prompt for database adapter, name, and connection details.

source
PormG.tuiMethod
tui(db_path::String; models_module=nothing, fps=30)

Launch the PormG terminal dashboard with Migrations and Query Inspection panes. Requires Tachikoma.jl to be installed and loaded (using Tachikoma).

See ext/PormGTachikomaExt.jl for the full implementation.

source
PormG.QueryBuilder.CountMethod

Count(x; distinct::Bool = false)

Creates an aggregate COUNT function object for use in query building.

Arguments

  • x: The column or expression to count.
  • distinct::Bool = false: If true, counts only distinct values of x.

Examples

# Count just when other_model_id is distinct  
query = MyModels.model_test |> object;
query.filter("id__@gte" => 1)
query.values("id", "count" => Count("other_model_id", distinct=true))
df = query |> list |> DataFrame
source
PormG.QueryBuilder.QMethod

Q(x...)

Create a QObject with the given filters. Ex.: julia a = object("tb_user") a.filter(Q("name" => "John", Qor("age" => 18, "age" => 19)))

Arguments:

  • x: A list of key-value pairs or Qor(x...) or Q(x...) objects.
source
PormG.QueryBuilder.QorMethod

Qor(x...)

Create a QorObject from the given arguments. The QorObject represents a disjunction of SQLTypeQ or SQLTypeQor objects.

Ex.: julia a = object("tb_user") a.filter(Qor("name" => "John", Q("age__gte" => 18, "age__lte" => 19)))

Arguments

  • x...: A variable number of arguments. Each argument can be either a SQLTypeQ or SQLTypeQor object, or a Pair object.
source
PormG.QueryBuilder.WithFunction

Add a Common Table Expression (CTE) to the query object.

CTEs can be joined like regular tables using their field names.

Arguments

  • q::SQLObject: The SQL object to add the CTE to (available as query.object)
  • name::String: The name of the CTE (will be used as table name in JOINs and Lookups)
  • query::SQLObjectHandler: The subquery that defines the CTE

Keyword Arguments

  • join_field::Pair{String, String}: The relationship for joining (e.g., "local_field" => "cte_field").
  • join_type::String: The SQL join type ("LEFT", "INNER", etc). Default is "LEFT".

Returns

  • The modified SQLObject with the CTE added.

Examples

import PormG.models as M

# Example 1: Basic CTE with JOIN (Finding total results per driver)
drivers_stats = M.Result.objects
drivers_stats.values("driverid", "total_races" => Count("resultid"))

main_query = M.Result.objects
With(main_query.object, "stats", drivers_stats, join_field="driverid" => "driverid")

# Filter and select using CTE fields with "cte_name__" prefix
main_query.filter("resultid__@lte" => 100)
main_query.values("resultid", "driverid", "stats__total_races")

df = main_query |> DataFrame
# Example 2: CTE with INNER JOIN and Multiple Aggregations
high_scorers = M.Result.objects
high_scorers.filter("points__@gte" => 10)
high_scorers.values("driverid", "max_points" => Sum("points"))

query = M.Driver.objects
With(query.object, "hs", high_scorers, join_field="driverid" => "driverid", join_type="INNER")

query.values("driverid", "surname", "hs_points" => "hs__max_points")
query.filter("driverid__@lte" => 50)

df = query |> DataFrame
source
PormG.QueryBuilder.WithMethod

Pair-accepting overload for With, enabling the functor-style API:

# Django-idiomatic chain:
races_91 = M.Race.objects.filter("year" => 1991).values("raceid")
q = M.Result.objects
  .with("r91" => races_91, join_field="raceid" => "raceid")
  .filter("positionorder" => 1)

The Pair first argument maps the CTE name to its sub-query handler. All keyword arguments are forwarded to the underlying With implementation.

source
PormG.QueryBuilder._apply_like_wildcardsMethod
_apply_like_wildcards(value::Any, operator::String)::Any

Apply appropriate LIKE wildcards based on the operator:

  • contains/icontains: %value%
  • startswith: value%
  • endswith: %value
  • Other operators: no wildcards
source
PormG.QueryBuilder._cache_joinMethod
_cache_join(field::String, instruct::SQLInstruction)

Checks if a join path field is already in the cache. If not, and it's a join path (contains __), it attempts to build the join and cache it. Returns true if the field is in cache (either before or after the attempt), false otherwise.

source
PormG.QueryBuilder._get_pair_to_operMethod

getpairtooper(x::Pair)

Converts a Pair object to an OperObject. If the Pair's key is a string, it checks if it contains an operator suffix (e.g. "@gte", "@lte") and returns an OperObject with the corresponding operator. If the key does not contain an operator suffix, it returns an OperObject with the "=" operator. If the key is not a string, it throws an error.

Arguments

  • x::Pair: A Pair object to be converted to an OperObject.

Returns

  • OperObject: An OperObject with the corresponding operator and values.
source
PormG.QueryBuilder._infer_case_output_typeMethod

Infer the output PormGField type for a CASE/WHEN expression by inspecting the then values from WHEN branches and the default/else value.

Returns IntegerField if all values are integers, FloatField if any are floats, or CharField as a safe fallback for strings or mixed types.

source
PormG.QueryBuilder._preset_cte_fieldsMethod

Set the field definitions from a CTE query to create temporary PormGField objects. This allows the CTE to be treated like a table with queryable fields for JOINs.

source
PormG.QueryBuilder._solve_fieldMethod

This function checks if the given field is a valid field in the provided model. If the field is valid, it returns the field name, potentially modified based on certain conditions.

source
PormG.QueryBuilder._validation_errorMethod
validate_field_data(model::PormGModel, field::String, value::Any, operation::String; allow_primary_key::Bool = true)

Validates that a value is compatible with the model field definition before SQL generation. Checks:

  1. Field existence in model.
  2. Primary key modification protection (disabled if allowprimarykey is false).
  3. Max length for CharFields.
  4. Max digits for Decimal/Numeric fields.

Returns true if valid, throws an ErrorException otherwise. SQL expressions (SQLTypeF, SQLTypeFunction) skip data validation as they are evaluated by the DB.

source
PormG.QueryBuilder.build_cte_clauseMethod

Build CTE (WITH clause) SQL string from the CTEs defined in the query object.

Arguments

  • ctes::Dict{String, Dict{String, Union{SQLObjectHandler, PormGField}}}: Dict of CTE name => fields dict
  • connection: Database connection for quoting identifiers
  • parameters: Parameterized query object to collect all parameters

Returns

  • String containing the WITH clause SQL, or empty string if no CTEs
source
PormG.QueryBuilder.bulk_copyMethod
bulk_copy(objct::SQLObjectHandler, df_o::DataFrames.DataFrame; kwargs...)

Performs a high-speed bulk insert operation using PostgreSQL's COPY protocol. This is significantly faster than bulk_insert for large datasets.

Arguments

  • objct::SQLObjectHandler: The database handler object (e.g., M.Model).
  • df_o::DataFrames.DataFrame: The DataFrame containing the data to be inserted.
  • columns: (Optional) Specifies which columns to insert. Can be a String, a Pair{String, String}, or a Vector of these.
  • copy::Bool = true: If true, creates a copy of the DataFrame before processing.
  • show_query::Bool = false: If true, prints the COPY command (note: data stream is not printed).

Example

bulk_copy(M.Driver, df)
source
PormG.QueryBuilder.bulk_insertMethod

Inserts multiple rows into the database in bulk from a DataFrame.

Arguments

  • objct::SQLObjectHandler: The SQL object handler to use for the operation.
  • df_o::DataFrames.DataFrame: The DataFrame containing the data to be inserted.
  • columns: Optional. Specifies the columns to insert and their mappings. Can be nothing, a String, a Pair{String, String}, or a Vector of these. If nothing, all columns from the DataFrame are used.
  • chunk_size::Integer: Optional. The number of rows to insert in each batch (default: 1000).
  • show_query::Bool: Optional. If true, prints the generated SQL query (default: false).
  • copy::Bool: Optional. If true, creates a copy of the DataFrame before processing (default: false).

Examples

```julia include("models.jl") import models as mdl

Basic usage

query = mdl.User |> object df = DataFrame(name=["Alice", "Bob"], age=[30, 25]) bulk_insert(query, df)

With column mapping and excluding unwanted variables

query = mdl.Boook |> object df = DataFrame(title=["Book A", "Book B"], authorname=["Alice", "Bob"], year=[2020, 2021], ignoreme=["x", "y"])

Map DataFrame column "author_name" to model field "author"

Exclude "ignore_me" by not including it in the columns argument

bulkinsert(query, df, columns=["title", "year", "authorname" => "author"])

the df will be modified to only include the columns "title", "year", and "author_name" (renamed to "author").

If you want to copy the DataFrame before processing, set copy=true:

bulkinsert(query, df, columns=["title", "year", "authorname" => "author"], copy=true)

```

source
PormG.QueryBuilder.bulk_updateMethod

Performs a bulk update operation on a database table using the provided DataFrame and a query object.

Arguments

  • objct::SQLObjectHandler: The database handler object.
  • df::DataFrames.DataFrame: The DataFrame containing the data to be used for the update.
  • columns: (Optional) Specifies which columns to update. Can be a String, a Pair{String, String}, or a Vector of these. If nothing, no columns are specified.
  • filters: (Optional) Specifies the filters to apply for the update. Can be a String, a Pair{String, T} where T is String, Integer, Bool, Date, or DateTime, or a Vector of these. If nothing, no filters are applied.
  • show_query::Bool: (Optional) If true, prints the generated SQL query. Defaults to false.
  • chunk_size::Integer: (Optional) Number of rows to process per chunk. Defaults to 1000.
  • copy::Bool: (Optional) If true, creates a copy of the DataFrame before processing. Defaults to true. Set to false to modify the original DataFrame and improve performance, but this may lead to unintended side effects when the operation is performed in asynchronous contexts.

Example

# Update the columns of the DataFrame df if df contains the primary key of the table
bulk_update(objct, df)
# Update the name and dof columns for the security_id in the DataFrame df
bulk_update(objct, df, columns=["security_id", "name", "dof"], filters=["security_id"])
source
PormG.QueryBuilder.cjoinFunction

Add a custom join to the query object that does not have to follow the model's foreign key relationships.

Arguments

  • q::SQLObject: The SQL object to add the custom join to
  • main_join::Pair{String, String}: A pair where the first element is the field in the main model to join on, and the second element is the related model name to join with
  • filters::AbstractVector: (Optional) An array of filters (Pair, Q, Qor, OP, F) to apply to the join condition
  • join_type::Union{String, Nothing}: (Optional) The type of join

Examples

  query = M.New_join_position |> object;
  cjoin(query, "result" => "Result");
  query.values("result__statusid__status", "description", "result");

  @info query |> show_query
  ┌ Info: SELECT
  │    "Tb_2"."status" as result__statusid__status,
  │   "Tb"."description" as description,
  │   "Tb"."result" as result
  │ FROM "new_join_position" as "Tb"
  │  LEFT JOIN "result" AS "Tb_1" ON "Tb"."result" = "Tb_1"."resultid"
  └  LEFT JOIN "status" AS "Tb_2" ON "Tb_1"."statusid" = "Tb_2"."statusid"
source
PormG.QueryBuilder.deleteMethod

Delete objects from the database with proper handling of foreign key relationships and cascading operations.

Arguments

  • objct::SQLObjectHandler: The SQL object handler containing the query and model information
  • show_query::Bool=false: If true, displays the generated SQL queries instead of executing them
  • allow_delete_all::Bool=false: If true, allows deletion without WHERE clause filters (dangerous operation)

Returns

  • Tuple{Integer, Dict{String, Integer}}: A tuple containing:
    • Total number of deleted objects
    • Dictionary mapping model names to their respective deletion counts

Behavior

  • Validates that the connection allows data modification operations
  • Requires WHERE clause filters unless allow_delete_all is explicitly set to true
  • Handles foreign key relationships by building a deletion dependency graph
  • Processes SETNULL, SETDEFAULT, and cascading delete operations appropriately
  • Executes all operations within a database transaction for data integrity

Examples

# Delete objects from a model with a specific filter
query = M.Status |> object
query.filter("status" => "Engine")
total, dict = delete(query)

# Show the SQL query without executing it
query = M.Just_a_test_deletion |> object
query.filter("test_result__constructorid__name" => "Williams")
total, dict = delete(query, show_query = :sql)

# Delete related tables (cascading delete)
query = M.Result |> object
query.filter("resultid" => 1)
total, dict = delete(query)

# Delete all objects from a model (use with caution)
query = M.Just_a_test_deletion |> object
total, dict = delete(query; allow_delete_all = true)

source
PormG.QueryBuilder.get_filter_queryMethod

getfilterquery(object::SQLObject, instruc::SQLInstruction)

Iterates over the filter of the object and generates the WHERE query for the given SQLInstruction object.

ALERT

  • This internal function is called by the build function.

Arguments

  • object::SQLObject: The object containing the filter to be selected.
  • instruc::SQLInstruction: The SQLInstruction object to which the WHERE query will be added.
source
PormG.QueryBuilder.get_final_parametersMethod
get_final_parameters(p::AbstractPormGParam) -> Vector{Any}

Return all collected parameter values in the order expected by the final SQL string.

  • PostgreSQL: returns the single linear vector (order already matches $N numbering).
  • SQLite: concatenates buckets in standard SQL clause order: cte → select → join → where → having so that each positional ? aligns with its value.
source
PormG.QueryBuilder.get_select_queryMethod

getselectquery(object::SQLObject, instruc::SQLInstruction)

Iterates over the values of the object and generates the SELECT query for the given SQLInstruction object.

ALERT

  • This internal function is called by the build function.

Arguments

  • object::SQLObject: The object containing the values to be selected.
  • instruc::SQLInstruction: The SQLInstruction object to which the SELECT query will be added.
source
PormG.QueryBuilder.get_settingsMethod
get_settings(obj::Union{SQLObject, SQLObjectHandler}; connection::Union{Nothing, PormGPostgres, PormGSQLite} = nothing)

Resolves the database settings for a query. Returns a tuple of (settings::SQLConn, connection, conn_key::String).

If a connection is provided, it is returned as is. Otherwise, it returns the default connection from the resolved settings.

source
PormG.QueryBuilder.inspect_queryMethod
inspect_query(q::SQLObjectHandler) -> Dict

Comprehensive query inspection API that provides full metadata about a query without executing it. Returns a rich dictionary with SQL, parameters, dialect information, and structural metadata.

This is the explicit API for query inspection - use this when you want to examine a query's structure and generated SQL without ambiguity.

Arguments

  • q::SQLObjectHandler: The query object to inspect
  • operation::Union{Nothing, Symbol} = nothing: Optional operation override (:select, :insert, :update, :delete). If not provided, the operation is detected automatically based on the query structure.

Returns

  • Dict: A dictionary containing:
    • :sql_text (String): The generated SQL query
    • :parameters (Vector): The parameterized values in bucket order
    • :dialect (Symbol): The database dialect (:postgresql or :sqlite)
    • :model (String): The model/table name
    • :operation (Symbol): The query operation type (:select, :insert, :update, :delete)
    • :bucketing (Symbol): The parameter bucketing strategy (:numbered for PostgreSQL, :positional for SQLite)
    • :parameter_count (Int): Number of parameters
    • :parameter_buckets (Dict): Breakdown of parameters by bucket (for positional strategies)

Example

q = M.Driver.objects
q.filter("nationality" => "British")
q.order_by("surname")

inspection = q |> inspect_query()
# Dict with:
# :sql_text => "SELECT ... WHERE drivers.nationality = $1 ORDER BY ..."
# :parameters => ["British"]
# :dialect => :postgresql
# :model => "drivers"
# :operation => :select
# :bucketing => :numbered
source
PormG.QueryBuilder.listMethod

Fetches a list of records from the database and returns them as an array of dictionaries.

This function executes the query and converts each row to a dictionary with column names as keys.

Arguments

  • objct::SQLObjectHandler: The SQL object handler containing the query

Returns

  • Vector{Dict{Symbol, Any}}: Array of dictionaries, where each dictionary represents a row

Example

query = M.Result |> object
query.filter("raceid__year" => 2020)
query.values("driverid__forename", "constructorid__name", "laps")
records = query |> list  # Returns array of dictionaries
# Example output: [Dict(:driverid__forename => "Lewis", :constructorid__name => "Mercedes", :laps => 58), ...]
source
PormG.QueryBuilder.list_jsonMethod

Fetches a list of records from the database and returns them as a JSON string.

This function executes the query, converts each row to a dictionary, and serializes the result as JSON.

Arguments

  • objct::SQLObjectHandler: The SQL object handler containing the query

Returns

  • String: JSON string representation of the query results

Example

query = M.Result |> object
query.filter("raceid__year" => 2020)
query.values("driverid__forename", "constructorid__name", "laps")
json_data = query |> list_json  # Returns JSON string
# Example output: "[{"driverid__forename":"Lewis","constructorid__name":"Mercedes","laps":58}]"
source
PormG.QueryBuilder.objectMethod

Wraps a PormGModel into an ObjectHandler on which you can call:

- .filter(...) to add WHERE clauses
- .values(...) to choose/annotate columns
- .order_by(...) to sort
- .distinct() to add DISTINCT clause
- .create(...) for single-row DML
- .update(...) for single-row DML
- .limit(...), .offset(...), .page(...) for pagination
- plus bulk_insert, bulk_update, do_count, do_exists, list, etc.

Arguments

  • model::PormGModel: The model to be wrapped and handled.

Example

using PormG, DataFrames

# assume models loaded as `M`
query = M.User.objects

# 1) Filtering & selecting
query.filter("is_active" => true)
query.values("id", "username", "email")
df = query |> DataFrame

# 2) Counting
active_users = query.count()

# 3) Inserting a single row
new = M.Status.objects.create("statusid" => 42, "status" => "Foo")  
# returns a Dict of the inserted row

# 4) Updating a single row
M.Status.objects.filter("statusid" => 42).update("status" => "Bar")

# 5) Ordering & aggregation
query = M.Result.objects.filter("raceid__year" => 2020)
query.values(
  "driverid__forename", 
  "constructorid__name", 
  "laps" => Count("laps")
).order_by("-laps")
df2 = query |> DataFrame

# 6) Existence check
exists = M.User.objects.filter("id" => 1).exists()
source
PormG.QueryBuilder.pageMethod

Set pagination parameters for a SQL query object.

Arguments

  • object::SQLObjectHandler: The SQL object handler to modify
  • limit::Integer: Maximum number of records to return (default: 10)
  • offset::Integer: Number of records to skip from the beginning (default: 0)

Examples

query.page(20, 10) |> DataFrame query.page(20) |> DataFrame

The function form page(query, 20, 10) is still supported, but the fluent query.page(...) style is the preferred public API.

source
PormG.QueryBuilder.query_listMethod

Fetches a list of records from the database for the given SQLObjectHandler.

Returns

  • The result of the database query as returned by fetch.

Example

query = M.Result |> object
query.filter("raceid__year" => 2020)
query.values("driverid__forename", "constructorid__name", "laps" => Count("laps"))
query.order_by("-laps")
df = query |> list |> DataFrame
source
PormG.QueryBuilder.set_context!Method
set_context!(params::AbstractPormGParam, context::Symbol)

Switch the active parameter bucket for positional-parameter backends (SQLite). Valid contexts: :cte, :select, :update, :join, :where, :having.

For numbered-parameter backends (PostgreSQL) this is a no-op.

source
PormG.QueryBuilder.up_filter!Method

up_filter!(q::SQLObject, filter) Add filters to the SQLObject query.

Arguments

  • q::SQLObject: The SQL object to add filters to.
  • filter: A collection of filters to add. Each filter can be a Pair, SQLTypeQ, SQLTypeQor, SQLTypeOper, or SQLTypeF.

Returns

  • The modified SQLObject with the new filters added.
source
DataFrames.DataFrameMethod

Creates a DataFrame directly from a SQLObjectHandler query.

This extends the DataFrame constructor to work directly with PormG query objects,

Arguments

  • objct::SQLObjectHandler: The SQL object handler containing the query

Returns

  • DataFrames.DataFrame: The query results as a DataFrame

Example

query = M.Result |> object
query.filter("raceid__year" => 2020)
query.values("driverid__forename", "constructorid__name", "laps")
df = query |> DataFrame  # Direct conversion to DataFrame
source
PormG.QueryBuilder.FExpressionType

F object for direct database field references and operations (similar to Django F expressions).

Allows you to reference database fields directly in operations without pulling data into Julia.

Examples

# Update a field with another field's value
query = MyModel |> object
query.filter("id" => 1)
query.update("field1" => F("field2"))

# Increment a field by a constant
query.update("counter" => F("counter") + 1)

# Update with arithmetic operations between fields
query.update("total" => F("price") * F("quantity"))

# Use in filters to compare fields
query.filter(F("start_date") <= F("end_date"))

# Use in annotations/values
query.values("price", "discounted_price" => F("price") * 0.9)
source
PormG.QueryBuilder.OperObjectType

Mutable struct representing an SQL operator object for using in the filter and annotate. That is a internal function, please do not use it.

Fields

  • operator::String: the operator used in the SQL query.
  • values::Union{String, Integer, Bool}: the value(s) to be used with the operator.
  • column::Union{String, SQLTypeFunction}: the column to be used with the operator.
source
PormG.Models.AutoFieldMethod
AutoField(; kwargs...)

A field type for auto-incrementing integer primary keys, equivalent to PostgreSQL's SERIAL columns.

The AutoField is designed for auto-incrementing integer primary keys and automatically generates unique integer values for each record. Unlike IDField which uses BIGINT, AutoField uses INTEGER type and is suitable for applications that don't require the extended range of BIGINT values.

Keyword Arguments

  • verbose_name::Union{String, Nothing} = nothing: A human-readable name for the field
  • primary_key::Bool = true: Whether this field is the primary key for the table
  • auto_increment::Bool = true: Whether the field should auto-increment (generate values automatically)
  • unique::Bool = true: Whether values in this field must be unique across all records
  • blank::Bool = false: Whether the field can be left blank in forms (not applicable for auto fields)
  • null::Bool = false: Whether the database column can store NULL values
  • db_index::Bool = false: Whether to create a database index on this field (primary keys are automatically indexed)
  • default::Union{Int64, Nothing} = nothing: Default value for the field (rarely used with auto-increment)
  • editable::Bool = false: Whether the field should be editable in forms (typically false for auto fields)

Database Mapping

  • PostgreSQL Type: INTEGER with SERIAL auto-increment
  • Auto-increment: Supported through PostgreSQL's SERIAL type (sequence-based)
  • Index: Automatically indexed as primary key
  • Range: 32-bit signed integers (-2,147,483,648 to 2,147,483,647)

AutoField vs IDField Comparison

FeatureAutoFieldIDField
Database TypeINTEGER (SERIAL)BIGINT (BIGSERIAL/IDENTITY)
Range32-bit (-2B to 2B)64-bit (-9Q to 9Q)
Storage4 bytes8 bytes
GenerationSequence-basedIdentity columns or sequence
Use CaseSmall to medium appsLarge-scale applications

When to Use AutoField vs IDField

Use AutoField when:

  • Building small to medium-sized applications
  • You don't expect more than ~2 billion records
  • Storage efficiency is important (4 bytes vs 8 bytes per ID)
  • Working with legacy systems that expect INTEGER primary keys
  • Building lookup tables, categories, or reference data

Use IDField when:

  • Building large-scale applications with potential for massive growth
  • You need the extended range of 64-bit integers
  • Working with data warehouses or analytics platforms
  • Future-proofing against scale requirements
  • Using modern PostgreSQL features like identity columns
source
PormG.Models.BigIntegerFieldMethod
BigIntegerField(; kwargs...)

A field for storing 64-bit signed integers, equivalent to PostgreSQL's BIGINT columns.

The BigIntegerField stores large whole numbers within the 64-bit signed integer range (-9,223,372,036,854,775,808 to 9,223,372,036,854,775,807). It's ideal for large identifiers, timestamps, population counts, and other numeric data requiring extended range beyond regular integers.

Keyword Arguments

  • verbose_name::Union{String, Nothing} = nothing: A human-readable name for the field
  • unique::Bool = false: Whether values in this field must be unique across all records
  • blank::Bool = false: Whether the field can be left blank in forms
  • null::Bool = false: Whether the database column can store NULL values
  • db_index::Bool = false: Whether to create a database index on this field
  • default::Union{Int64, Nothing} = nothing: Default value for the field
  • editable::Bool = false: Whether the field should be editable in forms

Database Mapping

  • PostgreSQL Type: BIGINT
  • Storage: 8 bytes per value
  • Range: -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807
  • Index: Optional, recommended for frequently queried fields

Examples

Large identifier field:

Analytics = Models.Model(
    _id = IDField(),
    user_id = BigIntegerField(db_index=true),
    session_id = BigIntegerField(),
    timestamp_ms = BigIntegerField()  # Unix timestamp in milliseconds
)

Population and statistics:

Country = Models.Model(
    _id = IDField(),
    name = CharField(max_length=100),
    population = BigIntegerField(null=true),
    gdp_usd = BigIntegerField(null=true),  # GDP in USD cents
    area_sq_meters = BigIntegerField()
)

Large external identifiers:

SocialMedia = Models.Model(
    _id = IDField(),
    user = ForeignKey("User"),
    twitter_id = BigIntegerField(unique=true, null=true),
    facebook_id = BigIntegerField(unique=true, null=true),
    follower_count = BigIntegerField(default=0)
)

Common Use Cases

  1. Large Identifiers: External API IDs, social media IDs
  2. Timestamps: Unix timestamps in milliseconds or microseconds
  3. Population Data: Country populations, large counts
  4. Financial Data: Large monetary values in smallest units
  5. Scientific Data: Large measurements, particle counts
  6. Analytics: Large user IDs, session identifiers

Migration Considerations

  • From IntegerField: Safe upgrade, no data loss
  • To IntegerField: Requires validation that all values fit in 32-bit range
  • Index Changes: Indexes will be recreated with new size
  • Application Code: May need updates if expecting different ranges
source
PormG.Models.BooleanFieldMethod
BooleanField(; kwargs...)

A field for storing boolean (true/false) values, equivalent to PostgreSQL's BOOLEAN columns.

The BooleanField stores binary true/false values and is ideal for flags, switches, status indicators, and any field that represents a yes/no or on/off state. It maps directly to PostgreSQL's BOOLEAN type and Julia's Bool type.

Keyword Arguments

  • verbose_name::Union{String, Nothing} = nothing: A human-readable name for the field
  • unique::Bool = false: Whether values in this field must be unique (rarely used with booleans)
  • blank::Bool = false: Whether the field can be left blank in forms
  • null::Bool = false: Whether the database column can store NULL values
  • db_index::Bool = false: Whether to create a database index on this field
  • default::Union{Bool, Nothing} = nothing: Default value for the field (true or false)
  • editable::Bool = false: Whether the field should be editable in forms

Examples

Basic boolean flags:

User = Models.Model(
    _id = IDField(),
    username = CharField(max_length=150),
    is_active = BooleanField(default=true),
    is_staff = BooleanField(default=false),
    email_verified = BooleanField(default=false)
)

Boolean Values and Conversion

The field handles various input formats:

  • Julia Bool: true, false
  • Integers: 1 (true), 0 (false)
  • Strings: "true", "false", "1", "0", "yes", "no"
  • NULL: When null=true, accepts NULL/nothing
source
PormG.Models.CharFieldMethod
CharField(; kwargs...)

A field for storing short to medium-length strings, equivalent to PostgreSQL's VARCHAR columns.

The CharField is the most commonly used field for storing textual data with a limited length. It maps to a PostgreSQL VARCHAR column and supports validation, indexing, choices, and various constraints. This field is ideal for names, titles, codes, and other string data with known maximum lengths.

Keyword Arguments

  • verbose_name::Union{String, Nothing} = nothing: A human-readable name for the field
  • max_length::Int = 250: Maximum number of characters allowed (1-255)
  • unique::Bool = false: Whether values in this field must be unique across all records
  • blank::Bool = false: Whether the field can be left blank in forms
  • null::Bool = false: Whether the database column can store NULL values
  • db_index::Bool = false: Whether to create a database index on this field
  • db_column::Union{String, Nothing} = nothing: Custom database column name (defaults to field name)
  • default::Union{String, Nothing} = nothing: Default value for the field
  • choices::Union{NTuple{N, Tuple{AbstractString, AbstractString}}, Nothing} = nothing: Restricted set of valid values
  • editable::Bool = true: Whether the field should be editable in forms

Length Constraints

  • Minimum: 1 character
  • Maximum: 255 characters
  • Validation: Automatically enforced at the field level
  • Storage: Efficient variable-length storage in PostgreSQL

Examples

Basic string field:

User = Models.Model(
    _id = IDField(),
    username = CharField(max_length=150, unique=true),
    first_name = CharField(max_length=50),
    last_name = CharField(max_length=50)
)

String field with choices (enumeration):

Order = Models.Model(
    _id = IDField()
    status = CharField(
        max_length=20,
        choices=(
            ("1", "Pending"),
            ("2", "Processing"),
            ("3", "Shipped"),
            ("4", "Delivered"),
            ("5", "Cancelled")
        ),
        default="1"
    )
    customer_name = CharField(max_length=200)
)

Optional field with custom database column:

Product = Models.Model(
    _id = IDField(),
    name = CharField(max_length=200),
    sku = CharField(
        max_length=50, 
        unique=true, 
        db_column="product_sku",
        verbose_name="Stock Keeping Unit"
    )
    category = CharField(max_length=100, null=true, blank=true)
)

Indexed field for performance:

Article = Models.Model(
    _id = IDField(),
    title = CharField(max_length=200, db_index=true),
    slug = CharField(max_length=200, unique=true, db_index=true),
    content = TextField()
)

Choices Feature

The choices parameter allows you to restrict field values to a predefined set:

# Define choices as tuples of (value, display_name)
priority_choices = (
    ("low", "Low Priority"),
    ("medium", "Medium Priority"),
    ("high", "High Priority"),
    ("urgent", "Urgent")
)

Task = Models.Model(
    _id = IDField(),
    title = CharField(max_length=200),
    priority = CharField(max_length=10, choices=priority_choices, default="medium")
)

Choice Format Options:

  1. Tuple of Tuples: (("value1", "Display 1"), ("value2", "Display 2"))
  2. String Format: "(value1, Display 1)(value2, Display 2)"

Default Values

  • Static Default: default="some_value"
  • Must Match Choices: If choices are specified, default must be one of the choice values
  • Length Validation: Default value must not exceed max_length

Database Column Naming

  • Conventions: Follow PostgreSQL naming conventions (lowercase, underscores)

CharField vs TextField

FeatureCharFieldTextField
LengthLimited (1-255)Unlimited
Database TypeVARCHARTEXT
Use CaseShort stringsLong content
IndexingEfficientLess efficient
PerformanceFast queriesSlower for large content

Migration Considerations

  • Increasing Length: Safe operation
  • Decreasing Length: Requires data validation
  • Adding Choices: Application-level change only
  • Changing Column Name: Use db_column parameter

Notes

  • The field uses VARCHAR type which is efficient for short to medium strings
  • Choices are validated at the Julia application level, not in the database
  • The editable=true default makes this field suitable for user input forms
  • Database indexing is optional but recommended for frequently queried fields
  • Compatible with PostgreSQL's text search and pattern matching features

See Also

  • TextField for unlimited length text content
  • EmailField for email address validation
  • Database design best practices for string field sizing
source
PormG.Models.DateFieldMethod
DateField(; kwargs...)

A field for storing date values (without time), equivalent to PostgreSQL's DATE columns.

The DateField stores calendar dates in YYYY-MM-DD format and is ideal for birth dates, event dates, deadlines, and any date information that doesn't require time precision. It maps to PostgreSQL's DATE type and Julia's Date type.

Keyword Arguments

  • verbose_name::Union{String, Nothing} = nothing: A human-readable name for the field
  • unique::Bool = false: Whether values in this field must be unique across all records
  • blank::Bool = false: Whether the field can be left blank in forms
  • null::Bool = false: Whether the database column can store NULL values
  • db_index::Bool = false: Whether to create a database index on this field
  • default::Union{String, Nothing} = nothing: Default value for the field (YYYY-MM-DD format)
  • editable::Bool = false: Whether the field should be editable in forms
  • auto_now::Bool = false: Whether to automatically set to current date on every save
  • auto_now_add::Bool = false: Whether to automatically set to current date on creation only

Examples

Basic date fields:

User = Models.Model(
    _id = IDField(),
    username = CharField(max_length=150),
    birth_date = DateField(null=true, blank=true),
    join_date = DateField(auto_now_add=true),
    last_login_date = DateField(null=true)
)

Event and scheduling:

Event = Models.Model(
    _id = IDField(),
    title = CharField(max_length=200),
    event_date = DateField(db_index=true),
    registration_deadline = DateField(),
    created_date = DateField(auto_now_add=true)
)

Business dates:

Invoice = Models.Model(
    _id = IDField(),
    customer = ForeignKey("Customer"),
    issue_date = DateField(auto_now_add=true),
    due_date = DateField(),
    paid_date = DateField(null=true, blank=true)
)

Auto Date Features

autonowadd

Sets the date automatically when the record is first created:

created_date = DateField(auto_now_add=true)
# Automatically set to today's date on creation
# Never changes after initial creation

auto_now

Updates the date automatically every time the record is saved:

last_modified_date = DateField(auto_now=true)
# Set to today's date on every save operation
# Useful for tracking last update dates

Date Input Formats

The field accepts various input formats:

  • Julia Date: Date(2024, 7, 28)
  • DateTime: DateTime(2024, 7, 28, 10, 30) (time ignored)
  • String ISO: "2024-07-28"
  • String formats: Various date strings parseable by Julia
source
PormG.Models.DateTimeFieldMethod
DateTimeField(; kwargs...)

A field for storing date and time values with timezone information.

Keyword Arguments

  • verbose_name::Union{String, Nothing}: Human-readable name for the field. Default: nothing
  • unique::Bool: If true, ensures field values are unique across the table. Default: false
  • blank::Bool: If true, allows empty values in forms/validation. Default: false
  • null::Bool: If true, allows NULL values in the database. Default: false
  • db_index::Bool: If true, creates a database index for faster queries. Default: false
  • default::Union{DateTime, Nothing, String}: Default value for the field. Can be a DateTime object, ISO string, or nothing. Default: nothing
  • editable::Bool: If true, field can be edited in forms. Default: false
  • auto_now::Bool: If true, automatically updates to current datetime on every save. Default: false
  • auto_now_add::Bool: If true, automatically sets to current datetime when record is created. Default: false
  • type::String: The database column type. Can be either "TIMESTAMPTZ" (default) or "TIMESTAMP". Default: "TIMESTAMPTZ"

Important Note: TIMESTAMPTZ vs TIMESTAMP

By default, DateTimeField uses TIMESTAMPTZ.

  • TIMESTAMPTZ (Recommended): Stores values in UTC internally and converts them to your session's timezone upon retrieval. This ensures consistency across different geographical regions.
  • TIMESTAMP: Stores the exact date and time provided without any timezone conversion.

Examples

# Basic datetime field
created_at = DateTimeField()

# Auto-timestamp fields
created_at = DateTimeField(auto_now_add=true)
updated_at = DateTimeField(auto_now=true)

# Indexed datetime for queries
event_time = DateTimeField(db_index=true, verbose_name="Event Timestamp")

# With default value
scheduled_at = DateTimeField(default=DateTime(2024, 1, 1, 12, 0, 0))

# Optional datetime field
deadline = DateTimeField(null=true, blank=true)```
source
PormG.Models.DecimalFieldMethod
DecimalField(; kwargs...)

A field for storing decimal numbers with fixed precision and scale.

Keyword Arguments

  • verbose_name::Union{String, Nothing}: Human-readable name for the field. Default: nothing
  • unique::Bool: If true, ensures field values are unique across the table. Default: false
  • blank::Bool: If true, allows empty values in forms/validation. Default: false
  • null::Bool: If true, allows NULL values in the database. Default: false
  • db_index::Bool: If true, creates a database index for faster queries. Default: false
  • default::Union{Float64, Nothing}: Default value for the field. Default: nothing
  • editable::Bool: If true, field can be edited in forms. Default: false
  • max_digits::Int: Maximum number of digits allowed (including decimal places). Default: 10
  • decimal_places::Int: Number of decimal places to store. Default: 2

Examples

# Currency field (2 decimal places)
price = DecimalField(max_digits=10, decimal_places=2)

# High precision scientific values
measurement = DecimalField(max_digits=15, decimal_places=6)

# Percentage with 4 decimal places
rate = DecimalField(max_digits=7, decimal_places=4, default=0.0)

# Financial calculation field
amount = DecimalField(
    max_digits=12, 
    decimal_places=2, 
    verbose_name="Transaction Amount",
    db_index=true
)

# Optional decimal field
discount = DecimalField(
    max_digits=5, 
    decimal_places=2, 
    null=true, 
    blank=true
)
source
PormG.Models.EmailFieldMethod
EmailField(; kwargs...)

A field for storing and validating email addresses.

Keyword Arguments

  • verbose_name::Union{String, Nothing}: Human-readable name for the field. Default: nothing
  • unique::Bool: If true, ensures field values are unique across the table. Default: false
  • blank::Bool: If true, allows empty values in forms/validation. Default: false
  • null::Bool: If true, allows NULL values in the database. Default: false
  • db_index::Bool: If true, creates a database index for faster queries. Default: false
  • default::Union{String, Nothing}: Default email address. Default: nothing
  • editable::Bool: If true, field can be edited in forms. Default: false

Examples

# Basic email field
email = EmailField()

# Unique email for user accounts
user_email = EmailField(unique=true, verbose_name="User Email")

# Optional contact email
contact_email = EmailField(null=true, blank=true)

# Email with default value
notification_email = EmailField(default="admin@example.com")

# Indexed email for fast lookups
primary_email = EmailField(
    unique=true, 
    db_index=true, 
)
source
PormG.Models.FloatFieldMethod
FloatField(; kwargs...)

A field for storing floating-point numbers with double precision.

Keyword Arguments

  • verbose_name::Union{String, Nothing}: Human-readable name for the field. Default: nothing
  • unique::Bool: If true, ensures field values are unique across the table. Default: false
  • blank::Bool: If true, allows empty values in forms/validation. Default: false
  • null::Bool: If true, allows NULL values in the database. Default: false
  • db_index::Bool: If true, creates a database index for faster queries. Default: false
  • default::Union{Float64, String, Int64, Nothing}: Default value for the field. Default: nothing
  • editable::Bool: If true, field can be edited in forms. Default: false

Examples

# Basic float field
temperature = FloatField()

# Scientific measurement with default
ph_level = FloatField(default=7.0)

# Optional measurement
weight = FloatField(null=true)
source
PormG.Models.ForeignKeyMethod
ForeignKey(to::Union{String, PormGModel}; kwargs...)

A field that creates a many-to-one relationship to another model, similar to Django's ForeignKey.

The ForeignKey field represents a relationship where many records in the current model can reference a single record in the target model. It creates a foreign key constraint in the database and enables efficient querying of related data.

Required Arguments

  • to::Union{String, PormGModel}: The target model that this field references. Can be either:
    • A string with the model name (e.g., "User", "Category")
    • A direct reference to a PormGModel instance

Keyword Arguments

  • verbose_name::Union{String, Nothing} = nothing: A human-readable name for the field
  • primary_key::Bool = false: Whether this field is the primary key (rarely used with ForeignKey)
  • unique::Bool = false: Whether values must be unique (creates a one-to-one relationship if true)
  • blank::Bool = false: Whether the field can be left blank in forms
  • null::Bool = false: Whether the database column can store NULL values
  • db_index::Bool = true: Whether to create a database index on this field (recommended for performance)
  • default::Union{Int64, Nothing} = nothing: Default value for the field (ID of the referenced record)
  • editable::Bool = false: Whether the field should be editable in forms
  • pk_field::Union{String, Symbol, Nothing} = nothing: Which field in the target model to reference (defaults to primary key)
  • on_delete::Union{Function, String, Nothing} = nothing: Action when the referenced object is deleted
  • on_update::Union{String, Nothing} = nothing: Action when the referenced object's key is updated
  • deferrable::Bool = false: Whether the constraint check can be deferred until transaction commit
  • initially_deferred::Bool = false: Whether constraint checking is initially deferred
  • how::Union{String, Nothing} = nothing: Join type for queries ("INNER JOIN", "LEFT JOIN", etc.)
  • related_name::Union{String, Nothing} = nothing: Name for the reverse relation
  • db_constraint::Bool = true: Whether to create a database foreign key constraint

Database Mapping

  • PostgreSQL Type: BIGINT with foreign key constraint
  • Constraint: Creates FOREIGN KEY constraint linking to target table
  • Index: Automatically indexed for query performance

On Delete Options

The on_delete parameter controls what happens when the referenced object is deleted:

  • CASCADE: Delete this object when referenced object is deleted
  • RESTRICT: Prevent deletion of referenced object if this object exists
  • SET_NULL: Set this field to NULL (requires null=true)
  • SET_DEFAULT: Set this field to its default value (requires default to be set)
  • SET: Set this field to a specific value
  • PROTECT: Raise an error to prevent deletion
  • DO_NOTHING: Take no action (may cause database integrity errors)

Examples

Basic foreign key relationship:

Article = Models.Model(
    _id = IDField()
    title = CharField(max_length=200)
    author = ForeignKey("User")
    category = ForeignKey("Category", on_delete=CASCADE)
)

Foreign key allowing NULL values:

Product = Models.Model(
    _id = IDField()
    _id = IDField()
    name = CharField(max_length=100)
    category = ForeignKey("Category", null=true, blank=true, on_delete=SET_NULL)
)

Multiple foreign keys to same model (requires related_name):

Message = Models.Model(
    _id = IDField()
    sender = ForeignKey("User", related_name="sent_messages")
    recipient = ForeignKey("User", related_name="received_messages")
    content = TextField()
)

Related Names and Reverse Relations

  • If related_name is not specified, PormG automatically generates one
  • When multiple ForeignKeys point to the same model, related_name must be explicitly set
  • The related name allows querying from the target model back to this model
  • If you can't remember the related name, you can type your_query.objects.related_objects or your_model.related_objects to see all related names

Database Constraints

  • When db_constraint=true (default), creates actual foreign key constraints in PostgreSQL
  • When db_constraint=false, no database constraint is created (useful for legacy databases)
  • Database constraints ensure referential integrity but may impact performance

Validation

  • The to parameter must be a valid model name or PormGModel instance
  • All boolean parameters are validated for type safety
  • The on_delete parameter is validated against allowed values
  • Invalid parameters trigger warnings but don't cause errors

Notes

  • The field stores the primary key value of the referenced object
  • Uses BIGINT type to match IDField primary keys
  • Supports deferred constraint checking for complex transactions
  • Compatible with PostgreSQL's foreign key features

See Also

  • Django's ForeignKey documentation for conceptual understanding
source
PormG.Models.IDFieldMethod
IDField(; kwargs...)

A field type for auto-incrementing integer primary keys, equivalent to PostgreSQL's BIGSERIAL or GENERATED AS IDENTITY columns.

The IDField is typically used as the primary key for models and automatically generates unique integer values for each record. It maps to a PostgreSQL BIGINT column with auto-increment capabilities.

Keyword Arguments

  • verbose_name::Union{String, Nothing} = nothing: A human-readable name for the field
  • primary_key::Bool = true: Whether this field is the primary key for the table
  • auto_increment::Bool = true: Whether the field should auto-increment (generate values automatically)
  • unique::Bool = true: Whether values in this field must be unique across all records
  • blank::Bool = false: Whether the field can be left blank in forms (not applicable for ID fields)
  • null::Bool = false: Whether the database column can store NULL values
  • db_index::Bool = true: Whether to create a database index on this field
  • default::Union{Int64, Nothing} = nothing: Default value for the field (rarely used with auto-increment)
  • editable::Bool = false: Whether the field should be editable in forms (typically false for ID fields)
  • generated::Bool = true: Whether to use PostgreSQL's GENERATED AS IDENTITY feature
  • generated_always::Bool = false: Whether to use GENERATED ALWAYS AS IDENTITY (stricter than regular GENERATED)

Database Mapping

  • PostgreSQL Type: BIGINT with GENERATED AS IDENTITY or GENERATED ALWAYS AS IDENTITY
  • Auto-increment: Supported through PostgreSQL's identity columns
  • Index: Automatically indexed as primary key

Examples

Basic usage (most common):

User = Models.Model(
    _id::PormGField = IDField()
    name::PormGField = CharField(max_length=100)
    email::PormGField = EmailField()
)

Using GENERATED ALWAYS (stricter identity):

Order = Models.Model(
    _id::PormGField = IDField(generated_always=true)
    customer_id::PormGField = ForeignKey("Customer")
    order_date::PormGField = DateTimeField()
)

Notes

  • The IDField is designed to be the primary key and should typically be the first field in your model
  • Values are automatically generated by the database, so you don't need to provide them when creating records
  • The field uses BIGINT type to support large ranges of ID values
  • When generated_always=true, the database will reject any attempts to manually insert ID values
  • This field type is PostgreSQL-specific and optimized for PormG's PostgreSQL backend

Validation

  • All boolean parameters are validated to ensure type safety
  • The verbose_name must be a String or nothing
  • The default value, if provided, must be convertible to Int64
  • Invalid parameters will trigger warnings but won't cause errors (they'll be ignored)
source
PormG.Models.ImageFieldMethod
ImageField(; kwargs...)

A field for storing image file references and metadata.

Keyword Arguments

  • verbose_name::Union{String, Nothing}: Human-readable name for the field. Default: nothing
  • unique::Bool: If true, ensures field values are unique across the table. Default: false
  • blank::Bool: If true, allows empty values in forms/validation. Default: false
  • null::Bool: If true, allows NULL values in the database. Default: false
  • db_index::Bool: If true, creates a database index for faster queries. Default: false
  • default::Union{String, Nothing}: Default image path or URL. Default: nothing
  • editable::Bool: If true, field can be edited in forms. Default: false

Examples

# Basic image field
avatar = ImageField()

# Product image with default
product_image = ImageField(
    default="/static/images/default-product.jpg",
    verbose_name="Product Image"
)

# Optional profile picture
profile_pic = ImageField(null=true)

# Unique banner image
banner = ImageField(
    unique=true,
    db_index=true
)
source
PormG.Models.IntegerFieldMethod
IntegerField(; kwargs...)

A field for storing 32-bit signed integers, equivalent to PostgreSQL's INTEGER columns.

The IntegerField stores whole numbers within the 32-bit signed integer range (-2,147,483,648 to 2,147,483,647). It's ideal for counts, quantities, ratings, and other numeric data that doesn't require decimal places or extremely large values.

Keyword Arguments

  • verbose_name::Union{String, Nothing} = nothing: A human-readable name for the field
  • unique::Bool = false: Whether values in this field must be unique across all records
  • blank::Bool = false: Whether the field can be left blank in forms
  • null::Bool = false: Whether the database column can store NULL values
  • db_index::Bool = false: Whether to create a database index on this field
  • default::Union{Int64, Nothing} = nothing: Default value for the field
  • editable::Bool = false: Whether the field should be editable in forms

Examples

Basic integer field:

Product = Models.Model(
    _id = IDField(),
    name = CharField(max_length=200),
    quantity = IntegerField(default=0),
    price_cents = IntegerField()  # Store price in cents to avoid decimals
)

Integer field with constraints:

User = Models.Model(
    _id = IDField(),
    username = CharField(max_length=150, unique=true),
    age = IntegerField(null=true, blank=true),
    score = IntegerField(default=0, db_index=true)
)

Rating system:

Review = Models.Model(
    _id = IDField(),
    product = ForeignKey("Product"),
    rating = IntegerField(default=5),  # 1-5 star rating
    helpful_votes = IntegerField(default=0)
)

Validation and Constraints

  • Range: Automatically validates within INTEGER bounds
  • Type: Accepts integers, numeric strings (converted automatically)
  • Default: Must be an integer or convertible to integer
  • Null: When null=true, accepts NULL values

Migration Considerations

  • Range Changes: Changing to BigIntegerField is safe
  • Adding Constraints: Adding uniqueness or indexes is safe
  • Default Values: Can be added or modified safely
  • Null Constraints: Removing null constraint requires data validation
source
PormG.Models.Model_to_strMethod

Converts a model object to a string representation to create the model.

Arguments

Model_to_str(model::Union{Model_Type, PormGModel}; contants_julia::Vector{String}=reserved_words)::String
  • model::Union{Model_Type, PormGModel}: The model object to convert.
  • contants_julia::Vector{String}=reserved_words: A vector of reserved words in Julia.

Returns

  • String: The string representation of the model object.

Examples

users = Models.Model("users", 
  name = Models.CharField(), 
  email = Models.CharField(), 
  age = Models.IntegerField()
)
source
PormG.Models.OneToOneFieldMethod
OneToOneField(to::Union{String, PormGModel}; kwargs...)

A field that creates a one-to-one relationship to another model, similar to Django's OneToOneField.

The OneToOneField represents a strict one-to-one relationship where each record in the current model corresponds to exactly one record in the target model, and vice versa. It's essentially a ForeignKey with a unique constraint that ensures no two records can reference the same target record.

Required Arguments

  • to::Union{String, PormGModel}: The target model that this field references. Can be either:
    • A string with the model name (e.g., "UserProfile", "Settings")
    • A direct reference to a PormGModel instance

Keyword Arguments

  • verbose_name::Union{String, Nothing} = nothing: A human-readable name for the field
  • primary_key::Bool = false: Whether this field is the primary key (rarely used with OneToOneField)
  • unique::Bool = true: Whether values must be unique (always true for one-to-one relationships)
  • blank::Bool = false: Whether the field can be left blank in forms
  • null::Bool = false: Whether the database column can store NULL values
  • db_index::Bool = true: Whether to create a database index on this field (recommended for performance)
  • default::Union{Int64, Nothing} = nothing: Default value for the field (ID of the referenced record)
  • editable::Bool = false: Whether the field should be editable in forms
  • pk_field::Union{String, Symbol, Nothing} = nothing: Which field in the target model to reference (defaults to primary key)
  • on_delete::Union{Function, String, Nothing} = nothing: Action when the referenced object is deleted
  • on_update::Union{String, Nothing} = nothing: Action when the referenced object's key is updated
  • deferrable::Bool = false: Whether the constraint check can be deferred until transaction commit
  • initially_deferred::Bool = false: Whether constraint checking is initially deferred
  • how::Union{String, Nothing} = nothing: Join type for queries ("INNER JOIN", "LEFT JOIN", etc.)
  • related_name::Union{String, Nothing} = nothing: Name for the reverse relation
  • db_constraint::Bool = true: Whether to create a database foreign key constraint

Database Mapping

  • PostgreSQL Type: BIGINT with unique foreign key constraint
  • Constraint: Creates FOREIGN KEY constraint with UNIQUE constraint
  • Index: Automatically indexed for query performance and uniqueness enforcement

One-to-One Relationship Characteristics

  • Uniqueness: Each target record can only be referenced by one record in the current model
  • Bidirectional: The relationship can be traversed in both directions
  • Inheritance: Often used to extend models without modifying the original table
  • Profile Pattern: Commonly used for user profiles, settings, or detailed information tables

On Delete Options

The on_delete parameter controls what happens when the referenced object is deleted:

  • CASCADE: Delete this object when referenced object is deleted
  • RESTRICT: Prevent deletion of referenced object if this object exists
  • SET_NULL: Set this field to NULL (requires null=true)
  • SET_DEFAULT: Set this field to its default value (requires default to be set)
  • SET: Set this field to a specific value
  • PROTECT: Raise an error to prevent deletion
  • DO_NOTHING: Take no action (may cause database integrity errors)

Examples

Basic one-to-one relationship (User Profile pattern):

User = Models.Model(
    _id = IDField()
    username = CharField(max_length=150, unique=true)
    email = EmailField()
)

UserProfile = Models.Model(
    _id = IDField()
    user = OneToOneField("User", on_delete=CASCADE)
    bio = TextField(blank=true)
    avatar = ImageField(blank=true)
    birth_date = DateField(null=true, blank=true)
)

One-to-one with null values allowed:

Employee = Models.Model(
    _id = IDField()
    name = CharField(max_length=100)
    department = CharField(max_length=50)
)

EmployeeSettings = Models.Model(
    _id = IDField()
    employee = OneToOneField("Employee", null=true, blank=true, on_delete=SET_NULL)
    email_notifications = BooleanField(default=true)
    theme_preference = CharField(max_length=20, default="light")
)

Extending a model without modifying it:

Product = Models.Model(
    _id = IDField()
    name = CharField(max_length=200)
    price = DecimalField(max_digits=10, decimal_places=2)
)

ProductDetails = Models.Model(
    _id = IDField()
    product = OneToOneField("Product", on_delete=CASCADE, related_name="details")
    detailed_description = TextField()
    technical_specs = TextField()
    warranty_info = TextField()
)

Database Constraints vs. Unique ForeignKey

OneToOneField is equivalent to:

# These are functionally identical:
user = OneToOneField("User")
user = ForeignKey("User", unique=true)

However, OneToOneField is more explicit about the intended relationship type and provides better semantic meaning.

Validation

  • The to parameter must be a valid model name or PormGModel instance
  • All boolean parameters are validated for type safety
  • The on_delete parameter is validated against allowed values
  • Uniqueness is automatically enforced at the database level
  • Invalid parameters trigger warnings but don't cause errors

See Also

  • Django's OneToOneField documentation for conceptual understanding
  • Database normalization principles for when to use one-to-one relationships
source
PormG.Models.PasswordFieldMethod
PasswordField(; kwargs...)

A field for securely storing passwords using PBKDF2-SHA256 hashing (Django-compatible).

The PasswordField stores hashed passwords in a format compatible with Django's authentication system. Passwords are never stored in plain text - they are automatically hashed using PBKDF2-SHA256 with a randomly generated salt and configurable iterations.

Keyword Arguments

  • verbose_name::Union{String, Nothing} = nothing: A human-readable name for the field
  • blank::Bool = false: Whether the field can be left blank in forms
  • null::Bool = false: Whether the database column can store NULL values
  • editable::Bool = true: Whether the field should be editable in forms
  • max_length::Int = 128: Maximum length for stored hash (Django default)
  • auto_hash::Bool = true: Whether to automatically hash passwords on insert/update

Database Mapping

  • PostgreSQL Type: VARCHAR(128)
  • Storage Format: pbkdf2_sha256$iterations$salt$base64hash
  • Index: Not indexed by default (passwords shouldn't be queried)

Stored Format

The password is stored in Django-compatible format:

pbkdf2_sha256$720000$salt$base64encodedHash

Where:

  • pbkdf2_sha256: Algorithm identifier
  • 720000: Number of iterations
  • salt: Random 22-character salt
  • base64encodedHash: The derived key in base64

Examples

Basic password field:

# Define a User model with password
User = Models.Model(
    _id = Models.IDField(),
    username = Models.CharField(max_length=150, unique=true),
    email = Models.EmailField(unique=true),
    password = Models.PasswordField()
)

Creating a user with hashed password:

import PormG.Models: make_password, check_password

# Hash the password before storing
hashed = make_password("securePassword123!")

query = M.User |> object
query.bulk_insert(
    username = "ayrton_senna",
    email = "senna@mclaren.com",
    password = hashed
)

Verifying a password during login:

import PormG.Models: check_password

# Fetch user from database
user_query = M.User |> object
user_query.filter("username" => "ayrton_senna")
users = user_query |> list

if !isempty(users)
    user = users[1]
    # Verify the password
    if check_password("securePassword123!", user[:password])
        println("Login successful!")
    else
        println("Invalid password")
    end
end

Related Functions

  • make_password(raw): Hash a plain text password
  • check_password(raw, encoded): Verify a password against stored hash
  • password_needs_upgrade(encoded): Check if hash needs re-hashing

Security Notes

  • Never store plain text passwords - always use make_password()
  • The default 720000 iterations provides strong security (Django 4.2+ default)
  • Salts are automatically generated per-password
  • Use check_password() for verification (includes timing attack protection)
  • Consider implementing password upgrade on login if using older hashes

Migration from Django

If you're migrating from a Django application, password hashes are fully compatible. Users can continue to log in without any password reset.

See Also

  • CharField for generic string storage
  • Django's password management documentation
source
PormG.Models.TextFieldMethod
TextField(; kwargs...)

A field for storing large amounts of text without length restrictions.

Keyword Arguments

  • verbose_name::Union{String, Nothing}: Human-readable name for the field. Default: nothing
  • unique::Bool: If true, ensures field values are unique across the table. Default: false
  • blank::Bool: If true, allows empty values in forms/validation. Default: false
  • null::Bool: If true, allows NULL values in the database. Default: false
  • db_index::Bool: If true, creates a database index for faster queries. Default: false
  • default::Union{String, Nothing}: Default text content. Default: nothing
  • editable::Bool: If true, field can be edited in forms. Default: false

Examples

# Basic text field for long content
description = TextField()

# Blog post content
content = TextField(blank=true)

# Optional notes field
notes = TextField(null=true, blank=true)

# Indexed text field for search
searchable_content = TextField(
    db_index=true
)

# Text field with default content
template = TextField(
    default="Enter your text here...",
    verbose_name="Template Content"
)
source
PormG.Models.ensure_model_initializedMethod
ensure_model_initialized(model::PormGModel)

Checks if a model has been initialized (i.e., has a connect_key that exists in config). If not, attempts self-healing by:

  1. Remapping stale path-based keys to current session alias keys
  2. Re-registering via REGISTERED_MODULES
  3. Scanning loaded modules for pormginitpath markers
  4. Using the model's own _module reference (survives precompilation)
source
PormG.Models.get_all_modelsMethod

Returns a vector containing all the models defined in the given module.

Arguments

get_all_models(modules::Module; symbol::Bool=false)::Vector{Union{Symbol, PormGModel}}
  • modules::Module: The module to search for models.
  • symbol::Bool=false: If true, returns the model names as symbols. If false, returns the model instances.

Returns

A vector containing all the models defined in the module.

source
PormG.Models.validate_defaultMethod

validatedefault(default, expectedtype::Type, field_name::String, converter::Function)

Validate the default value for a field based on the expected type.

Arguments

  • default: The default value to be validated.
  • expected_type::Type: The expected type for the default value.
  • field_name::String: The name of the field being validated.
  • converter::Function: A function used to convert the default value if it is not of the expected type.

Returns

  • If the default value is of the expected type, it is returned as is.
  • If the default value can be converted to the expected type using the provided converter function, the converted value is returned.
  • If the default value is neither of the expected type nor convertible to it, an ArgumentError is thrown.
source