Changeset: e13fcc82b4d9 for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=e13fcc82b4d9
Modified Files:
monetdb5/extras/jaql/jaqlscenario.c
monetdb5/extras/jaql/jaqltests/Tests/documents.stable.err
monetdb5/extras/jaql/jaqltree.h
monetdb5/extras/jaql/parser/jaql.l
Branch: Oct2012
Log Message:
jaql: implemented multi-line input
The parser now requests (more) data from the stream, like the SQL
scanner does. This triggers the "more>" prompt in mclient when the
parser needs more data to complete the query.
diffs (261 lines):
diff --git a/monetdb5/extras/jaql/jaqlscenario.c
b/monetdb5/extras/jaql/jaqlscenario.c
--- a/monetdb5/extras/jaql/jaqlscenario.c
+++ b/monetdb5/extras/jaql/jaqlscenario.c
@@ -145,14 +145,19 @@ freeVariables(Client c, MalBlkPtr mb, Ma
str
JAQLreader(Client c)
{
- if (MCreadClient(c) > 0)
- return MAL_SUCCEED;
+ /* dummy stub, the scanner reads for us
+ * TODO: pre-fill the buf if we have single line mode */
- c->mode = FINISHING;
- if (c->fdin) {
- c->fdin->buf[c->fdin->pos] = 0;
- } else {
+ if (c->fdin == NULL)
throw(MAL, "jaql.reader", RUNTIME_IO_EOF);
+
+ /* "activate" the stream by sending a prompt (client sync) */
+ if (c->fdin->eof != 0) {
+ if (mnstr_flush(c->fdout) < 0) {
+ c->mode = FINISHING;
+ } else {
+ c->fdin->eof = 0;
+ }
}
return MAL_SUCCEED;
@@ -183,37 +188,36 @@ JAQLparser(Client c)
oldstop = c->curprg->def->stop;
j->vtop = oldvtop;
j->explain = j->plan = j->planf = j->debug = j->trace = j->mapimode = 0;
- j->buf = in->buf + in->pos;
+ j->buf = NULL;
+ j->scanstreamin = in;
+ j->scanstreamout = out;
+ j->scanstreameof = 0;
j->pos = 0;
j->p = NULL;
jaqlparse(j);
-
- /* now the parsing is done we should advance the stream */
- in->pos = in->len;
+
+ /* stop if it seems nothing is going to come any more */
+ if (j->scanstreameof == 1) {
+ c->mode = FINISHING;
+ freetree(j->p);
+ j->p = NULL;
+ return MAL_SUCCEED;
+ }
+
+ /* parsing is done */
+ in->pos = j->pos;
c->yycur = 0;
if (j->err[0] != '\0') {
/* tell the client */
mnstr_printf(out, "!%s\n", j->err);
- /* read away anything left */
- while (j->buf[j->pos + (j->tokstart - j->scanbuf)] != '\0') {
- freetree(j->p);
- jaqlparse(j);
- }
j->err[0] = '\0';
return MAL_SUCCEED;
}
- if (j->p == NULL) { /* there was nothing to parse, EOF */
- /* read away anything left */
- while (j->buf[j->pos + (j->tokstart - j->scanbuf)] != '\0') {
- freetree(j->p);
- jaqlparse(j);
- }
- j->err[0] = '\0';
+ if (j->p == NULL) /* there was nothing to parse, EOF */
return MAL_SUCCEED;
- }
if (!j->plan && !j->planf) {
Symbol prg = c->curprg;
@@ -246,12 +250,6 @@ JAQLparser(Client c)
}
}
- /* read away anything left */
- while (j->buf[j->pos + (j->tokstart - j->scanbuf)] != '\0') {
- freetree(j->p);
- jaqlparse(j);
- }
- j->err[0] = '\0';
return MAL_SUCCEED;
}
diff --git a/monetdb5/extras/jaql/jaqltests/Tests/documents.stable.err
b/monetdb5/extras/jaql/jaqltests/Tests/documents.stable.err
--- a/monetdb5/extras/jaql/jaqltests/Tests/documents.stable.err
+++ b/monetdb5/extras/jaql/jaqltests/Tests/documents.stable.err
@@ -29,11 +29,13 @@ stderr of test 'documents` in directory
# 09:19:01 > "mclient" "-ljaql" "-ftest" "-Eutf-8" "-i" "-e" "--host=Phoebe"
"--port=31818"
# 09:19:01 >
-MAPI = monetdb@Phoebe:33035
-QUERY = load("doctest");
+MAPI = monetdb@Phoebe:34968
+QUERY = # shouldn't exist
+ load("doctest");
ERROR = !no such JSON object with name: doctest
-MAPI = monetdb@Phoebe:33035
-QUERY = load("doctest");
+MAPI = monetdb@Phoebe:34968
+QUERY = # hence, shouldn't exist any more
+ load("doctest");
ERROR = !no such JSON object with name: doctest
# 09:19:01 >
diff --git a/monetdb5/extras/jaql/jaqltree.h b/monetdb5/extras/jaql/jaqltree.h
--- a/monetdb5/extras/jaql/jaqltree.h
+++ b/monetdb5/extras/jaql/jaqltree.h
@@ -40,10 +40,18 @@ typedef struct _jc {
size_t start;
size_t pos;
char *scanbuf;
+ void *scanstreamin;
+ void *scanstreamout;
char *tokstart;
char err[1024];
void *scanner;
- char explain:1, debug:2, trace:3, plan:4, planf:5, mapimode:6;
+ char explain:1,
+ debug:2,
+ trace:3,
+ plan:4,
+ planf:5,
+ mapimode:6,
+ scanstreameof:7;
jvar *vars;
int j1, j2, j3, j4, j5, j6, j7, startoid;
char ro1:1, ro2:2, ro3:3, ro4:4, ro5:5, ro6:6, ro7:7;
diff --git a/monetdb5/extras/jaql/parser/jaql.l
b/monetdb5/extras/jaql/parser/jaql.l
--- a/monetdb5/extras/jaql/parser/jaql.l
+++ b/monetdb5/extras/jaql/parser/jaql.l
@@ -19,8 +19,13 @@
%{
#include <stdio.h>
+#include <stream.h>
#include "jaqltree.h"
#include "jaql.tab.h"
+
+/* prompt: more data needed (stolen from mapi.h to avoid conflicts) */
+#define PROMPT2 "\001\002\n"
+
#ifdef _MSC_VER
#define snprintf _snprintf
#define fileno _fileno
@@ -62,8 +67,8 @@ extern void jaqlerror(jc* j, char const
#define stdout (FILE *)0
static void readinput(jc *j, char *buf, int *res, size_t max_size) {
- if (j->buf[j->pos] != '\0') {
- *res = (int)strlen(j->buf + j->pos);
+ if (j->buf != NULL && j->buf[j->pos] != '\0') {
+ *res = (int)strlen(j->buf + j->pos); /* FIXME: cache this */
if ((size_t)*res > max_size)
*res = (int)max_size;
memcpy(buf, j->buf + j->pos, *res);
@@ -71,6 +76,40 @@ static void readinput(jc *j, char *buf,
j->pos += *res;
j->scanbuf = buf;
} else {
+ if (j->expect_json != ';' && j->scanstreamin != NULL) {
+ bstream *bs = (bstream *)j->scanstreamin;
+
+ /* try and read some more data */
+ if (bstream_next(bs) < 0) {
+ /* read failed, force shutdown next iteration */
+ j->scanstreameof = 1;
+ *res = YY_NULL;
+ return;
+ }
+
+ /* request more if we appear to be at the end of current
+ * block */
+ if (j->buf != NULL && bs->eof == 1) {
+ stream *s = (stream *)j->scanstreamout;
+ if (mnstr_write(s, PROMPT2, sizeof(PROMPT2) -
1, 1) == 1) {
+ mnstr_flush(s);
+ bs->eof = 0;
+ }
+ if (bstream_next(bs) < 0) {
+ /* read failed, force shutdown next
iteration */
+ j->scanstreameof = 1;
+ *res = YY_NULL;
+ return;
+ }
+ }
+
+ /* did we get some query text */
+ if (bs->eof == 0) {
+ j->buf = bs->buf;
+ readinput(j, buf, res, max_size);
+ return;
+ }
+ }
*res = YY_NULL;
}
}
@@ -82,12 +121,14 @@ static void readinput(jc *j, char *buf,
%%
/* if the parser expects a JSON bit, give it */
if (yyextra->expect_json == '[') {
- yyextra->esc_depth = 1;
+ yyextra->esc_depth = 0;
yyextra->expect_json = 0;
+ unput('[');
BEGIN(ARR);
} else if (yyextra->expect_json == '{') {
- yyextra->esc_depth = 1;
+ yyextra->esc_depth = 0;
yyextra->expect_json = 0;
+ unput('{');
BEGIN(OBJ);
}
@@ -150,7 +191,7 @@ null return NIL;
<ARR>{
"]" {
if (--yyextra->esc_depth == 0) {
- yylval->j_json = GDKstrdup(yytext - 1);
+ yylval->j_json = GDKstrdup(yytext);
BEGIN(INITIAL);
return ARRAY;
} else {
@@ -174,7 +215,7 @@ null return NIL;
<OBJ>{
"}" {
if (--yyextra->esc_depth == 0) {
- yylval->j_json = GDKstrdup(yytext - 1);
+ yylval->j_json = GDKstrdup(yytext);
BEGIN(INITIAL);
return OBJECT;
} else {
@@ -195,13 +236,12 @@ null return NIL;
}
"}" return '}';
"{" return '{';
-";" BEGIN(SCOLON);
+";" { yyextra->expect_json = ';'; BEGIN(SCOLON); }
<SCOLON>{
";" /* ignore superfluous semi-colons */;
[ \t\r\n]+ /* ignore whitespace */;
- ("#"|"//").*\n /* ignore comments */;
- <<EOF>> { BEGIN(INITIAL); return ';'; }
- . { unput(yytext[0]); BEGIN(INITIAL); return ';'; }
+ <<EOF>> { yyextra->expect_json = 0; BEGIN(INITIAL); return ';'; }
+ . { unput(yytext[0]); yyextra->expect_json = 0; BEGIN(INITIAL); return
';'; }
}
[ \t\r\n]+ /* ignore whitespace */;
("#"|"//").*\n /* ignore comments */;
_______________________________________________
checkin-list mailing list
[email protected]
http://mail.monetdb.org/mailman/listinfo/checkin-list