]> granicus.if.org Git - postgresql/commitdiff
Avoid incrementing the CommandCounter when CommandCounterIncrement is called
authorTom Lane <tgl@sss.pgh.pa.us>
Fri, 30 Nov 2007 21:22:54 +0000 (21:22 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Fri, 30 Nov 2007 21:22:54 +0000 (21:22 +0000)
but no database changes have been made since the last CommandCounterIncrement.
This should result in a significant improvement in the number of "commands"
that can typically be performed within a transaction before hitting the 2^32
CommandId size limit.  In particular this buys back (and more) the possible
adverse consequences of my previous patch to fix plan caching behavior.

The implementation requires tracking whether the current CommandCounter
value has been "used" to mark any tuples.  CommandCounter values stored into
snapshots are presumed not to be used for this purpose.  This requires some
small executor changes, since the executor used to conflate the curcid of
the snapshot it was using with the command ID to mark output tuples with.
Separating these concepts allows some small simplifications in executor APIs.

Something for the TODO list: look into having CommandCounterIncrement not do
AcceptInvalidationMessages.  It seems fairly bogus to be doing it there,
but exactly where to do it instead isn't clear, and I'm disinclined to mess
with asynchronous behavior during late beta.

20 files changed:
contrib/pgrowlocks/pgrowlocks.c
src/backend/access/heap/heapam.c
src/backend/access/heap/tuptoaster.c
src/backend/access/transam/xact.c
src/backend/commands/async.c
src/backend/commands/copy.c
src/backend/commands/explain.c
src/backend/commands/trigger.c
src/backend/executor/execMain.c
src/backend/executor/execUtils.c
src/backend/executor/spi.c
src/backend/storage/ipc/procarray.c
src/backend/utils/cache/inval.c
src/backend/utils/time/tqual.c
src/include/access/xact.h
src/include/commands/trigger.h
src/include/executor/executor.h
src/include/nodes/execnodes.h
src/test/regress/expected/combocid.out
src/test/regress/sql/combocid.sql

index aaa132fbc4752a540bb94a687b675801c47b0dc5..fb19983bf863f69b8a4e87f1f35acc0c96486d82 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $PostgreSQL: pgsql/contrib/pgrowlocks/pgrowlocks.c,v 1.7 2007/08/28 22:59:30 tgl Exp $
+ * $PostgreSQL: pgsql/contrib/pgrowlocks/pgrowlocks.c,v 1.8 2007/11/30 21:22:53 tgl Exp $
  *
  * Copyright (c) 2005-2006     Tatsuo Ishii
  *
@@ -117,8 +117,9 @@ pgrowlocks(PG_FUNCTION_ARGS)
                /* must hold a buffer lock to call HeapTupleSatisfiesUpdate */
                LockBuffer(scan->rs_cbuf, BUFFER_LOCK_SHARE);
 
-               if (HeapTupleSatisfiesUpdate(tuple->t_data, GetCurrentCommandId(), scan->rs_cbuf)
-                       == HeapTupleBeingUpdated)
+               if (HeapTupleSatisfiesUpdate(tuple->t_data,
+                                                                        GetCurrentCommandId(false),
+                                                                        scan->rs_cbuf) == HeapTupleBeingUpdated)
                {
 
                        char      **values;
index 20027592b500fd4250ad5475ad803021183765c5..1a4fc92f1c29c23f198ecd5a594e25cd29eab3fa 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/access/heap/heapam.c,v 1.245 2007/11/15 21:14:32 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/access/heap/heapam.c,v 1.246 2007/11/30 21:22:53 tgl Exp $
  *
  *
  * INTERFACE ROUTINES
@@ -1891,7 +1891,7 @@ heap_insert(Relation relation, HeapTuple tup, CommandId cid,
 Oid
 simple_heap_insert(Relation relation, HeapTuple tup)
 {
-       return heap_insert(relation, tup, GetCurrentCommandId(), true, true);
+       return heap_insert(relation, tup, GetCurrentCommandId(true), true, true);
 }
 
 /*
@@ -2174,7 +2174,7 @@ simple_heap_delete(Relation relation, ItemPointer tid)
 
        result = heap_delete(relation, tid,
                                                 &update_ctid, &update_xmax,
-                                                GetCurrentCommandId(), InvalidSnapshot,
+                                                GetCurrentCommandId(true), InvalidSnapshot,
                                                 true /* wait for commit */ );
        switch (result)
        {
@@ -2817,7 +2817,7 @@ simple_heap_update(Relation relation, ItemPointer otid, HeapTuple tup)
 
        result = heap_update(relation, otid, tup,
                                                 &update_ctid, &update_xmax,
-                                                GetCurrentCommandId(), InvalidSnapshot,
+                                                GetCurrentCommandId(true), InvalidSnapshot,
                                                 true /* wait for commit */ );
        switch (result)
        {
index 0a8873f9945d6a95017c75346b663a23457692af..f26fa9f4a6ba2d6b39199b7fe0aeab6d2c580150 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/access/heap/tuptoaster.c,v 1.79 2007/11/15 21:14:32 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/access/heap/tuptoaster.c,v 1.80 2007/11/30 21:22:53 tgl Exp $
  *
  *
  * INTERFACE ROUTINES
@@ -1086,7 +1086,7 @@ toast_save_datum(Relation rel, Datum value,
        TupleDesc       toasttupDesc;
        Datum           t_values[3];
        bool            t_isnull[3];
-       CommandId       mycid = GetCurrentCommandId();
+       CommandId       mycid = GetCurrentCommandId(true);
        struct varlena *result;
        struct varatt_external toast_pointer;
        struct
index 04804c38711ccffcecee376b31669c4f582d979c..ce0dd812819fe64becd087566eb9ee38c832d992 100644 (file)
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/access/transam/xact.c,v 1.253 2007/11/15 21:14:32 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/access/transam/xact.c,v 1.254 2007/11/30 21:22:53 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -161,6 +161,7 @@ static TransactionState CurrentTransactionState = &TopTransactionStateData;
  */
 static SubTransactionId currentSubTransactionId;
 static CommandId currentCommandId;
+static bool currentCommandIdUsed;
 
 /*
  * xactStartTimestamp is the value of transaction_timestamp().
@@ -435,11 +436,18 @@ GetCurrentSubTransactionId(void)
 
 /*
  *     GetCurrentCommandId
+ *
+ * "used" must be TRUE if the caller intends to use the command ID to mark
+ * inserted/updated/deleted tuples.  FALSE means the ID is being fetched
+ * for read-only purposes (ie, as a snapshot validity cutoff).  See
+ * CommandCounterIncrement() for discussion.
  */
 CommandId
-GetCurrentCommandId(void)
+GetCurrentCommandId(bool used)
 {
        /* this is global to a transaction, not subtransaction-local */
+       if (used)
+               currentCommandIdUsed = true;
        return currentCommandId;
 }
 
@@ -566,25 +574,50 @@ TransactionIdIsCurrentTransactionId(TransactionId xid)
 void
 CommandCounterIncrement(void)
 {
-       currentCommandId += 1;
-       if (currentCommandId == FirstCommandId)         /* check for overflow */
+       /*
+        * If the current value of the command counter hasn't been "used" to
+        * mark tuples, we need not increment it, since there's no need to
+        * distinguish a read-only command from others.  This helps postpone
+        * command counter overflow, and keeps no-op CommandCounterIncrement
+        * operations cheap.
+        */
+       if (currentCommandIdUsed)
        {
-               currentCommandId -= 1;
-               ereport(ERROR,
-                               (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
+               currentCommandId += 1;
+               if (currentCommandId == FirstCommandId) /* check for overflow */
+               {
+                       currentCommandId -= 1;
+                       ereport(ERROR,
+                                       (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
                  errmsg("cannot have more than 2^32-1 commands in a transaction")));
-       }
+               }
+               currentCommandIdUsed = false;
 
-       /* Propagate new command ID into static snapshots, if set */
-       if (SerializableSnapshot)
-               SerializableSnapshot->curcid = currentCommandId;
-       if (LatestSnapshot)
-               LatestSnapshot->curcid = currentCommandId;
+               /* Propagate new command ID into static snapshots, if set */
+               if (SerializableSnapshot)
+                       SerializableSnapshot->curcid = currentCommandId;
+               if (LatestSnapshot)
+                       LatestSnapshot->curcid = currentCommandId;
+
+               /*
+                * Make any catalog changes done by the just-completed command
+                * visible in the local syscache.  We obviously don't need to do
+                * this after a read-only command.  (But see hacks in inval.c
+                * to make real sure we don't think a command that queued inval
+                * messages was read-only.)
+                */
+               AtCommit_LocalCache();
+       }
 
        /*
-        * make cache changes visible to me.
+        * Make any other backends' catalog changes visible to me.
+        *
+        * XXX this is probably in the wrong place: CommandCounterIncrement
+        * should be purely a local operation, most likely.  However fooling
+        * with this will affect asynchronous cross-backend interactions,
+        * which doesn't seem like a wise thing to do in late beta, so save
+        * improving this for another day - tgl 2007-11-30
         */
-       AtCommit_LocalCache();
        AtStart_Cache();
 }
 
@@ -1416,6 +1449,7 @@ StartTransaction(void)
        s->subTransactionId = TopSubTransactionId;
        currentSubTransactionId = TopSubTransactionId;
        currentCommandId = FirstCommandId;
+       currentCommandIdUsed = false;
 
        /*
         * must initialize resource-management stuff first
@@ -4007,13 +4041,14 @@ ShowTransactionStateRec(TransactionState s)
 
        /* use ereport to suppress computation if msg will not be printed */
        ereport(DEBUG3,
-                       (errmsg_internal("name: %s; blockState: %13s; state: %7s, xid/subid/cid: %u/%u/%u, nestlvl: %d, children: %s",
+                       (errmsg_internal("name: %s; blockState: %13s; state: %7s, xid/subid/cid: %u/%u/%u%s, nestlvl: %d, children: %s",
                                                         PointerIsValid(s->name) ? s->name : "unnamed",
                                                         BlockStateAsString(s->blockState),
                                                         TransStateAsString(s->state),
                                                         (unsigned int) s->transactionId,
                                                         (unsigned int) s->subTransactionId,
                                                         (unsigned int) currentCommandId,
+                                                        currentCommandIdUsed ? " (used)" : "",
                                                         s->nestingLevel,
                                                         nodeToString(s->childXids))));
 }
index 55b99f8c922bd94db13a3b08165c9ff72ff6c622..c32dd2b19fc0f1979d59d8e4d5f688982b4653b8 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/commands/async.c,v 1.136 2007/04/12 06:53:46 neilc Exp $
+ *       $PostgreSQL: pgsql/src/backend/commands/async.c,v 1.137 2007/11/30 21:22:53 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -562,7 +562,8 @@ AtCommit_Notify(void)
                                 */
                                result = heap_update(lRel, &lTuple->t_self, rTuple,
                                                                         &update_ctid, &update_xmax,
-                                                                        GetCurrentCommandId(), InvalidSnapshot,
+                                                                        GetCurrentCommandId(true),
+                                                                        InvalidSnapshot,
                                                                         false /* no wait for commit */ );
                                switch (result)
                                {
index ef7e04ca286cf62378e56a5b47a4f8e01ef32cbc..c68d828fea0337b2da732a88981ad8073508eb77 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/commands/copy.c,v 1.288 2007/11/15 21:14:33 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/commands/copy.c,v 1.289 2007/11/30 21:22:53 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1033,7 +1033,7 @@ DoCopy(const CopyStmt *stmt, const char *queryString)
                 * which COPY can be invoked, I think it's OK, because the active
                 * snapshot shouldn't be shared with anything else anyway.)
                 */
-               ActiveSnapshot->curcid = GetCurrentCommandId();
+               ActiveSnapshot->curcid = GetCurrentCommandId(false);
 
                /* Create dest receiver for COPY OUT */
                dest = CreateDestReceiver(DestCopyOut, NULL);
@@ -1637,7 +1637,7 @@ CopyFrom(CopyState cstate)
        ExprContext *econtext;          /* used for ExecEvalExpr for default atts */
        MemoryContext oldcontext = CurrentMemoryContext;
        ErrorContextCallback errcontext;
-       CommandId       mycid = GetCurrentCommandId();
+       CommandId       mycid = GetCurrentCommandId(true);
        bool            use_wal = true; /* by default, use WAL logging */
        bool            use_fsm = true; /* by default, use FSM for free space */
 
index a9aa2cb3e13052e674a8b313d1f5e408fb31a87b..f77f8cdc5ec9b32630fe4b1eced629e6f8f891cd 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994-5, Regents of the University of California
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/commands/explain.c,v 1.167 2007/11/15 22:25:15 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/commands/explain.c,v 1.168 2007/11/30 21:22:54 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -233,7 +233,7 @@ ExplainOnePlan(PlannedStmt *plannedstmt, ParamListInfo params,
         * EXPLAIN can be invoked, I think it's OK, because the active snapshot
         * shouldn't be shared with anything else anyway.)
         */
-       ActiveSnapshot->curcid = GetCurrentCommandId();
+       ActiveSnapshot->curcid = GetCurrentCommandId(false);
 
        /* Create a QueryDesc requesting no output */
        queryDesc = CreateQueryDesc(plannedstmt,
index 7dc195053426d12ad1cc95d809c5c741a7e89d6b..1b66bd22ba8ba08b7ed35e09b1f8d739f60e7aae 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/commands/trigger.c,v 1.224 2007/11/16 01:51:22 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/commands/trigger.c,v 1.225 2007/11/30 21:22:54 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -51,7 +51,6 @@ static void InsertTrigger(TriggerDesc *trigdesc, Trigger *trigger, int indx);
 static HeapTuple GetTupleForTrigger(EState *estate,
                                   ResultRelInfo *relinfo,
                                   ItemPointer tid,
-                                  CommandId cid,
                                   TupleTableSlot **newSlot);
 static HeapTuple ExecCallTriggerFunc(TriggerData *trigdata,
                                        int tgindx,
@@ -1801,8 +1800,7 @@ ExecASDeleteTriggers(EState *estate, ResultRelInfo *relinfo)
 
 bool
 ExecBRDeleteTriggers(EState *estate, ResultRelInfo *relinfo,
-                                        ItemPointer tupleid,
-                                        CommandId cid)
+                                        ItemPointer tupleid)
 {
        TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
        int                     ntrigs = trigdesc->n_before_row[TRIGGER_EVENT_DELETE];
@@ -1814,7 +1812,7 @@ ExecBRDeleteTriggers(EState *estate, ResultRelInfo *relinfo,
        TupleTableSlot *newSlot;
        int                     i;
 
-       trigtuple = GetTupleForTrigger(estate, relinfo, tupleid, cid, &newSlot);
+       trigtuple = GetTupleForTrigger(estate, relinfo, tupleid, &newSlot);
        if (trigtuple == NULL)
                return false;
 
@@ -1871,9 +1869,7 @@ ExecARDeleteTriggers(EState *estate, ResultRelInfo *relinfo,
        if (trigdesc && trigdesc->n_after_row[TRIGGER_EVENT_DELETE] > 0)
        {
                HeapTuple       trigtuple = GetTupleForTrigger(estate, relinfo,
-                                                                                                  tupleid,
-                                                                                                  (CommandId) 0,
-                                                                                                  NULL);
+                                                                                                  tupleid, NULL);
 
                AfterTriggerSaveEvent(relinfo, TRIGGER_EVENT_DELETE,
                                                          true, trigtuple, NULL);
@@ -1952,8 +1948,7 @@ ExecASUpdateTriggers(EState *estate, ResultRelInfo *relinfo)
 
 HeapTuple
 ExecBRUpdateTriggers(EState *estate, ResultRelInfo *relinfo,
-                                        ItemPointer tupleid, HeapTuple newtuple,
-                                        CommandId cid)
+                                        ItemPointer tupleid, HeapTuple newtuple)
 {
        TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
        int                     ntrigs = trigdesc->n_before_row[TRIGGER_EVENT_UPDATE];
@@ -1965,7 +1960,7 @@ ExecBRUpdateTriggers(EState *estate, ResultRelInfo *relinfo,
        TupleTableSlot *newSlot;
        int                     i;
 
-       trigtuple = GetTupleForTrigger(estate, relinfo, tupleid, cid, &newSlot);
+       trigtuple = GetTupleForTrigger(estate, relinfo, tupleid, &newSlot);
        if (trigtuple == NULL)
                return NULL;
 
@@ -2025,9 +2020,7 @@ ExecARUpdateTriggers(EState *estate, ResultRelInfo *relinfo,
        if (trigdesc && trigdesc->n_after_row[TRIGGER_EVENT_UPDATE] > 0)
        {
                HeapTuple       trigtuple = GetTupleForTrigger(estate, relinfo,
-                                                                                                  tupleid,
-                                                                                                  (CommandId) 0,
-                                                                                                  NULL);
+                                                                                                  tupleid, NULL);
 
                AfterTriggerSaveEvent(relinfo, TRIGGER_EVENT_UPDATE,
                                                          true, trigtuple, newtuple);
@@ -2038,7 +2031,7 @@ ExecARUpdateTriggers(EState *estate, ResultRelInfo *relinfo,
 
 static HeapTuple
 GetTupleForTrigger(EState *estate, ResultRelInfo *relinfo,
-                                  ItemPointer tid, CommandId cid,
+                                  ItemPointer tid,
                                   TupleTableSlot **newSlot)
 {
        Relation        relation = relinfo->ri_RelationDesc;
@@ -2060,7 +2053,8 @@ GetTupleForTrigger(EState *estate, ResultRelInfo *relinfo,
 ltrmark:;
                tuple.t_self = *tid;
                test = heap_lock_tuple(relation, &tuple, &buffer,
-                                                          &update_ctid, &update_xmax, cid,
+                                                          &update_ctid, &update_xmax,
+                                                          estate->es_output_cid,
                                                           LockTupleExclusive, false);
                switch (test)
                {
@@ -2086,8 +2080,7 @@ ltrmark:;
                                        epqslot = EvalPlanQual(estate,
                                                                                   relinfo->ri_RangeTableIndex,
                                                                                   &update_ctid,
-                                                                                  update_xmax,
-                                                                                  cid);
+                                                                                  update_xmax);
                                        if (!TupIsNull(epqslot))
                                        {
                                                *tid = update_ctid;
index 4b6ad47adb047bf14af1e0867bec86a9c201d3bc..5886234a1e821e5849ae10e1bb3d08a7dc0ec7d6 100644 (file)
@@ -26,7 +26,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.300 2007/11/15 22:25:15 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.301 2007/11/30 21:22:54 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -160,6 +160,30 @@ ExecutorStart(QueryDesc *queryDesc, int eflags)
                estate->es_param_exec_vals = (ParamExecData *)
                        palloc0(queryDesc->plannedstmt->nParamExec * sizeof(ParamExecData));
 
+       /*
+        * If non-read-only query, set the command ID to mark output tuples with
+        */
+       switch (queryDesc->operation)
+       {
+               case CMD_SELECT:
+                       /* SELECT INTO and SELECT FOR UPDATE/SHARE need to mark tuples */
+                       if (queryDesc->plannedstmt->intoClause != NULL ||
+                               queryDesc->plannedstmt->rowMarks != NIL)
+                               estate->es_output_cid = GetCurrentCommandId(true);
+                       break;
+
+               case CMD_INSERT:
+               case CMD_DELETE:
+               case CMD_UPDATE:
+                       estate->es_output_cid = GetCurrentCommandId(true);
+                       break;
+
+               default:
+                       elog(ERROR, "unrecognized operation code: %d",
+                                (int) queryDesc->operation);
+                       break;
+       }
+
        /*
         * Copy other important information into the EState
         */
@@ -1285,7 +1309,7 @@ lnext:    ;
 
                                        test = heap_lock_tuple(erm->relation, &tuple, &buffer,
                                                                                   &update_ctid, &update_xmax,
-                                                                                  estate->es_snapshot->curcid,
+                                                                                  estate->es_output_cid,
                                                                                   lockmode, erm->noWait);
                                        ReleaseBuffer(buffer);
                                        switch (test)
@@ -1309,8 +1333,7 @@ lnext:    ;
                                                                newSlot = EvalPlanQual(estate,
                                                                                                           erm->rti,
                                                                                                           &update_ctid,
-                                                                                                          update_xmax,
-                                                                                               estate->es_snapshot->curcid);
+                                                                                                          update_xmax);
                                                                if (!TupIsNull(newSlot))
                                                                {
                                                                        slot = planSlot = newSlot;
@@ -1503,7 +1526,7 @@ ExecInsert(TupleTableSlot *slot,
         * t_self field.
         */
        newId = heap_insert(resultRelationDesc, tuple,
-                                               estate->es_snapshot->curcid,
+                                               estate->es_output_cid,
                                                true, true);
 
        IncrAppended();
@@ -1557,8 +1580,7 @@ ExecDelete(ItemPointer tupleid,
        {
                bool            dodelete;
 
-               dodelete = ExecBRDeleteTriggers(estate, resultRelInfo, tupleid,
-                                                                               estate->es_snapshot->curcid);
+               dodelete = ExecBRDeleteTriggers(estate, resultRelInfo, tupleid);
 
                if (!dodelete)                  /* "do nothing" */
                        return;
@@ -1575,7 +1597,7 @@ ExecDelete(ItemPointer tupleid,
 ldelete:;
        result = heap_delete(resultRelationDesc, tupleid,
                                                 &update_ctid, &update_xmax,
-                                                estate->es_snapshot->curcid,
+                                                estate->es_output_cid,
                                                 estate->es_crosscheck_snapshot,
                                                 true /* wait for commit */ );
        switch (result)
@@ -1599,8 +1621,7 @@ ldelete:;
                                epqslot = EvalPlanQual(estate,
                                                                           resultRelInfo->ri_RangeTableIndex,
                                                                           &update_ctid,
-                                                                          update_xmax,
-                                                                          estate->es_snapshot->curcid);
+                                                                          update_xmax);
                                if (!TupIsNull(epqslot))
                                {
                                        *tupleid = update_ctid;
@@ -1708,8 +1729,7 @@ ExecUpdate(TupleTableSlot *slot,
                HeapTuple       newtuple;
 
                newtuple = ExecBRUpdateTriggers(estate, resultRelInfo,
-                                                                               tupleid, tuple,
-                                                                               estate->es_snapshot->curcid);
+                                                                               tupleid, tuple);
 
                if (newtuple == NULL)   /* "do nothing" */
                        return;
@@ -1755,7 +1775,7 @@ lreplace:;
         */
        result = heap_update(resultRelationDesc, tupleid, tuple,
                                                 &update_ctid, &update_xmax,
-                                                estate->es_snapshot->curcid,
+                                                estate->es_output_cid,
                                                 estate->es_crosscheck_snapshot,
                                                 true /* wait for commit */ );
        switch (result)
@@ -1779,8 +1799,7 @@ lreplace:;
                                epqslot = EvalPlanQual(estate,
                                                                           resultRelInfo->ri_RangeTableIndex,
                                                                           &update_ctid,
-                                                                          update_xmax,
-                                                                          estate->es_snapshot->curcid);
+                                                                          update_xmax);
                                if (!TupIsNull(epqslot))
                                {
                                        *tupleid = update_ctid;
@@ -1973,7 +1992,6 @@ ExecProcessReturning(ProjectionInfo *projectReturning,
  *     rti - rangetable index of table containing tuple
  *     *tid - t_ctid from the outdated tuple (ie, next updated version)
  *     priorXmax - t_xmax from the outdated tuple
- *     curCid - command ID of current command of my transaction
  *
  * *tid is also an output parameter: it's modified to hold the TID of the
  * latest version of the tuple (note this may be changed even on failure)
@@ -1983,7 +2001,7 @@ ExecProcessReturning(ProjectionInfo *projectReturning,
  */
 TupleTableSlot *
 EvalPlanQual(EState *estate, Index rti,
-                        ItemPointer tid, TransactionId priorXmax, CommandId curCid)
+                        ItemPointer tid, TransactionId priorXmax)
 {
        evalPlanQual *epq;
        EState     *epqstate;
@@ -2063,17 +2081,17 @@ EvalPlanQual(EState *estate, Index rti,
 
                        /*
                         * If tuple was inserted by our own transaction, we have to check
-                        * cmin against curCid: cmin >= curCid means our command cannot
-                        * see the tuple, so we should ignore it.  Without this we are
-                        * open to the "Halloween problem" of indefinitely re-updating the
-                        * same tuple.  (We need not check cmax because
+                        * cmin against es_output_cid: cmin >= current CID means our
+                        * command cannot see the tuple, so we should ignore it.  Without
+                        * this we are open to the "Halloween problem" of indefinitely
+                        * re-updating the same tuple. (We need not check cmax because
                         * HeapTupleSatisfiesDirty will consider a tuple deleted by our
                         * transaction dead, regardless of cmax.)  We just checked that
                         * priorXmax == xmin, so we can test that variable instead of
                         * doing HeapTupleHeaderGetXmin again.
                         */
                        if (TransactionIdIsCurrentTransactionId(priorXmax) &&
-                               HeapTupleHeaderGetCmin(tuple.t_data) >= curCid)
+                               HeapTupleHeaderGetCmin(tuple.t_data) >= estate->es_output_cid)
                        {
                                ReleaseBuffer(buffer);
                                return NULL;
@@ -2360,6 +2378,7 @@ EvalPlanQualStart(evalPlanQual *epq, EState *estate, evalPlanQual *priorepq)
        epqstate->es_snapshot = estate->es_snapshot;
        epqstate->es_crosscheck_snapshot = estate->es_crosscheck_snapshot;
        epqstate->es_range_table = estate->es_range_table;
+       epqstate->es_output_cid = estate->es_output_cid;
        epqstate->es_result_relations = estate->es_result_relations;
        epqstate->es_num_result_relations = estate->es_num_result_relations;
        epqstate->es_result_relation_info = estate->es_result_relation_info;
@@ -2718,7 +2737,7 @@ intorel_receive(TupleTableSlot *slot, DestReceiver *self)
 
        heap_insert(estate->es_into_relation_descriptor,
                                tuple,
-                               estate->es_snapshot->curcid,
+                               estate->es_output_cid,
                                estate->es_into_relation_use_wal,
                                false);                 /* never any point in using FSM */
 
index 230d5c919f2a556d952b786a3214f9144e1eb686..12ddc910f47ae6ae8e60a81667e10adf9e1d9a1a 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/executor/execUtils.c,v 1.152 2007/11/15 21:14:34 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/executor/execUtils.c,v 1.153 2007/11/30 21:22:54 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -178,6 +178,8 @@ CreateExecutorState(void)
        estate->es_crosscheck_snapshot = InvalidSnapshot;       /* no crosscheck */
        estate->es_range_table = NIL;
 
+       estate->es_output_cid = (CommandId) 0;
+
        estate->es_result_relations = NULL;
        estate->es_num_result_relations = 0;
        estate->es_result_relation_info = NULL;
index a5601ecdfca44bd39ea3e733c7a548fa4aa63c90..e08e91cb0a022b300101fdc4e3689a26bd0cd37f 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/executor/spi.c,v 1.185 2007/11/30 18:38:34 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/executor/spi.c,v 1.186 2007/11/30 21:22:54 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1593,7 +1593,7 @@ _SPI_execute_plan(SPIPlanPtr plan, Datum *Values, const char *Nulls,
                                         */
                                        ActiveSnapshot = CopySnapshot(snapshot);
                                        if (!read_only)
-                                               ActiveSnapshot->curcid = GetCurrentCommandId();
+                                               ActiveSnapshot->curcid = GetCurrentCommandId(false);
                                }
 
                                if (IsA(stmt, PlannedStmt) &&
index d7c8d706fd905bffbe162a232a53858f5096f394..156f947604e414ddb3d393f17c4884128f802fe4 100644 (file)
@@ -23,7 +23,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/storage/ipc/procarray.c,v 1.37 2007/11/15 21:14:38 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/storage/ipc/procarray.c,v 1.38 2007/11/30 21:22:54 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -814,7 +814,7 @@ GetSnapshotData(Snapshot snapshot, bool serializable)
        snapshot->xcnt = count;
        snapshot->subxcnt = subcount;
 
-       snapshot->curcid = GetCurrentCommandId();
+       snapshot->curcid = GetCurrentCommandId(false);
 
        return snapshot;
 }
index 844dbc2be0645bea4505a7e960daed75df6c9c1d..803727f0840568f82b986d91a0825ba4f16baab5 100644 (file)
@@ -80,7 +80,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/cache/inval.c,v 1.81 2007/11/15 21:14:39 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/cache/inval.c,v 1.82 2007/11/30 21:22:54 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -402,6 +402,14 @@ RegisterRelcacheInvalidation(Oid dbId, Oid relId)
        AddRelcacheInvalidationMessage(&transInvalInfo->CurrentCmdInvalidMsgs,
                                                                   dbId, relId);
 
+       /*
+        * Most of the time, relcache invalidation is associated with system
+        * catalog updates, but there are a few cases where it isn't.  Quick
+        * hack to ensure that the next CommandCounterIncrement() will think
+        * that we need to do CommandEndInvalidationMessages().
+        */
+       (void) GetCurrentCommandId(true);
+
        /*
         * If the relation being invalidated is one of those cached in the
         * relcache init file, mark that we need to zap that file at commit.
@@ -420,6 +428,11 @@ RegisterSmgrInvalidation(RelFileNode rnode)
 {
        AddSmgrInvalidationMessage(&transInvalInfo->CurrentCmdInvalidMsgs,
                                                           rnode);
+
+       /*
+        * As above, just in case there is not an associated catalog change.
+        */
+       (void) GetCurrentCommandId(true);
 }
 
 /*
index 4c128e4446b0c209226af66fee781db583cc3cc8..dad379573c2f64e6f738f2b8141a0053653db3a4 100644 (file)
@@ -31,7 +31,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/time/tqual.c,v 1.107 2007/11/15 21:14:41 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/time/tqual.c,v 1.108 2007/11/30 21:22:54 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -382,7 +382,7 @@ HeapTupleSatisfiesNow(HeapTupleHeader tuple, Snapshot snapshot, Buffer buffer)
                }
                else if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmin(tuple)))
                {
-                       if (HeapTupleHeaderGetCmin(tuple) >= GetCurrentCommandId())
+                       if (HeapTupleHeaderGetCmin(tuple) >= GetCurrentCommandId(false))
                                return false;   /* inserted after scan started */
 
                        if (tuple->t_infomask & HEAP_XMAX_INVALID)      /* xid invalid */
@@ -401,7 +401,7 @@ HeapTupleSatisfiesNow(HeapTupleHeader tuple, Snapshot snapshot, Buffer buffer)
                                return true;
                        }
 
-                       if (HeapTupleHeaderGetCmax(tuple) >= GetCurrentCommandId())
+                       if (HeapTupleHeaderGetCmax(tuple) >= GetCurrentCommandId(false))
                                return true;    /* deleted after scan started */
                        else
                                return false;   /* deleted before scan started */
@@ -443,7 +443,7 @@ HeapTupleSatisfiesNow(HeapTupleHeader tuple, Snapshot snapshot, Buffer buffer)
        {
                if (tuple->t_infomask & HEAP_IS_LOCKED)
                        return true;
-               if (HeapTupleHeaderGetCmax(tuple) >= GetCurrentCommandId())
+               if (HeapTupleHeaderGetCmax(tuple) >= GetCurrentCommandId(false))
                        return true;            /* deleted after scan started */
                else
                        return false;           /* deleted before scan started */
index 8a311dda3bac3c202f84d8b7d414ca756c05779b..9a6fa607a0e8614ff5aa002e23c348136ad796a7 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/access/xact.h,v 1.91 2007/11/15 21:14:42 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/access/xact.h,v 1.92 2007/11/30 21:22:54 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -143,7 +143,7 @@ extern TransactionId GetTopTransactionIdIfAny(void);
 extern TransactionId GetCurrentTransactionId(void);
 extern TransactionId GetCurrentTransactionIdIfAny(void);
 extern SubTransactionId GetCurrentSubTransactionId(void);
-extern CommandId GetCurrentCommandId(void);
+extern CommandId GetCurrentCommandId(bool used);
 extern TimestampTz GetCurrentTransactionStartTimestamp(void);
 extern TimestampTz GetCurrentStatementStartTimestamp(void);
 extern TimestampTz GetCurrentTransactionStopTimestamp(void);
index 69ad97b4ec80a0da6ae6c54fd18056ffb237b0ce..5a1d50edf94b9ea410b8dcb868800fc6125d2667 100644 (file)
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/commands/trigger.h,v 1.63 2007/11/15 21:14:43 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/commands/trigger.h,v 1.64 2007/11/30 21:22:54 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -124,8 +124,7 @@ extern void ExecASDeleteTriggers(EState *estate,
                                         ResultRelInfo *relinfo);
 extern bool ExecBRDeleteTriggers(EState *estate,
                                         ResultRelInfo *relinfo,
-                                        ItemPointer tupleid,
-                                        CommandId cid);
+                                        ItemPointer tupleid);
 extern void ExecARDeleteTriggers(EState *estate,
                                         ResultRelInfo *relinfo,
                                         ItemPointer tupleid);
@@ -136,8 +135,7 @@ extern void ExecASUpdateTriggers(EState *estate,
 extern HeapTuple ExecBRUpdateTriggers(EState *estate,
                                         ResultRelInfo *relinfo,
                                         ItemPointer tupleid,
-                                        HeapTuple newtuple,
-                                        CommandId cid);
+                                        HeapTuple newtuple);
 extern void ExecARUpdateTriggers(EState *estate,
                                         ResultRelInfo *relinfo,
                                         ItemPointer tupleid,
index 08b97e3adfcb3d9740a850942eaad8ca39f015ed..78a0a2560a3fa3fda02a6e888659fd3f287e59fe 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/executor/executor.h,v 1.144 2007/11/15 22:25:17 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/executor/executor.h,v 1.145 2007/11/30 21:22:54 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -143,7 +143,7 @@ extern bool ExecContextForcesOids(PlanState *planstate, bool *hasoids);
 extern void ExecConstraints(ResultRelInfo *resultRelInfo,
                                TupleTableSlot *slot, EState *estate);
 extern TupleTableSlot *EvalPlanQual(EState *estate, Index rti,
-                        ItemPointer tid, TransactionId priorXmax, CommandId curCid);
+                        ItemPointer tid, TransactionId priorXmax);
 extern PlanState *ExecGetActivePlanTree(QueryDesc *queryDesc);
 extern DestReceiver *CreateIntoRelDestReceiver(void);
 
index ca0e9c8fa78665a51be15bafa9715e9104702dc5..a140a7533d4852ea353a4b709523e16ff8aaa457 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/nodes/execnodes.h,v 1.181 2007/11/15 22:25:17 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/execnodes.h,v 1.182 2007/11/30 21:22:54 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -311,6 +311,9 @@ typedef struct EState
        Snapshot        es_crosscheck_snapshot; /* crosscheck time qual for RI */
        List       *es_range_table; /* List of RangeTblEntry */
 
+       /* If query can insert/delete tuples, the command ID to mark them with */
+       CommandId       es_output_cid;
+
        /* Info about target table for insert/update/delete queries: */
        ResultRelInfo *es_result_relations; /* array of ResultRelInfos */
        int                     es_num_result_relations;                /* length of array */
index 14e45fe4893417f60ac5e33695ea2a8fcfa585ff..b63894c2837ef96093217d706e8aac88a3195871 100644 (file)
@@ -4,66 +4,16 @@
 CREATE TEMP TABLE combocidtest (foobar int);
 BEGIN;
 -- a few dummy ops to push up the CommandId counter
-SELECT 1;
- ?column? 
-----------
-        1
-(1 row)
-
-SELECT 1;
- ?column? 
-----------
-        1
-(1 row)
-
-SELECT 1;
- ?column? 
-----------
-        1
-(1 row)
-
-SELECT 1;
- ?column? 
-----------
-        1
-(1 row)
-
-SELECT 1;
- ?column? 
-----------
-        1
-(1 row)
-
-SELECT 1;
- ?column? 
-----------
-        1
-(1 row)
-
-SELECT 1;
- ?column? 
-----------
-        1
-(1 row)
-
-SELECT 1;
- ?column? 
-----------
-        1
-(1 row)
-
-SELECT 1;
- ?column? 
-----------
-        1
-(1 row)
-
-SELECT 1;
- ?column? 
-----------
-        1
-(1 row)
-
+INSERT INTO combocidtest SELECT 1 LIMIT 0;
+INSERT INTO combocidtest SELECT 1 LIMIT 0;
+INSERT INTO combocidtest SELECT 1 LIMIT 0;
+INSERT INTO combocidtest SELECT 1 LIMIT 0;
+INSERT INTO combocidtest SELECT 1 LIMIT 0;
+INSERT INTO combocidtest SELECT 1 LIMIT 0;
+INSERT INTO combocidtest SELECT 1 LIMIT 0;
+INSERT INTO combocidtest SELECT 1 LIMIT 0;
+INSERT INTO combocidtest SELECT 1 LIMIT 0;
+INSERT INTO combocidtest SELECT 1 LIMIT 0;
 INSERT INTO combocidtest VALUES (1);
 INSERT INTO combocidtest VALUES (2);
 SELECT ctid,cmin,* FROM combocidtest;
@@ -79,8 +29,8 @@ UPDATE combocidtest SET foobar = foobar + 10;
 SELECT ctid,cmin,* FROM combocidtest;
  ctid  | cmin | foobar 
 -------+------+--------
- (0,3) |   13 |     11
- (0,4) |   13 |     12
+ (0,3) |   12 |     11
+ (0,4) |   12 |     12
 (2 rows)
 
 ROLLBACK TO s1;
@@ -109,8 +59,8 @@ DELETE FROM combocidtest;
 FETCH ALL FROM c;
  ctid  | cmin | foobar 
 -------+------+--------
- (0,1) |    2 |      1
- (0,2) |    2 |      2
+ (0,1) |    1 |      1
+ (0,2) |    1 |      2
  (0,5) |    0 |    333
 (3 rows)
 
@@ -118,79 +68,29 @@ ROLLBACK;
 SELECT ctid,cmin,* FROM combocidtest;
  ctid  | cmin | foobar 
 -------+------+--------
- (0,1) |    2 |      1
- (0,2) |    2 |      2
+ (0,1) |    1 |      1
+ (0,2) |    1 |      2
 (2 rows)
 
 -- check behavior with locked tuples
 BEGIN;
 -- a few dummy ops to push up the CommandId counter
-SELECT 1;
- ?column? 
-----------
-        1
-(1 row)
-
-SELECT 1;
- ?column? 
-----------
-        1
-(1 row)
-
-SELECT 1;
- ?column? 
-----------
-        1
-(1 row)
-
-SELECT 1;
- ?column? 
-----------
-        1
-(1 row)
-
-SELECT 1;
- ?column? 
-----------
-        1
-(1 row)
-
-SELECT 1;
- ?column? 
-----------
-        1
-(1 row)
-
-SELECT 1;
- ?column? 
-----------
-        1
-(1 row)
-
-SELECT 1;
- ?column? 
-----------
-        1
-(1 row)
-
-SELECT 1;
- ?column? 
-----------
-        1
-(1 row)
-
-SELECT 1;
- ?column? 
-----------
-        1
-(1 row)
-
+INSERT INTO combocidtest SELECT 1 LIMIT 0;
+INSERT INTO combocidtest SELECT 1 LIMIT 0;
+INSERT INTO combocidtest SELECT 1 LIMIT 0;
+INSERT INTO combocidtest SELECT 1 LIMIT 0;
+INSERT INTO combocidtest SELECT 1 LIMIT 0;
+INSERT INTO combocidtest SELECT 1 LIMIT 0;
+INSERT INTO combocidtest SELECT 1 LIMIT 0;
+INSERT INTO combocidtest SELECT 1 LIMIT 0;
+INSERT INTO combocidtest SELECT 1 LIMIT 0;
+INSERT INTO combocidtest SELECT 1 LIMIT 0;
 INSERT INTO combocidtest VALUES (444);
 SELECT ctid,cmin,* FROM combocidtest;
  ctid  | cmin | foobar 
 -------+------+--------
- (0,1) |    2 |      1
- (0,2) |    2 |      2
+ (0,1) |    1 |      1
+ (0,2) |    1 |      2
  (0,6) |   10 |    444
 (3 rows)
 
@@ -199,16 +99,16 @@ SAVEPOINT s1;
 SELECT ctid,cmin,* FROM combocidtest FOR UPDATE;
  ctid  | cmin | foobar 
 -------+------+--------
- (0,1) |    2 |      1
- (0,2) |    2 |      2
+ (0,1) |    1 |      1
+ (0,2) |    1 |      2
  (0,6) |   10 |    444
 (3 rows)
 
 SELECT ctid,cmin,* FROM combocidtest;
  ctid  | cmin | foobar 
 -------+------+--------
- (0,1) |    2 |      1
- (0,2) |    2 |      2
+ (0,1) |    1 |      1
+ (0,2) |    1 |      2
  (0,6) |   10 |    444
 (3 rows)
 
@@ -217,17 +117,17 @@ UPDATE combocidtest SET foobar = foobar + 10;
 SELECT ctid,cmin,* FROM combocidtest;
  ctid  | cmin | foobar 
 -------+------+--------
- (0,7) |   14 |     11
- (0,8) |   14 |     12
- (0,9) |   14 |    454
+ (0,7) |   12 |     11
+ (0,8) |   12 |     12
+ (0,9) |   12 |    454
 (3 rows)
 
 ROLLBACK TO s1;
 SELECT ctid,cmin,* FROM combocidtest;
  ctid  | cmin | foobar 
 -------+------+--------
- (0,1) |   14 |      1
- (0,2) |   14 |      2
+ (0,1) |   12 |      1
+ (0,2) |   12 |      2
  (0,6) |    0 |    444
 (3 rows)
 
@@ -235,8 +135,8 @@ COMMIT;
 SELECT ctid,cmin,* FROM combocidtest;
  ctid  | cmin | foobar 
 -------+------+--------
- (0,1) |   14 |      1
- (0,2) |   14 |      2
+ (0,1) |   12 |      1
+ (0,2) |   12 |      2
  (0,6) |    0 |    444
 (3 rows)
 
index 3f30839b1f6be38a1f7047de53190d15e816bc20..f24ac6b01a1b5f796aba6f00894444835e752f92 100644 (file)
@@ -6,16 +6,16 @@ CREATE TEMP TABLE combocidtest (foobar int);
 BEGIN;
 
 -- a few dummy ops to push up the CommandId counter
-SELECT 1;
-SELECT 1;
-SELECT 1;
-SELECT 1;
-SELECT 1;
-SELECT 1;
-SELECT 1;
-SELECT 1;
-SELECT 1;
-SELECT 1;
+INSERT INTO combocidtest SELECT 1 LIMIT 0;
+INSERT INTO combocidtest SELECT 1 LIMIT 0;
+INSERT INTO combocidtest SELECT 1 LIMIT 0;
+INSERT INTO combocidtest SELECT 1 LIMIT 0;
+INSERT INTO combocidtest SELECT 1 LIMIT 0;
+INSERT INTO combocidtest SELECT 1 LIMIT 0;
+INSERT INTO combocidtest SELECT 1 LIMIT 0;
+INSERT INTO combocidtest SELECT 1 LIMIT 0;
+INSERT INTO combocidtest SELECT 1 LIMIT 0;
+INSERT INTO combocidtest SELECT 1 LIMIT 0;
 
 INSERT INTO combocidtest VALUES (1);
 INSERT INTO combocidtest VALUES (2);
@@ -58,16 +58,16 @@ SELECT ctid,cmin,* FROM combocidtest;
 BEGIN;
 
 -- a few dummy ops to push up the CommandId counter
-SELECT 1;
-SELECT 1;
-SELECT 1;
-SELECT 1;
-SELECT 1;
-SELECT 1;
-SELECT 1;
-SELECT 1;
-SELECT 1;
-SELECT 1;
+INSERT INTO combocidtest SELECT 1 LIMIT 0;
+INSERT INTO combocidtest SELECT 1 LIMIT 0;
+INSERT INTO combocidtest SELECT 1 LIMIT 0;
+INSERT INTO combocidtest SELECT 1 LIMIT 0;
+INSERT INTO combocidtest SELECT 1 LIMIT 0;
+INSERT INTO combocidtest SELECT 1 LIMIT 0;
+INSERT INTO combocidtest SELECT 1 LIMIT 0;
+INSERT INTO combocidtest SELECT 1 LIMIT 0;
+INSERT INTO combocidtest SELECT 1 LIMIT 0;
+INSERT INTO combocidtest SELECT 1 LIMIT 0;
 
 INSERT INTO combocidtest VALUES (444);