docs: private void XreadWithList(WithList withList) {
          // <with list element> ::= <query name>
          //                         [ <left paren> <with column list> <right paren> ]
          //                         AS <left paren> <query expression> <right paren>
          //                         [ <search or cycle clause> ]
          //
          boolean recursive = withList.isRecursive();
          for (boolean done = false; ! done; done = ! readIfThis(Tokens.COMMA)) {
              HsqlName queryName = readNewSchemaObjectName(SchemaObject.TABLE);
              queryName.setSchemaIfNull(session.getCurrentSchemaHsqlName());
              List<HsqlName> columnNames = parseColumnNames();
              readThis(Tokens.AS);
              readThis(Tokens.OPENBRACKET);
              // Read a query.  If it's recursive it has to be of the form:
              //    Q1 union all Q2.
              // In Q1 we can't use an order by or limit.  It's ok
              // to use group by, aggregates and having, though.  The
              // query name will be visible in Q2 but not in Q1.
              //
              // If this with statement is not recursive then anything goes,
              // but the query name will not be visible in the query.
              QueryExpression baseQueryExpression = null;
              QueryExpression recursionQueryExpression = null;
              // This is not really standard behavior.  This should
              // really be just reading a query expression.  However,
              // This short circuits a great deal of complexity, and
              // will serve for prototype purposes.
              if (recursive) {
                  baseQueryExpression = XreadQueryPrimary();
              } else {
                  baseQueryExpression = XreadQueryExpressionBodyAndSortAndSlice();
              }
              // We have to resolve this here because we need
              // to fetch the types and perhaps the column aliases.
              // But we can't define the table now, because it is
              // not visible in the base query expression.
              baseQueryExpression.resolve(session);
              //
              // Calculate the schema of the common table.
              //
              HsqlName[] colNames = null;
              if (columnNames != null) {
                  colNames = columnNames.toArray(new HsqlName[columnNames.size()]);
              } else {
                  String[] queryNames = baseQueryExpression.getColumnNames();
                  colNames = new HsqlName[queryNames.length];
                  for (int idx = 0; idx < queryNames.length; idx += 1) {
                      String queryColumnName = queryNames[idx];
                      colNames[idx] = database.nameManager.newHsqlName(queryColumnName,
                                                                       false,
                                                                       SchemaObject.COLUMN);
                  }
              }
              Type[] colTypes = baseQueryExpression.getColumnTypes();
              String cmp = null;
              if (colNames.length > colTypes.length) {
                  cmp = "many";
              }
              else if (colNames.length < colTypes.length) {
                  cmp = "few";
              }
              if (cmp != null) {
                  throw Error.error("Too " + cmp + " column names in common table expression " + queryName.name);
              }
              // Now, define it.
              Table newTable = session.defineLocalTable(queryName, colNames, colTypes);
              if (recursive) {
                  readThis(Tokens.UNION);
                  readThis(Tokens.ALL);
                  recursionQueryExpression = XreadQueryExpressionBody();
              }
              readThis(Tokens.CLOSEBRACKET);
              WithExpression withExpression = new WithExpression();
              withExpression.setQueryName(queryName);
              withExpression.setBaseQuery(baseQueryExpression);
              withExpression.setRecursiveQuery(recursionQueryExpression);
              withExpression.setTable(newTable);
              withList.add(withExpression);
          }
      }