question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

ISE caused by an object-returning function wrapped into a SELECT

See original GitHub issue
  • Error Message:
InternalServerError: there is no range var for (__derived__::expr~6) source in <pg.SelectStmt at 0x7efbfbfa67c0>
Hint: This is most likely a bug in EdgeDB. Please consider opening an issue ticket...
  • EdgeDB Version: 1.0a2-2020012220~buster
  • OS Version: Debian 10

Steps to Reproduce: 0. Create the database and module.

CREATE DATABASE name;
\c name;
...
CREATE MODULE api;
  1. Create the schema (shown at the bottom).
  2. Add the following DDL functions. The error occurs after attempting to run CREATE FUNCTION api::LoginCredentialSession.
WITH MODULE api
CREATE FUNCTION validate_credentials(EMAIL: str, PASS: str) -> SET OF api::User
USING EdgeQL $$
    WITH MODULE api
    SELECT
        User
    FILTER
        .email = EMAIL
        AND
        .password = PASS
    LIMIT 1
$$;

WITH MODULE api
CREATE FUNCTION random_big_str_id() -> str
USING EdgeQL $$
    SELECT 
        std::re_replace(
            r'^[ \t]+',
            r'',
            (
                SELECT std::to_str(
                    random() * 10 ^ 256, 
                    '999999999999999999999\
                     999999999999999999999\
                     999999999999999999999\
                     999999999999999999999\
                     999999999999999999999\
                     999999999999999999999\
                     999999999999999999999\
                     999999999999999999999\
                     999999999999999999999\
                     999999999999999999999\
                     999999999999999999999\
                     999999999999999999999\
                     99999'
                )
            )
        )
$$;

WITH MODULE api
CREATE FUNCTION create_new_session(EMAIL: str, PASS: str) -> api::Session
USING EdgeQL $$
    WITH MODULE api
    INSERT Session {
        token := <str>(SELECT api::random_big_str_id()),
        sessionID := <str>(SELECT api::random_big_str_id()),
        user := (SELECT api::validate_credentials(EMAIL, PASS) LIMIT 1)
    }
$$;
WITH MODULE api
CREATE FUNCTION LoginCredentialSession(EMAIL: str, PASS: str) -> SET OF api::Session
USING EdgeQL $$
    # First case to split on is whether the user
    # authenticates correctly:
    WITH MODULE api
    SELECT ( 
        SELECT Session
        FILTER .sessionID = (
            SELECT (SELECT api::create_new_session(EMAIL, PASS))
            ).sessionID
        )
    )
    IF
    (
        SELECT api::validate_credentials(EMAIL, PASS)) ?!= <Session>{}
    )
    ELSE <Session>{}
$$;

Schema:

CREATE MIGRATION %s TO {
    module api {
        type Session {
            property token -> str;
            required link user -> User;
            required property sessionID -> str;
            required property createdAt -> datetime {
                default := datetime_current();
            }
            required property allottedDuration -> duration {
                default := <duration>'24 hours';
            }
        }
        type User {
            required property name -> str;
            property isDevice -> bool {
                default := False
            }
            link device -> Device;
            multi link devices -> Device;
            property phone_1 -> str {
                default := '';
            }
            property phone_2 -> str {
                default := '';
            }
            property email -> str;
            property storageDirectory := ('/' ++ __source__.email ++ '/');
            property _storageDirectory := ('/ware/blob' ++ __source__.storageDirectory);
            property password -> str;
            property isAdmin -> bool {
                default := False;
            }
            required property isGuest -> bool {
                default := False;
            }
            multi link files -> File;
            multi link widgets -> Widget;
        }
        type Device {
            property device_name -> str;
            property ipv4_address -> str;
            property ipv6_address -> str;
            property mac_address -> str;
            property online -> bool;
        }
        type Widget {
            required property name -> str;
            property path -> str;
            property executable_name -> str;
            property indexHtmlPath -> str;
            property runCommand -> str;
        }
        type File {
            required property filename -> str;
            required property path -> str;
            required property readable -> bool {
                default := True;
            }
            required property writeable -> bool {
                default := True;
            }
            required property executable -> bool {
                default := False;
            }
            required property isDirectory -> bool {
                default := False;
            }
            required property isPublic -> bool {
                default := False;
            }
            required property isDownloadable -> bool {
                default := True;
            }
            property uploadedBy -> str;
            property uploadedAt -> datetime {
                default := datetime_current();
            }
            required property temporary -> bool {
                default := False;
            }
        }
    }
};
COMMIT MIGRATION %s;

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Comments:6 (6 by maintainers)

github_iconTop GitHub Comments

1reaction
elpranscommented, Feb 23, 2020

The syntax is FOR variable IN { <set> }, where <set> is an arbitrary expression of type T, and variable would hold a singleton value of the type T on every “iteration”. The curly brackets in this case are needed for grammar disambiguation.

1reaction
elpranscommented, Feb 23, 2020

Actually, there’s a way to do this using a FOR statement. Here’s the solution:

WITH MODULE api
FOR user IN {api::validate_credentials(EMAIL, PASSWORD)}
 UNION (
     INSERT Session { user := user, sessionID := ... }
);
Read more comments on GitHub >

github_iconTop Results From Across the Web

Lodash Documentation
Creates an array of elements split into groups the length of size . ... Subsequent calls to the created function return the result...
Read more >
JavaScript methods index - MDN - LIA
defineProperties() method defines new or modifies existing properties directly on an object, returning the object.
Read more >
To Null, or not to Null?!? - Medium
I'll start this post with a question: Who is responsible for a NullReferenceException being thrown? Is it the dev who forgot to check...
Read more >
IBrokers: R API to Interactive Brokers Trader Workstation
Setting debug=NULL will cause empty function objects to be created within the eWrapper object returned. This object can be treated as a ...
Read more >
bootstrap-vue - UNPKG
querySelectorAll(selector))\n\n// Select a single element, returns `null` if not ... whileOpenListen(true)\n\n // Wrap in nextTick to ensure menu is fully ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found