Constructions lets someone design a schema in the browser, compile it to dialect-specific DDL and apply it. It is the only path in Qrly that changes the shape of a customer database — and it is gated by a three-tier cascade in which every tier defaults to off, on top of a full data-access requirement, with every applied statement recorded verbatim.
If a BI tool asked you for DDL rights, your first instinct would be no. That instinct is correct, and this page is written for it.
A Construction is not a script. It is a document describing schemas and tables, which the DDL generator turns into statements for the target dialect.
Planning a Construction produces the exact ordered list of statements Qrly intends to execute, rendered as a runnable script, together with warnings about anything the target dialect will not do — for example that Snowflake has no CREATE INDEX.
Crucially, preview needs no DDL permission at all. Anyone allowed to design can see precisely what would be applied. That is the right split: reading a plan is not dangerous, and making people ask for write rights in order to review a change is how reviews stop happening.
Statements are emitted in a fixed order: schemas first, then any opted-in drops, then tables, then indexes, then foreign keys. Deferring the foreign keys to the end is what allows two tables that reference each other to be created at all — neither has to exist before the other.
SQLite cannot add foreign keys after the fact, so it inlines them, and the plan says so with a warning rather than failing halfway through.
Statements run individually in auto-commit. This is deliberate: on most engines DDL commits implicitly, so wrapping a batch in a transaction would promise a rollback that cannot happen. Qrly declines to make that promise.
Execution stops at the first failure. Nothing after the failing statement is attempted, so a broken plan leaves a partially built schema you can inspect rather than an unpredictable one it kept pushing through.
Each run records the verbatim SQL, the total number of statements and the number actually run, status, error, duration and who triggered it. Constructions carry a status of DRAFT, APPLIED or ERROR; runs carry RUNNING, SUCCESS or ERROR.
An apply-history table shows when each attempt happened, its status, its statements and its detail. When something is wrong in the database at nine on a Monday, the answer to "what did this tool actually execute" is one page away, exact, and not reconstructed from logs.
DDL is not a role you hold. It is a property of the tenant, the organisation and the connection — all three of which must agree, before permissions are even consulted.
Each of the three ddl_enabled flags defaults to off. A freshly installed Qrly cannot execute DDL anywhere, against any connection, for anyone — including administrators. Turning it on is a series of explicit decisions taken at three different levels of the hierarchy, each by someone with authority at that level.
Two ways to arrive at a design document without drawing every column by hand — both of which end at the same generator and the same preview.
Point the importer at existing DDL and it reconstructs a design document from it. Dialect-specific type spellings are folded into the portable logical types, so an imported Postgres schema can be previewed against SQL Server without hand-editing every column.
The warnings are the important part. A tool that quietly discards your check constraints and partitioning while reporting success has told you a comfortable lie; Qrly lists what it could not represent so you know what the design does not carry.
The AI assistant returns a whole design document. It does not return statements, and there is no path by which its output reaches the database as text. The proposal is rebuilt field by field through the same DDL generator that compiles a hand-authored design.
That rebuild is the trust boundary. Model output is treated as structured data to be validated against the same rules as human input — the identifier regex, the default-expression allow-list, the referential-action allow-list — rather than as instructions to be run.
An AI-proposed design is capped at 60 tables, and at 200 columns, indexes and foreign keys per table. A model asked for "a data warehouse" cannot return something arbitrarily large that somebody then applies without reading it.
And it arrives as a draft, subject to the same preview and the same cascade as anything else. Nothing about the AI path shortens the route to execution.
Identifiers must match an identifier regex. Column defaults are restricted to NULL, TRUE, FALSE, CURRENT_TIMESTAMP, CURRENT_DATE, CURRENT_TIME, NOW(), a numeric literal or a simple quoted string. Referential actions are restricted to the five standard actions.
The point of an allow-list rather than an escaping routine is that it fails closed. An unrecognised default expression is rejected, not escaped and hoped for — and there is no field anywhere on the path where free-form SQL text is carried through to the target.
No. You cannot type arbitrary DDL and have Qrly run it. You build a structured design document — schemas, tables, columns with portable logical types, indexes and foreign keys — and Qrly compiles that document into dialect-specific statements. Everything that reaches the database has been generated by the DDL generator from validated fields.
Constructions is also the only path in the product that changes the shape of a customer database: elsewhere the connection pool hands out read-only connections, native SQL passes the sanitizer and every parameter is bound.
Four things, all of them. The tenant must have ddl_enabled, the organisation must have ddl_enabled and the connection must have ddl_enabled — all three default to off — and the caller must hold FULL data access on the target connection.
The policy service reports the outermost blocking tier, so an administrator is told which level to fix rather than guessing, and a policy-blocked banner appears in the UI when DDL is disabled.
No, and Qrly does not pretend otherwise. Statements run one at a time in auto-commit, because DDL commits implicitly on most engines and wrapping it in a transaction would be a false promise.
Execution stops at the first failure, and the run records the verbatim SQL, statements total and statements run, status, error, duration and who triggered it — so you know exactly how far it got and exactly what reached the database.
Yes. The SQL importer reads existing DDL back into a design document: CREATE SCHEMA, CREATE TABLE with inline and table-level primary key, unique and foreign key constraints, CREATE [UNIQUE] INDEX, and ALTER TABLE … ADD FOREIGN KEY.
It folds dialect spellings such as SERIAL, IDENTITY, AUTO_INCREMENT, VARCHAR2, NVARCHAR and NUMBER into portable logical types, and warns on features the design document cannot express — check constraints, partitioning, storage clauses, triggers and generated columns. It caps at 200 tables and 2,000,000 characters.
No. The assistant proposes a whole design document, never SQL. That proposal is rebuilt field by field through the same DDL generator that compiles a hand-authored design, which is the trust boundary: model output is treated as structured data to be validated, not as statements to be executed.
It is capped at 60 tables and 200 columns, indexes and foreign keys per table, and the result is still a draft you preview before applying.
Three allow-lists. Identifiers must match an identifier regex. Column default expressions are restricted to an allow-list — NULL, TRUE, FALSE, CURRENT_TIMESTAMP, CURRENT_DATE, CURRENT_TIME, NOW(), a numeric literal or a simple quoted string. Referential actions are restricted to CASCADE, SET NULL, SET DEFAULT, RESTRICT and NO ACTION.
Anything outside those sets is rejected before compilation, so there is no free-text field on the path to the database.
Default off at three levels, full data access required, every statement previewed and every run recorded verbatim.