anchor.diff:  === Stored procedures
   
   A stored procedure has a name and takes a fixed number of named and typed arguments in a fixed sequence and either just
  -yields nothing (i.e. causes a side effect) or yields a stream of result records.  Each record yielded contains values for a fixed number of named and typed columns in the same fixed sequence such that each column value in a yielded record
  -matches its column's type.
  -
  -The name of the stored procedure, its argument names, and if applicable any result column names must not contain any
  -leading or trailing whitespace characters and must not be empty.
  -
  -The arguments of the procedure, their types, and their order are called its argument signature. All information about
  -what is being returned by the procedure (either if the procedure yields nothing or the result columns, their types, and
  -their order) are called the result signature of the procedure. Together, the argument signature and the result signature
  -form the (full) signature of the stored procedure.
  -
  -Note that according to this definition a procedure may take zero arguments and/or may yield zero result columns.
  -
  -Procedures may be written in different programming languages and provided with APIs for accessing the underlying graph
  -database or graph processing system as dictated by the implementation.
  -
  -=== Calling stored procedures
  -
  -A procedure call constitutes an entire Cypher statement. According to this CIP, a procedure cannot be used alongside
  -other clauses. It is intended that this restriction will be lifted in the future.
  -
  -Calling a stored procedures requires providing it with argument values. This may be done in one of two ways.
  -
  -==== Call with arguments
  -
  -Arguments are provided as a sequence of expressions as required by the procedure's signature. To call the procedure, all
  -argument expressions are evaluated to argument values in order. It is an error if the number of provided arguments
  -differs from the number of arguments required by the procedure's argument signature. It is an error if the argument
  -values are incompatible with the argument types required by the procedure's argument signature.
  -
  -[source, cypher]
  -----
  -CALL myProc("Test", 1+2)
  -----
  -
  -==== Call with parameters
  -
  -Arguments are provided as parameters to the Cypher query. To call the procedure, the argument values are obtained by
  -using the parameter in scope with the same name as the argument. If such a parameter does not exist, the argument value
  -is assumed to be `NULL`. It is an error, if the resulting argument values are incompatible with the argument types
  -required by the procedure's argument signature.
  -
  +yields nothing (i.e. only potentially causes a side effect) or yields a stream of result records.
  +Each record yielded contains values for a fixed number of named and typed fields in the same fixed sequence such that each field value in a yielded record matches its field's type.
  +
  +The name of a stored procedure, its argument names, and if applicable any result field names follow the same rules as other symbolic names in Cypher (like variables, labels, relationship types, and property keys).
  +
  +==== Procedure signatures
  +
  +The arguments of a procedure, their types, and their order are called its argument signature.
  +All information about what is being returned by the procedure (either if the procedure yields nothing or the yielded result field names and types, as well as their order) are called the result signature of the procedure.
  +Together, the argument signature and the result signature form the (full) signature of a stored procedure.
  +
  +According to this definition, a procedure may take zero arguments and/or may yield records with zero result fields.
  +Note that yielding records with zero result fields is considered different from yielding nothing.
  +
  +==== Procedure signature notation
  +
  +This CIP suggests a standard notation for printing procedure names together with their signatures.
  +This notation may be used in system monitoring, documentation and error reporting, and perhaps more importantly is to be used in future CIPs.
  +It is based on the syntax for type annotations as specified by the Cypher type system:
  +
  +- Procedures returning nothing: `<procName>(arguments) :: VOID`
  +- Procedures returning a stream of records: `<procName>(arguments) :: (results)`
  +- Arguments and results are written as comma-separated lists of `<name> :: <type>`
  +
  +An actual implementation may choose to support a notion of default value for procedure arguments.
  +For such a case, this CIP suggests that arguments with default values are written as `<name> = <value> :: <type`.
  +
  +==== Procedure implementation
  +
  +In an actual implementation, procedures may be written in different programming languages and provided with APIs for accessing the underlying graph database or graph processing system as appropriate.
  +The details of this are outside of the scope of this proposal.
  +
  +=== Procedure calls
  +
  +Procedures are called for each incoming record produced by preceding clauses and each time produce arbitrary many result rows. If a statement starts with a procedure call, this call is executed once, i.e. procedure calls behave similiar to `UNWIND` regarding how they change the result cardinality.
  +
  +We propose new syntax that introduces a new clause for calling procedures.
  +This clause for calling procedures starts with the `CALL` keyword.
  +Next follows the actual call (i.e. procedure name and arguments in signature order).
  +Finally (and optionally) the clause may end with the `YIELD` keyword followed by any chosen result field projections.
  +
  +A procedure call constitutes either an entire Cypher statement (i.e. is a "standalone call"), or is called as part of a larger query (i.e. is an "in-query call"). In standalone calls, arguments may be either passed implicitly or explicitly. These different calling modes are detailed in the following subsections.
  +
  +==== In-query calls
  +
  +Calling a procedure as part of a larger query follows three basic rules:
  +
  +- All arguments are always passed explicitly in the order given by the signature.
  +- Result fields are projected and appended as new variable bindings explicitly in the order given by the procedure call.
  +- New variable bindings projected from result fields are not allowed to shadow existing variable bindings that are already in scope.
  +
  +These rules ensure that looking at a procedure call provides enough information to ascertain it's impact on the variable scope in it's part of the query without having to be aware of any other already bound variables.
  +
  +As a basic example, consider a call to the stored procedure `myProc(name``::``STRING?``,``id``::``INTEGER?)``::`` (last``::``STRING?)`:
  +
  +.Calling stored procedure inside a larger query
  +[source, cypher]
  +----
  +MATCH (n:Person)-[r:IN]->(g:Group)
  +CALL myProc(n.name, g.id*1000+r.id) YIELD last AS lastLogin
  +RETURN *
  +----
  +
  +This calls `myProc` for each record produced by the preceding `MATCH` clause with a `name` argument obtained by evaluating `n.name` and an `id` argument obtained by evaluating `g.id*1000+r.id`.
  +Each call may yield multiple procedure result records with a single result field `last`.
  +For each of them, a new statement result record is created that contains the original variables already in scope (i.e. `n`, `r`, `g`) as well as the projected result field `last` renamed as `lastLogin`.
  +
  +The `YIELD` subclause may be omitted.
  +In this case the procedure is still called; it just does not project any result fields and introduces no new variable bindings.
  +
  +The `YIELD` subclause is always omitted if the procedure returns nothing (i.e. is of type `VOID`).
  +As an example, consider a call to the stored procedure `myVoidProc(name``::``STRING?``,``id``::``INTEGER?)``::``VOID`:
  +
  +.Calling a stored procedure that returns nothing
  +[source, cypher]
  +----
  +MATCH (n:Person)-[r:IN]->(g:Group)
  +CALL myVoidProc(n.name, g.id*1000+r.id)
  +RETURN n.name AS name
  +----
  +
  +This will behave in the same way as above but since the procedure now returns nothing, calling it will not change the result cardinality, i.e. conceptually the procedure is called once for each record produced by `MATCH` and will just pass that record on to `RETURN`.
  +
  +=== Standalone calls
  +
  +Procedures may also be called standalone, i.e. without taking arguments from or combining their results with other parts of a larger query.
  +In this case, the trailing `RETURN` clause may be omitted and all variable in scope are returned implicitly by the statement.
  +Furthermore, we propose two optional simplifications that are available for standalone calls only.
  +These simplifications are outlined in the following:
  +
  +==== Calling with implicitly passed arguments (parameters)
  +
  +Standalone calls may ommit passing arguments explicitly.  In this case, all required procedure arguments are taken implicitly from statement parameters with the same name.
  +
  +Again consider a call to the stored procedure `myProc(name``::``STRING?``,``id``::``INTEGER?)``::`` (last``::``STRING?)`:
  +
  +.Standalone call to a stored procedure using implicitly passed arguments
  +[source, cypher]
  +----
  +CALL myProc YIELD last AS lastLogin
  +----
  +
  +This is the same as executing:
  +
  +.Standalone call to a stored procedure using explicitly passed arguments
  +[source, cypher]
  +----
  +CALL myProc({name}, {id}) YIELD last AS lastLogin
  +----
  +
  +==== Calling without `YIELD`
  +
  +Standalone calls that ommit the `YIELD` subclause will always project out all result fields.
  +
  +Again consider a call to the stored procedure `myProc(name``::``STRING?``,``id``::``INTEGER?)``::`` (last``::``STRING?)`:
  +
  +.Standalone call to a stored procedure without `YIELD`
  +[source, cypher]
  +----
  +CALL myProc("Donald", 12)
  +----
  +
  +This is the same as executing:
  +
  +.Equivalent in-query call for standalone call to a stored procedure without `YIELD`
  +[source, cypher]
  +----
  +CALL myProc("Donald", 12) YIELD last
  +RETURN *
  +----
  +
  +Note that omitting `YIELD` in standalon calls projects out all result fields while omitting it when calling a procedure inside a larger query projects out no result fields.
  +
  +==== Calling with implicitly passed arguments (parameters) and without `YIELD`
  +
  +Both simplifications may be used in a single standalone procedure call, leading to a very concise syntax for just executing a single procedure call:
  +
  +.Simplified standalone procedure call
   [source, cypher]
   ----
   CALL myProc
   ----
   
  -=== Executing a procedure call
  +=== Procedure call semantics details
   
   The technical details of how procedure calls are executed are left to the implementation as long as they do not violate
   the following rules:
   
   It is an error if calling a procedure fails to yield results in accordance with its declared result signature.
   
  -If calling a procedure yields nothing, the Cypher statement for the procedure call yields no rows and the list of return columns is empty.
  -
  -If calling a procedure yields records, these records are yielded from the Cypher statement for the procedure call in the same order as they are yielded by the procedure and the list of return columns of the statement is set to be the sequence of result columns of the procedure's result signature.
  -
  -If a procedure call fails to execute ("throws an exception"), this error is propagated to the user in the same way
  -as other runtime errors are propagated to the user by the implementation. The error message should provide the
  -user at least with the name of the failed stored procedures, its signature, and all argument values.
  -
  -If executing a procedure call causes any side effects ("writes to the database"), all such changes must be executed
  +A standalone call to a procedure that yields nothing returns no result records for the whole Cypher statement.
  +
  +An in-query call to a procedure that yields nothing executes the whole procedure without projecting any result fields and without changing the cardinality of the input record (i.e. all incoming records just pass through).
  +
  +If calling a procedure yields records, these records are yielded from the Cypher statement (or clause resp.) for the procedure call in the same order as they are yielded by the procedure.
  +
  +If a procedure call fails to execute (i.e. it "throws an exception"), this error is propagated to the user in the same way as other runtime errors are propagated to the user by the implementation.
  +
  +If executing a procedure call causes any side effects (i.e. it "updates the graph"), all such changes should be executed
   before any results are returned to the user. An implementation may provide the user with a way to opt out of this
  -behavior for a procedure, however this must be done explicitly (by configuration or annotation of the procedure).
  -
  -=== Syntax
  -
  -[source, ebnf]
  -----
  -statement          = procedure call
  -                   | ...
  -                   ;
  -
  -procedure call     = "CALL", procedure name, "(", [ expression,  { ",", expression } ], ")"
  -                   | "CALL", procedure name
  -                   ;
  -
  -procedure name     = identifier ;
  -----
  +behavior, however this must be done explicitly (e.g. via a configuration setting).
  +
  +==== Semantic details of explicit argument passing
  +
  +In this scenario, arguments are provided explicitly as a sequence of expressions as required by the procedure's signature.
  +It is an error if the number of provided arguments differs from the number of arguments required by the procedure signature.
  +
  +To call the procedure, all argument expressions are evaluated to argument values in order.
  +It is an error if the argument values are incompatible with the argument types required by the procedure signature.
  +
  +==== Semantic details of implicit argument passing
  +
  +In this scenario, arguments are providede implicitly via the parameters of the Cypher statement.
  +
  +To call the procedure, the argument values are obtained by using the parameter in scope with the same name as the procedure argument.
  +If such a parameter does not exist, the argument value is taken to be `null`.
  +It is an error, if the resulting argument values are incompatible with the argument types required by the procedure  signature.
   
   == What others do
   
   The stored procedures survey (separate google doc) is extremely comprehensive, examining how stored procedures are
  -implemented and deployed as well as their API access mechanisms and usage. Products surveyed include PostgreSQL, MS SQL
  -Server, Oracle, MySQL, MongoDB, Aerospike and Virtuoso.
  +implemented and deployed as well as their API access mechanisms and usage.
  +Products surveyed include PostgreSQL, MS SQL Server, Oracle, MySQL, MongoDB, Aerospike and Virtuoso.
   
   == Benefits to this proposal
   
  
positive.code: 
  == Caveats to this proposal
  
  All of the following shall be dealt with as part of future work, or as part of an upcoming design sprint:
  
  * User-defined functions
  * The extension API
  * The mechanism by which results are delivered
  * Error handling
  
  == Appendix
  
  All content in this appendix is informative only. It serves to capture the discussion around this CIP.
  
  === Listing procedures
  
  The listing of procedures could be done in various ways, for example via dedicated syntax, a system graph, or a built-in
  procedure.  Any mechanism for listing should also extend to other schema artifacts, like indices or constraints and
  was thus considered out of scope for this CIP. Furthermore, it may be necessary to be able to filter the stored
  procedures listed when there are many.
  
  Suggested syntax for this feature was: `SHOW PROCEDURES` possibly followed by `STARTS WITH`, `CONTAINS`, or
  `ENDS WITH`.
  
  [source,cypher]
  ----
  SHOW PROCEDURES
  SHOW PROCEDURES WHERE name STARTS WITH "app."
  SHOW PROCEDURES WHERE name ENDS WITH "Info"
  ----
  
  Listing should return
  
  * the name of the procedure
  * the signature as a string
  * the language in which the procedure was written
  * possibly if the procedure is built-in or was user-defined
  
  === Supporting Procedures with more complex Signatures
  
  We could consider allowing a procedure to be able to accept any of the following:
  
  * Optional and default arguments
  * A variable number of arguments (similar to Java's variadic arguments)
  * Multiple argument groups
  
  Furthermore we could consider supporting calling procedures with explicitly named arguments (similar to Python's
  kwargs).
  
  These features should be introduced in a future CIP, if required.
  
negative.code: == Motivation & Background
  
  While Cypher is a very expressive graph query language, its declarative nature and scope is currently not sufficient for
  expressing certain classes of graph traversals, like traversals relying on using specialized data structures (e.g.
  queues) or on accessing third-party functionality.
  
  This CIP proposes to add stored procedures to Cypher in order to address these issues.
  
  