Search docs.molo17.com

    Query entities

    A Query entity is an entity whose source is a SQL query. Gluesync writes one document for each root key of the result, with the columns of the query as its fields, and keeps the documents up to date as the tables the query reads change. A model with child levels builds nested documents: an order with its lines inside it.

    Available from Gluesync 2.3.2. For the overview of data modeling and of the reverse direction, see Data modeling.

    What you need

    Item Requirement

    Source agent

    The MSSQL CDC agent (SQL Server with Change Data Capture). The MSSQL Change Tracking agent and the other SQL agents do not run Query entities. An agent that does not run them lists no Query entity type, and Gluesync refuses the entity with UNSUPPORTED_BY_CONNECTOR.

    Target agent

    Couchbase, for flat and for nested documents. SQL Server, for flat rows. Other targets that write documents or tables receive a flat result, but only these two are tested. A model with child levels needs a target that keeps nested values, which today is Couchbase (TARGET_CANNOT_HOLD_NESTED otherwise).

    SQL Server

    Change Data Capture enabled on the database and on every table the query reads, and SQL Server Agent running, because its capture job fills the change tables. Gluesync enables CDC by itself when Enable automatic Change Data Capture / Change Tracking activation is on and its login is allowed to. Otherwise describe shows the statement to run.

    Read isolation

    SNAPSHOT isolation allowed on the source database is recommended: Gluesync then reads each document from one consistent state.

    Source login

    SELECT on the tables the query reads and on their change tables, and VIEW DEFINITION on the functions and views it calls. A function or view whose definition the login cannot see counts as not deterministic and is refused.

    Role

    A role that can create entities (Super Admin or Manager). Describe and preview also go through the data access policies of Query Studio: a table a policy hides cannot be read here either.

    Rules every query follows

    Each level is one read-only SELECT. Gluesync analyses it before anything runs and refuses a model that breaks one of these rules, in every mode, snapshot-only included.

    • One statement, listed columns. A single SELECT, with an explicit column list and a label (an alias) for every expression. A SELECT *, a statement with INTO, several statements, a WITH common table expression, APPLY, an OPTION clause, a locking or isolation hint and a remote source (OPENQUERY, a four-part name) are refused.

    • No top-level ORDER BY. The order of an array is declared on the level (orderBy), and the database applies it.

    • Deterministic. The result must depend on the data only. The current date or time, random values, session values, and functions or views SQL Server does not declare deterministic are refused (NON_DETERMINISTIC_QUERY), and so is a row limit without a total order. Apply a time filter in the application that reads the documents, or through a flag or date column that you maintain in the source.

    • Plain keys. Every key column and every parent link is a plain column of the table the level’s root key comes from, never an expression (KEY_NOT_PLAIN_COLUMN).

    • Sibling levels are separate queries. Each child level is its own statement, so two arrays never multiply each other.

    Levels, keys and cardinality

    A model is a root level plus child levels. Each child sits one step below the root: documents built from SQL Server go as deep as the root and its child levels, and any number of sibling child levels is allowed. A level below a child level is refused with DEPTH_EXCEEDED.

    Setting Meaning

    name

    Unique name of the level, letters, digits and _. The root is called root unless you choose another name.

    source

    The statement of the level: { "type": "Sql", "query": "SELECT …​" }.

    key

    The labels of the full key of the level. For the root it is the root key, which names the document. For a child it is the labels of the parent link followed by the item key.

    parentLink

    For a child, the pairs childColumn and parentColumn that link the child to the key of its parent. They cover the whole key of the parent. The child statement must project them, so every level carries the root key.

    path

    For a child, the name of the field that holds the level in the parent document.

    cardinality

    MANY is an array of items. ONE is an object, with at most one row per parent: more than one is a data error (ONE_LEVEL_MULTIPLE_ROWS). The root ignores it.

    orderBy

    The order of the items of an array, as columns and a direction. Without it the items are ordered by their item key.

    emptyArray

    What a child with no rows becomes: EMPTY (the default) writes [], OMIT leaves the field out. A level can override the model option.

    Every column of a level’s statement becomes a field of its item, the key columns included. Within a level, identical rows with the same key collapse into one item. Different rows with the same key are a data error (KEY_NOT_UNIQUE).

    Example: an order with its lines and its shipment

    -- root: one document per order
    SELECT o.ORDER_ID, o.ORDER_NO, c.NAME AS CUSTOMER_NAME
    FROM dbo.ORDERS o
    INNER JOIN dbo.CUSTOMERS c ON c.CUSTOMER_ID = o.CUSTOMER_ID
    
    -- level "lines", MANY, ordered by LINE_NO
    SELECT l.ORDER_ID, l.LINE_NO, l.SKU, l.QTY, l.UNIT_PRICE
    FROM dbo.ORDER_LINES l
    
    -- level "shipment", ONE
    SELECT s.ORDER_ID, s.CARRIER, s.TRACKING_NO
    FROM dbo.SHIPMENTS s

    With the root key ORDER_ID, the item key LINE_NO for the lines, and ORDER_ID as the parent link of both child levels, the document of order 5001 is:

    {
      "ORDER_ID": 5001,
      "ORDER_NO": "SO-5001",
      "CUSTOMER_NAME": "Anna Rossi",
      "lines": [
        { "ORDER_ID": 5001, "LINE_NO": 1, "SKU": "KB-100", "QTY": 2, "UNIT_PRICE": 24.9 },
        { "ORDER_ID": 5001, "LINE_NO": 2, "SKU": "MS-200", "QTY": 1, "UNIT_PRICE": 12.5 }
      ],
      "shipment": { "ORDER_ID": 5001, "CARRIER": "DHL", "TRACKING_NO": "TRK-77120" }
    }

    Create a Query entity in the Control Plane

    The wizard builds a Query entity with a single level, so flat documents or rows. For child levels, use the REST API or the MCP server.

    1. Open the pipeline and, in the entity toolbar, open + Entities and choose From SQL query. The item shows up only when the source agent runs Query entities.

    2. SQL query. Give the entity a name and write the statement. The source agent is shown by its logo, with its name in the tooltip, next to the editor. Select Describe (Ctrl+Enter). Describe reads the catalog of the source and does not run the statement. It fills three tabs: the typed result columns with their provenance and a flag for personal data, the tables the statement reads, and the issues, each with its code and hint. Errors are listed first and block the next step.

      SQL query step of the Query entity wizard with the ORDERS_VIEW statement and its two joins in the editor and the feasibility panel showing CDC supported
    3. Key & tables. Pick the root key among the plain columns of the root table. If you pick none, describe proposes the primary key of the first table. Select Check uniqueness to have the source confirm that the key identifies one row. Every table the statement reads is tracked by default. Switch a lookup to untracked when its changes need not rewrite the documents (see Tracked and untracked tables).

      Key and tables step of the Query entity wizard with ORDER_ID proposed as the root key and the columns of the joined tables disabled
    4. Feasibility. The verdict is one of three. CDC supported: changes of every tracked table reach the documents. Snapshot only: the statement cannot follow its changes, and the reasons are listed. Rejected: errors block the entity in every mode. For a snapshot-only verdict you choose to run snapshot-only, to mark the blocking tables untracked and keep CDC, or to fix the statement and describe again.

    5. Target mapping. Choose the target collection or table. Map the result columns to its fields, or select Auto-map by name. For a document target, the Document key card sets the custom document key, as in Custom document keys, and the value rendering of the key values when the target supports it. It shows an example id after a preview. Use Run preview to see up to 50 documents as the snapshot would write them, as a table or as JSON. Give root keys, one per line, to look at specific documents, or leave the box empty to see the first rows.

      Target mapping step of the Query entity wizard with arrows from the query result columns to the fields of a Couchbase collection and the preview panel showing the first document as JSON
    6. Sync mode. Choose CDC + initial snapshot or Snapshot only. CDC is offered only when the agent supports it and the verdict allows it.

    7. Review & save. Check the summary, pick the group, and select Save entity. Gluesync validates the entity first and saves nothing if validation finds errors.

      Review and save step of the Query entity wizard with the summary of every choice and the Save entity button

    To change an entity later, open it and choose Edit Query entity. A change of the statement, the key or the tracked tables may ask for a resync: saving does not rebuild the documents already written.

    Create a Query entity with the REST API

    The calls below are the ones the wizard makes. They need the permission to create entities, and a Bearer token as in Core Hub REST API.

    Step Request Answer

    Describe

    POST /pipelines/{pipelineId}/agents/{agentId}/discovery/data-model

    The model with typed columns and proposed keys, the tables read with their capture state, the verdict (CDC, or SNAPSHOT_ONLY with its reasons) and every issue.

    Preview

    POST /pipelines/{pipelineId}/agents/{agentId}/discovery/data-model/preview

    Up to 50 documents as the snapshot would write them, with their ids.

    Validate

    POST /pipelines/{pipelineId}/config/entities/validate

    The issues of the entity, against the model, the source and the target. Nothing is saved.

    Save

    PUT /pipelines/{pipelineId}/config/entities

    The entity saved, or 400 with every issue that refuses it.

    Start

    POST /pipelines/{pipelineId}/commands/sync/start?entity={entityId}&withSnapshot=true

    The first snapshot, then CDC. A snapshot-only entity is refreshed with .../commands/sync/one-time-snapshot?entity={entityId}.

    Describe

    The request holds the model and two optional settings. The level columns can stay empty: describe fills them.

    {
      "model": {
        "root": {
          "name": "root",
          "columns": [],
          "key": ["ORDER_ID"],
          "source": {
            "type": "Sql",
            "query": "SELECT o.ORDER_ID, o.ORDER_NO, c.NAME AS CUSTOMER_NAME FROM dbo.ORDERS o INNER JOIN dbo.CUSTOMERS c ON c.CUSTOMER_ID = o.CUSTOMER_ID"
          },
          "children": [
            {
              "name": "lines",
              "path": "lines",
              "cardinality": "MANY",
              "columns": [],
              "key": ["ORDER_ID", "LINE_NO"],
              "parentLink": [{ "childColumn": "ORDER_ID", "parentColumn": "ORDER_ID" }],
              "orderBy": [{ "column": "LINE_NO" }],
              "source": {
                "type": "Sql",
                "query": "SELECT l.ORDER_ID, l.LINE_NO, l.SKU, l.QTY, l.UNIT_PRICE FROM dbo.ORDER_LINES l"
              }
            },
            {
              "name": "shipment",
              "path": "shipment",
              "cardinality": "ONE",
              "columns": [],
              "key": ["ORDER_ID"],
              "parentLink": [{ "childColumn": "ORDER_ID", "parentColumn": "ORDER_ID" }],
              "source": {
                "type": "Sql",
                "query": "SELECT s.ORDER_ID, s.CARRIER, s.TRACKING_NO FROM dbo.SHIPMENTS s"
              }
            }
          ]
        },
        "options": { "emptyArray": "OMIT" }
      },
      "checkKeyUniqueness": true,
      "untrackedTables": []
    }

    checkKeyUniqueness runs a bounded check that each level’s key is unique. untrackedTables lists tables as schema.table that you mark untracked. Leave key empty on the root to get the primary key of the first table proposed.

    Describe never runs the statement. The source agent asks SQL Server for the result columns of each level. A statement that is not a single read-only SELECT never reaches the database: describe answers 200 with the structure issues. A SQL error answers 400 with the driver message, the SQLState and the vendor code.

    Preview

    Send the entity (source Query and, to see document ids, the target side) and optionally the root keys and a limit.

    {
      "entity": { "entityName": "ORDERS_DOC", "agentEntities": [ "..." ] },
      "rootKeys": [["5001"], ["9999"]],
      "limit": 10
    }

    The answer holds documents (the root key, the document id, the body, its size in bytes and the list of masked paths), missingRootKeys (keys that no root matched) and failures (the roots that would be skipped, or that would stop the entity, with their issue code). Without rootKeys you get the first limit roots in root-key order, at most 50. Values of columns that hold personal data are masked as in Query Studio, and a masked root key comes back as sha256: followed by 12 hexadecimal characters. Through MCP the values are always masked.

    Save

    A payload for PUT /pipelines/{pipelineId}/config/entities carries two sides in agentEntities: the source Query entity and the target entity (a NoSqlEntity for Couchbase, a SingleTable for SQL Server) with its columnsMappingMatrix. The numeric ids in it are not random: a label’s id, the id of a level’s result view and the id of a collection or a table come from a hash of their names, so a client can compute them before it calls anything.

    Id of Hash of the text

    A column or a field label

    The label, for example ORDER_ID

    The result view of a level, the source side of the mapping

    #gs_model.<level name>, for example #gs_model.root

    A Couchbase collection

    <scope>.<collection>

    A SQL Server table

    <schema>.<table>

    The id is the first 8 bytes of the SHA-256 digest of the text, read as a signed big-endian 64-bit integer. These values exceed 253: build the payload with a tool that keeps 64-bit integers. The easiest way to get a complete payload is the MCP tool draft_data_model_entity, which builds it from a described model and types the target columns in the target agent’s own types. Each child level of a model becomes one array or object field of the target: the target column is typed array or object, and mapped from the container column of the level.

    {
      "entities": [
        {
          "entityName": "ORDERS_DOC",
          "agentEntities": [
            {
              "type": "Query",
              "entityName": "ORDERS_DOC",
              "agentId": "<source agent id>",
              "entityType": { "type": "Source", "snapshotOnly": false },
              "model": { "root": { "...": "the model that describe returned" } }
            },
            {
              "type": "NoSqlEntity",
              "entityName": "ORDERS_DOC",
              "agentId": "<Couchbase agent id>",
              "entityType": { "type": "Target", "insertConflictStrategy": "UPSERT", "columnsMappingMatrix": [ "..." ] },
              "entityObject": { "id": 0, "scope": "sales", "collection": "orders" },
              "keyMapping": { "prefix": "ORDER", "suffix": "", "separator": "::", "keys": [ 0 ], "valueRendering": "TRIMMED" },
              "columns": [ "..." ]
            }
          ]
        }
      ]
    }

    The id fields shown as 0 stand for the hashed ids described above. Validation returns {"valid": true, "issues": […​]}. On a refusal, save answers 400 with notificationId and the list of issues. When the source agent cannot be reached at save time, the entity is saved with the warning DESCRIBE_UNAVAILABLE, and the catalog checks run at the next describe and at every setup of the agent.

    To update an entity, send the same payload with the entityId and the agentEntityId of each side from GET /pipelines/{pipelineId}/entities. A blank agentEntityId adds a second agent entity instead of replacing the first.

    Create a Query entity with MCP

    The same flow is available as tools of the MCP server, so an AI Studio agent or any MCP client can design and check a Query entity. The tools take snake case arguments and a personal API token.

    Step Tool What it does

    Describe

    describe_data_model

    As the REST describe. Arguments: pipeline_id, agent_id, model, check_key_uniqueness, untracked_tables.

    Draft

    draft_data_model_entity

    Builds the complete entity payload from a described model: the source Query, the target table (target_schema, target_table) or collection (target_scope, target_collection, document_id_prefix), the typed target columns and the mapping. snapshot_only is true unless you pass false. Nothing is written.

    Preview

    preview_data_model

    As the REST preview, always masked. Arguments: pipeline_id, agent_id, entity, root_keys, limit.

    Validate and save

    validate_entities, upsert_entities

    The generic entity tools, with the drafted entity.

    Run

    start_sync, one_time_snapshot, redo_sync, stop_sync

    The usual sync commands.

    Describe, preview and validate

    Three checks tell you what Gluesync will do before it does anything.

    • Describe returns the typed columns of each level, the proposed key, the base tables the model reads with their keys and capture state, how each table takes part (root key source, lookup, filter, subquery), the SQL constructs found, the effective read consistency, the verdict and the issues. When an issue can be cured by rewriting the statement, for example by dropping a top-level ORDER BY, the level carries the rewritten statement as suggestedSql, and the wizard offers it as Apply suggestion.

    • Preview assembles real documents, with the ids the target would give them, without writing.

    • Validate checks the whole entity, including the match between the model and the target, and reports every issue at once.

    The verdict

    The verdict says how the entity can run.

    Verdict Meaning

    CDC

    Each change of a tracked table finds the documents it touches through the joins of the model, reads them again from the source and writes them whole. Before and after values both count, so a row that moves from one document to another refreshes both.

    SNAPSHOT_ONLY

    The model can only be refreshed by a snapshot, started by hand or on a schedule (see Schedule jobs). Each reason has a code. Typical reasons: a set operation (UNION), a row limit, a full outer join, a derived table, a table with no change capture or with no primary key, a view, a table of another database, a user function, a join that is not a plain column equality, or a source connection on a readable secondary replica.

    Not assessed

    A statement with structure errors never reaches the database, so no catalog check ran. The errors refuse the model in every mode.

    A CDC entity whose verdict is SNAPSHOT_ONLY is refused, and its reasons become errors. A snapshot-only entity keeps the reasons as warnings.

    At every setup of the source agent each Query entity is described again. If a CDC entity can no longer follow its changes, because capture was disabled or a capture instance was recreated without a column the model reads, its sync does not start (MODEL_NO_LONGER_DERIVABLE) and a notification names the cause. The other entities of the agent are not affected.

    Tracked and untracked tables

    Every base table a model reads is tracked by default: its changes decide which documents are read again. You can mark a table untracked, for a lookup that rarely changes or that has no change capture. An untracked table is still read, but a change in it alone rewrites nothing. The change reaches a document with the next change of a tracked table that touches it, or with the next snapshot (warning UNTRACKED_TABLE_DRIFT). A scheduled reconcile sweep, described below, repairs the drift.

    How a Query entity runs

    Snapshot and CDC

    The snapshot reads the roots in pages ordered by the root key and, for each page, the children of those roots. CDC then reads the SQL Server change tables of every tracked table in windows and applies the changes after the position the snapshot started from.

    • A window reads at most 50,000 changes and never ends inside a source transaction. A larger transaction is read alone.

    • An update of a column the model never reads writes nothing.

    • A change of a root key deletes the old document and writes the new one.

    • A document whose root row left the result is deleted.

    • A window that touches more than 200,000 documents reads them in pages, logs a warning and raises a DATA_MODEL_FANOUT_LARGE notification.

    • A crash or a restart in the middle of a window replays the whole window. It writes the same documents again, and the Couchbase target does not rewrite a document whose stored body is already equal.

    Safeguards

    Situation What Gluesync does

    The change history was cleaned up before Gluesync read it

    The entity stops with RETENTION_EXCEEDED_RESYNC_REQUIRED and needs a resync. SQL Server keeps changes for 3 days by default. Keep the retention longer than the longest time the entity may stay stopped. Drop an old capture instance only after the entity’s position has passed it.

    A truncate of a tracked table, or one source transaction with more than 1,000,000 change rows

    The entity stops with REBUILD_REQUIRED until a resync. A reconcile sweep can repair it where a sweep can run.

    A window would delete more documents than maxDeletesPerWindow (10,000 by default)

    Nothing of the window is deleted, and the entity stops with DATA_MODEL_MASS_DELETE_HELD and retries. A reload upstream passes once the reload commits. For a genuine mass delete, raise the limit or set 0 to switch the guard off, then restart the entity. This is an option change, so no resync is needed.

    A root cannot be built as one document

    A data error of that root: KEY_NOT_UNIQUE, ROOT_ID_COLLISION, ONE_LEVEL_MULTIPLE_ROWS or AGGREGATE_TOO_LARGE. The write strategy of the target entity decides: FAIL stops the entity, SKIP and UPSERT skip the root and raise DATA_MODEL_ROOTS_SKIPPED, at most once per snapshot page or window.

    A root key holds NULL

    No document is written for that root.

    Options of a model

    The options sit next to the root in model.options. Changing an option only restarts the entity.

    Option Default Meaning

    readConsistency

    SNAPSHOT_IF_AVAILABLE

    The isolation of the reads: SNAPSHOT_IF_AVAILABLE uses SNAPSHOT, else read committed snapshot if on, else locking read committed. REQUIRE_SNAPSHOT fails the reads when the database does not allow SNAPSHOT isolation. READ_COMMITTED reads committed data.

    queryTimeoutSeconds

    300

    The timeout of every statement. Describe and preview cap it at 120 seconds.

    maxDeletesPerWindow

    10,000

    The mass-delete guard. 0 switches it off.

    maxItemsPerLevel

    10,000

    The most items one child level may hold in one document.

    maxDocumentBytes

    none

    A document above this estimated size is a data error (AGGREGATE_TOO_LARGE). When empty, only the limit of the target applies.

    emptyArray

    EMPTY

    EMPTY or OMIT, as above.

    reconcileEveryMinutes

    none

    Schedules a reconcile sweep every so many minutes.

    Targets

    Couchbase

    The id of a document is the keyMapping of the target entity: the prefix, the values of the root key in the order of keys, the suffix, joined with the separator (::, -, _, / or none). valueRendering says how a key value becomes text.

    Value rendering Result

    TRIMMED (default)

    The text of the value, trimmed. A NULL is an empty component.

    GS1

    The id Gluesync 1.x gave the same row: strings trimmed, a decimal with no fractional part written as an integer, a NULL as the text null.

    GS1_DROP_NULLS

    As GS1, with a NULL component left out, as Gluesync 1.x did for configured key mappings.

    The GS1 renderings are accepted by the Couchbase target only, and refused (GS1_ID_KEY_TYPE_NOT_SUPPORTED) for a key from a date-time, time or binary column, where the ids could not be the same. A nullable key column under a GS1 rendering raises the warning ROOT_KEY_NULLABLE.

    Two entities that write one collection need distinct, non-empty prefixes (DOCUMENT_KEYSPACE_SHARED). A Query entity’s collection must not be read back by a Couchbase source entity (BIDIRECTIONAL_NOT_SUPPORTED).

    The Couchbase target neither truncates nor deletes on a snapshot. The documents of roots that left the result stay after a snapshot-only refresh or a resync, and a snapshot-only entity warns about it (TARGET_KEEPS_REMOVED_DOCUMENTS). A reconcile sweep removes them, as described next.

    SQL Server

    A Query entity writes flat rows to a SQL Server table, with the root key as its primary key. The table is emptied when a snapshot starts, so a scheduled snapshot leaves it empty while it re-runs. Child levels need a target that keeps nested values and are refused here.

    Reconcile sweep

    A reconcile sweep repairs a target that drifted from its source. It has two passes: TARGET_IDS lists the document ids under the entity’s prefix and deletes every document that no live root renders, and SOURCE_MEMBERS reads the roots of the query and writes each one again. FULL runs both.

    # Dry run: reports what would be written and deleted
    curl -X POST "https://your-gluesync.com/pipelines/$PIPELINE/commands/sync/reconcile?entityId=$ENTITY&mode=TARGET_IDS&dryRun=true" \
      -H "Authorization: Bearer <your-token>"
    
    # Where the sweep stands: RUNNING, COMPLETED, HELD, INTERRUPTED or NONE
    curl "https://your-gluesync.com/pipelines/$PIPELINE/commands/sync/reconcile?entityId=$ENTITY" \
      -H "Authorization: Bearer <your-token>"

    The MCP tool is reconcile_sync, a dry run unless dry_run is false.

    • TARGET_IDS needs a target that can list its document ids, which Couchbase does with an index on META().id of the collection. Without one, the sweep is refused with RECONCILE_INDEX_MISSING and the exact CREATE INDEX statement to run. A primary index also works. It also needs a keyMapping whose keys come from root-key labels, so that an id decomposes into a root key.

    • A sweep also runs after a completed snapshot on a target that does not delete on snapshot, on the schedule reconcileEveryMinutes, and as an escalation after REBUILD_REQUIRED. Those sweeps obey maxDeletesPerWindow: a page that would exceed it deletes nothing and the sweep ends HELD. A sweep you start yourself is not guarded, so run a dry run first.

    • A sweep lives in the memory of Core Hub. After a restart a started sweep reads INTERRUPTED.

    Issue codes

    Every issue has a stable code, a message and a hint. Treat the code as an open text: new codes are added, none is renamed.

    Group Effect and main codes

    Structure

    Errors: the save is refused in every mode. PARSE_ERROR, NOT_A_SELECT, MULTIPLE_STATEMENTS, STAR_PROJECTION, DUPLICATE_LABEL, AMBIGUOUS_COLUMN, UNKNOWN_ALIAS, EXPRESSION_WITHOUT_LABEL, ORDER_BY_NOT_ALLOWED, CTE_NOT_SUPPORTED, APPLY_NOT_SUPPORTED, DIRTY_READ_HINT, REMOTE_SOURCE_NOT_ALLOWED, NON_DETERMINISTIC_QUERY, KEY_NOT_PLAIN_COLUMN, KEY_NOT_PROJECTED, KEY_NOT_UNIQUE, PARENT_LINK_MISSING, DUPLICATE_LEVEL_NAME, DEPTH_EXCEEDED.

    Feasibility

    The verdict is SNAPSHOT_ONLY: a warning on a snapshot-only entity, an error on a CDC entity. NO_LINEAGE_PATH, NON_EQUI_JOIN_SNAPSHOT_ONLY, SOURCE_WITHOUT_BEFORE_IMAGES, CAPTURE_NOT_ENABLED, CAPTURE_COLUMNS_MISSING, NOT_CAPTURABLE, VIEW_NOT_CAPTURABLE, CROSS_DATABASE_TABLE, USER_FUNCTION_DEPENDENCY, READ_REPLICA_LAG, TABLE_WITHOUT_PRIMARY_KEY, ROW_LIMIT_SNAPSHOT_ONLY, SET_OPERATION_SNAPSHOT_ONLY, FULL_OUTER_JOIN_SNAPSHOT_ONLY, DERIVED_TABLE_SNAPSHOT_ONLY, SCALAR_SUBQUERY_SNAPSHOT_ONLY.

    Warning

    Accepted, shown on describe and validate. UNTRACKED_TABLE_DRIFT, LINEAGE_COLUMN_NOT_INDEXED, SNAPSHOT_ISOLATION_UNAVAILABLE, DESCRIBE_UNAVAILABLE, TARGET_KEEPS_REMOVED_DOCUMENTS, ROOT_KEY_NULLABLE, PARTITION_SWITCH_NOT_CAPTURED.

    Between model and target

    Errors: the save is refused. ROOT_KEY_NOT_MAPPED, MAPPING_FUNCTION_NOT_SUPPORTED, TECHNICAL_FIELD_NOT_SUPPORTED, TARGET_KEY_MISMATCH, DOCUMENT_KEYSPACE_SHARED, UNSUPPORTED_BY_CONNECTOR, GS1_ID_KEY_TYPE_NOT_SUPPORTED, BIDIRECTIONAL_NOT_SUPPORTED, TARGET_CANNOT_HOLD_NESTED.

    Data error

    One root, handled per the write strategy. KEY_NOT_UNIQUE, ONE_LEVEL_MULTIPLE_ROWS, ROOT_ID_COLLISION, AGGREGATE_TOO_LARGE.

    System

    The entity stops, the other entities go on. MODEL_NO_LONGER_DERIVABLE, RETENTION_EXCEEDED_RESYNC_REQUIRED, REBUILD_REQUIRED, DATA_MODEL_MASS_DELETE_HELD, RECONCILE_INDEX_MISSING.

    Technical fields other than a static value, and field functions on key columns, are not supported on a Query entity, because a document is assembled from several rows and has no single transaction, time or operation.

    Monitor a Query entity

    • Notifications. DATA_MODEL_ROOTS_SKIPPED, DATA_MODEL_FANOUT_LARGE, DATA_MODEL_NO_LONGER_DERIVABLE, and the entity errors titled with a system code.

    • Metrics of the agent, tagged with pipeline and entity: gluesync_datamodel_window_changes_total, gluesync_datamodel_affected_roots_total, gluesync_datamodel_missing_roots_total, gluesync_datamodel_irrelevant_updates_total, gluesync_datamodel_fanout_roots, gluesync_datamodel_escalations_total, gluesync_datamodel_derivation_seconds, gluesync_datamodel_reread_seconds, gluesync_datamodel_dropped_rows_total and gluesync_datamodel_skipped_roots_total. The usual lag probe of each entity covers Query entities too. See Metrics and insights.

    • Support bundle. The log archive holds, for each Query entity, its levels with the string and number literals of the SQL replaced by ?, the tables read with their tracked flag, the verdict, the last skipped roots by hashed key and the last windows. Key values and bind values never appear.

    Limits

    • Query entities run on the MSSQL CDC agent. Nested documents need a Couchbase target.

    • The wizard builds single-level models. Child levels are written through the REST API or the MCP server.

    • A model goes as deep as the root and its child levels.

    • The Validator does not compare Query entities.

    • SQL Server rejects TRUNCATE on a table with CDC enabled, so a truncate in practice follows a capture that was dropped and created again.

    • Rows moved by ALTER TABLE …​ SWITCH on a partitioned table reach no change table. Describe warns with PARTITION_SWITCH_NOT_CAPTURED when its login can read cdc.change_tables.

    • A change of an untracked table alone rewrites no document.