Quellcodebibliothek Statistik Leitseite    (Postgres Database Version 18.4©)  

Quelle  test_predtest.c

  Sprache: C
 

/*--------------------------------------------------------------------------
 *
 * test_predtest.c
 *  Test correctness of optimizer's predicate proof logic.
 *
 * Copyright (c) 2018-2025, PostgreSQL Global Development Group
 *
 * IDENTIFICATION
 *  src/test/modules/test_predtest/test_predtest.c
 *
 * -------------------------------------------------------------------------
 */


#include "postgres.h"

#include "access/htup_details.h"
#include "catalog/pg_type.h"
#include "executor/spi.h"
#include "funcapi.h"
#include "nodes/makefuncs.h"
#include "optimizer/optimizer.h"
#include "utils/builtins.h"

PG_MODULE_MAGIC;

/*
 * test_predtest(query text) returns record
 */

PG_FUNCTION_INFO_V1(test_predtest);

Datum
test_predtest(PG_FUNCTION_ARGS)
{
 text    *txt = PG_GETARG_TEXT_PP(0);
 char    *query_string = text_to_cstring(txt);
 SPIPlanPtr spiplan;
 int   spirc;
 TupleDesc tupdesc;
 bool  s_i_holds,
    w_i_holds,
    s_r_holds,
    w_r_holds;
 CachedPlan *cplan;
 PlannedStmt *stmt;
 Plan    *plan;
 Expr    *clause1;
 Expr    *clause2;
 bool  strong_implied_by,
    weak_implied_by,
    strong_refuted_by,
    weak_refuted_by;
 Datum  values[8];
 bool  nulls[8] = {0};
 int   i;

 /* We use SPI to parse, plan, and execute the test query */
 SPI_connect();

 /*
  * First, plan and execute the query, and inspect the results.  To the
  * extent that the query fully exercises the two expressions, this
  * provides an experimental indication of whether implication or
  * refutation holds.
 */

 spiplan = SPI_prepare(query_string, 0, NULL);
 if (spiplan == NULL)
  elog(ERROR, "SPI_prepare failed for \"%s\"", query_string);

 spirc = SPI_execute_plan(spiplan, NULL, NULL, true0);
 if (spirc != SPI_OK_SELECT)
  elog(ERROR, "failed to execute \"%s\"", query_string);
 tupdesc = SPI_tuptable->tupdesc;
 if (tupdesc->natts != 2 ||
  TupleDescAttr(tupdesc, 0)->atttypid != BOOLOID ||
  TupleDescAttr(tupdesc, 1)->atttypid != BOOLOID)
  elog(ERROR, "test_predtest query must yield two boolean columns");

 s_i_holds = w_i_holds = s_r_holds = w_r_holds = true;
 for (i = 0; i < SPI_processed; i++)
 {
  HeapTuple tup = SPI_tuptable->vals[i];
  Datum  dat;
  bool  isnull;
  char  c1,
     c2;

  /* Extract column values in a 3-way representation */
  dat = SPI_getbinval(tup, tupdesc, 1, &isnull);
  if (isnull)
   c1 = 'n';
  else if (DatumGetBool(dat))
   c1 = 't';
  else
   c1 = 'f';

  dat = SPI_getbinval(tup, tupdesc, 2, &isnull);
  if (isnull)
   c2 = 'n';
  else if (DatumGetBool(dat))
   c2 = 't';
  else
   c2 = 'f';

  /* Check for violations of various proof conditions */

  /* strong implication: truth of c2 implies truth of c1 */
  if (c2 == 't' && c1 != 't')
   s_i_holds = false;
  /* weak implication: non-falsity of c2 implies non-falsity of c1 */
  if (c2 != 'f' && c1 == 'f')
   w_i_holds = false;
  /* strong refutation: truth of c2 implies falsity of c1 */
  if (c2 == 't' && c1 != 'f')
   s_r_holds = false;
  /* weak refutation: truth of c2 implies non-truth of c1 */
  if (c2 == 't' && c1 == 't')
   w_r_holds = false;
 }

 /*
  * Strong refutation implies weak refutation, so we should never observe
  * s_r_holds = true with w_r_holds = false.
  *
  * We can't make a comparable assertion for implication since moving from
  * strong to weak implication expands the allowed values of "A" from true
  * to either true or NULL.
  *
  * If this fails it constitutes a bug not with the proofs but with either
  * this test module or a more core part of expression evaluation since we
  * are validating the logical correctness of the observed result rather
  * than the proof.
 */

 if (s_r_holds && !w_r_holds)
  elog(WARNING, "s_r_holds was true; w_r_holds must not be false");

 /*
  * Now, dig the clause querytrees out of the plan, and see what predtest.c
  * does with them.
 */

 cplan = SPI_plan_get_cached_plan(spiplan);

 if (cplan == NULL || list_length(cplan->stmt_list) != 1)
  elog(ERROR, "test_predtest query string must contain exactly one query");
 stmt = linitial_node(PlannedStmt, cplan->stmt_list);
 if (stmt->commandType != CMD_SELECT)
  elog(ERROR, "test_predtest query must be a SELECT");
 plan = stmt->planTree;
 Assert(list_length(plan->targetlist) >= 2);
 clause1 = linitial_node(TargetEntry, plan->targetlist)->expr;
 clause2 = lsecond_node(TargetEntry, plan->targetlist)->expr;

 /*
  * Because the clauses are in the SELECT list, preprocess_expression did
  * not pass them through canonicalize_qual nor make_ands_implicit.
  *
  * We can't do canonicalize_qual here, since it's unclear whether the
  * expressions ought to be treated as WHERE or CHECK clauses. Fortunately,
  * useful test expressions wouldn't be affected by those transformations
  * anyway.  We should do make_ands_implicit, though.
  *
  * Another way in which this does not exactly duplicate the normal usage
  * of the proof functions is that they are often given qual clauses
  * containing RestrictInfo nodes.  But since predtest.c just looks through
  * those anyway, it seems OK to not worry about that point.
 */

 clause1 = (Expr *) make_ands_implicit(clause1);
 clause2 = (Expr *) make_ands_implicit(clause2);

 strong_implied_by = predicate_implied_by((List *) clause1,
            (List *) clause2,
            false);

 weak_implied_by = predicate_implied_by((List *) clause1,
             (List *) clause2,
             true);

 strong_refuted_by = predicate_refuted_by((List *) clause1,
            (List *) clause2,
            false);

 weak_refuted_by = predicate_refuted_by((List *) clause1,
             (List *) clause2,
             true);

 /*
  * Issue warning if any proof is demonstrably incorrect.
 */

 if (strong_implied_by && !s_i_holds)
  elog(WARNING, "strong_implied_by result is incorrect");
 if (weak_implied_by && !w_i_holds)
  elog(WARNING, "weak_implied_by result is incorrect");
 if (strong_refuted_by && !s_r_holds)
  elog(WARNING, "strong_refuted_by result is incorrect");
 if (weak_refuted_by && !w_r_holds)
  elog(WARNING, "weak_refuted_by result is incorrect");

 /*
  * As with our earlier check of the logical consistency of whether strong
  * and weak refutation hold, we ought never prove strong refutation
  * without also proving weak refutation.
  *
  * Also as earlier we cannot make the same guarantee about implication
  * proofs.
  *
  * A warning here suggests a bug in the proof code.
 */

 if (strong_refuted_by && !weak_refuted_by)
  elog(WARNING, "strong_refuted_by was proven; weak_refuted_by should also be proven");

 /*
  * Clean up and return a record of the results.
 */

 if (SPI_finish() != SPI_OK_FINISH)
  elog(ERROR, "SPI_finish failed");

 tupdesc = CreateTemplateTupleDesc(8);
 TupleDescInitEntry(tupdesc, (AttrNumber) 1,
        "strong_implied_by", BOOLOID, -10);
 TupleDescInitEntry(tupdesc, (AttrNumber) 2,
        "weak_implied_by", BOOLOID, -10);
 TupleDescInitEntry(tupdesc, (AttrNumber) 3,
        "strong_refuted_by", BOOLOID, -10);
 TupleDescInitEntry(tupdesc, (AttrNumber) 4,
        "weak_refuted_by", BOOLOID, -10);
 TupleDescInitEntry(tupdesc, (AttrNumber) 5,
        "s_i_holds", BOOLOID, -10);
 TupleDescInitEntry(tupdesc, (AttrNumber) 6,
        "w_i_holds", BOOLOID, -10);
 TupleDescInitEntry(tupdesc, (AttrNumber) 7,
        "s_r_holds", BOOLOID, -10);
 TupleDescInitEntry(tupdesc, (AttrNumber) 8,
        "w_r_holds", BOOLOID, -10);
 tupdesc = BlessTupleDesc(tupdesc);

 values[0] = BoolGetDatum(strong_implied_by);
 values[1] = BoolGetDatum(weak_implied_by);
 values[2] = BoolGetDatum(strong_refuted_by);
 values[3] = BoolGetDatum(weak_refuted_by);
 values[4] = BoolGetDatum(s_i_holds);
 values[5] = BoolGetDatum(w_i_holds);
 values[6] = BoolGetDatum(s_r_holds);
 values[7] = BoolGetDatum(w_r_holds);

 PG_RETURN_DATUM(HeapTupleGetDatum(heap_form_tuple(tupdesc, values, nulls)));
}

Messung V0.5 in Prozent
C=94 H=90 G=91

¤ Dauer der Verarbeitung: 0.14 Sekunden  (vorverarbeitet am  2026-08-08) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.