From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from [87.239.111.99] (localhost [127.0.0.1]) by dev.tarantool.org (Postfix) with ESMTP id 6B8F4711B3; Tue, 26 Oct 2021 13:39:17 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org 6B8F4711B3 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=tarantool.org; s=dev; t=1635244757; bh=Kescv933ljWOnzv5WFZBuDu+UDvZOQwIkZT1QKtMZog=; h=To:Cc:Date:In-Reply-To:References:Subject:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From:Reply-To:From; b=hCXcsQuy6NyfxosdBHvxQEGzpexok0RnPsGk2PLnGBT+9LkMSAqHZFXVARIV0Uu6r 3mhNC02cgP3iKXr1VIpfDJrnUqPt9pxiWQxth6TQdn1VuM3YyMxDocp1tq2jgl44Uj 1mo65rzAI9KZcNkMN/OCrHRIzru4Y9eCwcFOwSiY= Received: from smtpng1.i.mail.ru (smtpng1.i.mail.ru [94.100.181.251]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dev.tarantool.org (Postfix) with ESMTPS id 0F738711B3 for ; Tue, 26 Oct 2021 13:34:23 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org 0F738711B3 Received: by smtpng1.m.smailru.net with esmtpa (envelope-from ) id 1mfJmg-0000hA-9U; Tue, 26 Oct 2021 13:34:22 +0300 To: kyukhin@tarantool.org Cc: tarantool-patches@dev.tarantool.org Date: Tue, 26 Oct 2021 13:34:22 +0300 Message-Id: <5606a33ae4ca842b23774b0d2e4cc33c0c6a0ed0.1635244212.git.imeevma@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-4EC0790: 10 X-7564579A: B8F34718100C35BD X-77F55803: 4F1203BC0FB41BD9D1D35DBD2D15487E657BD385B6B7DC1C21BEC69EAD562B5E182A05F5380850405E2F30342CE95CA99BAB931CB8F975CF8BCC37667B66025961AD5FEBFE84EC9A X-7FA49CB5: FF5795518A3D127A4AD6D5ED66289B5278DA827A17800CE785DAC9A352760686C2099A533E45F2D0395957E7521B51C2CFCAF695D4D8E9FCEA1F7E6F0F101C6778DA827A17800CE7965AF5021CACFC748F08D7030A58E5AD1A62830130A00468AEEEE3FBA3A834EE7353EFBB553375662749EEF4D85F8CCA70ECEA52FFEC92E32AA4745BFEDF6FE7A471835C12D1D9774AD6D5ED66289B5278DA827A17800CE77A825AB47F0FC8649FA2833FD35BB23D2EF20D2F80756B5F868A13BD56FB6657A471835C12D1D977725E5C173C3A84C33F395433950BAD63117882F4460429728AD0CFFFB425014E868A13BD56FB6657E2021AF6380DFAD1A18204E546F3947CB11811A4A51E3B096D1867E19FE1407959CC434672EE6371089D37D7C0E48F6C8AA50765F79006377AA2284B41911753EFF80C71ABB335746BA297DBC24807EABDAD6C7F3747799A X-C1DE0DAB: C20DE7B7AB408E4181F030C43753B8186998911F362727C414F749A5E30D975C2749EEF4D85F8CCA70ECEA52FFEC92E32AA4745BFEDF6FE79C2B6934AE262D3EE7EAB7254005DCED7532B743992DF240BDC6A1CF3F042BAD6DF99611D93F60EF691691B2CB2A81D8699F904B3F4130E343918A1A30D5E7FCCB5012B2E24CD356 X-C8649E89: 4E36BF7865823D7055A7F0CF078B5EC49A30900B95165D348B532EA2091F4FF6A9470662D53B3308D5495438F929C7E1525B4C6CBAD82A325670F394464C0DD91D7E09C32AA3244CB62DA2E6A8D90DD6B54B7DC75E50D886408A6A02710B7304729B2BEF169E0186 X-D57D3AED: 3ZO7eAau8CL7WIMRKs4sN3D3tLDjz0dLbV79QFUyzQ2Ujvy7cMT6pYYqY16iZVKkSc3dCLJ7zSJH7+u4VD18S7Vl4ZUrpaVfd2+vE6kuoey4m4VkSEu530nj6fImhcD4MUrOEAnl0W826KZ9Q+tr5ycPtXkTV4k65bRjmOUUP8cvGozZ33TWg5HZplvhhXbhDGzqmQDTd6OAevLeAnq3Ra9uf7zvY2zzsIhlcp/Y7m53TZgf2aB4JOg4gkr2biojNvH0qP3qm71IqBDQjePELw== X-Mailru-Sender: 689FA8AB762F7393C37E3C1AEC41BA5D6CFF059CA356268E6E733B650106D72283D72C36FC87018B9F80AB2734326CD2FB559BB5D741EB96352A0ABBE4FDA4210A04DAD6CC59E33667EA787935ED9F1B X-Mras: Ok Subject: [Tarantool-patches] [PATCH v4 10/16] sql: refactor AVG() function X-BeenThere: tarantool-patches@dev.tarantool.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Tarantool development patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , From: Mergen Imeev via Tarantool-patches Reply-To: imeevma@tarantool.org Errors-To: tarantool-patches-bounces@dev.tarantool.org Sender: "Tarantool-patches" Part of #4145 --- src/box/sql/func.c | 116 ++++++++++++++++++++------------------------- src/box/sql/mem.h | 8 ++++ 2 files changed, 59 insertions(+), 65 deletions(-) diff --git a/src/box/sql/func.c b/src/box/sql/func.c index c3c7ebec0..8be553110 100644 --- a/src/box/sql/func.c +++ b/src/box/sql/func.c @@ -102,6 +102,55 @@ fin_total(struct sql_context *ctx) mem_copy_as_ephemeral(ctx->pOut, ctx->pMem); } +/** Implementation of the AVG() function. */ +static void +step_avg(struct sql_context *ctx, int argc, struct Mem **argv) +{ + assert(argc == 1); + (void)argc; + assert(mem_is_null(ctx->pMem) || mem_is_bin(ctx->pMem)); + if (mem_is_null(argv[0])) + return; + struct Mem *mem; + uint32_t *count; + if (mem_is_null(ctx->pMem)) { + uint32_t size = sizeof(struct Mem) + sizeof(uint32_t); + mem = sqlDbMallocRawNN(sql_get(), size); + if (mem == NULL) { + ctx->is_aborted = true; + return; + } + count = (uint32_t *)(mem + 1); + mem_create(mem); + *count = 1; + mem_copy_as_ephemeral(mem, argv[0]); + mem_set_bin_allocated(ctx->pMem, (char *)mem, size); + return; + } + mem = (struct Mem *)ctx->pMem->z; + count = (uint32_t *)(mem + 1); + ++*count; + if (mem_add(mem, argv[0], mem) != 0) + ctx->is_aborted = true; +} + +/** Finalizer for the AVG() function. */ +static void +fin_avg(struct sql_context *ctx) +{ + assert(mem_is_null(ctx->pMem) || mem_is_bin(ctx->pMem)); + if (mem_is_null(ctx->pMem)) + return mem_set_null(ctx->pOut); + struct Mem *sum = (struct Mem *)ctx->pMem->z; + uint32_t *count_val = (uint32_t *)(sum + 1); + assert(mem_is_trivial(sum)); + struct Mem count; + mem_create(&count); + mem_set_uint(&count, *count_val); + if (mem_div(sum, &count, ctx->pOut) != 0) + ctx->is_aborted = true; +} + static const unsigned char * mem_as_ustr(struct Mem *mem) { @@ -1663,69 +1712,6 @@ soundexFunc(sql_context * context, int argc, sql_value ** argv) } } -/* - * An instance of the following structure holds the context of a - * sum() or avg() aggregate computation. - */ -typedef struct SumCtx SumCtx; -struct SumCtx { - struct Mem mem; - uint32_t count; -}; - -/* - * Routines used to compute the sum, average, and total. - * - * The SUM() function follows the (broken) SQL standard which means - * that it returns NULL if it sums over no inputs. TOTAL returns - * 0.0 in that case. In addition, TOTAL always returns a float where - * SUM might return an integer if it never encounters a floating point - * value. TOTAL never fails, but SUM might through an exception if - * it overflows an integer. - */ -static void -sum_step(struct sql_context *context, int argc, sql_value **argv) -{ - assert(argc == 1); - UNUSED_PARAMETER(argc); - struct SumCtx *p = sql_aggregate_context(context, sizeof(*p)); - if (p == NULL) { - context->is_aborted = true; - return; - } - if (p->count == 0) { - mem_create(&p->mem); - assert(context->func->def->returns == FIELD_TYPE_INTEGER || - context->func->def->returns == FIELD_TYPE_DOUBLE); - if (context->func->def->returns == FIELD_TYPE_INTEGER) - mem_set_uint(&p->mem, 0); - else - mem_set_double(&p->mem, 0.0); - } - if (argv[0]->type == MEM_TYPE_NULL) - return; - ++p->count; - assert(mem_is_num(argv[0])); - if (mem_add(&p->mem, argv[0], &p->mem) != 0) - context->is_aborted = true; -} - -static void -avgFinalize(sql_context * context) -{ - SumCtx *p; - p = sql_aggregate_context(context, 0); - if (p == NULL || p->count == 0) { - mem_set_null(context->pOut); - return; - } - struct Mem mem; - mem_create(&mem); - mem_set_uint(&mem, p->count); - if (mem_div(&p->mem, &mem, context->pOut) != 0) - context->is_aborted = true; -} - /* * The following structure keeps track of state information for the * count() aggregate function. @@ -2022,8 +2008,8 @@ struct sql_func_definition { static struct sql_func_definition definitions[] = { {"ABS", 1, {FIELD_TYPE_INTEGER}, FIELD_TYPE_INTEGER, absFunc, NULL}, {"ABS", 1, {FIELD_TYPE_DOUBLE}, FIELD_TYPE_DOUBLE, absFunc, NULL}, - {"AVG", 1, {FIELD_TYPE_INTEGER}, FIELD_TYPE_INTEGER, sum_step, avgFinalize}, - {"AVG", 1, {FIELD_TYPE_DOUBLE}, FIELD_TYPE_DOUBLE, sum_step, avgFinalize}, + {"AVG", 1, {FIELD_TYPE_INTEGER}, FIELD_TYPE_INTEGER, step_avg, fin_avg}, + {"AVG", 1, {FIELD_TYPE_DOUBLE}, FIELD_TYPE_DOUBLE, step_avg, fin_avg}, {"CHAR", -1, {FIELD_TYPE_INTEGER}, FIELD_TYPE_STRING, charFunc, NULL}, {"CHAR_LENGTH", 1, {FIELD_TYPE_STRING}, FIELD_TYPE_INTEGER, lengthFunc, NULL}, diff --git a/src/box/sql/mem.h b/src/box/sql/mem.h index 7d5a750f5..52a63949a 100644 --- a/src/box/sql/mem.h +++ b/src/box/sql/mem.h @@ -237,6 +237,14 @@ mem_is_allocated(const struct Mem *mem) return mem_is_bytes(mem) && mem->z == mem->zMalloc; } +/** Return TRUE if MEM does not need to be freed or destroyed. */ +static inline bool +mem_is_trivial(const struct Mem *mem) +{ + return mem->szMalloc == 0 && (mem->flags & MEM_Dyn) == 0 && + (mem->type & (MEM_TYPE_FRAME | MEM_TYPE_AGG)) == 0; +} + static inline bool mem_is_cleared(const struct Mem *mem) { -- 2.25.1