Changeset: 3230faec824a for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=3230faec824a
Added Files:
        sql/test/miscellaneous/Tests/create_func_temp.sql
        sql/test/miscellaneous/Tests/create_func_temp.stable.err
        sql/test/miscellaneous/Tests/create_func_temp.stable.out
Modified Files:
        clients/examples/perl/sqlsample.pl
        clients/odbc/driver/ODBCConvert.c
        clients/odbc/driver/ODBCUtil.c
        clients/odbc/driver/SQLPrepare.c
        sql/server/rel_psm.c
        sql/server/rel_rel.c
        sql/server/rel_select.c
        sql/server/rel_unnest.c
        sql/server/rel_unnest.h
        sql/server/sql_scan.c
        sql/server/sql_scan.h
        sql/storage/store.c
        sql/test/BugTracker-2014/Tests/copy-into.Bug-3481.SQL.py
        sql/test/BugTracker-2014/Tests/utf8bom.Bug-3436.SQL.py
        sql/test/BugTracker-2016/Tests/convert-function-test.Bug-3460.sql
        sql/test/BugTracker-2016/Tests/convert-function-test.Bug-3460.stable.out
        
sql/test/BugTracker-2016/Tests/convert-function-test.Bug-3460.stable.out.int128
        
sql/test/BugTracker-2019/Tests/copy-into-from-stdin-empty-line.Bug-6669.sql
        sql/test/BugTracker-2019/Tests/insert-into-select.Bug-6718.sql
        sql/test/BugTracker-2019/Tests/python-loader-string.Bug-6759.py
        sql/test/Tests/unicode.sql
        sql/test/Tests/unicode.stable.out
        sql/test/Users/Tests/copyinto.SQL.py
        sql/test/Users/Tests/copyinto.stable.err
        sql/test/mapi/Tests/perl_dbi.stable.out
        sql/test/miscellaneous/Tests/All
        sql/test/subquery/Tests/subquery5.sql
        sql/test/subquery/Tests/subquery5.stable.err
        sql/test/subquery/Tests/subquery5.stable.out
Branch: default
Log Message:

Merged with Jun2020


diffs (truncated from 1712 to 300 lines):

diff --git a/clients/examples/perl/sqlsample.pl 
b/clients/examples/perl/sqlsample.pl
--- a/clients/examples/perl/sqlsample.pl
+++ b/clients/examples/perl/sqlsample.pl
@@ -48,6 +48,9 @@ my $dbh = DBI->connect( $dsn,
   $sth->bind_param( 1,     7 , DBI::SQL_INTEGER() );
   $sth->bind_param( 2,'seven' );
   $sth->execute;
+  $sth->bind_param( 1,    42 , DBI::SQL_INTEGER() );
+  $sth->bind_param( 2,  '\\n' );
+  $sth->execute;
 }
 {
   my $sth = $dbh->prepare('select * from perl_table;');
diff --git a/clients/odbc/driver/ODBCConvert.c 
b/clients/odbc/driver/ODBCConvert.c
--- a/clients/odbc/driver/ODBCConvert.c
+++ b/clients/odbc/driver/ODBCConvert.c
@@ -3197,6 +3197,7 @@ ODBCStore(ODBCStmt *stmt,
        case SQL_WCHAR:
        case SQL_WVARCHAR:
        case SQL_WLONGVARCHAR:
+               assign(buf, bufpos, buflen, 'r', stmt); /* RAW string */
                assign(buf, bufpos, buflen, '\'', stmt);
                switch (ctype) {
                case SQL_C_CHAR:
@@ -3205,22 +3206,11 @@ ODBCStore(ODBCStmt *stmt,
                        for (i = 0; i < slen; i++) {
                                unsigned char c = (unsigned char) sval[i];
 
-                               if (c == 0) {
+                               if (c == 0)
                                        break;
-                               } else if (c < 0x20 /* || c >= 0x7F */) {
-                                       assign(buf, bufpos, buflen, '\\', stmt);
-                                       assign(buf, bufpos, buflen, '0' + (c >> 
6), stmt);
-                                       assign(buf, bufpos, buflen, '0' + ((c 
>> 3) & 0x7), stmt);
-                                       assign(buf, bufpos, buflen, '0' + (c & 
0x7), stmt);
-                               } else if (c == '\\') {
-                                       assign(buf, bufpos, buflen, '\\', stmt);
-                                       assign(buf, bufpos, buflen, '\\', stmt);
-                               } else if (c == '\'') {
-                                       assign(buf, bufpos, buflen, '\\', stmt);
+                               if (c == '\'')
                                        assign(buf, bufpos, buflen, '\'', stmt);
-                               } else {
-                                       assign(buf, bufpos, buflen, c, stmt);
-                               }
+                               assign(buf, bufpos, buflen, c, stmt);
                        }
                        break;
                case SQL_C_BIT:
diff --git a/clients/odbc/driver/ODBCUtil.c b/clients/odbc/driver/ODBCUtil.c
--- a/clients/odbc/driver/ODBCUtil.c
+++ b/clients/odbc/driver/ODBCUtil.c
@@ -679,7 +679,7 @@ ODBCTranslateSQL(ODBCDbc *dbc, const SQL
                                length = (size_t) sprintf(q, "%.*s ESCAPE '''' 
%s", n, nquery, p);
                                break;
                        case '\\':
-                               length = (size_t) sprintf(q, "%.*s ESCAPE 
'\\\\' %s", n, nquery, p);
+                               length = (size_t) sprintf(q, "%.*s ESCAPE r'\\' 
%s", n, nquery, p);
                                break;
                        default:
                                length = (size_t) sprintf(q, "%.*s ESCAPE '%c' 
%s", n, nquery, esc, p);
@@ -784,9 +784,7 @@ ODBCTranslateSQL(ODBCDbc *dbc, const SQL
                                                        p++;
                                        } else if (*p == '\'') {
                                                while (*++p && *p != '\'')
-                                                       if (*p == '\\' &&
-                                                           *++p == 0)
-                                                               break;
+                                                       ;
                                                if (*p)
                                                        p++;
                                        } else {
@@ -820,7 +818,7 @@ ODBCTranslateSQL(ODBCDbc *dbc, const SQL
                                if (strncasecmp(func->name, scalarfunc, 
scalarfunclen) == 0 && func->name[scalarfunclen] == 0 && func->nargs == nargs) {
                                        if (func->repl) {
                                                const char *r;
-                                               q = malloc(length - pr + 
strlen(func->repl) - nargs + (nargs > 0 ? args[0].arglen : 0) + (nargs > 1 ? 
args[1].arglen : 0) + (nargs > 2 ? args[2].arglen : 0) + 1);
+                                               q = malloc(length - pr + 
strlen(func->repl) - nargs + (nargs > 0 ? args[0].arglen + 1 : 0) + (nargs > 1 
? args[1].arglen + 1 : 0) + (nargs > 2 ? args[2].arglen + 1 : 0) + 1);
                                                if (q == NULL) {
                                                        free(nquery);
                                                        return NULL;
@@ -829,6 +827,8 @@ ODBCTranslateSQL(ODBCDbc *dbc, const SQL
                                                strncpy(q, nquery, pr);
                                                for (r = func->repl; *r; r++) {
                                                        if (*r == '\1' || *r == 
'\2' || *r == '\3' || *r == '\4') {
+                                                               if (args[*r - 
1].argstart[0] == '\'')
+                                                                       q[pr++] 
= 'r';
                                                                strncpy(q + pr, 
args[*r - 1].argstart, args[*r - 1].arglen);
                                                                pr += (int) 
args[*r - 1].arglen;
                                                        } else {
@@ -865,12 +865,17 @@ ODBCTranslateSQL(ODBCDbc *dbc, const SQL
                                                for (c = convert; c->odbc; c++) 
{
                                                        if 
(strncasecmp(c->odbc, args[1].argstart, args[1].arglen) == 0 &&
                                                            
c->odbc[args[1].arglen] == 0) {
-                                                               q = 
malloc(length - pr + 11 + args[0].arglen + strlen(c->server));
+                                                               const char *raw;
+                                                               q = 
malloc(length - pr + 11 + args[0].arglen + 1 + strlen(c->server));
                                                                if (q == NULL) {
                                                                        
free(nquery);
                                                                        return 
NULL;
                                                                }
-                                                               length = 
(size_t) sprintf(q, "%.*scast(%.*s as %s)%s", n, nquery, (int) args[0].arglen, 
args[0].argstart, c->server, p);
+                                                               if 
(args[0].argstart[0] == '\'')
+                                                                       raw = 
"r";
+                                                               else
+                                                                       raw = 
"";
+                                                               length = 
(size_t) sprintf(q, "%.*scast(%s%.*s as %s)%s", n, nquery, raw, (int) 
args[0].arglen, args[0].argstart, c->server, p);
                                                                free(nquery);
                                                                nquery = q;
                                                                break;
@@ -924,7 +929,7 @@ ODBCParsePV(const char *tab, const char 
                if (*s == '\'' || *s == '\\')
                        i++;
        }
-       i += strlen(tab) + strlen(col) + 25; /* ""."" like '' escape '\\' */
+       i += strlen(tab) + strlen(col) + 25; /* ""."" like '' escape r'\' */
        res = malloc(i + 1);
        if (res == NULL)
                return NULL;
@@ -934,7 +939,7 @@ ODBCParsePV(const char *tab, const char 
                        res[i++] = *s;
                res[i++] = *s;
        }
-       for (s = "' escape '\\\\'"; *s; s++)
+       for (s = "' escape r'\\'"; *s; s++)
                res[i++] = *s;
        res[i] = 0;
        return res;
diff --git a/clients/odbc/driver/SQLPrepare.c b/clients/odbc/driver/SQLPrepare.c
--- a/clients/odbc/driver/SQLPrepare.c
+++ b/clients/odbc/driver/SQLPrepare.c
@@ -74,10 +74,6 @@ MNDBPrepare(ODBCStmt *stmt,
        }
 
        fixODBCstring(StatementText, TextLength, SQLINTEGER, addStmtError, 
stmt, return SQL_ERROR);
-       /* TODO: convert ODBC escape sequences ( {d 'value'} or {t
-        * 'value'} or {ts 'value'} or {escape 'e-char'} or {oj
-        * outer-join} or {fn scalar-function} etc. ) to MonetDB SQL
-        * syntax */
        query = ODBCTranslateSQL(stmt->Dbc, StatementText, (size_t) TextLength,
                                 stmt->noScan);
        if (query == NULL) {
diff --git a/sql/server/rel_psm.c b/sql/server/rel_psm.c
--- a/sql/server/rel_psm.c
+++ b/sql/server/rel_psm.c
@@ -672,8 +672,10 @@ sequential_block (sql_query *query, sql_
                case SQL_TRUNCATE:
                case SQL_MERGE: {
                        sql_rel *r = rel_updates(query, s);
-                       if (!r)
+                       if (!r) {
+                               stack_pop_frame(sql);
                                return NULL;
+                       }
                        res = exp_rel(sql, r);
                }       break;
                default:
@@ -1310,8 +1312,11 @@ create_trigger(sql_query *query, dlist *
                if (old_name)
                        stack_update_rel_view(sql, old_name, 
new_name?rel_dup(rel):rel);
        }
-       if (!(sq = sequential_block(query, NULL, NULL, stmts, NULL, 1)))
+       if (!(sq = sequential_block(query, NULL, NULL, stmts, NULL, 1))) {
+               if (!instantiate)
+                       stack_pop_frame(sql);
                return NULL;
+       }
        r = rel_psm_block(sql->sa, sq);
 
        if (!instantiate)
diff --git a/sql/server/rel_rel.c b/sql/server/rel_rel.c
--- a/sql/server/rel_rel.c
+++ b/sql/server/rel_rel.c
@@ -122,17 +122,10 @@ rel_create( sql_allocator *sa )
        if(!r)
                return NULL;
 
+       *r = (sql_rel) {
+               .card = CARD_ATOM,
+       };
        sql_ref_init(&r->ref);
-       r->l = r->r = NULL;
-       r->exps = NULL;
-       r->nrcols = 0;
-       r->flag = 0;
-       r->card = CARD_ATOM;
-       r->distinct = 0;
-       r->processed = 0;
-       r->dependent = 0;
-       r->subquery = 0;
-       r->p = NULL;
        return r;
 }
 
diff --git a/sql/server/rel_select.c b/sql/server/rel_select.c
--- a/sql/server/rel_select.c
+++ b/sql/server/rel_select.c
@@ -3351,6 +3351,7 @@ static sql_exp *
        if (args && args->data.sym) {
                int ungrouped_col = -1, i, all_aggr = query_has_outer(query);
                all_freevar = 1;
+               bool found_nested_aggr = false;
                for (i = 0; args && args->data.sym; args = args->next, i++) {
                        int base = (!groupby || !is_project(groupby->op) || 
is_base(groupby->op) || is_processed(groupby));
                        bool found_one = false;
@@ -3359,7 +3360,7 @@ static sql_exp *
 
                        has_args = true;
                        if (gl && gl != ogl) {
-                               if (groupby->grouped) {
+                               if (gl->grouped) {
                                        char *uaname = GDKmalloc(strlen(aname) 
+ 1);
                                        sql_exp *e = sql_error(sql, 02, 
SQLSTATE(42000) "%s: aggregate functions cannot be nested",
                                                uaname ? toUpperCopy(uaname, 
aname) : aname);
@@ -3401,10 +3402,10 @@ static sql_exp *
                        } else {
                                all_aggr &= (exp_card(e) <= CARD_AGGR && 
!exp_is_atom(e) && is_aggr(e->type) && !is_func(e->type) && (!groupby || 
!is_groupby(groupby->op) || !groupby->r || !exps_find_exp(groupby->r, e)));
                        }
-                       all_freevar &= (exp_only_freevar(sql, e, &found_one) && 
found_one);
+                       all_freevar &= (exp_only_freevar(query, e, &found_one, 
&found_nested_aggr) && found_one);
                        list_append(exps, e);
                }
-               if (all_freevar && all_aggr)
+               if (all_freevar && (all_aggr || found_nested_aggr))
                        return sql_error(sql, 05, SQLSTATE(42000) "SELECT: 
aggregate function calls cannot be nested");
                if (!all_freevar) {
                        if (all_aggr) {
diff --git a/sql/server/rel_unnest.c b/sql/server/rel_unnest.c
--- a/sql/server/rel_unnest.c
+++ b/sql/server/rel_unnest.c
@@ -16,6 +16,7 @@
 #include "rel_exp.h"
 #include "rel_select.h"
 #include "rel_rewriter.h"
+#include "sql_query.h"
 #include "mal_errors.h" /* for SQLSTATE() */
  
 static void
@@ -170,41 +171,50 @@ rel_has_freevar(mvc *sql, sql_rel *rel)
        return 0;
 }
 
-static int exps_only_freevar(mvc *sql, list *exps, bool *found_one);
-static int rel_only_freevar(mvc *sql, sql_rel *rel, bool *found_one);
+static int exps_only_freevar(sql_query *query, list *exps, bool *found_one, 
bool *found_aggr);
+static int rel_only_freevar(sql_query *query, sql_rel *rel, bool *found_one, 
bool *found_aggr);
 
 int /* look for expressions with either only freevars or atoms */
-exp_only_freevar(mvc *sql, sql_exp *e, bool *found_one)
+exp_only_freevar(sql_query *query, sql_exp *e, bool *found_one, bool 
*found_aggr)
 {
        if (THRhighwater()) {
-               (void) sql_error(sql, 10, SQLSTATE(42000) "Query too complex: 
running out of stack space");
+               (void) sql_error(query->sql, 10, SQLSTATE(42000) "Query too 
complex: running out of stack space");
                return 0;
        }
 
        if (is_freevar(e)) {
+               sql_rel *outer;
+               sql_exp *a;
+
                *found_one = true;
+               if (e->type == e_column) {
+                       if ((outer = query_fetch_outer(query, 
is_freevar(e)-1))) {
+                               if ((a = rel_find_exp(outer, e)) && 
is_aggr(a->type))
+                                       *found_aggr = true;
+                       }
+               }
                return 1;
        }
        switch(e->type) {
        case e_cmp:
                if (e->flag == cmp_or || e->flag == cmp_filter) {
-                       return (exps_only_freevar(sql, e->l, found_one) && 
exps_only_freevar(sql, e->r, found_one));
+                       return (exps_only_freevar(query, e->l, found_one, 
found_aggr) && exps_only_freevar(query, e->r, found_one, found_aggr));
                } else if (e->flag == cmp_in || e->flag == cmp_notin) {
-                       return (exp_only_freevar(sql, e->l, found_one) && 
exps_only_freevar(sql, e->r, found_one));
+                       return (exp_only_freevar(query, e->l, found_one, 
found_aggr) && exps_only_freevar(query, e->r, found_one, found_aggr));
                } else {
-                       return (exp_only_freevar(sql, e->l, found_one) && 
exp_only_freevar(sql, e->r, found_one) && 
-                                       (!e->f || (e->f && 
exp_only_freevar(sql, e->f, found_one))));
+                       return (exp_only_freevar(query, e->l, found_one, 
found_aggr) && exp_only_freevar(query, e->r, found_one, found_aggr) && 
+                                       (!e->f || (e->f && 
exp_only_freevar(query, e->f, found_one, found_aggr))));
                }
        case e_convert:
-               return exp_only_freevar(sql, e->l, found_one);
+               return exp_only_freevar(query, e->l, found_one, found_aggr);
        case e_func:
        case e_aggr:
                if (e->l)
-                       return exps_only_freevar(sql, e->l, found_one);
+                       return exps_only_freevar(query, e->l, found_one, 
found_aggr);
                return 1;
        case e_psm:
                if (exp_is_rel(e))
-                       return rel_only_freevar(sql, e->l, found_one);
+                       return rel_only_freevar(query, e->l, found_one, 
found_aggr);
                return 1;
        case e_atom:
_______________________________________________
checkin-list mailing list
checkin-list@monetdb.org
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to