|
1 | 1 | /*
|
2 |
| - * $Header: /cvsroot/pgsql/src/test/regress/regress.c,v 1.15 1997/09/18 20:22:54 momjian Exp $ |
| 2 | + * $Header: /cvsroot/pgsql/src/test/regress/regress.c,v 1.16 1997/09/24 08:35:10 vadim Exp $ |
3 | 3 | */
|
4 | 4 |
|
5 | 5 | #include <float.h> /* faked on sunos */
|
@@ -411,3 +411,232 @@ funny_dup17()
|
411 | 411 |
|
412 | 412 | return (tuple);
|
413 | 413 | }
|
| 414 | + |
| 415 | +#include <ctype.h> /* tolower () */ |
| 416 | + |
| 417 | +HeapTuple ttdummy(void); |
| 418 | +int32 set_ttdummy(int32 on); |
| 419 | + |
| 420 | +extern int4 nextval(struct varlena * seqin); |
| 421 | + |
| 422 | +#define TTDUMMY_INFINITY 999999 |
| 423 | + |
| 424 | +static void *splan = NULL; |
| 425 | +static bool ttoff = false; |
| 426 | + |
| 427 | +HeapTuple |
| 428 | +ttdummy() |
| 429 | +{ |
| 430 | + Trigger *trigger; /* to get trigger name */ |
| 431 | + char **args; /* arguments */ |
| 432 | + int attnum[2]; /* fnumbers of start/stop columns */ |
| 433 | + Datum oldon, oldoff; |
| 434 | + Datum newon, newoff; |
| 435 | + Datum *cvals; /* column values */ |
| 436 | + char *cnulls; /* column nulls */ |
| 437 | + char *relname; /* triggered relation name */ |
| 438 | + Relation rel; /* triggered relation */ |
| 439 | + HeapTuple trigtuple; |
| 440 | + HeapTuple newtuple = NULL; |
| 441 | + HeapTuple rettuple; |
| 442 | + TupleDesc tupdesc; /* tuple description */ |
| 443 | + int natts; /* # of attributes */ |
| 444 | + bool isnull; /* to know is some column NULL or not */ |
| 445 | + int ret; |
| 446 | + int i; |
| 447 | + |
| 448 | + if (!CurrentTriggerData) |
| 449 | + elog(WARN, "ttdummy: triggers are not initialized"); |
| 450 | + if (TRIGGER_FIRED_FOR_STATEMENT(CurrentTriggerData->tg_event)) |
| 451 | + elog(WARN, "ttdummy: can't process STATEMENT events"); |
| 452 | + if (TRIGGER_FIRED_AFTER(CurrentTriggerData->tg_event)) |
| 453 | + elog(WARN, "ttdummy: must be fired before event"); |
| 454 | + if (TRIGGER_FIRED_BY_INSERT(CurrentTriggerData->tg_event)) |
| 455 | + elog (WARN, "ttdummy: can't process INSERT event"); |
| 456 | + if (TRIGGER_FIRED_BY_UPDATE(CurrentTriggerData->tg_event)) |
| 457 | + newtuple = CurrentTriggerData->tg_newtuple; |
| 458 | + |
| 459 | + trigtuple = CurrentTriggerData->tg_trigtuple; |
| 460 | + |
| 461 | + rel = CurrentTriggerData->tg_relation; |
| 462 | + relname = SPI_getrelname(rel); |
| 463 | + |
| 464 | + /* check if TT is OFF for this relation */ |
| 465 | + if (ttoff) /* OFF - nothing to do */ |
| 466 | + { |
| 467 | + pfree (relname); |
| 468 | + return ((newtuple != NULL) ? newtuple : trigtuple); |
| 469 | + } |
| 470 | + |
| 471 | + trigger = CurrentTriggerData->tg_trigger; |
| 472 | + |
| 473 | + if (trigger->tgnargs != 2) |
| 474 | + elog(WARN, "ttdummy (%s): invalid (!= 2) number of arguments %d", |
| 475 | + relname, trigger->tgnargs); |
| 476 | + |
| 477 | + args = trigger->tgargs; |
| 478 | + tupdesc = rel->rd_att; |
| 479 | + natts = tupdesc->natts; |
| 480 | + |
| 481 | + CurrentTriggerData = NULL; |
| 482 | + |
| 483 | + for (i = 0; i < 2; i++ ) |
| 484 | + { |
| 485 | + attnum[i] = SPI_fnumber (tupdesc, args[i]); |
| 486 | + if ( attnum[i] < 0 ) |
| 487 | + elog(WARN, "ttdummy (%s): there is no attribute %s", relname, args[i]); |
| 488 | + if (SPI_gettypeid (tupdesc, attnum[i]) != INT4OID) |
| 489 | + elog(WARN, "ttdummy (%s): attributes %s and %s must be of abstime type", |
| 490 | + relname, args[0], args[1]); |
| 491 | + } |
| 492 | + |
| 493 | + oldon = SPI_getbinval (trigtuple, tupdesc, attnum[0], &isnull); |
| 494 | + if (isnull) |
| 495 | + elog(WARN, "ttdummy (%s): %s must be NOT NULL", relname, args[0]); |
| 496 | + |
| 497 | + oldoff = SPI_getbinval (trigtuple, tupdesc, attnum[1], &isnull); |
| 498 | + if (isnull) |
| 499 | + elog(WARN, "ttdummy (%s): %s must be NOT NULL", relname, args[1]); |
| 500 | + |
| 501 | + if (newtuple != NULL) /* UPDATE */ |
| 502 | + { |
| 503 | + newon = SPI_getbinval (newtuple, tupdesc, attnum[0], &isnull); |
| 504 | + if (isnull) |
| 505 | + elog(WARN, "ttdummy (%s): %s must be NOT NULL", relname, args[0]); |
| 506 | + newoff = SPI_getbinval (newtuple, tupdesc, attnum[1], &isnull); |
| 507 | + if (isnull) |
| 508 | + elog(WARN, "ttdummy (%s): %s must be NOT NULL", relname, args[1]); |
| 509 | + |
| 510 | + if ( oldon != newon || oldoff != newoff ) |
| 511 | + elog (WARN, "ttdummy (%s): you can't change %s and/or %s columns (use set_ttdummy)", |
| 512 | + relname, args[0], args[1]); |
| 513 | + |
| 514 | + if ( newoff != TTDUMMY_INFINITY ) |
| 515 | + { |
| 516 | + pfree (relname); /* allocated in upper executor context */ |
| 517 | + return (NULL); |
| 518 | + } |
| 519 | + } |
| 520 | + else if (oldoff != TTDUMMY_INFINITY) /* DELETE */ |
| 521 | + { |
| 522 | + pfree (relname); |
| 523 | + return (NULL); |
| 524 | + } |
| 525 | + |
| 526 | + { |
| 527 | + struct varlena *seqname = textin ("ttdummy_seq"); |
| 528 | + |
| 529 | + newoff = nextval (seqname); |
| 530 | + pfree (seqname); |
| 531 | + } |
| 532 | + |
| 533 | + /* Connect to SPI manager */ |
| 534 | + if ((ret = SPI_connect()) < 0) |
| 535 | + elog(WARN, "ttdummy (%s): SPI_connect returned %d", relname, ret); |
| 536 | + |
| 537 | + /* Fetch tuple values and nulls */ |
| 538 | + cvals = (Datum *) palloc (natts * sizeof (Datum)); |
| 539 | + cnulls = (char *) palloc (natts * sizeof (char)); |
| 540 | + for (i = 0; i < natts; i++) |
| 541 | + { |
| 542 | + cvals[i] = SPI_getbinval ((newtuple != NULL) ? newtuple : trigtuple, |
| 543 | + tupdesc, i + 1, &isnull); |
| 544 | + cnulls[i] = (isnull) ? 'n' : ' '; |
| 545 | + } |
| 546 | + |
| 547 | + /* change date column(s) */ |
| 548 | + if (newtuple) /* UPDATE */ |
| 549 | + { |
| 550 | + cvals[attnum[0] - 1] = newoff; /* start_date eq current date */ |
| 551 | + cnulls[attnum[0] - 1] = ' '; |
| 552 | + cvals[attnum[1] - 1] = TTDUMMY_INFINITY; /* stop_date eq INFINITY */ |
| 553 | + cnulls[attnum[1] - 1] = ' '; |
| 554 | + } |
| 555 | + else /* DELETE */ |
| 556 | + { |
| 557 | + cvals[attnum[1] - 1] = newoff; /* stop_date eq current date */ |
| 558 | + cnulls[attnum[1] - 1] = ' '; |
| 559 | + } |
| 560 | + |
| 561 | + /* if there is no plan ... */ |
| 562 | + if (splan == NULL) |
| 563 | + { |
| 564 | + void *pplan; |
| 565 | + Oid *ctypes; |
| 566 | + char sql[8192]; |
| 567 | + |
| 568 | + /* allocate ctypes for preparation */ |
| 569 | + ctypes = (Oid *) palloc(natts * sizeof(Oid)); |
| 570 | + |
| 571 | + /* |
| 572 | + * Construct query: |
| 573 | + * INSERT INTO _relation_ VALUES ($1, ...) |
| 574 | + */ |
| 575 | + sprintf(sql, "INSERT INTO %s VALUES (", relname); |
| 576 | + for (i = 1; i <= natts; i++) |
| 577 | + { |
| 578 | + sprintf(sql + strlen(sql), "$%d%s", |
| 579 | + i, (i < natts) ? ", " : ")"); |
| 580 | + ctypes[i - 1] = SPI_gettypeid(tupdesc, i); |
| 581 | + } |
| 582 | + |
| 583 | + /* Prepare plan for query */ |
| 584 | + pplan = SPI_prepare(sql, natts, ctypes); |
| 585 | + if (pplan == NULL) |
| 586 | + elog(WARN, "ttdummy (%s): SPI_prepare returned %d", relname, SPI_result); |
| 587 | + |
| 588 | + pplan = SPI_saveplan(pplan); |
| 589 | + if (pplan == NULL) |
| 590 | + elog(WARN, "ttdummy (%s): SPI_saveplan returned %d", relname, SPI_result); |
| 591 | + |
| 592 | + splan = pplan; |
| 593 | + } |
| 594 | + |
| 595 | + ret = SPI_execp(splan, cvals, cnulls, 0); |
| 596 | + |
| 597 | + if (ret < 0) |
| 598 | + elog(WARN, "ttdummy (%s): SPI_execp returned %d", relname, ret); |
| 599 | + |
| 600 | + /* Tuple to return to upper Executor ... */ |
| 601 | + if (newtuple) /* UPDATE */ |
| 602 | + { |
| 603 | + HeapTuple tmptuple; |
| 604 | + |
| 605 | + tmptuple = SPI_copytuple (trigtuple); |
| 606 | + rettuple = SPI_modifytuple (rel, tmptuple, 1, &(attnum[1]), &newoff, NULL); |
| 607 | + SPI_pfree (tmptuple); |
| 608 | + } |
| 609 | + else /* DELETE */ |
| 610 | + rettuple = trigtuple; |
| 611 | + |
| 612 | + SPI_finish(); /* don't forget say Bye to SPI mgr */ |
| 613 | + |
| 614 | + pfree (relname); |
| 615 | + |
| 616 | + return (rettuple); |
| 617 | +} |
| 618 | + |
| 619 | +int32 |
| 620 | +set_ttdummy(int32 on) |
| 621 | +{ |
| 622 | + |
| 623 | + if (ttoff) /* OFF currently */ |
| 624 | + { |
| 625 | + if (on == 0) |
| 626 | + return (0); |
| 627 | + |
| 628 | + /* turn ON */ |
| 629 | + ttoff = false; |
| 630 | + return (0); |
| 631 | + } |
| 632 | + |
| 633 | + /* ON currently */ |
| 634 | + if (on != 0) |
| 635 | + return (1); |
| 636 | + |
| 637 | + /* turn OFF */ |
| 638 | + ttoff = true; |
| 639 | + |
| 640 | + return (1); |
| 641 | + |
| 642 | +} |
0 commit comments