Navigation Menu

Skip to content

Commit

Permalink
Support sum in grn_table_group()
Browse files Browse the repository at this point in the history
You can use it in select such as:

    select \
      --drilldown[lable].calc_type SUM \
      --drilldown[lable].calc_target target_column
  • Loading branch information
kou committed Jan 19, 2015
1 parent d731539 commit 0e5e39f
Show file tree
Hide file tree
Showing 8 changed files with 482 additions and 47 deletions.
4 changes: 4 additions & 0 deletions include/groonga/groonga.h
Expand Up @@ -719,6 +719,8 @@ struct _grn_table_group_result {
int limit;
grn_table_group_flags flags;
grn_operator op;
unsigned int max_n_subrecs;
grn_obj *calc_target;
};

GRN_API grn_rc grn_table_group(grn_ctx *ctx, grn_obj *table,
Expand Down Expand Up @@ -751,6 +753,8 @@ GRN_API unsigned int grn_table_size(grn_ctx *ctx, grn_obj *table);
#define GRN_COLUMN_NAME_SCORE_LEN (sizeof(GRN_COLUMN_NAME_SCORE) - 1)
#define GRN_COLUMN_NAME_NSUBRECS "_nsubrecs"
#define GRN_COLUMN_NAME_NSUBRECS_LEN (sizeof(GRN_COLUMN_NAME_NSUBRECS) - 1)
#define GRN_COLUMN_NAME_SUM "_sum"
#define GRN_COLUMN_NAME_SUM_LEN (sizeof(GRN_COLUMN_NAME_SUM) - 1)

GRN_API grn_obj *grn_column_create(grn_ctx *ctx, grn_obj *table,
const char *name, unsigned int name_size,
Expand Down
291 changes: 262 additions & 29 deletions lib/db.c

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions lib/grn_ctx.h
Expand Up @@ -558,6 +558,9 @@ typedef struct {
uint8_t subrec_offset;
uint8_t record_unit;
uint8_t subrec_unit;
union {
grn_table_group_flags group;
} flags;
// grn_obj_flags flags;
} grn_db_obj;

Expand Down
9 changes: 9 additions & 0 deletions lib/grn_db.h
Expand Up @@ -47,6 +47,12 @@ typedef struct {

#define GRN_RSET_UTIL_BIT (0x80000000)

#define GRN_RSET_N_SUBRECS_SIZE (sizeof(int))
#define GRN_RSET_MAX_SIZE (sizeof(int64_t))
#define GRN_RSET_MIN_SIZE (sizeof(int64_t))
#define GRN_RSET_SUM_SIZE (sizeof(int64_t))
#define GRN_RSET_AVG_SIZE (sizeof(double))

#define GRN_RSET_SCORE_SIZE (sizeof(int))

#define GRN_RSET_N_SUBRECS(ri) ((ri)->n_subrecs & ~GRN_RSET_UTIL_BIT)
Expand All @@ -58,6 +64,8 @@ typedef struct {
((int *)((byte *)subrecs + n * GRN_RSET_SUBREC_SIZE(size)))
#define GRN_RSET_SUBRECS_COPY(subrecs,size,n,src) \
(memcpy(GRN_RSET_SUBRECS_NTH(subrecs, size, n), src, GRN_RSET_SUBREC_SIZE(size)))
#define GRN_RSET_SUBRECS_SIZE(subrec_size,n) \
(GRN_RSET_SUBREC_SIZE(subrec_size) * n)

#define GRN_JSON_LOAD_OPEN_BRACKET 0x40000000
#define GRN_JSON_LOAD_OPEN_BRACE 0x40000001
Expand Down Expand Up @@ -246,6 +254,7 @@ enum {
GRN_ACCESSOR_GET_VALUE,
GRN_ACCESSOR_GET_SCORE,
GRN_ACCESSOR_GET_NSUBRECS,
GRN_ACCESSOR_GET_SUM,
GRN_ACCESSOR_GET_COLUMN_VALUE,
GRN_ACCESSOR_GET_DB_OBJ,
GRN_ACCESSOR_LOOKUP,
Expand Down
17 changes: 17 additions & 0 deletions lib/output.c
Expand Up @@ -533,6 +533,23 @@ grn_text_atoj(grn_ctx *ctx, grn_obj *outbuf, grn_content_type output_type,
}
buf.header.domain = GRN_DB_INT32;
break;
case GRN_ACCESSOR_GET_SUM :
{
grn_rset_recinfo *ri = (grn_rset_recinfo *)grn_obj_get_value_(ctx, a->obj, id, &vs);
byte *values;
values = ((char *)(ri->subrecs) +
GRN_RSET_SUBRECS_SIZE(DB_OBJ(a->obj)->subrec_size,
DB_OBJ(a->obj)->max_n_subrecs));
if (DB_OBJ(a->obj)->flags.group & GRN_TABLE_GROUP_CALC_MAX) {
values += GRN_RSET_MAX_SIZE;
}
if (DB_OBJ(a->obj)->flags.group & GRN_TABLE_GROUP_CALC_MIN) {
values += GRN_RSET_MIN_SIZE;
}
GRN_INT64_PUT(ctx, &buf, *((int64_t *)values));
}
buf.header.domain = GRN_DB_INT64;
break;
case GRN_ACCESSOR_GET_COLUMN_VALUE :
if ((a->obj->header.flags & GRN_OBJ_COLUMN_TYPE_MASK) == GRN_OBJ_COLUMN_VECTOR) {
if (a->next) {
Expand Down
107 changes: 89 additions & 18 deletions lib/proc.c
@@ -1,6 +1,6 @@
/* -*- c-basic-offset: 2 -*- */
/*
Copyright(C) 2009-2014 Brazil
Copyright(C) 2009-2015 Brazil
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
Expand Down Expand Up @@ -584,16 +584,62 @@ typedef struct {
unsigned int output_columns_len;
int offset;
int limit;
grn_table_group_flags calc_types;
const char *calc_target_name;
unsigned int calc_target_name_len;
} drilldown_info;

static grn_table_group_flags
grn_parse_table_group_calc_types(grn_ctx *ctx,
const char *calc_types,
unsigned int calc_types_len)
{
grn_table_group_flags flags = 0;
const char *calc_types_end = calc_types + calc_types_len;

while (calc_types < calc_types_end) {
if (*calc_types == '|' || *calc_types == ' ') {
calc_types += 1;
continue;
}

#define CHECK_TABLE_GROUP_CALC_TYPE(name)\
if (((calc_types_end - calc_types) >= (sizeof(#name) - 1)) &&\
(!memcmp(calc_types, #name, sizeof(#name) - 1))) {\
flags |= GRN_TABLE_GROUP_CALC_ ## name;\
calc_types += sizeof(#name);\
continue;\
}

CHECK_TABLE_GROUP_CALC_TYPE(COUNT);
CHECK_TABLE_GROUP_CALC_TYPE(MAX);
CHECK_TABLE_GROUP_CALC_TYPE(MIN);
CHECK_TABLE_GROUP_CALC_TYPE(SUM);
CHECK_TABLE_GROUP_CALC_TYPE(AVG);

#define GRN_TABLE_GROUP_CALC_NONE 0
CHECK_TABLE_GROUP_CALC_TYPE(NONE);
#undef GRN_TABLE_GROUP_CALC_NONE

ERR(GRN_INVALID_ARGUMENT, "invalid table group calc type: <%.*s>",
(int)(calc_types_end - calc_types), calc_types);
return 0;
#undef CHECK_TABLE_GROUP_CALC_TYPE
}

return flags;
}

static void
drilldown_info_fill(grn_ctx *ctx,
drilldown_info *drilldown,
grn_obj *keys,
grn_obj *sortby,
grn_obj *output_columns,
grn_obj *offset,
grn_obj *limit)
grn_obj *limit,
grn_obj *calc_types,
grn_obj *calc_target)
{
if (keys) {
drilldown->keys = GRN_TEXT_VALUE(keys);
Expand Down Expand Up @@ -636,6 +682,23 @@ drilldown_info_fill(grn_ctx *ctx,
} else {
drilldown->limit = DEFAULT_DRILLDOWN_LIMIT;
}

if (calc_types && GRN_TEXT_LEN(calc_types)) {
drilldown->calc_types =
grn_parse_table_group_calc_types(ctx,
GRN_TEXT_VALUE(calc_types),
GRN_TEXT_LEN(calc_types));
} else {
drilldown->calc_types = 0;
}

if (calc_target && GRN_TEXT_LEN(calc_target)) {
drilldown->calc_target_name = GRN_TEXT_VALUE(calc_target);
drilldown->calc_target_name_len = GRN_TEXT_LEN(calc_target);
} else {
drilldown->calc_target_name = NULL;
drilldown->calc_target_name_len = 0;
}
}

static void
Expand Down Expand Up @@ -725,7 +788,7 @@ grn_select_drilldowns(grn_ctx *ctx, grn_obj *table,
int offset;
int limit;
grn_table_group_result result = {
NULL, 0, 0, 1, GRN_TABLE_GROUP_CALC_COUNT, 0
NULL, 0, 0, 1, GRN_TABLE_GROUP_CALC_COUNT, 0, 0, NULL
};

keys = grn_table_sort_key_from_str(ctx,
Expand All @@ -736,23 +799,22 @@ grn_select_drilldowns(grn_ctx *ctx, grn_obj *table,
continue;
}

if (n_keys == 1) {
result.table = grn_table_create_for_group(ctx, NULL, 0, NULL,
keys[0].key, table, 0);
} else {
result.table = grn_table_create_for_group(ctx, NULL, 0, NULL,
NULL, table, 1);
}

if (!result.table) {
grn_table_sort_key_close(ctx, keys, n_keys);
continue;
}

GRN_OUTPUT_STR(drilldown->label, drilldown->label_len);

result.key_begin = 0;
result.key_end = n_keys - 1;
if (n_keys > 1) {
result.max_n_subrecs = 1;
}
if (drilldown->calc_target_name) {
result.calc_target = grn_obj_column(ctx, table,
drilldown->calc_target_name,
drilldown->calc_target_name_len);
}
if (result.calc_target) {
result.flags |= drilldown->calc_types;
}

grn_table_group(ctx, table, keys, n_keys, &result, 1);
n_hits = grn_table_size(ctx, result.table);

Expand Down Expand Up @@ -790,6 +852,9 @@ grn_select_drilldowns(grn_ctx *ctx, grn_obj *table,
}

grn_table_sort_key_close(ctx, keys, n_keys);
if (result.calc_target) {
grn_obj_unlink(ctx, result.calc_target);
}
grn_obj_unlink(ctx, result.table);

GRN_QUERY_LOG(ctx, GRN_QUERY_LOG_SIZE,
Expand Down Expand Up @@ -1191,7 +1256,8 @@ proc_select(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data)
drilldown->label = NULL;
drilldown->label_len = 0;
drilldown_info_fill(ctx, drilldown,
VAR(9), VAR(10), VAR(11), VAR(12), VAR(13));
VAR(9), VAR(10), VAR(11), VAR(12), VAR(13),
NULL, NULL);
n_drilldowns++;
} else {
unsigned int i;
Expand All @@ -1207,6 +1273,8 @@ proc_select(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data)
grn_obj *output_columns;
grn_obj *offset;
grn_obj *limit;
grn_obj *calc_types;
grn_obj *calc_target;

label_len = grn_vector_get_element(ctx, &drilldown_labels, i,
&label, NULL, NULL);
Expand All @@ -1223,11 +1291,14 @@ proc_select(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data)
GET_VAR(output_columns);
GET_VAR(offset);
GET_VAR(limit);
GET_VAR(calc_types);
GET_VAR(calc_target);

#undef GET_VAR

drilldown_info_fill(ctx, drilldown,
keys, sortby, output_columns, offset, limit);
keys, sortby, output_columns, offset, limit,
calc_types, calc_target);
}
}
if (grn_select(ctx, GRN_TEXT_VALUE(VAR(0)), GRN_TEXT_LEN(VAR(0)),
Expand Down
@@ -0,0 +1,78 @@
table_create Tags TABLE_PAT_KEY ShortText
[[0,0.0,0.0],true]
table_create Memos TABLE_HASH_KEY ShortText
[[0,0.0,0.0],true]
column_create Memos tag COLUMN_SCALAR Tags
[[0,0.0,0.0],true]
column_create Memos value COLUMN_SCALAR Int64
[[0,0.0,0.0],true]
load --table Memos
[
{"_key": "Groonga is fast!", "tag": "Groonga", "value": 10},
{"_key": "Mroonga is fast!", "tag": "Mroonga", "value": 20},
{"_key": "Groonga sticker!", "tag": "Groonga", "value": 40},
{"_key": "Rroonga is fast!", "tag": "Rroonga", "value": 80}
]
[[0,0.0,0.0],4]
select Memos --limit 0 --drilldown[tag].keys tag --drilldown[tag].calc_types SUM --drilldown[tag].calc_target value --drilldown[tag].output_columns _key,_sum
[
[
0,
0.0,
0.0
],
[
[
[
4
],
[
[
"_id",
"UInt32"
],
[
"_key",
"ShortText"
],
[
"tag",
"Tags"
],
[
"value",
"Int64"
]
]
],
{
"tag": [
[
3
],
[
[
"_key",
"ShortText"
],
[
"_sum",
"Int64"
]
],
[
"Groonga",
50
],
[
"Mroonga",
20
],
[
"Rroonga",
80
]
]
}
]
]
20 changes: 20 additions & 0 deletions test/command/suite/select/drilldown/labeled/calc_types/sum.test
@@ -0,0 +1,20 @@
table_create Tags TABLE_PAT_KEY ShortText

table_create Memos TABLE_HASH_KEY ShortText
column_create Memos tag COLUMN_SCALAR Tags
column_create Memos value COLUMN_SCALAR Int64

load --table Memos
[
{"_key": "Groonga is fast!", "tag": "Groonga", "value": 10},
{"_key": "Mroonga is fast!", "tag": "Mroonga", "value": 20},
{"_key": "Groonga sticker!", "tag": "Groonga", "value": 40},
{"_key": "Rroonga is fast!", "tag": "Rroonga", "value": 80}
]

select Memos \
--limit 0 \
--drilldown[tag].keys tag \
--drilldown[tag].calc_types SUM \
--drilldown[tag].calc_target value \
--drilldown[tag].output_columns _key,_sum

0 comments on commit 0e5e39f

Please sign in to comment.