Changeset: 898375af9d96 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/898375af9d96
Modified Files:
sql/backends/monet5/sql.c
sql/backends/monet5/sql_statistics.c
sql/backends/monet5/sql_statistics.h
sql/scripts/80_statistics.sql
Branch: analyze-fix
Log Message:
First version of statistics retrieval function
diffs (truncated from 384 to 300 lines):
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
@@ -5272,6 +5272,10 @@ static mel_func sql_init_funcs[] = {
pattern("sql", "analyze", sql_analyze, true, "Update statistics for schema",
args(1,2, arg("",void),arg("sch",str))),
pattern("sql", "analyze", sql_analyze, true, "Update statistics for table",
args(1,3, arg("",void),arg("sch",str),arg("tbl",str))),
pattern("sql", "analyze", sql_analyze, true, "Update statistics for column",
args(1,4, arg("",void),arg("sch",str),arg("tbl",str),arg("col",str))),
+ pattern("sql", "statistics", sql_statistics, false, "return a table with
statistics information", args(12,12,
batarg("schema",str),batarg("table",str),batarg("column",str),batarg("type",str),batarg("with",int),batarg("count",lng),batarg("unique",bit),batarg("nils",bit),batarg("minval",str),batarg("maxval",str),batarg("sorted",bit),batarg("revsorted",bit))),
+ pattern("sql", "statistics", sql_statistics, false, "return a table with
statistics information for a particular schema", args(12,13,
batarg("schema",str),batarg("table",str),batarg("column",str),batarg("type",str),batarg("with",int),batarg("count",lng),batarg("unique",bit),batarg("nils",bit),batarg("minval",str),batarg("maxval",str),batarg("sorted",bit),batarg("revsorted",bit),arg("sname",str))),
+ pattern("sql", "statistics", sql_statistics, false, "return a table with
statistics information for a particular table", args(12,14,
batarg("schema",str),batarg("table",str),batarg("column",str),batarg("type",str),batarg("with",int),batarg("count",lng),batarg("unique",bit),batarg("nils",bit),batarg("minval",str),batarg("maxval",str),batarg("sorted",bit),batarg("revsorted",bit),arg("sname",str),arg("tname",str))),
+ pattern("sql", "statistics", sql_statistics, false, "return a table with
statistics information for a particular column", args(12,15,
batarg("schema",str),batarg("table",str),batarg("column",str),batarg("type",str),batarg("with",int),batarg("count",lng),batarg("unique",bit),batarg("nils",bit),batarg("minval",str),batarg("maxval",str),batarg("sorted",bit),batarg("revsorted",bit),arg("sname",str),arg("tname",str),arg("cname",str))),
pattern("sql", "storage", sql_storage, false, "return a table with storage
information ", args(17,17,
batarg("schema",str),batarg("table",str),batarg("column",str),batarg("type",str),batarg("mode",str),batarg("location",str),batarg("count",lng),batarg("atomwidth",int),batarg("columnsize",lng),batarg("heap",lng),batarg("hashes",lng),batarg("phash",bit),batarg("imprints",lng),batarg("sorted",bit),batarg("revsorted",bit),batarg("key",bit),batarg("orderidx",lng))),
pattern("sql", "storage", sql_storage, false, "return a table with storage
information for a particular schema ", args(17,18,
batarg("schema",str),batarg("table",str),batarg("column",str),batarg("type",str),batarg("mode",str),batarg("location",str),batarg("count",lng),batarg("atomwidth",int),batarg("columnsize",lng),batarg("heap",lng),batarg("hashes",lng),batarg("phash",bit),batarg("imprints",lng),batarg("sorted",bit),batarg("revsorted",bit),batarg("key",bit),batarg("orderidx",lng),arg("sname",str))),
pattern("sql", "storage", sql_storage, false, "return a table with storage
information for a particular table", args(17,19,
batarg("schema",str),batarg("table",str),batarg("column",str),batarg("type",str),batarg("mode",str),batarg("location",str),batarg("count",lng),batarg("atomwidth",int),batarg("columnsize",lng),batarg("heap",lng),batarg("hashes",lng),batarg("phash",bit),batarg("imprints",lng),batarg("sorted",bit),batarg("revsorted",bit),batarg("key",bit),batarg("orderidx",lng),arg("sname",str),arg("tname",str))),
diff --git a/sql/backends/monet5/sql_statistics.c
b/sql/backends/monet5/sql_statistics.c
--- a/sql/backends/monet5/sql_statistics.c
+++ b/sql/backends/monet5/sql_statistics.c
@@ -170,3 +170,254 @@ sql_analyze(Client cntxt, MalBlkPtr mb,
}
return MAL_SUCCEED;
}
+
+str
+sql_statistics(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
+{
+ BAT *sch, *tab, *col, *type, *width, *count, *unique, *nils, *minval,
*maxval, *sorted, *revsorted, *bs = NULL, *fb = NULL;
+ mvc *m = NULL;
+ sql_trans *tr = NULL;
+ sqlstore *store = NULL;
+ bat *rsch = getArgReference_bat(stk, pci, 0);
+ bat *rtab = getArgReference_bat(stk, pci, 1);
+ bat *rcol = getArgReference_bat(stk, pci, 2);
+ bat *rtype = getArgReference_bat(stk, pci, 3);
+ bat *rwidth = getArgReference_bat(stk, pci, 4);
+ bat *rcount = getArgReference_bat(stk, pci, 5);
+ bat *runique = getArgReference_bat(stk, pci, 6);
+ bat *rnils = getArgReference_bat(stk, pci, 7);
+ bat *rminval = getArgReference_bat(stk, pci, 8);
+ bat *rmaxval = getArgReference_bat(stk, pci, 9);
+ bat *rsorted = getArgReference_bat(stk, pci, 10);
+ bat *rrevsorted = getArgReference_bat(stk, pci, 11);
+ str sname = NULL, tname = NULL, cname = NULL, msg = MAL_SUCCEED;
+ struct os_iter si = {0};
+ int sfnd = 0, tfnd = 0, cfnd = 0;
+
+ if ((msg = getSQLContext(cntxt, mb, &m, NULL)) != NULL)
+ return msg;
+ if ((msg = checkSQLContext(cntxt)) != NULL)
+ return msg;
+
+ if (pci->argc - pci->retc >= 1) {
+ sname = *getArgReference_str(stk, pci, pci->retc);
+ if (strNil(sname))
+ throw(SQL, "sql.statistics", SQLSTATE(42000) "Schema
name cannot be NULL");
+ }
+ if (pci->argc - pci->retc >= 2) {
+ tname = *getArgReference_str(stk, pci, pci->retc + 1);
+ if (strNil(tname))
+ throw(SQL, "sql.statistics", SQLSTATE(42000) "Table
name cannot be NULL");
+ }
+ if (pci->argc - pci->retc >= 3) {
+ cname = *getArgReference_str(stk, pci, pci->retc + 2);
+ if (strNil(cname))
+ throw(SQL, "sql.statistics", SQLSTATE(42000) "Column
name cannot be NULL");
+ }
+
+ tr = m->session->tr;
+ store = tr->store;
+ /* Do all the validations before retrieving any statistics */
+ os_iterator(&si, tr->cat->schemas, tr, NULL);
+ for(sql_base *b = oi_next(&si); b; b = oi_next(&si)) {
+ sql_schema *s = (sql_schema *)b;
+ if (s->base.name[0] == '%')
+ continue;
+
+ if (sname && strcmp(s->base.name, sname))
+ continue;
+ sfnd = 1;
+ struct os_iter oi;
+ os_iterator(&oi, s->tables, tr, NULL);
+ for(sql_base *b = oi_next(&oi); b; b = oi_next(&oi)) {
+ sql_table *t = (sql_table *)b;
+
+ if (tname && strcmp(t->base.name, tname))
+ continue;
+ tfnd = 1;
+ if (tname && !isTable(t))
+ throw(SQL, "sql.statistics", SQLSTATE(42S02)
"%s '%s' is not persistent", TABLE_TYPE_DESCRIPTION(t->type, t->properties),
t->base.name);
+ if (!table_privs(m, t, PRIV_SELECT))
+ throw(SQL, "sql.statistics", SQLSTATE(42000)
"STATISTICS: access denied for %s to table '%s.%s'",
+ get_string_global_var(m,
"current_user"), t->s->base.name, t->base.name);
+ if (isTable(t) && ol_first_node(t->columns)) {
+ for (node *ncol = ol_first_node((t)->columns);
ncol; ncol = ncol->next) {
+ sql_column *c = (sql_column *)
ncol->data;
+
+ if (cname && strcmp(c->base.name,
cname))
+ continue;
+ cfnd = 1;
+ if (!column_privs(m, c, PRIV_SELECT))
+ throw(SQL, "sql.statistics",
SQLSTATE(42000) "STATISTICS: access denied for %s to column '%s' on table
'%s.%s'",
+
get_string_global_var(m, "current_user"), c->base.name, t->s->base.name,
t->base.name);
+ }
+ }
+ }
+ }
+ if (sname && !sfnd)
+ throw(SQL, "sql.statistics", SQLSTATE(3F000) "Schema '%s' does
not exist", sname);
+ if (tname && !tfnd)
+ throw(SQL, "sql.statistics", SQLSTATE(42S02) "Table '%s' does
not exist", tname);
+ if (cname && !cfnd)
+ throw(SQL, "sql.statistics", SQLSTATE(38000) "Column '%s' does
not exist", cname);
+
+ sch = COLnew(0, TYPE_str, 0, TRANSIENT);
+ tab = COLnew(0, TYPE_str, 0, TRANSIENT);
+ col = COLnew(0, TYPE_str, 0, TRANSIENT);
+ type = COLnew(0, TYPE_str, 0, TRANSIENT);
+ width = COLnew(0, TYPE_int, 0, TRANSIENT);
+ count = COLnew(0, TYPE_lng, 0, TRANSIENT);
+ unique = COLnew(0, TYPE_bit, 0, TRANSIENT);
+ nils = COLnew(0, TYPE_bit, 0, TRANSIENT);
+ minval = COLnew(0, TYPE_str, 0, TRANSIENT);
+ maxval = COLnew(0, TYPE_str, 0, TRANSIENT);
+ sorted = COLnew(0, TYPE_bit, 0, TRANSIENT);
+ revsorted = COLnew(0, TYPE_bit, 0, TRANSIENT);
+
+ if (!sch || !tab || !col || !type || !width || !count || !unique ||
!nils || !minval || !maxval || !sorted || !revsorted) {
+ msg = createException(SQL, "sql.statistics", SQLSTATE(HY013)
MAL_MALLOC_FAIL);
+ goto bailout;
+ }
+
+ si = (struct os_iter) {0};
+ os_iterator(&si, tr->cat->schemas, tr, NULL);
+ for (sql_base *b = oi_next(&si); b; b = oi_next(&si)) {
+ sql_schema *s = (sql_schema *) b;
+ if ((sname && strcmp(b->name, sname)) || b->name[0] == '%')
+ continue;
+ if (s->tables) {
+ struct os_iter oi;
+
+ os_iterator(&oi, s->tables, tr, NULL);
+ for (sql_base *bt = oi_next(&oi); bt; bt =
oi_next(&oi)) {
+ sql_table *t = (sql_table *) bt;
+ if (tname && strcmp(bt->name, tname))
+ continue;
+ if (isTable(t) && ol_first_node(t->columns)) {
+ for (node *ncol =
ol_first_node((t)->columns); ncol; ncol = ncol->next) {
+ sql_column *c = (sql_column *)
ncol->data;
+ int w;
+ lng cnt;
+ bit un, hnils, issorted,
isrevsorted;
+
+ if (cname &&
strcmp(c->base.name, cname))
+ continue;
+ if (!(bs =
store->storage_api.bind_col(tr, c, QUICK))) {
+ msg =
createException(SQL, "sql.statistics", SQLSTATE(HY005) "Cannot access column
descriptor");
+ goto bailout;
+ }
+ w = bs->twidth;
+ cnt = BATcount(bs);
+ un = bs->tkey;
+ hnils = !bs->tnonil;
+ issorted = bs->tsorted;
+ isrevsorted = bs->trevsorted;
+
+ if (BUNappend(sch, b->name,
false) != GDK_SUCCEED ||
+ BUNappend(tab,
bt->name, false) != GDK_SUCCEED ||
+ BUNappend(col,
c->base.name, false) != GDK_SUCCEED ||
+ BUNappend(type,
c->type.type->base.name, false) != GDK_SUCCEED ||
+ BUNappend(width, &w,
false) != GDK_SUCCEED ||
+ BUNappend(count, &cnt,
false) != GDK_SUCCEED ||
+ BUNappend(unique, &un,
false) != GDK_SUCCEED ||
+ BUNappend(nils, &hnils,
false) != GDK_SUCCEED ||
+ BUNappend(sorted,
&issorted, false) != GDK_SUCCEED ||
+ BUNappend(revsorted,
&isrevsorted, false) != GDK_SUCCEED)
+ goto bailout;
+
+ if (bs->tminpos != BUN_NONE ||
bs->tmaxpos != BUN_NONE) {
+ ssize_t
(*tostr)(str*,size_t*,const void*,bool) = BATatoms[bs->ttype].atomToStr;
+
MT_lock_set(&bs->theaplock);
+ if (bs->tminpos !=
BUN_NONE || bs->tmaxpos != BUN_NONE) {
+ size_t minlen =
0, maxlen = 0;
+ char *min =
NULL, *max = NULL;
+ gdk_return res
= GDK_SUCCEED;
+
+ if (!(fb =
store->storage_api.bind_col(tr, c, RDONLY))) {
+
MT_lock_unset(&bs->theaplock);
+ msg =
createException(SQL, "sql.statistics", SQLSTATE(HY005) "Cannot access column
descriptor");
+ goto
bailout;
+ }
+
+ BATiter bi =
bat_iterator_nolock(fb);
+ if (bs->tminpos
!= BUN_NONE) {
+ if
(tostr(&min, &minlen, BUNtail(bi, bs->tminpos), false) < 0) {
+
BBPunfix(fb->batCacheid);
+
MT_lock_unset(&bs->theaplock);
+
msg = createException(SQL, "sql.statistics", SQLSTATE(HY013) MAL_MALLOC_FAIL);
+
goto bailout;
+ }
+ } else {
+ min =
(char *) str_nil;
+ }
+ res =
BUNappend(minval, min, false);
+ if (bs->tminpos
!= BUN_NONE)
+
GDKfree(min);
+ if (res !=
GDK_SUCCEED) {
+
BBPunfix(fb->batCacheid);
+
MT_lock_unset(&bs->theaplock);
+ goto
bailout;
+ }
+
+ if (bs->tmaxpos
!= BUN_NONE) {
+ if
(tostr(&max, &maxlen, BUNtail(bi, bs->tmaxpos), false) < 0) {
+
BBPunfix(fb->batCacheid);
+
MT_lock_unset(&bs->theaplock);
+
msg = createException(SQL, "sql.statistics", SQLSTATE(HY013) MAL_MALLOC_FAIL);
+
goto bailout;
+ }
+ } else {
+ max =
(char *) str_nil;
+ }
+ res =
BUNappend(maxval, max, false);
+ if (bs->tmaxpos
!= BUN_NONE)
+
GDKfree(max);
+
BBPunfix(fb->batCacheid);
+ if (res !=
GDK_SUCCEED) {
+
MT_lock_unset(&bs->theaplock);
+ goto
bailout;
+ }
+ } else if
(BUNappend(minval, str_nil, false) != GDK_SUCCEED || BUNappend(maxval, str_nil,
false) != GDK_SUCCEED) {
+
MT_lock_unset(&bs->theaplock);
+ goto bailout;
+ }
+
MT_lock_unset(&bs->theaplock);
+ } else if (BUNappend(minval,
str_nil, false) != GDK_SUCCEED || BUNappend(maxval, str_nil, false) !=
GDK_SUCCEED) {
+ goto bailout;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ BBPkeepref(*rsch = sch->batCacheid);
+ BBPkeepref(*rtab = tab->batCacheid);
+ BBPkeepref(*rcol = col->batCacheid);
+ BBPkeepref(*rtype = type->batCacheid);
+ BBPkeepref(*rwidth = width->batCacheid);
+ BBPkeepref(*rcount = count->batCacheid);
+ BBPkeepref(*runique = unique->batCacheid);
+ BBPkeepref(*rnils = nils->batCacheid);
+ BBPkeepref(*rminval = minval->batCacheid);
+ BBPkeepref(*rmaxval = maxval->batCacheid);
+ BBPkeepref(*rsorted = sorted->batCacheid);
+ BBPkeepref(*rrevsorted = revsorted->batCacheid);
+ return MAL_SUCCEED;
+bailout:
+ BBPreclaim(sch);
+ BBPreclaim(tab);
+ BBPreclaim(col);
+ BBPreclaim(type);
+ BBPreclaim(width);
+ BBPreclaim(count);
+ BBPreclaim(unique);
+ BBPreclaim(nils);
+ BBPreclaim(minval);
+ BBPreclaim(maxval);
+ BBPreclaim(sorted);
+ BBPreclaim(revsorted);
+ if (!msg)
+ msg = createException(SQL, "sql.statistics", GDK_EXCEPTION);
+ return msg;
+}
diff --git a/sql/backends/monet5/sql_statistics.h
b/sql/backends/monet5/sql_statistics.h
--- a/sql/backends/monet5/sql_statistics.h
+++ b/sql/backends/monet5/sql_statistics.h
@@ -13,5 +13,6 @@
#include "sql.h"
extern str sql_analyze(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr
pci);
+extern str sql_statistics(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr
pci);
#endif /* _SQL_STATISTICS_DEF */
diff --git a/sql/scripts/80_statistics.sql b/sql/scripts/80_statistics.sql
--- a/sql/scripts/80_statistics.sql
+++ b/sql/scripts/80_statistics.sql
@@ -11,11 +11,93 @@
create procedure sys.analyze()
external name sql.analyze;
-create procedure sys.analyze(sch string)
+create procedure sys.analyze("schema" varchar(1024))
+external name sql.analyze;
+
+create procedure sys.analyze("schema" varchar(1024), "tname" varchar(1024))
+external name sql.analyze;
+
+create procedure sys.analyze("schema" varchar(1024), "tname" varchar(1024),
"cname" varchar(1024))
external name sql.analyze;
-create procedure sys.analyze(sch string, tbl string)
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list