Update of /cvsroot/monetdb/sql/src/server
In directory sc8-pr-cvs7.sourceforge.net:/tmp/cvs-serv6989/src/server

Modified Files:
        sql_mvc.mx sql_parser.mx sql_privileges.mx sql_scan.mx 
        sql_schema.mx sql_select.mx sql_semantic.mx sql_sequence.mx 
        sql_statement.mx sql_updates.mx 
Log Message:
propagated changes of Friday Mar 16 2007 - Thursday Mar 22 2007
from the SQL_2-16 branch to the development trunk


Index: sql_semantic.mx
===================================================================
RCS file: /cvsroot/monetdb/sql/src/server/sql_semantic.mx,v
retrieving revision 1.159
retrieving revision 1.160
diff -u -d -r1.159 -r1.160
--- sql_semantic.mx     20 Mar 2007 18:26:02 -0000      1.159
+++ sql_semantic.mx     22 Mar 2007 09:26:56 -0000      1.160
@@ -986,9 +986,12 @@
                break;
        }
        case SQL_NEXT:{
-               char *seq = se->data.sval;
-               len = snprintf( buf+len, BUFSIZ-len, "next value for \"%s\"",
-                               sql_escape_ident(seq)); 
+               char *seq = qname_table(se->data.lval);
+               char *sname = qname_schema(se->data.lval);
+               
+               if (!sname)
+                       sname = sql->session->schema->base.name;
+               len = snprintf( buf+len, BUFSIZ-len, "next value for 
\"%s\".\"%s\"", sname, sql_escape_ident(seq)); 
        }       break;
        case SQL_COLUMN: {
                /* can only be variables */ 

Index: sql_updates.mx
===================================================================
RCS file: /cvsroot/monetdb/sql/src/server/sql_updates.mx,v
retrieving revision 1.105
retrieving revision 1.106
diff -u -d -r1.105 -r1.106
--- sql_updates.mx      4 Feb 2007 22:55:18 -0000       1.105
+++ sql_updates.mx      22 Mar 2007 09:26:56 -0000      1.106
@@ -1057,13 +1057,15 @@
 push_project(stmt *rows, stmt *val) 
 {
        switch (val->type) {
-       case st_convert:
+       case st_binop:
+               val->op2.stval = push_project(rows, val->op2.stval);
        case st_unop:
+       case st_convert:
                val->op1.stval = push_project(rows, val->op1.stval);
                val->nrcols = rows->nrcols;
                return val;
        default:
-               return stmt_const(rows, val);
+               return stmt_const(stmt_dup(rows), val);
        }
 }
 
@@ -1268,7 +1270,7 @@
                                                return sql_error(sql, 02, 
"INSERT INTO: column '%s' has no valid default value", c->base.name);
                                        }
                                        if (ic && !(ic->key && ic->nrcols == 0))
-                                               s = push_project(stmt_dup(ic), 
s);
+                                               s = push_project(ic, s);
                                        inserts[i] = stmt_append(stmt_bat(c, 
stmt_dup(tv->s), INS), s);
                                }
                        }

Index: sql_schema.mx
===================================================================
RCS file: /cvsroot/monetdb/sql/src/server/sql_schema.mx,v
retrieving revision 1.116
retrieving revision 1.117
diff -u -d -r1.116 -r1.117
--- sql_schema.mx       20 Mar 2007 18:26:02 -0000      1.116
+++ sql_schema.mx       22 Mar 2007 09:26:54 -0000      1.117
@@ -95,7 +95,8 @@
                           exception(count(r) > 0), "Role (%s,%s) already 
granted", role, grantee;
                           
relinsert(role_user,role_id,grantee_id,grantor,grant);
                         */
-                       sql_grant_role(sql, grantee, role);
+                       if (!sql_grant_role(sql, grantee, role)) 
+                               return sql_error(sql, 02, "GRANT: cannot grant 
ROLE '%s' to ROLE '%s'", grantee, role );
                }
        }
        return stmt_none();
@@ -583,6 +584,7 @@
                list_destroy(func_l);
                list_destroy(view_id_l);
                stmt_destroy(sq);
+               sq = NULL;
        }
        scope_close(scp);
        
@@ -1775,6 +1777,9 @@
 {
        stmt *ret = NULL;
 
+       if (!QUERY_MODE(sql->mode))
+               return sql_error(sql, 05, "Schema statements are directly 
executed and therefor cannot be debugged, explained, profiled, traced or used 
in a prepare statement");
+
        switch (s->token) {
        case SQL_CREATE_SCHEMA:
        {

Index: sql_statement.mx
===================================================================
RCS file: /cvsroot/monetdb/sql/src/server/sql_statement.mx,v
retrieving revision 1.142
retrieving revision 1.143
diff -u -d -r1.142 -r1.143
--- sql_statement.mx    21 Mar 2007 15:47:28 -0000      1.142
+++ sql_statement.mx    22 Mar 2007 09:26:56 -0000      1.143
@@ -183,7 +183,6 @@
 #define VAR_GLOBAL(f) ((f>>1)==1)
 extern stmt *stmt_var(char *varname, sql_subtype *t, int declare, int level);
 extern stmt *stmt_varnr(int nr, sql_subtype *t);
-extern stmt *stmt_seq_next(char *seqname);
 
 extern stmt *stmt_table(stmt *cols, int temp);
 extern stmt *stmt_basetable(sql_table *t, char *tname);
@@ -1023,18 +1022,6 @@
 }
 
 stmt *
-stmt_seq_next(char *seqname)
-{
-       sql_subtype *str_t = sql_bind_localtype("str");
-       stmt *seq = stmt_atom_string(seqname);
-       sql_subfunc *f;
-
-       f = sql_bind_func(NULL, "next_value_for", str_t, NULL);
-       assert(f);
-       return stmt_unop(seq, f);
-}
-
-stmt *
 stmt_table(stmt *cols, int temp)
 {
        stmt *s = stmt_create(st_table);

Index: sql_mvc.mx
===================================================================
RCS file: /cvsroot/monetdb/sql/src/server/sql_mvc.mx,v
retrieving revision 1.175
retrieving revision 1.176
diff -u -d -r1.175 -r1.176
--- sql_mvc.mx  20 Mar 2007 18:26:02 -0000      1.175
+++ sql_mvc.mx  22 Mar 2007 09:26:54 -0000      1.176
@@ -53,6 +53,7 @@
 } modes_t;
 
 #define CACHE_MODE(m) (m==m_normal||m==m_profile||m==m_debug||m==m_trace)
+#define QUERY_MODE(m) (m==m_normal||m==m_inplace||m==m_execute)
 
 typedef struct sql_var {
        struct stmt *s;
@@ -99,6 +100,7 @@
 
        sql_session *session;   
 
+       /* current stmt variables */
        int type;               /* query type */
        unsigned int depth;     /* depth of the current expression */
        int label;              /* numbers for relational projection labels */

Index: sql_privileges.mx
===================================================================
RCS file: /cvsroot/monetdb/sql/src/server/sql_privileges.mx,v
retrieving revision 1.59
retrieving revision 1.60
diff -u -d -r1.59 -r1.60
--- sql_privileges.mx   3 Jan 2007 12:39:47 -0000       1.59
+++ sql_privileges.mx   22 Mar 2007 09:26:54 -0000      1.60
@@ -113,7 +113,7 @@
        sql_table *auths = find_sql_table(sys, "auths");
        sql_table *roles = find_sql_table(sys, "user_role");
        sql_column *auths_name = find_sql_column(auths, "name");
-       sql_column *auths_id = find_sql_column(auths, "name");
+       sql_column *auths_id = find_sql_column(auths, "id");
 
        void *auth_id, *grantee_id;
 
@@ -144,7 +144,7 @@
        sql_table *auths = find_sql_table(sys, "auths");
        sql_table *roles = find_sql_table(sys, "user_role");
        sql_column *auths_name = find_sql_column(auths, "name");
-       sql_column *auths_id = find_sql_column(auths, "name");
+       sql_column *auths_id = find_sql_column(auths, "id");
        sql_column *role_id = find_sql_column(roles, "role_id");
        sql_column *login_id = find_sql_column(roles, "login_id");
 
@@ -330,15 +330,21 @@
 
        rid = column_find_row(m->session->tr, auths_name, role, NULL);
        if (rid >= 0) {
+               sql_table *roles = find_sql_table(sys, "user_role");
+               sql_column *role_id = find_sql_column(roles, "role_id");
+               sql_column *login_id = find_sql_column(roles, "login_id");
+
                sql_column *auths_id = find_sql_column(auths, "id");
                void *p = column_find_value(m->session->tr, auths_id, rid);
                int id = *(int *)p;
 
                _DELETE(p);
-               /* todo check if user is part of this role */
-               m->role_id = id;
-
-               res = 1;
+               rid = column_find_row(m->session->tr, login_id, &m->user_id, 
role_id, &id, NULL);
+               
+               if (rid >= 0) {
+                       m->role_id = id;
+                       res = 1;
+               }
        }
        return res;
 }

Index: sql_scan.mx
===================================================================
RCS file: /cvsroot/monetdb/sql/src/server/sql_scan.mx,v
retrieving revision 1.124
retrieving revision 1.125
diff -u -d -r1.124 -r1.125
--- sql_scan.mx 16 Mar 2007 12:36:25 -0000      1.124
+++ sql_scan.mx 22 Mar 2007 09:26:54 -0000      1.125
@@ -46,6 +46,8 @@
        int key;                /* query hash */
        int started;            /* found at least one token */
        prot mode;              /* which mode (line (1,N), blocked) */
+       char *schema;           /* Keep schema name of create statement, 
+                                  needed AUTO_INCREMENT, SERIAL */
 };
 
 #define QUERY(scanner) (scanner.rs->buf+scanner.rs->pos)
@@ -370,6 +372,7 @@
        s->as = s->view_end = 0;
 
        s->mode = LINE_N;
+       s->schema = NULL;
 }
 
 void
@@ -394,6 +397,7 @@
        s->key = 0;             /* keep a hash key of the query */
        s->started = 0;
        s->as = s->view_end = 0;
+       s->schema = NULL;
 }
 
 static int

Index: sql_parser.mx
===================================================================
RCS file: /cvsroot/monetdb/sql/src/server/sql_parser.mx,v
retrieving revision 1.237
retrieving revision 1.238
diff -u -d -r1.237 -r1.238
--- sql_parser.mx       9 Feb 2007 23:19:39 -0000       1.237
+++ sql_parser.mx       22 Mar 2007 09:26:54 -0000      1.238
@@ -1156,34 +1156,15 @@
  * - symbol: the symbol
  */
 opt_restart:
-       /* empty */                             {
-                                                               dlist *l = L();
-                                                               append_int(l, 
-1);
-                                                               $$ = l;
-                                                       }
-  |    RESTART                                 {
-                                                               dlist *l = L();
-                                                               append_int(l, 
0);
-                                                               $$ = l;
-                                                       }
-  | RESTART WITH                       {
-                                                               mvc *m = 
(mvc*)parm;
-                                                               m->scanner.as = 
m->scanner.yycur;
-                                                       }
-                               subquery        {
-                                                               mvc *m = 
(mvc*)parm;
-                                                               dlist *l = L();
-                                                               append_int(l, 
1);
-                                                               
append_symbol(l, $4);
-                                                               $$ = l;
-                                                               
m->scanner.view_end = m->scanner.yycur;
-                                                       }
-  |    RESTART WITH nonzero    {
-                                                               dlist *l = L();
-                                                               append_int(l, 
2);
-                                                               append_int(l, 
$3);
-                                                               $$ = l;
-                                                       }
+       /* empty */     { $$ = append_int(L(), -1); }
+  |    RESTART         { $$ = append_int(L(), 0); }
+  |    RESTART WITH 
+       nonzero         { $$ = append_int(append_int(L(), 2), $3); }
+  |    RESTART WITH    { mvc *m = (mvc*)parm;
+                         m->scanner.as = m->scanner.yycur; }
+       subquery        { mvc *m = (mvc*)parm;
+                         $$ = append_symbol(append_int(L(), 1), $4);
+                         m->scanner.view_end = m->scanner.yycur; }
   ;
 
 /*
@@ -1373,8 +1354,13 @@
                        dlist *l = L();
                        /* finally all the options */
                        dlist *o = L();
+
                        /* the name of the sequence */
-                       append_list(l, append_string(L(), sn));
+                       dlist *seqn1 = L(), *seqn2 = L();
+
+                       if (m->scanner.schema)
+                               append_string(seqn1, m->scanner.schema);
+                       append_list(l, append_string(seqn1, sn));
                        /* ultra dirty: inline 'integer' type generation */
                        sql_find_subtype(&it, "int", 32, 0);
                        append_type(l, &it);
@@ -1399,7 +1385,10 @@
                        append_string(l, $1);
                        append_type(l, &it);
                        o = L();
-                       append_symbol(o, _symbol_create_symbol(SQL_DEFAULT, 
_symbol_create(SQL_NEXT, sn)));
+                       if (m->scanner.schema)
+                               append_string(seqn2, m->scanner.schema);
+                       append_string(seqn2, sn);
+                       append_symbol(o, _symbol_create_symbol(SQL_DEFAULT, 
_symbol_create_list(SQL_NEXT, seqn2)));
                        p = L();
                        append_string(p, NULL);
                        append_symbol(p, _symbol_create(SQL_PRIMARY_KEY, NULL));
@@ -1476,7 +1465,7 @@
 
                /* finally all the options */
                append_list(l, $5);
-               $$ = _symbol_create_symbol(SQL_DEFAULT, 
_symbol_create(SQL_NEXT, sn));
+               $$ = _symbol_create_symbol(SQL_DEFAULT, 
_symbol_create_list(SQL_NEXT, append_string(L(), sn)));
 
                if (m->sym) {
                        stmts = m->sym->data.lval;
@@ -1498,8 +1487,13 @@
                dlist *l = L();
                /* finally all the options */
                dlist *o = L();
-               /* the name of the sequence (not known here) */
-               append_list(l, append_string(L(), sn));
+
+               /* the name of the sequence */
+               dlist *seqn1 = L(), *seqn2 = L();
+
+               if (m->scanner.schema)
+                       append_string(seqn1, m->scanner.schema);
+               append_list(l, append_string(seqn1, sn));
                /* ultra dirty: inline 'integer' type generation */
                sql_find_subtype(&it, "int", 32, 0);
                append_type(l, &it);
@@ -1511,7 +1505,10 @@
                append_int(o, 1); /* cache */
                append_int(o, 0); /* cycle */
                append_list(l, o);
-               $$ = _symbol_create_symbol(SQL_DEFAULT, 
_symbol_create(SQL_NEXT, sn));
+               if (m->scanner.schema)
+                       append_string(seqn2, m->scanner.schema);
+               append_string(seqn2, sn);
+               $$ = _symbol_create_symbol(SQL_DEFAULT, 
_symbol_create_list(SQL_NEXT, seqn2));
 
                if (m->sym) {
                        stmts = m->sym->data.lval;
@@ -3087,7 +3084,7 @@
  |  var_ref            
  |  aggr_ref
  |  func_ref
- |  NEXT VALUE FOR ident       { $$ = _symbol_create( SQL_NEXT, $4); }
+ |  NEXT VALUE FOR qname       { $$ = _symbol_create_list( SQL_NEXT, $4); }
  |  datetime_funcs
  |  string_funcs
  |  case_exp
@@ -3775,13 +3772,17 @@
 
 qname:
     ident                      { $$ = append_string(L(), $1); }
- |  ident '.' ident            { $$ = append_string(
+ |  ident '.' ident            { mvc *m = (mvc*)parm;
+                                 m->scanner.schema = $1;
+                                 $$ = append_string(
                                        append_string(L(), $1), $3);}
- |  ident '.' ident '.' ident  { $$ = append_string(
-                                               append_string(
-                                                       append_string(L(), $1), 
-                                                       $3), 
-                                               $5)
+ |  ident '.' ident '.' ident  { mvc *m = (mvc*)parm;
+                                 m->scanner.schema = $1;
+                                 $$ = append_string(
+                                       append_string(
+                                               append_string(L(), $1), 
+                                               $3), 
+                                       $5)
                                ;}
  ;
 

Index: sql_sequence.mx
===================================================================
RCS file: /cvsroot/monetdb/sql/src/server/sql_sequence.mx,v
retrieving revision 1.40
retrieving revision 1.41
diff -u -d -r1.40 -r1.41
--- sql_sequence.mx     3 Jan 2007 12:39:48 -0000       1.40
+++ sql_sequence.mx     22 Mar 2007 09:26:56 -0000      1.41
@@ -52,16 +52,22 @@
        int cycle)
 {
        char* name = qname_table(qname);
+       char *sname = qname_schema(qname);
+       sql_schema *s = NULL;
 
+       if (sname && !(s = mvc_bind_schema(sql, sname)))
+               return sql_error(sql, 02, "CREATE SEQUENCE: no such schema 
'%s'", sname);
+       if (s == NULL)
+               s = ss;
        (void) tpe;
-       if (find_sql_sequence(sql->session->schema, name)) {
+       if (find_sql_sequence(s, name)) {
                return sql_error(sql, 02,
                                "CREATE SEQUENCE: "
                                "name '%s' already in use", name);
-       } else if (!schema_privs(sql->role_id, ss)) {
+       } else if (!schema_privs(sql->role_id, s)) {
                return sql_error(sql, 02,
                                "CREATE SEQUENCE: insufficient privileges "
-                               "for '%s' in schema '%s'", 
stack_get_string(sql, "current_user"), ss->base.name);
+                               "for '%s' in schema '%s'", 
stack_get_string(sql, "current_user"), s->base.name);
        }
 
        /* generate defaults */
@@ -71,7 +77,7 @@
        if (max < 0) max = 0;
        if (cache <= 0) cache = 1;
 
-       sql_trans_create_sequence(sql->session->tr, ss, name, start, min, max, 
inc, cache, cycle);  
+       sql_trans_create_sequence(sql->session->tr, s, name, start, min, max, 
inc, cache, cycle);  
        return stmt_none();
 }
 
@@ -89,30 +95,34 @@
                int cycle)
 {
        char* name = qname_table(qname);
+       char *sname = qname_schema(qname);
        int start_type = start_list->h->data.ival;
        sql_sequence *seq;
-       stmt *val = NULL, *seqname = NULL;
-       sql_subfunc *f = NULL;
-       sql_subtype *str_t = sql_bind_localtype("str");
+       stmt *val = NULL, *ssname = NULL, *seqname = NULL;
        sql_subtype *lng_t = sql_bind_localtype("lng");
+       sql_schema *s = NULL;
 
+       if (sname && !(s = mvc_bind_schema(sql, sname)))
+               return sql_error(sql, 02, "CREATE SEQUENCE: no such schema 
'%s'", sname);
+       if (!s)
+               s = ss;
        (void) tpe;
-       if (!(seq = find_sql_sequence(sql->session->schema, name))) {
+       if (!(seq = find_sql_sequence(s, name))) {
                return sql_error(sql, 02,
                                "ALTER SEQUENCE: "
                                "no such sequence '%s'", name);
        }
-       if (!schema_privs(sql->role_id, ss)) {
+       if (!schema_privs(sql->role_id, s)) {
                return sql_error(sql, 02,
                                "ALTER SEQUENCE: insufficient privileges "
-                               "for '%s' in schema '%s'", 
stack_get_string(sql, "current_user"), ss->base.name);
+                               "for '%s' in schema '%s'", 
stack_get_string(sql, "current_user"), s->base.name);
        }
 
        /* first alter the known values */
        sql_trans_alter_sequence(sql->session->tr, seq, min, max, inc, cache, 
cycle);
 
-       /* restart maybe a query, ie we create a binary statement 
-          restart(seqname,value) */ 
+       /* restart maybe a query, ie we create a statement 
+          restart(ssname,seqname,value) */ 
 
        if (start_type == 0) {
                val = stmt_atom_lng(seq->start);
@@ -125,23 +135,28 @@
        } else if (start_type == 2) {
                val = stmt_atom_lng(start_list->h->next->data.ival);
        }
+       ssname = stmt_atom_string(_strdup(seq->s->base.name));
        seqname = stmt_atom_string(_strdup(name));
-       f = sql_bind_func(ss, "restart", str_t, lng_t);
-       assert(f);
-       return stmt_binop(seqname, val, f);
+       return sql_Nop_(sql, "restart", ssname, seqname, val);
 }
 
 static stmt *
 sql_drop_seq(mvc *sql, sql_schema *ss, dlist *qname)
 {
        char *name = qname_table(qname);
+       char *sname = qname_schema(qname);
+       sql_schema *s = NULL;
 
-       if (!find_sql_sequence(sql->session->schema, name)) {
+       if (sname && !(s = mvc_bind_schema(sql, sname)))
+               return sql_error(sql, 02, "CREATE SEQUENCE: no such schema 
'%s'", sname);
+       if (!s)
+               s = ss;
+       if (!find_sql_sequence(s, name)) {
                return sql_error(sql, 02, "DROP SEQUENCE: no such sequence 
'%s'", name);
-       } else if (!schema_privs(sql->role_id, ss)) {
-               return sql_error(sql, 02, "DROP SEQUENCE: insufficient 
privileges for '%s' in schema '%s'", stack_get_string(sql, "current_user"),  
ss->base.name);
+       } else if (!schema_privs(sql->role_id, s)) {
+               return sql_error(sql, 02, "DROP SEQUENCE: insufficient 
privileges for '%s' in schema '%s'", stack_get_string(sql, "current_user"),  
s->base.name);
        }
-       sql_trans_drop_sequence(sql->session->tr, ss, name);  
+       sql_trans_drop_sequence(sql->session->tr, s, name);  
        return stmt_none();
 }
 

Index: sql_select.mx
===================================================================
RCS file: /cvsroot/monetdb/sql/src/server/sql_select.mx,v
retrieving revision 1.178
retrieving revision 1.179
diff -u -d -r1.178 -r1.179
--- sql_select.mx       16 Mar 2007 12:36:27 -0000      1.178
+++ sql_select.mx       22 Mar 2007 09:26:55 -0000      1.179
@@ -66,6 +66,7 @@
 extern stmt *sql_compare(mvc *sql, scope *scp, stmt *ls, stmt *rs, char 
*compare_op, int f);
 extern stmt *complex_find_subset(stmt *subset, stmt *t);
 extern stmt *sql_and(mvc *sql, scope *scp, stmt *ls, stmt *rs, int f);
+extern stmt *sql_Nop_(mvc *sql, char *fname, stmt *a1, stmt *a2, stmt *a3);
 
 
 #endif /*_SQL_SELECT_H_*/
@@ -86,7 +87,6 @@
 static stmt *sql_simple_select(mvc *sql, scope *scp, SelectNode *sn);
 static tvar *query_exp_optname(mvc *sql, scope *scp, symbol *q);
 static tvar *sql_subquery_optname(mvc *sql, scope *scp, symbol *query);
-static stmt *sql_Nop_(mvc *sql, char *fname, stmt *a1, stmt *a2, stmt *a3);
 
 static void
 sql_select_cleanup(mvc *sql, stmt *s, stmt *subset, group *grp)
@@ -780,7 +780,7 @@
        return l;
 }
 
-static stmt *
+stmt *
 sql_Nop_(mvc *sql, char *fname, stmt *a1, stmt *a2, stmt *a3)
 {
        list *sl = create_stmt_list();
@@ -1493,6 +1493,15 @@
 }
 
 stmt *
+stmt_seq_next(mvc *sql, char *sname, char *seqname)
+{
+       stmt *schema = stmt_atom_string(sname);
+       stmt *seq = stmt_atom_string(seqname);
+       return sql_binop_(sql, NULL, NULL, "next_value_for", schema, seq);
+}
+
+
+stmt *
 sql_value_exp(mvc *sql, scope *scp, symbol *se, group *grp, stmt *subset, int 
f, exp_kind ek)
 {
 
@@ -1581,12 +1590,18 @@
        }
                break;
        case SQL_NEXT:{
-               char *seq = se->data.sval;
+               char *seq = qname_table(se->data.lval);
+               char *sname = qname_schema(se->data.lval);
+               sql_schema *s = NULL;
 
-               if (!find_sql_sequence(sql->session->schema, seq)) 
+               if (sname && !(s = mvc_bind_schema(sql, sname)))
+                       return sql_error(sql, 02, "NEXT VALUE FOR: no such 
schema '%s'", sname);
+               if (!s)
+                       s = sql->session->schema;
+               if (!find_sql_sequence(s, seq)) 
                        return sql_error(sql, 02, "NEXT VALUE FOR: "
-                                        "no such sequence '%s'", seq);
-               return stmt_seq_next( _strdup(seq) );
+                                        "no such sequence '%s'.'%s'", 
s->base.name, seq);
+               return stmt_seq_next(sql, _strdup(s->base.name), _strdup(seq) );
        }
                break;
        case SQL_CAST:


-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys-and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
Monetdb-sql-checkins mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/monetdb-sql-checkins

Reply via email to