Subject | Re: [ib-support] Re: -- Comment |
---|---|
Author | Claudio Valderrama C. |
Post date | 2001-11-16T05:23:03Z |
""Fabrice Aeschbacher"" <fabrice.aeschbacher@...> wrote in
message news:<9t0nc1+kpik@...>...
/* INPUT TESTDATAS.SQL */ ;
Now, tell me, what do you get? Same error message, right? There are a couple
of problems here:
1.- Unlike MsSql, the IB/FB engine can handle only one statement at a time.
The client is responsible for doing that. If you use the API to send two
statements separated by semicolon and try to prepare, you will get an error.
2.- Second, the built-in utility that handles interactive SQL is just isql.
As Mark O'Donohue pointed out several months ago, it's really painful to
have to deal with two parsers: one in the engine at the DSQL layer, the
other inside isql. Mark wanted to fix isql to handle those cases but he
couldn't find time to do that. The isql parser is primitive. Remember it
needs the SET TERM kludge because it doesn't know the FB syntax, so it can't
tell when a stored proc definition has finished if not for the terminator.
The nice isql sends anything it finds when a semicolon appears, unless the
terminator has been changed as one needs to do when creating triggers and
procedures. When isql sees
/* comment */ ;
or
-- comment ;
it takes the whole line and sends it to the engine. Mark's opinion is that
isql should be cleverer.
3.- The de-facto terminator in the DSQL layer, hardcoded in dsql.c is the
semicolon. When given a statement, the DSQL layer does:
- scans the string right to left, finding the first non-blank character.
Then it sees if it's a semicolon and in this case, decrements the length of
the string, ignoring the semicolon for the next phases;
- initializes the parser, including the pointer to the input string;
- calls the main parsing routine that does the dirty job.
As you can see, there's no place in the engine where it can deal with
multiple statements in a single command line. The preparation phase needs
one statement at a time to return a handle or it would have to work in a
really tricky way, maybe returning an array of statement handles. It would
be horrible. When you send a comment (old style or single line comment)
followed by the colon, the engine calls the parsing routine, the parser
calls the lexer and the lexer exhausts the input string looking for
something "useful" that's outside a comment. There's nothing, so the parser
in turn returns a nod_null type, the engine tries to prepare this "nothing"
statement and fails, obviously.
4.- While I'm not the only one that dislikes yacc-based parsers, I have to
admit that its attractive is that you "declare" instead of "program" the
syntax. Same as SQL, you say what you want instead of how you want it: you
don't write a descending parser, same as you don't pass the engine a
function to access each record in disk. Unfortunately, yacc generates a
goto-based C file with global variables. Also, as SQL users know,
declarative programming has its limits and same as GDML will beat SQL for
some tasks, a custom-made parser will beat the yacc-generated parser when
the grammar becomes too complex. I wrote "grammar" because this is not a
matter of simple parsing... in the middle (while recognizing the syntax) you
should generate information for the next phase in the engine, in the form of
nodes, and this is where the problem starts. Making error reporting 5% more
useful was tricky, as I know because I implemented that. The "column
unknown" error will tell you now the name of the unrecognized column, for
example.
5.- While I agree in general terms that the our yacc-based parser is not the
best thing we have, I think that it's not the main culprit of what happens
there. Given that the engine processes one statement at a time, if you send
it a comment, it can do no other thing than complain, as it's doing. As Mark
said, make isql better if possible.
C.
---------
Claudio Valderrama C.
Ingeniero en Informática - Consultor independiente
http://www.cvalde.com - http://www.firebirdSQL.org
message news:<9t0nc1+kpik@...>...
>Fabrice, try this:
> If I do this, I getthe following error:
>
> -- INPUT TESTDATAS.SQL; /* Insert some test data */
> Statement failed, SQLCODE =3D -104
>
> Dynamic SQL Error
> -SQL error code =3D -104
> -Unexpected end of command
/* INPUT TESTDATAS.SQL */ ;
Now, tell me, what do you get? Same error message, right? There are a couple
of problems here:
1.- Unlike MsSql, the IB/FB engine can handle only one statement at a time.
The client is responsible for doing that. If you use the API to send two
statements separated by semicolon and try to prepare, you will get an error.
2.- Second, the built-in utility that handles interactive SQL is just isql.
As Mark O'Donohue pointed out several months ago, it's really painful to
have to deal with two parsers: one in the engine at the DSQL layer, the
other inside isql. Mark wanted to fix isql to handle those cases but he
couldn't find time to do that. The isql parser is primitive. Remember it
needs the SET TERM kludge because it doesn't know the FB syntax, so it can't
tell when a stored proc definition has finished if not for the terminator.
The nice isql sends anything it finds when a semicolon appears, unless the
terminator has been changed as one needs to do when creating triggers and
procedures. When isql sees
/* comment */ ;
or
-- comment ;
it takes the whole line and sends it to the engine. Mark's opinion is that
isql should be cleverer.
3.- The de-facto terminator in the DSQL layer, hardcoded in dsql.c is the
semicolon. When given a statement, the DSQL layer does:
- scans the string right to left, finding the first non-blank character.
Then it sees if it's a semicolon and in this case, decrements the length of
the string, ignoring the semicolon for the next phases;
- initializes the parser, including the pointer to the input string;
- calls the main parsing routine that does the dirty job.
As you can see, there's no place in the engine where it can deal with
multiple statements in a single command line. The preparation phase needs
one statement at a time to return a handle or it would have to work in a
really tricky way, maybe returning an array of statement handles. It would
be horrible. When you send a comment (old style or single line comment)
followed by the colon, the engine calls the parsing routine, the parser
calls the lexer and the lexer exhausts the input string looking for
something "useful" that's outside a comment. There's nothing, so the parser
in turn returns a nod_null type, the engine tries to prepare this "nothing"
statement and fails, obviously.
4.- While I'm not the only one that dislikes yacc-based parsers, I have to
admit that its attractive is that you "declare" instead of "program" the
syntax. Same as SQL, you say what you want instead of how you want it: you
don't write a descending parser, same as you don't pass the engine a
function to access each record in disk. Unfortunately, yacc generates a
goto-based C file with global variables. Also, as SQL users know,
declarative programming has its limits and same as GDML will beat SQL for
some tasks, a custom-made parser will beat the yacc-generated parser when
the grammar becomes too complex. I wrote "grammar" because this is not a
matter of simple parsing... in the middle (while recognizing the syntax) you
should generate information for the next phase in the engine, in the form of
nodes, and this is where the problem starts. Making error reporting 5% more
useful was tricky, as I know because I implemented that. The "column
unknown" error will tell you now the name of the unrecognized column, for
example.
5.- While I agree in general terms that the our yacc-based parser is not the
best thing we have, I think that it's not the main culprit of what happens
there. Given that the engine processes one statement at a time, if you send
it a comment, it can do no other thing than complain, as it's doing. As Mark
said, make isql better if possible.
C.
---------
Claudio Valderrama C.
Ingeniero en Informática - Consultor independiente
http://www.cvalde.com - http://www.firebirdSQL.org