Class ProceduralExecutor

java.lang.Object
dev.frostlake.executor.ProceduralExecutor

public class ProceduralExecutor extends Object
  • Constructor Details

    • ProceduralExecutor

      public ProceduralExecutor()
  • Method Details

    • setQueryExecutor

      public void setQueryExecutor(QueryExecutor queryExecutor)
    • getQueryExecutor

      public QueryExecutor getQueryExecutor()
    • executeBlock

      public void executeBlock(ProceduralBlock block)
    • enterCompound

      public void enterCompound()
      A compound body run by another handler — an EXCEPTION handler's statements — is entered here.
    • exitCompound

      public void exitCompound()
    • pushDeclaredReturn

      public DeclaredReturnFrame pushDeclaredReturn(DataType returnsType, Set<String> parameterNames)
      Start a procedure body under its declared RETURNS type (null for a table-returning body), and hand back the caller's frame to put back when the body is done.
    • restoreDeclaredReturn

      public void restoreDeclaredReturn(DeclaredReturnFrame outer)
    • declaredReturnOfNextBlock

      public DataType declaredReturnOfNextBlock()
      The declared RETURNS type the block about to run judges its direct RETURNs against: only the procedure's OWN block, entered at the depth its body started from, and only for a scalar RETURNS type; null for every other block.
    • ownBlockParameterNames

      public Set<String> ownBlockParameterNames()
      The parameter names in scope of the block about to run: its procedure's signature when it is the procedure's OWN block, and none for any other block. The caller's variables are never among them.
    • getReturnedDeclaredType

      public DataType getReturnedDeclaredType()
      The declared RETURNS type the executed RETURN converted its value to, or null when it kept its own.
    • getReturnedResultType

      public DataType getReturnedResultType()
      The type the executed RETURN's result column declares (live-verified): the declared RETURNS type when the value converted to it, else the static type of the expression the RETURN names (see staticTypeOfReturn(dev.frostlake.executor.procedural.ReturnStatement, java.lang.Object)) — a text or a binary one at the column's full width either way, see AnonymousBlockResult.columnType(dev.frostlake.types.DataType) — else null, which leaves the column to the nominal VARCHAR.
    • pushContinueHandler

      public void pushContinueHandler(ContinueHandler handler)
      Push a block's CONTINUE handler while it executes, so enclosed loops can resume on a body error.
    • popContinueHandler

      public void popContinueHandler()
    • tryContinueHandler

      public boolean tryContinueHandler(Exception e)
      Offer an exception to the innermost active CONTINUE handler; true if it handled it (caller continues).
    • executeStatement

      public void executeStatement(Statement stmt)
      Run one statement, remembering WHERE it stood if it fails: an error escaping the block names the failing statement's own line and position, and the INNERMOST one wins because the record is taken as the exception unwinds and a later (outer) record is ignored. A statement that completes clears the record, so a handled failure does not label a later, unrelated one.
    • openCursorOverResultSet

      public void openCursorOverResultSet(Cursor cursor)
      Open a CURSOR FOR <resultset_var> over the RESULTSET's rows (empty if it does not resolve).
    • coerceArgument

      public Object coerceArgument(Object value, DataType type)
      A CALL argument under its parameter's declared type. A NUMBER argument is read at the declared scale (live: 1.7777 into a NUMBER(5,2) parameter is 1.78, and SYSTEM$TYPEOF of the parameter is NUMBER(5,2)) and a text into a DATE / TIME / TIMESTAMP parameter is read as one; a VARCHAR parameter's width is NOT enforced ('abcdef' into a VARCHAR(2) parameter answers abcdef on the account), so a text — and a container — passes untouched.
    • inferUntypedDeclarationType

      public DataType inferUntypedDeclarationType(BaseExpression initialiser)
      The type an UNTYPED declaration takes from its initialiser (live-verified): an integer literal makes a NUMBER(38,0), a decimal literal a FLOAT, and a NAME hands over its own type when that is a whole-number NUMBER — a FOR counter's NUMBER(9,0) — or FLOAT when it carries a scale (a NUMBER(10,4) holding 1.7777 makes a FLOAT). Any other initialiser is typed as a SQL expression by typeOfSqlInitialiser(dev.frostlake.executor.expressions.Expression).
    • typeOfSqlInitialiser

      public DataType typeOfSqlInitialiser(Expression sqlInitialiser)
      The type an untyped declaration takes from an initialiser inferUntypedDeclarationType(dev.frostlake.executor.procedural.BaseExpression) does not type directly — see DeclarationTypes — over the declared types in scope.
      Parameters:
      sqlInitialiser - the initialiser as a SQL expression, or null
      Returns:
      the declared type, or null when none can be determined
    • recordSqlRowCount

      public void recordSqlRowCount(ResultSet result)
      Record the DML-status globals after one executed SQL statement. A DML result — one carrying "number of rows …" (inserted / updated / deleted) columns — sets SQLROWCOUNT to the affected total, SQLFOUND/SQLNOTFOUND to whether that total is non-zero, and ACTIVITY_COUNT to the same total. EVERY OTHER completed statement — a SELECT, DDL, and TRUNCATE TABLE too — resets the three DML variables to NULL and sets ACTIVITY_COUNT to its own result's row count (a DDL status line counts 1, a SELECT its rows). All four start NULL. Live-verified, including the reset: a SELECT between the DML and the read answers NULL for the trio, and scripting-internal statements (LET, assignments, control flow) touch none of them. Called after each statement in a procedural block (top-level blocks execute their statements via the visitor, not executeSql).
    • recordStatementWithoutResult

      public void recordStatementWithoutResult()
      The DML-status effect of a completed statement whose result never surfaced as a result set.
    • pushHandledException

      public void pushHandledException(Exception e)
      Mark e as the exception now being handled (so a bare RAISE; inside the handler can re-raise it).
    • popHandledException

      public void popHandledException()
      Done handling the current exception.
    • getBlockDepth

      public int getBlockDepth()
      How many BEGIN…END blocks are currently open; 1 inside the outermost.
    • getCurrentHandledException

      public Exception getCurrentHandledException()
      The exception currently being handled, or null if not inside an exception handler.
    • hasException

      public boolean hasException(String name)
    • evaluateExpression

      public Object evaluateExpression(BaseExpression expr)
    • substituteBindVariables

      public String substituteBindVariables(String sql)
      Replace :varname bind-variable references in a SQL string with their current procedural-scope values, quoted as string literals.
    • enterScope

      public void enterScope()
    • exitScope

      public void exitScope()
    • enterIsolatedScope

      public void enterIsolatedScope()
      See Also:
    • markDeclaredInCurrentScope

      public void markDeclaredInCurrentScope(String name)
      Called when a variable is DECLARED (not just assigned) in the current scope.
    • getDeclaredVariableType

      public DataType getDeclaredVariableType(String name)
      The declared type recorded for a variable, or null when its declaration carried none.
    • declareVariableType

      public void declareVariableType(String name, DataType type)
    • setVariable

      public void setVariable(String name, Object value)
    • getVariable

      public Object getVariable(String name)
    • hasVariable

      public boolean hasVariable(String name)
      True when a procedural variable with this name exists in the current scope (even null-valued).
    • getAllVariables

      public Map<String,Object> getAllVariables()
    • lookupResultSet

      public ResultSet lookupResultSet(String rawName)
      For FROM TABLE(<name>) in procedural SQL: if name is an in-scope RESULTSET variable (raw ResultSet from := (EXECUTE IMMEDIATE …) or a ResultSetVariable from DEFAULT-init), return its rows (executing the DEFAULT query on first use); otherwise null. Lets the query-layer TABLE() resolver surface a procedural RESULTSET as a table source.
    • getReturnValue

      public Object getReturnValue()
    • hasReturned

      public boolean hasReturned()
    • hasBreak

      public boolean hasBreak()
    • hasContinue

      public boolean hasContinue()
    • clearReturnState

      public void clearReturnState()
    • recordStatementFailure

      public void recordStatementFailure(int line, int position)
      Remember where a failing statement stood — the FIRST record of a propagation wins, so the innermost statement names itself and the enclosing constructs it unwinds through do not.
    • recordExpressionFailure

      public void recordExpressionFailure(int line, int position)
      Remember where a failing EXPRESSION stood. Live splits the uncaught kinds by WHAT was running when the fault was raised: a fault from an expression is 'EXPRESSION_ERROR' anchored on the expression's own offset — a LET initialiser, an assignment's right side, a RETURN value, an IF condition — while a failing SQL statement stays 'STATEMENT_ERROR' at the statement's. The same first-record-wins rule applies, so the expression (which fails first, innermost) beats the statement record taken as the failure unwinds.
    • clearStatementFailure

      public void clearStatementFailure()
      Forget the last failure — a statement that COMPLETED means nothing is propagating any more.
    • getFailureKind

      public String getFailureKind()
      The uncaught kind live names for the recorded failure — see recordExpressionFailure(int, int).
    • getFailureLine

      public int getFailureLine()
      1-based line of the statement that is failing, or -1 when none is.
    • getFailurePosition

      public int getFailurePosition()
      0-based column of the statement that is failing.
    • enterBlock

      public void enterBlock()
    • exitBlock

      public void exitBlock()
      Mark that a BEGIN…END block handler has finished (nesting depth--).
    • isNestedBlock

      public boolean isNestedBlock()
      Whether the currently-executing BEGIN…END block is nested inside another one. A nested block's RETURN must be left in the return state (not consumed) so the enclosing block sees it and propagates it up.
    • isExecutingBlock

      public boolean isExecutingBlock()
      Whether a BEGIN…END block is currently executing. Transient procedural state (cursors, user-defined exceptions, declared variable types) belongs to that running block, so it must NOT be cleared while one is live — see clearCursorsAndExceptions().
    • clearCursorsAndExceptions

      public void clearCursorsAndExceptions()
      Clear cursors, exceptions, and declared variable types from a prior invocation so re-execution doesn't fail (or coerce against a stale declaration).
    • coerceToType

      public Object coerceToType(Object value, DataType type)
      Apply a DECLARED type to a value, exactly as the :: cast would — live converts at every assignment (a TZ initialiser assigned to a bare timestamp becomes the session mapping's NTZ, assigned to a date it truncates, a scalar assigned to an OBJECT is TO_OBJECT's own refusal and to an ARRAY it wraps), and the declared WIDTH is enforced: a too-long string is refused with the truncation sentence, never silently kept.
    • declaredExceptionNames

      public Set<String> declaredExceptionNames()
      The exception names declared so far. A nested block is validated as its own block when it runs, so the names an enclosing block declared have to be handed to it — and an exception is not a variable, so it would otherwise vanish from that seed.
    • saveCursorNames

      public Set<String> saveCursorNames()
    • restoreCursors

      public void restoreCursors(Set<String> savedNames)
    • getCursor

      public Cursor getCursor(String name)
    • registerCursor

      public void registerCursor(String name, Cursor cursor)
    • isReturnTable

      public boolean isReturnTable()
    • resetReturnTable

      public void resetReturnTable()