Changeset: b5c70672c18f for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=b5c70672c18f
Modified Files:
        clients/Tests/exports.stable.out
        clients/mapiclient/mclient.c
        clients/mapilib/mapi.c
        clients/mapilib/mapi.h
        sql/backends/monet5/sql.c
        sql/backends/monet5/sql_result.c
        sql/backends/monet5/sql_result.h
Branch: client-filetrans
Log Message:

Initial work on COPY INTO 'file'.


diffs (truncated from 431 to 300 lines):

diff --git a/clients/Tests/exports.stable.out b/clients/Tests/exports.stable.out
--- a/clients/Tests/exports.stable.out
+++ b/clients/Tests/exports.stable.out
@@ -559,7 +559,7 @@ MapiMsg mapi_seek_row(MapiHdl hdl, int64
 MapiHdl mapi_send(Mapi mid, const char *cmd);
 MapiMsg mapi_setAutocommit(Mapi mid, bool autocommit);
 MapiMsg mapi_set_size_header(Mapi mid, int value);
-void mapi_setfilecallback(Mapi mid, char *( *func)(void *priv, const char 
*filename, bool binary, uint64_t offset, uint64_t *size), void *priv);
+void mapi_setfilecallback(Mapi mid, char *( *getfunc)(void *priv, const char 
*filename, bool binary, uint64_t offset, size_t *size), char *( *putfunc)(void 
*priv, const char *filename, const void *restrict data, size_t size), void 
*priv);
 int mapi_split_line(MapiHdl hdl);
 MapiMsg mapi_start_talking(Mapi mid);
 MapiMsg mapi_store_field(MapiHdl hdl, int fnr, int outtype, void *outparam);
diff --git a/clients/mapiclient/mclient.c b/clients/mapiclient/mclient.c
--- a/clients/mapiclient/mclient.c
+++ b/clients/mapiclient/mclient.c
@@ -3036,7 +3036,7 @@ struct privdata {
 #define READSIZE       (1 << 20)
 
 static char *
-getfile(void *data, const char *filename, bool binary, uint64_t offset, 
uint64_t *size)
+getfile(void *data, const char *filename, bool binary, uint64_t offset, size_t 
*size)
 {
        stream *f;
        char *buf;
@@ -3086,10 +3086,33 @@ getfile(void *data, const char *filename
                priv->f = NULL;
                return NULL;
        }
-       *size = (uint64_t) s;
+       *size = (size_t) s;
        return buf;
 }
 
+static char *
+putfile(void *data, const char *filename, const void *restrict buf, size_t 
bufsize)
+{
+       struct privdata *priv = data;
+
+       if (filename != NULL) {
+               if ((priv->f = open_wastream(filename)) == NULL)
+                       return "cannot open file";
+               if (buf == NULL || bufsize == 0)
+                       return NULL;
+       } else if (buf == NULL) {
+               close_stream(priv->f);
+               priv->f = NULL;
+               return NULL;
+       }
+       if (mnstr_write(priv->f, buf, 1, bufsize) < (ssize_t) bufsize) {
+               close_stream(priv->f);
+               priv->f = NULL;
+               return "error writing output";
+       }
+       return NULL;            /* success */
+}
+
 __declspec(noreturn) static void usage(const char *prog, int xit)
        __attribute__((__noreturn__));
 
@@ -3494,7 +3517,7 @@ main(int argc, char **argv)
 
        struct privdata priv;
        priv = (struct privdata) {0};
-       mapi_setfilecallback(mid, getfile, &priv);
+       mapi_setfilecallback(mid, getfile, putfile, &priv);
 
        if (!autocommit)
                mapi_setAutocommit(mid, autocommit);
diff --git a/clients/mapilib/mapi.c b/clients/mapilib/mapi.c
--- a/clients/mapilib/mapi.c
+++ b/clients/mapilib/mapi.c
@@ -839,8 +839,9 @@ struct MapiStruct {
        stream *tracelog;       /* keep a log for inspection */
        stream *from, *to;
        uint32_t index;         /* to mark the log records */
-       void *getfilecontentprivate;
-       char *(*getfilecontent)(void *, const char *, bool, uint64_t, uint64_t 
*);
+       void *filecontentprivate;
+       char *(*getfilecontent)(void *, const char *, bool, uint64_t, size_t *);
+       char *(*putfilecontent)(void *, const char *, const void *restrict, 
size_t);
 };
 
 struct MapiResultSet {
@@ -2985,10 +2986,11 @@ mapi_disconnect(Mapi mid)
  * callback function the opportunity to free any resources.
  */
 void
-mapi_setfilecallback(Mapi mid, char *(*getfilecontent)(void *, const char *, 
bool, uint64_t, uint64_t *), void *getfilecontentprivate)
+mapi_setfilecallback(Mapi mid, char *(*getfilecontent)(void *, const char *, 
bool, uint64_t, size_t *), char *(*putfilecontent)(void *, const char *, const 
void *restrict, size_t), void *filecontentprivate)
 {
        mid->getfilecontent = getfilecontent;
-       mid->getfilecontentprivate = getfilecontentprivate;
+       mid->putfilecontent = putfilecontent;
+       mid->filecontentprivate = filecontentprivate;
 }
 
 #define testBinding(hdl,fnr,funcname)                                  \
@@ -3882,10 +3884,55 @@ parse_header_line(MapiHdl hdl, char *lin
 }
 
 static void
-handle_file(MapiHdl hdl, uint64_t off, char *filename, bool binary)
+write_file(MapiHdl hdl, char *filename)
 {
        Mapi mid = hdl->mid;
-       uint64_t size = 0, flushsize = 0;
+       char *line;
+       char data[BLOCK];
+       ssize_t len;
+
+       (void) read_line(mid);  /* read flush marker */
+       if (filename == NULL) {
+               /* malloc failure */
+               mnstr_printf(mid->to, "!HY001!allocation failure\n");
+               mnstr_flush(mid->to);
+               return;
+       }
+       if (mid->putfilecontent == NULL) {
+               free(filename);
+               mnstr_printf(mid->to, "!HY000!cannot send files\n");
+               mnstr_flush(mid->to);
+               return;
+       }
+       line = mid->putfilecontent(mid->filecontentprivate, filename, NULL, 0);
+       free(filename);
+       if (line != NULL) {
+               if (strchr(line, '\n'))
+                       line = "incorrect response from application";
+               mnstr_printf(mid->to, "!HY000!%.64s\n", line);
+               mnstr_flush(mid->to);
+               return;
+       }
+       mnstr_flush(mid->to);
+       while ((len = mnstr_read(mid->from, data, 1, sizeof(data))) > 0) {
+               if (line == NULL)
+                       line = mid->putfilecontent(mid->filecontentprivate,
+                                                  NULL, data, len);
+       }
+       if (line == NULL)
+               line = mid->putfilecontent(mid->filecontentprivate,
+                                          NULL, NULL, 0);
+       if (line && strchr(line, '\n'))
+               line = "incorrect response from application";
+       mnstr_printf(mid->to, "%s\n", line ? line : "");
+       mnstr_flush(mid->to);
+}
+
+static void
+read_file(MapiHdl hdl, uint64_t off, char *filename, bool binary)
+{
+       Mapi mid = hdl->mid;
+       size_t size = 0, flushsize = 0;
        char *data, *line;
 
        (void) read_line(mid);  /* read flush marker */
@@ -3901,7 +3948,7 @@ handle_file(MapiHdl hdl, uint64_t off, c
                mnstr_flush(mid->to);
                return;
        }
-       data = mid->getfilecontent(mid->getfilecontentprivate, filename, 
binary, off, &size);
+       data = mid->getfilecontent(mid->filecontentprivate, filename, binary, 
off, &size);
        free(filename);
        if (data != NULL && size == 0) {
                if (strchr(data, '\n'))
@@ -3917,24 +3964,24 @@ handle_file(MapiHdl hdl, uint64_t off, c
                        line = read_line(mid);
                        if (line == NULL) {
                                /* error */
-                               (void) 
mid->getfilecontent(mid->getfilecontentprivate, NULL, false, 0, NULL);
+                               (void) 
mid->getfilecontent(mid->filecontentprivate, NULL, false, 0, NULL);
                                return;
                        }
                        assert(line[0] == PROMPTBEG);
                        if (line[0] != PROMPTBEG) {
                                /* error */
-                               (void) 
mid->getfilecontent(mid->getfilecontentprivate, NULL, false, 0, NULL);
+                               (void) 
mid->getfilecontent(mid->filecontentprivate, NULL, false, 0, NULL);
                                return;
                        }
                        if (line[1] == PROMPT3[1]) {
-                               (void) 
mid->getfilecontent(mid->getfilecontentprivate, NULL, false, 0, NULL);
+                               (void) 
mid->getfilecontent(mid->filecontentprivate, NULL, false, 0, NULL);
                                (void) read_line(mid);
                                return;
                        }
                        assert(line[1] == PROMPT2[1]);
                        if (line[1] != PROMPT2[1]) {
                                /* error */
-                               (void) 
mid->getfilecontent(mid->getfilecontentprivate, NULL, false, 0, NULL);
+                               (void) 
mid->getfilecontent(mid->filecontentprivate, NULL, false, 0, NULL);
                                return;
                        }
                        (void) read_line(mid);
@@ -3945,7 +3992,7 @@ handle_file(MapiHdl hdl, uint64_t off, c
                        return;
                }
                flushsize += size;
-               data = mid->getfilecontent(mid->getfilecontentprivate, NULL, 
false, 0, &size);
+               data = mid->getfilecontent(mid->filecontentprivate, NULL, 
false, 0, &size);
        }
        mnstr_flush(mid->to);
        line = read_line(mid);
@@ -4035,12 +4082,13 @@ read_into_cache(MapiHdl hdl, int lookahe
                                        }
                                        assert(*line == ' ');
                                        line++; /* skip one space */
-                                       handle_file(hdl, off, strdup(line), 
binary);
+                                       read_file(hdl, off, strdup(line), 
binary);
                                        break;
                                }
                                case 'w':
-                                       assert(0);
-                                       /* not yet implemented */
+                                       line++; /* skip one space */
+                                       write_file(hdl, strdup(line));
+                                       break;
                                }
                                continue;
                        }
diff --git a/clients/mapilib/mapi.h b/clients/mapilib/mapi.h
--- a/clients/mapilib/mapi.h
+++ b/clients/mapilib/mapi.h
@@ -125,7 +125,13 @@ mapi_export char **mapi_resolve(const ch
 mapi_export MapiMsg mapi_disconnect(Mapi mid);
 mapi_export MapiMsg mapi_reconnect(Mapi mid);
 mapi_export MapiMsg mapi_ping(Mapi mid);
-mapi_export void mapi_setfilecallback(Mapi mid, char *(*func)(void *priv, 
const char *filename, bool binary, uint64_t offset, uint64_t *size), void 
*priv);
+mapi_export void mapi_setfilecallback(
+       Mapi mid,
+       char *(*getfunc)(void *priv, const char *filename,
+                        bool binary, uint64_t offset, size_t *size),
+       char *(*putfunc)(void *priv, const char *filename,
+                        const void *restrict data, size_t size),
+       void *priv);
 
 mapi_export MapiMsg mapi_error(Mapi mid);
 mapi_export const char *mapi_error_str(Mapi mid);
diff --git a/sql/backends/monet5/sql.c b/sql/backends/monet5/sql.c
--- a/sql/backends/monet5/sql.c
+++ b/sql/backends/monet5/sql.c
@@ -192,14 +192,11 @@ getSQLContext(Client cntxt, MalBlkPtr mb
 {
        backend *be;
        (void) mb;
-
-       if (cntxt == NULL)
-               throw(SQL, "mvc", SQLSTATE(42005) "No client record");
-       if (cntxt->sqlcontext == NULL)
-               throw(SQL, "mvc", SQLSTATE(42006) "SQL module not initialized");
+       str msg;
+
+       if ((msg = checkSQLContext(cntxt)) != MAL_SUCCEED)
+               return msg;
        be = (backend *) cntxt->sqlcontext;
-       if (be->mvc == NULL)
-               throw(SQL, "mvc", SQLSTATE(42006) "SQL module not initialized, 
mvc struct missing");
        if (c)
                *c = be->mvc;
        if (b)
@@ -2031,7 +2028,7 @@ mvc_result_set_wrap( Client cntxt, MalBl
                        BBPunfix(bid);
        }
        /* now send it to the channel cntxt->fdout */
-       if (mvc_export_result(cntxt->sqlcontext, cntxt->fdout, res, 
mb->starttime, mb->optimize))
+       if (mvc_export_result(cntxt->sqlcontext, cntxt->fdout, res, true, 
mb->starttime, mb->optimize))
                msg = createException(SQL, "sql.resultset", SQLSTATE(45000) 
"Result set construction failed");
        mb->starttime = 0;
        mb->optimize = 0;
@@ -2079,13 +2076,12 @@ mvc_export_table_wrap( Client cntxt, Mal
        mvc *m = NULL;
        BAT *order = NULL, *b = NULL, *tbl = NULL, *atr = NULL, *tpe = 
NULL,*len = NULL,*scale = NULL;
        res_table *t = NULL;
+       bool tostdout;
 
        (void) format;
 
        if ((msg = getSQLContext(cntxt, mb, &m, NULL)) != NULL)
                return msg;
-       if ((msg = checkSQLContext(cntxt)) != NULL)
-               return msg;
 
        bid = *getArgReference_bat(stk,pci,12);
        order = BATdescriptor(bid);
@@ -2165,22 +2161,38 @@ mvc_export_table_wrap( Client cntxt, Mal
                goto wrapup_result_set1;
 
        /* now select the file channel */
-       if ( strcmp(filename,"stdout") == 0 )
+       if ( strcmp(filename,"stdout") == 0 ) {
+               tostdout = true;
                s= cntxt->fdout;
-       else if ( (s = open_wastream(filename)) == NULL || mnstr_errnr(s)) {
-               int errnr = mnstr_errnr(s);
-               if (s)
-                       close_stream(s);
-               msg=  createException(IO, "streams.open", SQLSTATE(42000) 
"could not open file '%s': %s",
-                                     filename?filename:"stdout", 
strerror(errnr));
-               goto wrapup_result_set1;
+       } else {
+               tostdout = false;
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to