Мне тут надо чтобы по запросу всегда выдавалась одна запись. Если записи нет, то онна должна быть создана.

Для этого я состряпал нехитрую процедуру:

CREATE PROCEDURE GET_COMMENTING_THREAD(
    OBJECT_ID INTEGER,
    OBJECT_TYPE_ID INTEGER,
    OWNER_ID INTEGER)
RETURNS (
    "DB_KEY" CHAR(8) CHARACTER SET OCTETS)
AS
BEGIN
  SELECT RDB$DB_KEY FROM "CommentingThreads" T
    WHERE T."ObjectId" = :OBJECT_ID AND T."ObjectTypeId" = :OBJECT_TYPE_ID
    INTO :DB_KEY;

  IF (ROW_COUNT = 0) THEN
    INSERT INTO "CommentingThreads" ("ObjectId", "ObjectTypeId", "OwnerId")
      VALUES (:OBJECT_ID, :OBJECT_TYPE_ID, :OWNER_ID)
      RETURNING RDB$DB_KEY INTO :DB_KEY;

  SUSPEND;
END


Теперь вызываю её для уже созданной записи во вроде бы эквивалентных запросах и наблюдаю подозрительное поведение во втором случае:

1) Всё нормально - два индексированнных чтения показывает. Ну оно и понятно - сначала DB_KEY выбирается, а потом запись по нему.

SELECT T.* FROM GET_COMMENTING_THREAD(1, 1, 8) G
LEFT JOIN "CommentingThreads" T ON T.RDB$DB_KEY = G."DB_KEY"

PLAN JOIN (T INDEX (UNQ1_CommentingThreads), T INDEX ())


2) А вот тут лажа получается: DB_KEY в процедуре выгребается нормально, а потом вся таблица целиком проходится

SELECT * FROM "CommentingThreads" T
WHERE T.RDB$DB_KEY = (SELECT "DB_KEY" FROM GET_COMMENTING_THREAD(2, 1, 8))

PLAN (T INDEX (UNQ1_CommentingThreads)) PLAN (T NATURAL)



На 2.1 проверить не могу. Читал что в 2.1 что-то фиксилось с ДБ-кеями. Вот не знаю надо в трекер писать или нет...

Ответить