├── m4 ├── ax_load_sql.m4 ├── ltversion.m4 ├── ax_mysql_bin.m4 ├── ltsugar.m4 ├── ax_lib_mysql.m4 ├── lt~obsolete.m4 └── ltoptions.m4 ├── .gitignore ├── Downloads ├── udf_infusion-1.0-x64.zip ├── udf_infusion-1.0-x86.zip ├── udf_infusion-1.0-x64.zip.asc └── udf_infusion-1.0-x86.zip.asc ├── test ├── test_clean.sql ├── test_env.py ├── slug.test ├── stats_mode.test ├── corr.test ├── test_prepare.sql ├── Makefile.am ├── median.test ├── cut.test ├── test2result ├── percentile_disc.test ├── percentile_cont.test ├── generate_random_data └── Makefile.in ├── src ├── array.h ├── isbit.c ├── invbit.c ├── bround.c ├── rotbit.c ├── Makefile.am ├── getint.c ├── row_number.c ├── fnv.c ├── setint.c ├── array.c ├── rsumd.c ├── rsumi.c ├── setbit.c ├── bound.c ├── noverk.c ├── lesspart.c ├── lesspartpct.c ├── _quantile.cc ├── rotint.c ├── slug.c ├── lessavg.c ├── covariance.c ├── skewness.c ├── median.c ├── kurtosis.c ├── group_last.c ├── percentile_cont.c ├── group_first.c ├── percentile_disc.c ├── ngram.c ├── corr.c ├── xround.c ├── stats_mode.c ├── cut.c ├── common.h └── _translate_string.c ├── Makefile.am ├── LICENSE ├── configure.ac ├── unload.win.sql ├── udf_infusion.sln ├── unload.sql.sh ├── config.h.in ├── load.sql.sh ├── load.win.sql ├── README.win_x64.txt ├── README.win_x86.txt ├── udf_infusion.vcxproj.filters ├── udf_infusion.vcxproj ├── README.md └── config ├── missing └── install-sh /m4/ax_load_sql.m4: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.opensdf 2 | *.sdf 3 | *.suo 4 | /Debug/ 5 | /Release/ 6 | /x64/ 7 | -------------------------------------------------------------------------------- /Downloads/udf_infusion-1.0-x64.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infusion/udf_infusion/HEAD/Downloads/udf_infusion-1.0-x64.zip -------------------------------------------------------------------------------- /Downloads/udf_infusion-1.0-x86.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infusion/udf_infusion/HEAD/Downloads/udf_infusion-1.0-x86.zip -------------------------------------------------------------------------------- /test/test_clean.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- test_clean.sql 3 | -- 4 | -- Clean testing environment. 5 | -- 6 | -- Usage: mysql [options] < test_clean.sql 7 | -- 8 | 9 | drop database if exists udf_infusion_test; 10 | -------------------------------------------------------------------------------- /test/test_env.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from numpy import ma 3 | import scipy as sp 4 | import scipy.stats 5 | 6 | 7 | def load_table(filename): 8 | data = np.loadtxt(filename) 9 | return ma.masked_equal(data, 1e+20) 10 | 11 | 12 | def example_table(): 13 | if example_table.data is None: 14 | example_table.data = load_table('example_table') 15 | return example_table.data 16 | example_table.data = None 17 | -------------------------------------------------------------------------------- /test/slug.test: -------------------------------------------------------------------------------- 1 | disable_abort_on_error; 2 | 3 | use udf_infusion_test; 4 | 5 | select slug(); 6 | # ERROR HY000: Can't initialize function 'slug'; slug must have one or two arguments 7 | 8 | select slug('Hello Boy', '-'); 9 | # slug('Hello Boy', '-') 10 | # hello-boy 11 | 12 | select slug(NULL); 13 | # slug(NULL) 14 | # NULL 15 | 16 | select slug("Straße"); 17 | # slug("Straße") 18 | # strasse 19 | 20 | select slug("Paweł"); 21 | # slug("Paweł") 22 | # pawel 23 | 24 | -------------------------------------------------------------------------------- /src/array.h: -------------------------------------------------------------------------------- 1 | #ifndef ARRAY_H 2 | #define ARRAY_H 3 | 4 | #include "common.h" 5 | 6 | #define ARRAY_GET_DOUBLE(a, i) (*((double *) ((char *)(a).p + (a).size*(i)))) 7 | 8 | struct array { 9 | void *p; 10 | size_t n; 11 | size_t size; 12 | size_t n_alloc; 13 | }; 14 | 15 | extern struct array *array_init(struct array *, size_t, size_t); 16 | extern struct array *array_append(struct array *, void *); 17 | extern struct array *array_truncate(struct array *); 18 | extern void array_free(struct array *); 19 | 20 | #endif /* ARRAY_H */ 21 | -------------------------------------------------------------------------------- /Downloads/udf_infusion-1.0-x64.zip.asc: -------------------------------------------------------------------------------- 1 | -----BEGIN PGP SIGNATURE----- 2 | Version: GnuPG v1 3 | Comment: Gnu Privacy Tools 4 | Comment: Download at http://www.gnupt.de 5 | 6 | iQEcBAABAgAGBQJV5ZvlAAoJEL7SSk3bYfqGTj8H/3KzKm2Sq8tehiv6steK/Xxi 7 | SPo07OFoM/w30svMlhbLnjtbZRi0UmzUWA6RAswrUuohR3EBDQr3vsMkNE6jnPME 8 | Tk66ygZ5fTwoAtqigxs+MT06a37CRQZpSoLQhLWqfJQyDhl43kVYn2ePliDDrY+y 9 | XO8zlTwDxuBpEPk7S5fNfZMt369uD207a5gqt/2cj18TwYTv98z3RRU4II5k5NDA 10 | 6FOJ9aL9OWYFdtcMj5YMaO6IRTTqwmOJY+Ycoai9NEtba8eMrhWbB1e/PwoVon/4 11 | q+YtE5cQhD+8tXiG+Ji/HBFuHfahHJvdK3DEKdbqX72kt9Ej0p2r/d9BpLsO3So= 12 | =CBDD 13 | -----END PGP SIGNATURE----- 14 | -------------------------------------------------------------------------------- /Downloads/udf_infusion-1.0-x86.zip.asc: -------------------------------------------------------------------------------- 1 | -----BEGIN PGP SIGNATURE----- 2 | Version: GnuPG v1 3 | Comment: Gnu Privacy Tools 4 | Comment: Download at http://www.gnupt.de 5 | 6 | iQEcBAABAgAGBQJV5Zv4AAoJEL7SSk3bYfqGmcoH/R44oQvop+cDZz9jTaJXG6WP 7 | Il6+eMcw/NnDJpUVeK4ZH3AtuuwPptHivOedqYVO0O0TKjeBHG4CARCx8pIJglMe 8 | DybsR7YvY5t0Uwp80H+74P6k/Yz2cdS6BY2Y4MF379ChMPS5BsJ7y3qeYawxRhD9 9 | PGSKLcp25mhCS+F9Duxghh3rakKZulP5pBBoyfJs8j/njmW6Qs9OzbuhRbZq05Br 10 | TKLQo4K0Ayf86IMlF31IgRYzXMqckX86gA2Fa56UptraFwXV9dABqmddiwWQQkwd 11 | vZWZWKogF1v3+QDfmD5Sc9cgNZYZDKKPha6EK7mtOlhi15usRRAlo29AFAUHQDM= 12 | =fl6C 13 | -----END PGP SIGNATURE----- 14 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | ACLOCAL_AMFLAGS = -I m4 2 | SUBDIRS = src test 3 | EXTRA_DIST = load.sql unload.sql 4 | BUILT_SOURCES = load.sql unload.sql 5 | CLEANFILES = load.sql unload.sql 6 | 7 | enable_functions = @enable_functions@ 8 | 9 | load.sql: 10 | sh load.sql.sh $(enable_functions) > load.sql 11 | 12 | unload.sql: 13 | sh unload.sql.sh $(enable_functions) > unload.sql 14 | 15 | load: 16 | mysql $(MYSQL_OPTIONS) < load.sql 17 | 18 | unload: 19 | mysql $(MYSQL_OPTIONS) < unload.sql 20 | 21 | test test_prepare test_clean: all 22 | cd test && $(MAKE) $(AM_MAKEFLAGS) $@ 23 | 24 | .PHONY: load.sql unload.sql load unload test test_prepare test_clean 25 | -------------------------------------------------------------------------------- /test/stats_mode.test: -------------------------------------------------------------------------------- 1 | disable_abort_on_error; 2 | 3 | use udf_infusion_test; 4 | 5 | select stats_mode(); 6 | # ERROR HY000: Can't initialize function 'stats_mode'; stats_mode must have exaclty one argument 7 | 8 | select stats_mode(1, 2); 9 | # ERROR HY000: Can't initialize function 'stats_mode'; stats_mode must have exaclty one argument 10 | 11 | select stats_mode(NULL); 12 | # stats_mode(NULL) 13 | # NULL 14 | 15 | select stats_mode(x) from empty_table; 16 | # stats_mode(x) 17 | # NULL 18 | 19 | select stats_mode(x) from null_table; 20 | # stats_mode(x) 21 | # NULL 22 | 23 | select stats_mode(y) from small_table; 24 | # stats_mode(y) 25 | # -5 26 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (C) 2010 Robert Eisele 2 | 3 | This program is free software; you can redistribute it and/or modify 4 | it under the terms of the GNU General Public License as published by 5 | the Free Software Foundation; version 2 of the License. 6 | 7 | This program is distributed in the hope that it will be useful, 8 | but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | GNU General Public License for more details. 11 | 12 | You should have received a copy of the GNU General Public License 13 | along with this program; if not, write to the Free Software 14 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 15 | -------------------------------------------------------------------------------- /test/corr.test: -------------------------------------------------------------------------------- 1 | disable_abort_on_error; 2 | 3 | use udf_infusion_test; 4 | 5 | select corr(); 6 | # ERROR HY000: Can't initialize function 'corr'; corr must have exactly two arguments 7 | 8 | select corr(1, 2, 3); 9 | # ERROR HY000: Can't initialize function 'corr'; corr must have exactly two arguments 10 | 11 | select corr(NULL, NULL); 12 | # corr(NULL, NULL) 13 | # NULL 14 | 15 | select corr(x, y) from empty_table; 16 | # corr(x, y) 17 | # NULL 18 | 19 | select corr(x, y) from null_table; 20 | # corr(x, y) 21 | # NULL 22 | 23 | select corr(x, y) from small_table; 24 | # corr(x, y) 25 | # -0.23469609321250473 26 | 27 | select g, corr(x, y) from small_table group by g; 28 | # g corr(x, y) 29 | # 1 1 30 | # 2 NULL 31 | # 3 -0.8660254037844387 32 | -------------------------------------------------------------------------------- /m4/ltversion.m4: -------------------------------------------------------------------------------- 1 | # ltversion.m4 -- version numbers -*- Autoconf -*- 2 | # 3 | # Copyright (C) 2004 Free Software Foundation, Inc. 4 | # Written by Scott James Remnant, 2004 5 | # 6 | # This file is free software; the Free Software Foundation gives 7 | # unlimited permission to copy and/or distribute it, with or without 8 | # modifications, as long as this notice is preserved. 9 | 10 | # @configure_input@ 11 | 12 | # serial 3337 ltversion.m4 13 | # This file is part of GNU Libtool 14 | 15 | m4_define([LT_PACKAGE_VERSION], [2.4.2]) 16 | m4_define([LT_PACKAGE_REVISION], [1.3337]) 17 | 18 | AC_DEFUN([LTVERSION_VERSION], 19 | [macro_version='2.4.2' 20 | macro_revision='1.3337' 21 | _LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?]) 22 | _LT_DECL(, macro_revision, 0) 23 | ]) 24 | -------------------------------------------------------------------------------- /src/isbit.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | 3 | DLLEXPORT my_bool isbit_init(UDF_INIT *initid, UDF_ARGS *args, char *message) { 4 | 5 | if (2 != args->arg_count) { 6 | strcpy(message, "isbit must have exactly two arguments"); 7 | return 1; 8 | } 9 | 10 | args->arg_type[0] = INT_RESULT; 11 | args->arg_type[1] = INT_RESULT; 12 | initid->const_item = 1; 13 | initid->maybe_null = 1; 14 | 15 | return 0; 16 | } 17 | 18 | DLLEXPORT longlong isbit(UDF_INIT *initid __attribute__((unused)), UDF_ARGS *args, 19 | char *is_null, 20 | char *error __attribute__((unused))) { 21 | 22 | if (NULL == args->args[0] || NULL == args->args[1]) { 23 | *is_null = 1; 24 | return 0; 25 | } 26 | 27 | longlong bit = *((longlong *) args->args[0]); 28 | longlong n = *((longlong *) args->args[1]); 29 | 30 | return (bit >> n) & 1; 31 | } 32 | -------------------------------------------------------------------------------- /src/invbit.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | 3 | DLLEXPORT my_bool invbit_init(UDF_INIT *initid, UDF_ARGS *args, char *message) { 4 | 5 | if (2 != args->arg_count) { 6 | strcpy(message, "invbit must have exactly two arguments"); 7 | return 1; 8 | } 9 | 10 | args->arg_type[0] = INT_RESULT; 11 | args->arg_type[1] = INT_RESULT; 12 | initid->const_item = 1; 13 | initid->maybe_null = 1; 14 | 15 | return 0; 16 | } 17 | 18 | DLLEXPORT longlong invbit(UDF_INIT *initid __attribute__((unused)), UDF_ARGS *args, 19 | char *is_null, 20 | char *error __attribute__((unused))) { 21 | 22 | if (NULL == args->args[0] || NULL == args->args[1]) { 23 | *is_null = 1; 24 | return 0; 25 | } 26 | 27 | longlong bit = *((longlong *) args->args[0]); 28 | longlong n = *((longlong *) args->args[1]); 29 | 30 | return bit ^ (1 << n); 31 | } 32 | -------------------------------------------------------------------------------- /src/bround.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | 3 | DLLEXPORT my_bool bround_init(UDF_INIT *initid, UDF_ARGS *args, char *message) { 4 | 5 | if (2 != args->arg_count) { 6 | strcpy(message, "bround must have exactly two arguments"); 7 | return 1; 8 | } 9 | 10 | args->arg_type[0] = REAL_RESULT; 11 | args->arg_type[1] = REAL_RESULT; 12 | initid->const_item = 1; 13 | initid->maybe_null = 1; 14 | initid->decimals = NOT_FIXED_DEC; 15 | initid->max_length = 20; 16 | 17 | return 0; 18 | } 19 | 20 | DLLEXPORT double bround(UDF_INIT *initid __attribute__((unused)), UDF_ARGS *args, 21 | char *is_null, 22 | char *error __attribute__((unused))) { 23 | 24 | if (NULL == args->args[0] || NULL == args->args[1] || 0 == *((double *) args->args[1])) { 25 | *is_null = 1; 26 | return 0; 27 | } 28 | 29 | return ceil(*((double *) args->args[0]) / *((double *) args->args[1])) * *((double *) args->args[1]); 30 | } 31 | -------------------------------------------------------------------------------- /src/rotbit.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | 3 | DLLEXPORT my_bool rotbit_init(UDF_INIT *initid, UDF_ARGS *args, char *message) { 4 | 5 | if (2 != args->arg_count) { 6 | strcpy(message, "rotbit must have exactly two arguments"); 7 | return 1; 8 | } 9 | 10 | args->arg_type[0] = INT_RESULT; 11 | args->arg_type[1] = INT_RESULT; 12 | initid->const_item = 1; 13 | initid->maybe_null = 1; 14 | 15 | return 0; 16 | } 17 | 18 | DLLEXPORT longlong rotbit(UDF_INIT *initid __attribute__((unused)), UDF_ARGS *args, 19 | char *is_null, 20 | char *error __attribute__((unused))) { 21 | 22 | if (NULL == args->args[0] || NULL == args->args[1]) { 23 | *is_null = 1; 24 | return 0; 25 | } 26 | 27 | longlong bit = *((longlong *) args->args[0]); 28 | longlong n = *((longlong *) args->args[1]); 29 | 30 | n = (64 + (n % 64)) % 64; 31 | return ((bit << n) | (bit >> (64 - n))) & 0x7FFFFFFFFFFFFFFFLL; 32 | } 33 | -------------------------------------------------------------------------------- /test/test_prepare.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- test_prepare.sql 3 | -- 4 | -- Prepare testing environment. 5 | -- 6 | -- Usage: mysql [options] < test_prepare.sql 7 | -- 8 | 9 | drop database if exists udf_infusion_test; 10 | create database udf_infusion_test; 11 | use udf_infusion_test; 12 | 13 | create table empty_table(x real, y real); 14 | 15 | create table null_table(x real, y real); 16 | insert into null_table values (NULL, NULL), (NULL, NULL); 17 | 18 | create table small_table(x real, y real, g int); 19 | insert into small_table values 20 | (1, -5, 1), 21 | (NULL, NULL, 1), 22 | (2, 1, 1), 23 | (3, NULL, 2), 24 | (4, 0, 2), 25 | (5, 0, 2), 26 | (NULL, 1, 2), 27 | (6, 1, 3), 28 | (7, -5, 3), 29 | (8, -5, 3); 30 | 31 | create table example_table(x real, y real); 32 | load data local infile 'example_table' into table example_table fields terminated by ' '; 33 | update example_table set x = null where x = 1e+20; 34 | update example_table set y = null where y = 1e+20; 35 | -------------------------------------------------------------------------------- /src/Makefile.am: -------------------------------------------------------------------------------- 1 | lib_LTLIBRARIES = udf_infusion.la 2 | 3 | udf_infusion_la_SOURCES = \ 4 | array.c \ 5 | bound.c \ 6 | bround.c \ 7 | corr.c \ 8 | covariance.c \ 9 | cut.c \ 10 | fnv.c \ 11 | getint.c \ 12 | group_first.c \ 13 | group_last.c \ 14 | invbit.c \ 15 | isbit.c \ 16 | kurtosis.c \ 17 | lessavg.c \ 18 | lesspartpct.c \ 19 | lesspart.c \ 20 | median.c \ 21 | stats_mode.c \ 22 | ngram.c \ 23 | noverk.c \ 24 | percentile_cont.c \ 25 | percentile_disc.c \ 26 | rotbit.c \ 27 | rotint.c \ 28 | rsumd.c \ 29 | rsumi.c \ 30 | setbit.c \ 31 | setint.c \ 32 | skewness.c \ 33 | slug.c \ 34 | _translate_string.c \ 35 | _quantile.cc \ 36 | xround.c 37 | 38 | udf_infusion_la_CFLAGS = -DSTANDARD -DMYSQL_SERVER @MYSQL_CFLAGS@ 39 | udf_infusion_la_CXXFLAGS = -DSTANDARD -DMYSQL_SERVER @MYSQL_CFLAGS@ 40 | udf_infusion_la_LDFLAGS = -module -avoid-version -no-undefined -rpath @MYSQL_PLUGINDIR@ 41 | -------------------------------------------------------------------------------- /src/getint.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | 3 | DLLEXPORT my_bool getint_init(UDF_INIT *initid, UDF_ARGS *args, char *message) { 4 | 5 | if (3 != args->arg_count) { 6 | strcpy(message, "getint must have exactly three arguments"); 7 | return 1; 8 | } 9 | 10 | args->arg_type[0] = INT_RESULT; 11 | args->arg_type[1] = INT_RESULT; 12 | args->arg_type[2] = INT_RESULT; 13 | initid->const_item = 1; 14 | initid->maybe_null = 1; 15 | 16 | return 0; 17 | } 18 | 19 | DLLEXPORT longlong getint(UDF_INIT *initid __attribute__((unused)), UDF_ARGS *args, 20 | char *is_null, 21 | char *error __attribute__((unused))) { 22 | 23 | if (NULL == args->args[0] || NULL == args->args[1] || NULL == args->args[2]) { 24 | *is_null = 1; 25 | return 0; 26 | } 27 | longlong n = *((longlong *) args->args[0]); 28 | longlong x = *((longlong *) args->args[1]); 29 | longlong y = *((longlong *) args->args[2]); 30 | 31 | return (n >> x) & ((2 << (y - x)) - 1); 32 | } 33 | -------------------------------------------------------------------------------- /src/row_number.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | 3 | DLLEXPORT my_bool row_number_init(UDF_INIT *initid, UDF_ARGS *args, char *message) { 4 | longlong *data; 5 | 6 | if (0 != args->arg_count) { 7 | strcpy(message, "rownumber doesn't require an argument"); 8 | return 1; 9 | } 10 | 11 | if (NULL == (data = malloc(sizeof (*data)))) { 12 | strcpy(message, "Couldn't allocate memory"); 13 | return 1; 14 | } 15 | *data = 0; 16 | 17 | initid->ptr = (char *) data; 18 | initid->const_item = 0; 19 | initid->maybe_null = 1; 20 | 21 | return 0; 22 | } 23 | 24 | DLLEXPORT longlong row_number(UDF_INIT *initid, UDF_ARGS *args, char *is_null, char *error) { 25 | longlong *data; 26 | 27 | if (initid->ptr) { 28 | data = (longlong *) initid->ptr; 29 | return ++(*data); 30 | } 31 | 32 | *error = 1; 33 | return 0; 34 | } 35 | 36 | DLLEXPORT void row_number_deinit(UDF_INIT *initid) { 37 | if (initid->ptr) { 38 | free(initid->ptr); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | AC_PREREQ([2.59]) 2 | 3 | AC_INIT([lib_udf_infusion], [1.0], [robert@xarg.org]) 4 | 5 | AC_CONFIG_AUX_DIR([config]) 6 | AC_CONFIG_MACRO_DIR([m4]) 7 | AM_CONFIG_HEADER([config.h]) 8 | 9 | AM_INIT_AUTOMAKE([foreign]) 10 | 11 | LT_PREREQ([2.2]) 12 | LT_INIT([dlopen disable-static]) 13 | 14 | AC_PROG_CC 15 | AC_PROG_CXX 16 | 17 | m4_include([m4/ax_lib_mysql.m4]) 18 | AX_LIB_MYSQL(,,AC_MSG_ERROR("Can't find mysql library" )) 19 | 20 | if test -n "$MYSQL_PLUGINDIR" && test "$libdir" == '${exec_prefix}/lib' ; then 21 | AC_MSG_NOTICE([setting libdir to mysql plugin dir $MYSQL_PLUGINDIR]) 22 | libdir=$MYSQL_PLUGINDIR 23 | AC_SUBST([libdir]) 24 | fi 25 | 26 | m4_include([m4/ax_mysql_bin.m4]) 27 | AX_MYSQL_BIN 28 | 29 | AC_C_CONST 30 | AC_TYPE_SIZE_T 31 | AC_CHECK_HEADERS([limits.h syslimits.h]) 32 | 33 | AC_ARG_ENABLE([functions], AS_HELP_STRING( 34 | [--enable-functions=ARG], 35 | [enable only selected UDF functions] 36 | )) 37 | 38 | AC_SUBST([enable_functions]) 39 | 40 | AC_OUTPUT([Makefile src/Makefile test/Makefile]) 41 | -------------------------------------------------------------------------------- /src/fnv.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | 3 | DLLEXPORT my_bool fnv_init(UDF_INIT *initid, UDF_ARGS *args, char *message) { 4 | if (1 != args->arg_count) { 5 | strcpy(message, "fnv must have one argument"); 6 | return 1; 7 | } 8 | 9 | args->arg_type[0] = STRING_RESULT; 10 | 11 | initid->const_item = 1; 12 | initid->maybe_null = 1; 13 | 14 | return 0; 15 | } 16 | 17 | DLLEXPORT longlong fnv(UDF_INIT *initid __attribute__((unused)), UDF_ARGS *args, 18 | char *is_null, 19 | char *error __attribute__((unused))) { 20 | char *str = args->args[0]; 21 | size_t len = args->lengths[0]; 22 | 23 | const unsigned char *first = (unsigned char *) str, *last = first + len; 24 | 25 | longlong hash = 0xcbf29ce484222325ULL, 26 | magic = 0x00000100000001b3ULL; 27 | 28 | if (NULL == args->args[0]) { 29 | *is_null = 1; 30 | return 0; 31 | } 32 | 33 | while (first < last) { 34 | hash ^= *first++; 35 | hash *= magic; 36 | } 37 | return hash; 38 | } 39 | -------------------------------------------------------------------------------- /test/Makefile.am: -------------------------------------------------------------------------------- 1 | CLEANFILES=*.log *.reject *.result example_table 2 | EXTRA_DIST=*.test *.sql test2result generate_random_data 3 | 4 | MYSQL=mysql 5 | MYSQLTEST=mysqltest 6 | ALL_TESTS=$(wildcard *.test) 7 | 8 | test_prepare: test_prepare_start example_table test_prepare_sql test_results 9 | @echo "$@: Test environment ready!" 10 | @echo "$@: You can now run \`make test\`" 11 | 12 | test_prepare_start: 13 | @echo "$@: Preparing test environment (this may take a while)..." 14 | 15 | test_prepare_sql: 16 | $(MYSQL) --local-infile=1 $(MYSQL_OPTIONS) < test_prepare.sql 17 | 18 | example_table: 19 | ./generate_random_data 1000000 > example_table 20 | 21 | test_results: $(ALL_TESTS:%.test=%.result) 22 | 23 | %.result: %.test 24 | ./test2result < $*.test > $@ 25 | 26 | test_clean: 27 | $(MYSQL) $(MYSQL_OPTIONS) < test_clean.sql 28 | 29 | %.run : %.test 30 | $(MYSQLTEST) $(MYSQL_OPTIONS) -R $*.result < $*.test 31 | 32 | test: $(ALL_TESTS:%.test=%.run) 33 | 34 | .PHONY: test_prepare test_prepare_start example_table test_prepare_sql test_results test 35 | -------------------------------------------------------------------------------- /unload.win.sql: -------------------------------------------------------------------------------- 1 | USE mysql; 2 | 3 | DROP FUNCTION IF EXISTS bound; 4 | DROP FUNCTION IF EXISTS bround; 5 | DROP FUNCTION IF EXISTS corr; 6 | DROP FUNCTION IF EXISTS covariance; 7 | DROP FUNCTION IF EXISTS cut; 8 | DROP FUNCTION IF EXISTS fnv; 9 | DROP FUNCTION IF EXISTS getint; 10 | DROP FUNCTION IF EXISTS group_first; 11 | DROP FUNCTION IF EXISTS group_last; 12 | DROP FUNCTION IF EXISTS invbit; 13 | DROP FUNCTION IF EXISTS isbit; 14 | DROP FUNCTION IF EXISTS kurtosis; 15 | DROP FUNCTION IF EXISTS lessavg; 16 | DROP FUNCTION IF EXISTS lesspartpct; 17 | DROP FUNCTION IF EXISTS lesspart; 18 | DROP FUNCTION IF EXISTS median; 19 | DROP FUNCTION IF EXISTS stats_mode; 20 | DROP FUNCTION IF EXISTS ngram; 21 | DROP FUNCTION IF EXISTS noverk; 22 | DROP FUNCTION IF EXISTS percentile_cont; 23 | DROP FUNCTION IF EXISTS percentile_disc; 24 | DROP FUNCTION IF EXISTS rotbit; 25 | DROP FUNCTION IF EXISTS rotint; 26 | DROP FUNCTION IF EXISTS rsumd; 27 | DROP FUNCTION IF EXISTS rsumi; 28 | DROP FUNCTION IF EXISTS setbit; 29 | DROP FUNCTION IF EXISTS setint; 30 | DROP FUNCTION IF EXISTS skewness; 31 | DROP FUNCTION IF EXISTS slug; 32 | DROP FUNCTION IF EXISTS xround; 33 | -------------------------------------------------------------------------------- /src/setint.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | 3 | DLLEXPORT my_bool setint_init(UDF_INIT *initid, UDF_ARGS *args, char *message) { 4 | if (4 != args->arg_count) { 5 | strcpy(message, "setint must have exactly four arguments"); 6 | return 1; 7 | } 8 | 9 | args->arg_type[0] = INT_RESULT; 10 | args->arg_type[1] = INT_RESULT; 11 | args->arg_type[2] = INT_RESULT; 12 | args->arg_type[3] = INT_RESULT; 13 | initid->const_item = 1; 14 | initid->maybe_null = 1; 15 | 16 | return 0; 17 | } 18 | 19 | DLLEXPORT longlong setint(UDF_INIT *initid __attribute__((unused)), UDF_ARGS *args, 20 | char *is_null, 21 | char *error __attribute__((unused))) { 22 | 23 | if (NULL == args->args[0] || NULL == args->args[1] || NULL == args->args[2] || NULL == args->args[3]) { 24 | *is_null = 1; 25 | return 0; 26 | } 27 | longlong n = *((longlong *) args->args[0]); 28 | longlong x = *((longlong *) args->args[1]); 29 | longlong y = *((longlong *) args->args[2]); 30 | longlong m = *((longlong *) args->args[3]); 31 | 32 | return n & (~(((2 << (y - x)) - 1) << x)) | (m << x); 33 | } 34 | -------------------------------------------------------------------------------- /test/median.test: -------------------------------------------------------------------------------- 1 | disable_abort_on_error; 2 | 3 | use udf_infusion_test; 4 | 5 | select median(); 6 | # ERROR HY000: Can't initialize function 'median'; median must have exactly one argument 7 | 8 | select median(1, 2); 9 | # ERROR HY000: Can't initialize function 'median'; median must have exactly one argument 10 | 11 | select median(NULL); 12 | # median(NULL) 13 | # NULL 14 | 15 | select median(x) from empty_table; 16 | # median(x) 17 | # NULL 18 | 19 | select median(x) from null_table; 20 | # median(x) 21 | # NULL 22 | 23 | select median(x) from small_table; 24 | # median(x) 25 | # 4.5 26 | 27 | select median(x) from (select x from small_table where x is not null order by x limit 7) as t; 28 | # median(x) 29 | # 4 30 | 31 | select g, median(x) from small_table group by g; 32 | # g median(x) 33 | # 1 1.5 34 | # 2 4 35 | # 3 7 36 | 37 | select round(median(x), 12) as `median(x)` from example_table; 38 | # median(x) 39 | # >>> print '%.12f' % ma.median(example_table()[:,0]) 40 | 41 | select round(median(y), 12) as `median(y)` from example_table; 42 | # median(y) 43 | # >>> print '%.12f' % ma.median(example_table()[:,1]) 44 | -------------------------------------------------------------------------------- /src/array.c: -------------------------------------------------------------------------------- 1 | #include "array.h" 2 | 3 | struct array * array_init(struct array *a, size_t size, size_t n_alloc) { 4 | 5 | a->p = calloc(n_alloc, size); 6 | if (NULL == a->p) { 7 | return NULL; 8 | } 9 | a->size = size; 10 | a->n = 0; 11 | a->n_alloc = n_alloc; 12 | return a; 13 | } 14 | 15 | struct array * array_append(struct array *a, void *value) { 16 | 17 | if (a->n == a->n_alloc) { 18 | size_t n_alloc = a->n_alloc * 2; 19 | void *p = realloc(a->p, a->size * n_alloc); 20 | if (NULL == p) { 21 | return NULL; 22 | } 23 | memset((char *)p + a->size * a->n_alloc, 0, a->size * (n_alloc - a->n_alloc)); 24 | a->p = p; 25 | a->n_alloc = n_alloc; 26 | } 27 | memcpy((char *)a->p + a->size * a->n, value, a->size); 28 | a->n++; 29 | return a; 30 | } 31 | 32 | struct array *array_truncate(struct array *a) { 33 | a->n = 0; 34 | return a; 35 | } 36 | 37 | void array_free(struct array *a) { 38 | 39 | if (NULL != a->p) { 40 | free(a->p); 41 | } 42 | a->p = NULL; 43 | a->n_alloc = 0; 44 | a->size = 0; 45 | a->n = 0; 46 | } 47 | -------------------------------------------------------------------------------- /src/rsumd.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | 3 | DLLEXPORT my_bool rsumd_init(UDF_INIT *initid, UDF_ARGS *args, char *message) { 4 | double *data; 5 | 6 | if (1 != args->arg_count) { 7 | strcpy(message, "rsumd must have one argument"); 8 | return 1; 9 | } 10 | 11 | if (NULL == (data = malloc(sizeof (*data)))) { 12 | strcpy(message, "Couldn't allocate memory"); 13 | return 1; 14 | } 15 | *data = 0; 16 | 17 | args->arg_type[0] = REAL_RESULT; 18 | 19 | initid->ptr = (char *) data; 20 | initid->const_item = 0; 21 | initid->maybe_null = 1; 22 | 23 | return 0; 24 | } 25 | 26 | DLLEXPORT double rsumd(UDF_INIT *initid, UDF_ARGS *args, char *is_null, char *error) { 27 | double *data; 28 | 29 | if (initid->ptr) { 30 | data = (double *) initid->ptr; 31 | 32 | if (NULL == args->args[0]) { 33 | return *data; 34 | } 35 | 36 | (*data) += *((double *) args->args[0]); 37 | 38 | return *data; 39 | } 40 | *error = 1; 41 | return 0; 42 | } 43 | 44 | DLLEXPORT void rsumd_deinit(UDF_INIT *initid) { 45 | 46 | if (initid->ptr) { 47 | free(initid->ptr); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/rsumi.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | 3 | DLLEXPORT my_bool rsumi_init(UDF_INIT *initid, UDF_ARGS *args, char *message) { 4 | longlong *data; 5 | 6 | if (1 != args->arg_count) { 7 | strcpy(message, "rsumi must have one argument"); 8 | return 1; 9 | } 10 | 11 | if (NULL == (data = malloc(sizeof (*data)))) { 12 | strcpy(message, "Couldn't allocate memory"); 13 | return 1; 14 | } 15 | *data = 0; 16 | 17 | args->arg_type[0] = INT_RESULT; 18 | 19 | initid->ptr = (char *) data; 20 | initid->const_item = 0; 21 | initid->maybe_null = 1; 22 | 23 | return 0; 24 | } 25 | 26 | DLLEXPORT longlong rsumi(UDF_INIT *initid, UDF_ARGS *args, char *is_null, char *error) { 27 | longlong *data; 28 | 29 | if (initid->ptr) { 30 | data = (longlong *) initid->ptr; 31 | 32 | if (NULL == args->args[0]) { 33 | return *data; 34 | } 35 | 36 | (*data) += *((longlong *) args->args[0]); 37 | 38 | return *data; 39 | } 40 | *error = 1; 41 | return 0; 42 | } 43 | 44 | DLLEXPORT void rsumi_deinit(UDF_INIT *initid) { 45 | if (initid->ptr) { 46 | free(initid->ptr); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/setbit.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | 3 | DLLEXPORT my_bool setbit_init(UDF_INIT *initid, UDF_ARGS *args, char *message) { 4 | 5 | switch (args->arg_count) { 6 | case 3: 7 | args->arg_type[2] = INT_RESULT; 8 | case 2: 9 | args->arg_type[0] = INT_RESULT; 10 | args->arg_type[1] = INT_RESULT; 11 | break; 12 | default: 13 | strcpy(message, "setbit must have two or three arguments"); 14 | return 1; 15 | } 16 | 17 | initid->const_item = 1; 18 | initid->maybe_null = 1; 19 | 20 | return 0; 21 | } 22 | 23 | DLLEXPORT longlong setbit(UDF_INIT *initid __attribute__((unused)), UDF_ARGS *args, 24 | char *is_null, 25 | char *error __attribute__((unused))) { 26 | 27 | if (NULL == args->args[0] || NULL == args->args[1]) { 28 | *is_null = 1; 29 | return 0; 30 | } 31 | 32 | longlong bit = *((longlong *) args->args[0]); 33 | longlong n = *((longlong *) args->args[1]); 34 | 35 | if (2 == args->arg_count || (NULL != args->args[2] && 1 == *((longlong *) args->args[2]))) { 36 | return bit | (1 << n); 37 | } 38 | return bit & (~(1 << n)); 39 | } 40 | -------------------------------------------------------------------------------- /test/cut.test: -------------------------------------------------------------------------------- 1 | disable_abort_on_error; 2 | 3 | use udf_infusion_test; 4 | 5 | select cut(); 6 | # ERROR HY000: Can't initialize function 'cut'; cut must have two or three arguments 7 | 8 | select cut('Hello'); 9 | # ERROR HY000: Can't initialize function 'cut'; cut must have two or three arguments 10 | 11 | select cut(NULL, 15); 12 | # cut(NULL, 15) 13 | # NULL 14 | 15 | select cut("Hauptstraße", 10); 16 | # cut("Hauptstraße", 10) 17 | # Hauptstraß... 18 | 19 | SELECT cut('這是一個測試繁體中文',5); 20 | # cut('這是一個測試繁體中文',5) 21 | # 這是一個測... 22 | 23 | select cut('There it is', 150); 24 | # cut('There it is', 150) 25 | # There it is 26 | 27 | select cut('Lorem ipsum dolor sit amet, consectetur adipiscing elit.', 20); 28 | # cut('Lorem ipsum dolor sit amet, consectetur adipiscing elit.', 20) 29 | # Lorem ipsum dolor... 30 | 31 | select cut(repeat("a", 300), 300); 32 | # cut(repeat("a", 300), 300) 33 | # aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 34 | 35 | -------------------------------------------------------------------------------- /src/bound.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | 3 | DLLEXPORT my_bool bound_init(UDF_INIT *initid, UDF_ARGS *args, char *message) { 4 | 5 | if (3 != args->arg_count) { 6 | strcpy(message, "bound must have exactly three arguments"); 7 | return 1; 8 | } 9 | 10 | args->arg_type[0] = REAL_RESULT; 11 | args->arg_type[1] = REAL_RESULT; 12 | args->arg_type[2] = REAL_RESULT; 13 | 14 | initid->const_item = 1; 15 | initid->maybe_null = 1; 16 | initid->decimals = NOT_FIXED_DEC; 17 | initid->max_length = 20; 18 | 19 | return 0; 20 | } 21 | 22 | DLLEXPORT double bound(UDF_INIT *initid __attribute__((unused)), UDF_ARGS *args, 23 | char *is_null, 24 | char *error __attribute__((unused))) { 25 | double *n, *x, *y; 26 | 27 | n = (double *) args->args[0]; 28 | x = (double *) args->args[1]; 29 | y = (double *) args->args[2]; 30 | 31 | if (NULL == n) { 32 | *is_null = 1; 33 | return 0; 34 | } 35 | 36 | if (NULL != y && NULL != x && *y < *x) { 37 | return *x; 38 | } 39 | 40 | if (NULL != y && *y < *n) { 41 | return *y; 42 | } 43 | 44 | if (NULL != x && *n < *x) { 45 | return *x; 46 | } 47 | return *n; 48 | } 49 | -------------------------------------------------------------------------------- /src/noverk.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | 3 | DLLEXPORT my_bool noverk_init(UDF_INIT *initid, UDF_ARGS *args, char *message) { 4 | 5 | if (2 != args->arg_count) { 6 | strcpy(message, "noverk must have exactly two arguments"); 7 | return 1; 8 | } 9 | 10 | args->arg_type[0] = INT_RESULT; 11 | args->arg_type[1] = INT_RESULT; 12 | initid->const_item = 1; 13 | initid->decimals = NOT_FIXED_DEC; 14 | initid->max_length = 20; 15 | 16 | return 0; 17 | } 18 | 19 | DLLEXPORT longlong noverk(UDF_INIT *initid __attribute__((unused)), UDF_ARGS *args, 20 | char *is_null, 21 | char *error __attribute__((unused))) { 22 | 23 | if (NULL == args->args[0] || NULL == args->args[1]) { 24 | *is_null = 1; 25 | return 0; 26 | } 27 | 28 | int i; 29 | longlong res = 1; 30 | 31 | longlong n = *((longlong *) args->args[0]); 32 | longlong k = *((longlong *) args->args[1]); 33 | 34 | if (n < k || k < 0) { 35 | return 0; 36 | } 37 | 38 | k = k < (n - k) ? k : (n - k); 39 | n = n - k; 40 | 41 | for (i = 1; i <= k; i++) { 42 | res = res * (n + i) / i; // Simplified from res = res * (n - i + 1) / i 43 | } 44 | return res; 45 | } 46 | 47 | -------------------------------------------------------------------------------- /src/lesspart.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | 3 | DLLEXPORT my_bool lesspart_init(UDF_INIT *initid, UDF_ARGS *args, char *message) { 4 | struct DoubleBuffer* data = NULL; 5 | 6 | if (2 != args->arg_count) { 7 | strcpy(message, "lesspart must have exaclty two arguments"); 8 | return 1; 9 | } 10 | 11 | args->arg_type[0] = REAL_RESULT; 12 | args->arg_type[1] = REAL_RESULT; 13 | 14 | LESSINIT(); 15 | 16 | return 0; 17 | } 18 | 19 | DLLEXPORT void lesspart_clear(UDF_INIT* initid, char* is_null, char *error) { 20 | LESSCLEAR(); 21 | } 22 | 23 | DLLEXPORT void lesspart_add(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char *error) { 24 | int type = 0; 25 | LESSADD(); 26 | } 27 | 28 | DLLEXPORT void lesspart_deinit(UDF_INIT *initid) { 29 | LESSDEINIT(); 30 | } 31 | 32 | DLLEXPORT longlong lesspart(UDF_INIT *initid, UDF_ARGS *args, char *is_null, char *error) { 33 | struct DoubleBuffer *data = (struct DoubleBuffer *) initid->ptr; 34 | double limit = *((double*) args->args[1]); 35 | 36 | double psum = 0; 37 | 38 | ulonglong count = 0; 39 | 40 | if (limit < 0) { 41 | *error = 1; 42 | return 0; 43 | } 44 | 45 | LESS(); 46 | 47 | return (longlong) count; 48 | } 49 | -------------------------------------------------------------------------------- /src/lesspartpct.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | 3 | DLLEXPORT my_bool lesspartpct_init(UDF_INIT *initid, UDF_ARGS *args, char *message) { 4 | struct DoubleBuffer* data = NULL; 5 | 6 | if (2 != args->arg_count) { 7 | strcpy(message, "lesspartpct must have exaclty two arguments"); 8 | return 1; 9 | } 10 | 11 | args->arg_type[0] = REAL_RESULT; 12 | args->arg_type[1] = REAL_RESULT; 13 | 14 | LESSINIT(); 15 | 16 | return 0; 17 | } 18 | 19 | DLLEXPORT void lesspartpct_clear(UDF_INIT* initid, char* is_null, char *error) { 20 | LESSCLEAR(); 21 | } 22 | 23 | DLLEXPORT void lesspartpct_add(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char *error) { 24 | int type = 1; 25 | LESSADD(); 26 | } 27 | 28 | DLLEXPORT void lesspartpct_deinit(UDF_INIT *initid) { 29 | LESSDEINIT(); 30 | } 31 | 32 | DLLEXPORT longlong lesspartpct(UDF_INIT *initid, UDF_ARGS *args, char *is_null, char *error) { 33 | struct DoubleBuffer *data = (struct DoubleBuffer *) initid->ptr; 34 | double limit = *((double*) args->args[1]); 35 | 36 | double psum = 0; 37 | 38 | ulonglong count = 0; 39 | 40 | if (!(limit >= 0 && limit <= 1)) { 41 | *error = 1; 42 | return 0; 43 | } 44 | 45 | limit = limit * data->sum; 46 | 47 | LESS(); 48 | 49 | return (longlong) count; 50 | } 51 | -------------------------------------------------------------------------------- /src/_quantile.cc: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | 3 | #include 4 | 5 | /* 6 | * Quantile function. 7 | * 8 | * Returns quantile q of data samples pointed to by base. 9 | * nmemb is the number of samples. q is a real number from [0, 1]. 10 | */ 11 | double _quantile(double *base, size_t nmemb, double q) { 12 | 13 | if (nmemb == 0 || !isfinite(q) || q < 0 || q > 1) { 14 | return NAN; 15 | } 16 | 17 | double m = (nmemb - 1) * q; 18 | size_t m1 = floor(m); 19 | size_t m2 = ceil(m); 20 | 21 | /* Safeguard. */ 22 | if (m1 >= nmemb || m2 >= nmemb) { 23 | return NAN; 24 | } 25 | 26 | std::nth_element(base, base + m1, base + nmemb); 27 | 28 | if (m1 == m2) { 29 | return base[m1]; 30 | } else { 31 | double v1 = base[m1]; 32 | double v2 = *std::min_element(base + m2, base + nmemb); 33 | return v1 * (m2 - m) + v2 * (m - m1); 34 | } 35 | } 36 | 37 | /* 38 | * Discrete quantile function. 39 | * 40 | * Returns k-th smallest element of data samples pointed to by base. 41 | * nmemb is the number of samples. k is an integer between 0 and nmemb - 1 42 | * (incl.). 43 | */ 44 | double _quantile_disc(double *base, size_t nmemb, size_t k) { 45 | 46 | if (nmemb == 0 || k >= nmemb) { 47 | return NAN; 48 | } 49 | 50 | std::nth_element(base, base + k, base + nmemb); 51 | return base[k]; 52 | } 53 | -------------------------------------------------------------------------------- /test/test2result: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """ 3 | test2result 4 | 5 | Parse a mysqltest test case and output expected result. This allows results 6 | to be inlined in the test file: 7 | 8 | * Lines starting with "# " are treated as results and printed to the standard 9 | output. 10 | 11 | * Lines starting with "# >>>" are evaluated as python snippets. The python 12 | environment is initialized from test_env.py. 13 | 14 | This script implements only simple grammar rules which are not entirely 15 | consistent with the mysqltest syntax. 16 | 17 | Usage: test2result < .test > .result 18 | """ 19 | 20 | import sys 21 | 22 | commands = [ 23 | 'disable_abort_on_error', 24 | ] 25 | 26 | env = {} 27 | execfile('test_env.py', env) 28 | 29 | for line in sys.stdin.readlines(): 30 | if line.startswith('# >>> '): 31 | try: 32 | exec(line[8:], env) 33 | except Exception: 34 | print >> sys.stderr, line[8:] 35 | raise 36 | elif line.startswith('# '): 37 | sys.stdout.write(line[4:]) 38 | if line.strip() == '' or line.startswith('#') or line.startswith('--'): 39 | continue 40 | cmd = False 41 | for c in commands: 42 | if line.startswith(c): 43 | cmd = True 44 | break 45 | if not cmd: 46 | sys.stdout.write(line) 47 | -------------------------------------------------------------------------------- /src/rotint.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | 3 | DLLEXPORT my_bool rotint_init(UDF_INIT *initid, UDF_ARGS *args, char *message) { 4 | 5 | if (4 != args->arg_count) { 6 | strcpy(message, "rotint must have exactly four arguments"); 7 | return 1; 8 | } 9 | 10 | args->arg_type[0] = INT_RESULT; 11 | args->arg_type[1] = INT_RESULT; 12 | args->arg_type[2] = INT_RESULT; 13 | args->arg_type[3] = INT_RESULT; 14 | initid->const_item = 1; 15 | initid->maybe_null = 1; 16 | 17 | return 0; 18 | } 19 | 20 | DLLEXPORT longlong rotint(UDF_INIT *initid __attribute__((unused)), UDF_ARGS *args, 21 | char *is_null, 22 | char *error __attribute__((unused))) { 23 | 24 | longlong n, x, y, m, a, b; 25 | 26 | if (NULL == args->args[0] || NULL == args->args[1] || NULL == args->args[2] || NULL == args->args[3]) { 27 | *is_null = 1; 28 | return 0; 29 | } 30 | 31 | n = *((longlong *) args->args[0]); 32 | x = *((longlong *) args->args[1]); 33 | y = *((longlong *) args->args[2]); 34 | m = *((longlong *) args->args[3]); 35 | 36 | if (y < x || x < 1) { 37 | *is_null = 1; 38 | return 0; 39 | } 40 | 41 | y-= x; 42 | m = (y + (m % y)) % y; 43 | 44 | a = (1 << y) - 1; 45 | b = (n >> x) & a; 46 | 47 | return (n & (~(a << x))) | ((((b << m) | (b >> (y - m))) & a) << x); 48 | } 49 | -------------------------------------------------------------------------------- /udf_infusion.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Express 2013 for Windows Desktop 4 | VisualStudioVersion = 12.0.40629.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "udf_infusion", "udf_infusion.vcxproj", "{CC50FDE6-5D58-4D30-B3D7-8C79C94E3B61}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Win32 = Debug|Win32 11 | Debug|x64 = Debug|x64 12 | Release|Win32 = Release|Win32 13 | Release|x64 = Release|x64 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {CC50FDE6-5D58-4D30-B3D7-8C79C94E3B61}.Debug|Win32.ActiveCfg = Debug|Win32 17 | {CC50FDE6-5D58-4D30-B3D7-8C79C94E3B61}.Debug|Win32.Build.0 = Debug|Win32 18 | {CC50FDE6-5D58-4D30-B3D7-8C79C94E3B61}.Debug|x64.ActiveCfg = Debug|x64 19 | {CC50FDE6-5D58-4D30-B3D7-8C79C94E3B61}.Debug|x64.Build.0 = Debug|x64 20 | {CC50FDE6-5D58-4D30-B3D7-8C79C94E3B61}.Release|Win32.ActiveCfg = Release|Win32 21 | {CC50FDE6-5D58-4D30-B3D7-8C79C94E3B61}.Release|Win32.Build.0 = Release|Win32 22 | {CC50FDE6-5D58-4D30-B3D7-8C79C94E3B61}.Release|x64.ActiveCfg = Release|x64 23 | {CC50FDE6-5D58-4D30-B3D7-8C79C94E3B61}.Release|x64.Build.0 = Release|x64 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | EndGlobal 29 | -------------------------------------------------------------------------------- /test/percentile_disc.test: -------------------------------------------------------------------------------- 1 | disable_abort_on_error; 2 | 3 | use udf_infusion_test; 4 | 5 | select percentile_disc(); 6 | # ERROR HY000: Can't initialize function 'percentile_disc'; percentile_disc must have exactly two arguments 7 | 8 | select percentile_disc(1, 2, 3); 9 | # ERROR HY000: Can't initialize function 'percentile_disc'; percentile_disc must have exactly two arguments 10 | 11 | select percentile_disc(NULL, 0.5); 12 | # percentile_disc(NULL, 0.5) 13 | # NULL 14 | 15 | select percentile_disc(x, 0.5) from empty_table; 16 | # percentile_disc(x, 0.5) 17 | # NULL 18 | 19 | select percentile_disc(x, 0.5) from null_table; 20 | # percentile_disc(x, 0.5) 21 | # NULL 22 | 23 | select percentile_disc(x, 0.5) from small_table; 24 | # percentile_disc(x, 0.5) 25 | # 4 26 | 27 | select percentile_disc(x, 0) from small_table; 28 | # percentile_disc(x, 0) 29 | # 1 30 | 31 | select percentile_disc(x, 1) from small_table; 32 | # percentile_disc(x, 1) 33 | # 8 34 | 35 | select percentile_disc(x, 0.001) from small_table; 36 | # percentile_disc(x, 0.001) 37 | # 1 38 | 39 | select percentile_disc(x, 0.999) from small_table; 40 | # percentile_disc(x, 0.999) 41 | # 8 42 | 43 | select percentile_disc(x, 0.501) from small_table; 44 | # percentile_disc(x, 0.501) 45 | # 5 46 | 47 | select g, percentile_disc(x, 0.7) from small_table group by g; 48 | # g percentile_disc(x, 0.7) 49 | # 1 2 50 | # 2 5 51 | # 3 8 52 | -------------------------------------------------------------------------------- /src/slug.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | 3 | DLLEXPORT my_bool slug_init(UDF_INIT *initid, UDF_ARGS *args, char *message) { 4 | 5 | switch (args->arg_count) { 6 | case 2: 7 | args->arg_type[1] = STRING_RESULT; 8 | case 1: 9 | args->arg_type[0] = STRING_RESULT; 10 | break; 11 | default: 12 | strcpy(message, "slug must have one or two arguments"); 13 | return 1; 14 | } 15 | 16 | initid->max_length = args->lengths[0] * 2; 17 | initid->ptr = NULL; 18 | initid->const_item = 1; 19 | initid->maybe_null = 1; 20 | 21 | return 0; 22 | } 23 | 24 | DLLEXPORT char *slug(UDF_INIT *initid, UDF_ARGS *args, 25 | char *result, unsigned long *length, 26 | char *is_null, char *error __attribute__((unused))) { 27 | char *ptr; 28 | 29 | if (NULL == args->args[0]) { 30 | *is_null = 1; 31 | return result; 32 | } 33 | 34 | if (initid->max_length <= 255) { 35 | ptr = result; 36 | } else if (NULL != initid->ptr) { 37 | ptr = initid->ptr; 38 | } else if (NULL == (ptr = malloc(initid->max_length))) { 39 | *is_null = 1; 40 | return result; 41 | } else { 42 | initid->ptr = ptr; 43 | } 44 | 45 | if (args->arg_count == 2 && args->lengths[1] == 1) { 46 | return _translate_string(args, ptr, length, args->args[1][0]); 47 | } else { 48 | return _translate_string(args, ptr, length, '_'); 49 | } 50 | } 51 | 52 | DLLEXPORT void slug_deinit(UDF_INIT *initid, UDF_ARGS *args, char *message) { 53 | char *ptr = (char *) initid->ptr; 54 | 55 | if (NULL != ptr) { 56 | free(ptr); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/lessavg.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | 3 | DLLEXPORT my_bool lessavg_init(UDF_INIT *initid, UDF_ARGS *args, char *message) { 4 | struct DoubleBuffer* data = NULL; 5 | 6 | if (1 != args->arg_count) { 7 | strcpy(message, "lessavg must have exactly one argument"); 8 | return 1; 9 | } 10 | 11 | args->arg_type[0] = REAL_RESULT; 12 | 13 | LESSINIT(); 14 | 15 | return 0; 16 | } 17 | 18 | DLLEXPORT void lessavg_clear(UDF_INIT* initid, char* is_null, char *error) { 19 | LESSCLEAR(); 20 | } 21 | 22 | DLLEXPORT void lessavg_add(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char *error) { 23 | struct DoubleBuffer *data = (struct DoubleBuffer *) initid->ptr; 24 | double value = *((double*) args->args[0]); 25 | 26 | if (NULL == args->args[0]) 27 | return; 28 | 29 | LESSSIZE(); 30 | 31 | data->sum = data->sum + value; 32 | data->number[data->used] = value; 33 | data->used++; 34 | } 35 | 36 | DLLEXPORT void lessavg_deinit(UDF_INIT *initid) { 37 | LESSDEINIT(); 38 | } 39 | 40 | DLLEXPORT longlong lessavg(UDF_INIT *initid, UDF_ARGS *args, char *is_null, char *error) { 41 | struct DoubleBuffer *data = (struct DoubleBuffer *) initid->ptr; 42 | 43 | ulonglong count = 0; 44 | 45 | double /* volatile */ *ptr; 46 | double limit = data->sum / data->used; 47 | double *beg = data->number; 48 | 49 | if (1 == data->used % 2) { 50 | count = (data->number[--data->used] < limit); 51 | } 52 | 53 | ptr = &(data->number[data->used]); 54 | 55 | while (beg < ptr) { 56 | count += (*--ptr < limit); 57 | count += (*--ptr < limit); // new line saves the volatile pointer 58 | } 59 | return (longlong) count; 60 | } 61 | -------------------------------------------------------------------------------- /test/percentile_cont.test: -------------------------------------------------------------------------------- 1 | disable_abort_on_error; 2 | 3 | use udf_infusion_test; 4 | 5 | select percentile_cont(); 6 | # ERROR HY000: Can't initialize function 'percentile_cont'; percentile_cont must have exactly two arguments 7 | 8 | select percentile_cont(1, 2, 3); 9 | # ERROR HY000: Can't initialize function 'percentile_cont'; percentile_cont must have exactly two arguments 10 | 11 | select percentile_cont(NULL, 0.5); 12 | # percentile_cont(NULL, 0.5) 13 | # NULL 14 | 15 | select percentile_cont(x, 0.5) from empty_table; 16 | # percentile_cont(x, 0.5) 17 | # NULL 18 | 19 | select percentile_cont(x, 0.5) from null_table; 20 | # percentile_cont(x, 0.5) 21 | # NULL 22 | 23 | select percentile_cont(x, 0.5) from small_table; 24 | # percentile_cont(x, 0.5) 25 | # 4.5 26 | 27 | select percentile_cont(x, 0) from small_table; 28 | # percentile_cont(x, 0) 29 | # 1 30 | 31 | select percentile_cont(x, 1) from small_table; 32 | # percentile_cont(x, 1) 33 | # 8 34 | 35 | select percentile_cont(x, 0.001) from small_table; 36 | # percentile_cont(x, 0.001) 37 | # 1.007 38 | 39 | select percentile_cont(x, 0.999) from small_table; 40 | # percentile_cont(x, 0.999) 41 | # 7.993 42 | 43 | select percentile_cont(x, 0.6) from small_table; 44 | # percentile_cont(x, 0.6) 45 | # 5.2 46 | 47 | select g, percentile_cont(x, 0.7) from small_table group by g; 48 | # g percentile_cont(x, 0.7) 49 | # 1 1.7 50 | # 2 4.4 51 | # 3 7.4 52 | 53 | select round(percentile_cont(x, 0.7), 12) as `percentile_cont(x, 0.7)` from example_table; 54 | # percentile_cont(x, 0.7) 55 | # >>> print '%.12f' % np.percentile(example_table()[:,0].compressed(), 70) 56 | 57 | select round(percentile_cont(y, 0.7), 12) as `percentile_cont(y, 0.7)` from example_table; 58 | # percentile_cont(y, 0.7) 59 | # >>> print '%.12f' % np.percentile(example_table()[:,1].compressed(), 70) 60 | -------------------------------------------------------------------------------- /test/generate_random_data: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """Generate random data from a bivariate normal distribution with a small 3 | percentage of missing values. Missing values are indicated as 1e+20.""" 4 | 5 | import os 6 | import sys 7 | import numpy as np 8 | from numpy import ma 9 | 10 | from numpy.random import multivariate_normal, uniform 11 | 12 | 13 | CHUNK_SIZE = 10000 14 | program_name = 'generate_random_data' 15 | 16 | 17 | def usage(): 18 | print >> sys.stderr, 'Usage: %s \n' % program_name 19 | print >> sys.stderr, sys.modules[__name__].__doc__ 20 | 21 | 22 | def generate_random_data(mean, var, size=1, missing_fraction=0): 23 | data = multivariate_normal(mean, var, size) 24 | mask = uniform(0, 1, (size, 2)) < missing_fraction 25 | return ma.array(data, mask=mask) 26 | 27 | 28 | if __name__ == '__main__': 29 | program_name = sys.argv[0] 30 | 31 | if len(sys.argv) != 2: 32 | usage() 33 | sys.exit(1) 34 | 35 | try: 36 | nsamples = int(sys.argv[1]) 37 | except ValueError: 38 | print >> sys.stderr, 'Number of samples must be an integer' 39 | sys.exit(1) 40 | 41 | if nsamples < 0: 42 | print >> sys.stderr, 'Number of samples must be non-negative' 43 | sys.exit(1) 44 | 45 | log_progress = os.isatty(sys.stderr.fileno()) and \ 46 | not os.isatty(sys.stdout.fileno()) 47 | 48 | n = 0 49 | if log_progress: 50 | sys.stderr.write(' 0 %') 51 | while n < nsamples: 52 | chunk_size = min(CHUNK_SIZE, nsamples - n) 53 | chunk = generate_random_data( 54 | [0, 1], 55 | [[1, -0.7], [-0.7, 1]], 56 | chunk_size, 57 | missing_fraction=0.1 58 | ) 59 | np.savetxt(sys.stdout, chunk.filled(1e+20)) 60 | n += chunk_size 61 | if log_progress: 62 | sys.stderr.write('\r%3d %%' % (100.0*n/nsamples)) 63 | if log_progress: 64 | sys.stderr.write('\n') 65 | -------------------------------------------------------------------------------- /unload.sql.sh: -------------------------------------------------------------------------------- 1 | mysql_version="$1" 2 | mysql_version_major=`expr $mysql_version : '\([[0-9]]*\)'` 3 | shift 4 | 5 | [ $# -eq 0 ] && enable_all=1 6 | enable_functions="$@" 7 | 8 | if_enable() { 9 | [ "$enable_all" = 1 ] && return 0 10 | for func in $enable_functions; do 11 | [ "$func" = "$1" ] && return 0 12 | done 13 | return 1 14 | } 15 | 16 | drop_function() { 17 | echo "DROP FUNCTION IF EXISTS $1;" 18 | } 19 | 20 | if_enable "bound" && drop_function "bound" 21 | if_enable "bround" && drop_function "bround" 22 | if_enable "corr" && drop_function "corr" 23 | if_enable "covariance" && drop_function "covariance" 24 | if_enable "cut" && drop_function "cut" 25 | if_enable "fnv" && drop_function "fnv" 26 | if_enable "getint" && drop_function "getint" 27 | if_enable "group_first" && drop_function "group_first" 28 | if_enable "group_last" && drop_function "group_last" 29 | if_enable "invbit" && drop_function "invbit" 30 | if_enable "isbit" && drop_function "isbit" 31 | if_enable "kurtosis" && drop_function "kurtosis" 32 | if_enable "lessavg" && drop_function "lessavg" 33 | if_enable "lesspartpct" && drop_function "lesspartpct" 34 | if_enable "lesspart" && drop_function "lesspart" 35 | if_enable "median" && drop_function "median" 36 | if_enable "stats_mode" && drop_function "stats_mode" 37 | if_enable "ngram" && drop_function "ngram" 38 | if_enable "noverk" && drop_function "noverk" 39 | if_enable "percentile_cont" && drop_function "percentile_cont" 40 | if_enable "percentile_disc" && drop_function "percentile_disc" 41 | if_enable "rotbit" && drop_function "rotbit" 42 | if_enable "rotint" && drop_function "rotint" 43 | if_enable "rsumd" && drop_function "rsumd" 44 | if_enable "rsumi" && drop_function "rsumi" 45 | if_enable "setbit" && drop_function "setbit" 46 | if_enable "setint" && drop_function "setint" 47 | if_enable "skewness" && drop_function "skewness" 48 | if_enable "slug" && drop_function "slug" 49 | if_enable "xround" && drop_function "xround" 50 | 51 | true 52 | -------------------------------------------------------------------------------- /src/covariance.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | 3 | struct CovBuffer { 4 | double x; 5 | double y; 6 | double c; 7 | unsigned count; 8 | }; 9 | 10 | DLLEXPORT my_bool covariance_init(UDF_INIT *initid, UDF_ARGS *args, char *message) { 11 | struct CovBuffer *data; 12 | 13 | if (2 != args->arg_count) { 14 | strcpy(message, "covariance must have exaclty two arguments"); 15 | return 1; 16 | } 17 | 18 | args->arg_type[0] = REAL_RESULT; 19 | args->arg_type[1] = REAL_RESULT; 20 | 21 | if (NULL == (data = malloc(sizeof (*data)))) { 22 | strcpy(message, "Memory allocation failed"); 23 | return 1; 24 | } 25 | 26 | initid->decimals = NOT_FIXED_DEC; 27 | initid->maybe_null = 1; 28 | initid->ptr = (char*) data; 29 | 30 | return 0; 31 | } 32 | 33 | DLLEXPORT void covariance_clear(UDF_INIT* initid, char* is_null, char *error) { 34 | struct CovBuffer *data = (struct CovBuffer *) initid->ptr; 35 | 36 | data->count = 0; 37 | data->x = 0; 38 | data->y = 0; 39 | data->c = 0; 40 | } 41 | 42 | DLLEXPORT void covariance_add(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char *error) { 43 | struct CovBuffer *data = (struct CovBuffer *) initid->ptr; 44 | 45 | if (NULL == args->args[0] || NULL == args->args[1]) 46 | return; 47 | 48 | double x = *((double *) args->args[0]); 49 | double y = *((double *) args->args[1]); 50 | 51 | data->count++; 52 | 53 | data->x += x; 54 | data->y += y; 55 | data->c += x * y; 56 | } 57 | 58 | DLLEXPORT void covariance_deinit(UDF_INIT *initid) { 59 | struct CovBuffer *data = (struct CovBuffer *) initid->ptr; 60 | 61 | if (data) { 62 | free(data); 63 | } 64 | } 65 | 66 | DLLEXPORT double covariance(UDF_INIT *initid __attribute__((unused)), UDF_ARGS *args, 67 | char *is_null, 68 | char *error __attribute__((unused))) { 69 | struct CovBuffer *data = (struct CovBuffer *) initid->ptr; 70 | 71 | if (data->count == 0) { 72 | *is_null = 1; 73 | return 0; 74 | } 75 | return (data->c - data->x * data->y / data->count) / data->count; 76 | } 77 | -------------------------------------------------------------------------------- /src/skewness.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | 3 | DLLEXPORT my_bool skewness_init(UDF_INIT *initid, UDF_ARGS *args, char *message) { 4 | struct StatBuffer *data; 5 | 6 | if (1 != args->arg_count) { 7 | strcpy(message, "skewness must have exaclty one argument"); 8 | return 1; 9 | } 10 | 11 | args->arg_type[0] = REAL_RESULT; 12 | 13 | if (NULL == (data = malloc(sizeof (*data)))) { 14 | strcpy(message, "Memory allocation failed"); 15 | return 1; 16 | } 17 | 18 | initid->decimals = NOT_FIXED_DEC; 19 | initid->maybe_null = 1; 20 | initid->ptr = (char*) data; 21 | 22 | return 0; 23 | } 24 | 25 | DLLEXPORT void skewness_clear(UDF_INIT* initid, char* is_null, char *error) { 26 | struct StatBuffer *data = (struct StatBuffer *) initid->ptr; 27 | 28 | data->count = 0; 29 | data->mean = 0; 30 | data->M2 = 0; 31 | data->M3 = 0; 32 | } 33 | 34 | DLLEXPORT void skewness_add(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char *error) { 35 | struct StatBuffer *data = (struct StatBuffer *) initid->ptr; 36 | 37 | if (NULL == args->args[0]) 38 | return; 39 | 40 | // http://people.xiph.org/~tterribe/notes/homs.html 41 | 42 | double value = *((double *) args->args[0]); 43 | 44 | data->count++; 45 | 46 | double n = data->count; 47 | 48 | double delta = value - data->mean; 49 | 50 | double delta_n = delta / n; 51 | double shorten = delta * delta_n * (n - 1); 52 | 53 | data->mean = data->mean + delta_n; 54 | data->M3 = data->M3 + shorten * delta_n * (n - 2) - 3 * delta_n * data->M2; 55 | data->M2 = data->M2 + shorten; 56 | } 57 | 58 | DLLEXPORT void skewness_deinit(UDF_INIT *initid) { 59 | struct StatBuffer *data = (struct StatBuffer *) initid->ptr; 60 | 61 | if (data) { 62 | free(data); 63 | } 64 | } 65 | 66 | DLLEXPORT double skewness(UDF_INIT *initid __attribute__((unused)), UDF_ARGS *args, 67 | char *is_null, 68 | char *error __attribute__((unused))) { 69 | 70 | struct StatBuffer *data = (struct StatBuffer *) initid->ptr; 71 | 72 | if (data->count < 2) { 73 | *is_null = 1; 74 | return 0; 75 | } 76 | return pow(data->count, 0.5) * data->M3 / pow(data->M2, 1.5); 77 | } 78 | -------------------------------------------------------------------------------- /config.h.in: -------------------------------------------------------------------------------- 1 | /* config.h.in. Generated from configure.ac by autoheader. */ 2 | 3 | /* Define to 1 if you have the header file. */ 4 | #undef HAVE_DLFCN_H 5 | 6 | /* Define to 1 if you have the header file. */ 7 | #undef HAVE_INTTYPES_H 8 | 9 | /* Define to 1 if you have the header file. */ 10 | #undef HAVE_LIMITS_H 11 | 12 | /* Define to 1 if you have the header file. */ 13 | #undef HAVE_MEMORY_H 14 | 15 | /* Define to 1 if MySQL libraries are available */ 16 | #undef HAVE_MYSQL 17 | 18 | /* Define to 1 if you have the header file. */ 19 | #undef HAVE_STDINT_H 20 | 21 | /* Define to 1 if you have the header file. */ 22 | #undef HAVE_STDLIB_H 23 | 24 | /* Define to 1 if you have the header file. */ 25 | #undef HAVE_STRINGS_H 26 | 27 | /* Define to 1 if you have the header file. */ 28 | #undef HAVE_STRING_H 29 | 30 | /* Define to 1 if you have the header file. */ 31 | #undef HAVE_SYSLIMITS_H 32 | 33 | /* Define to 1 if you have the header file. */ 34 | #undef HAVE_SYS_STAT_H 35 | 36 | /* Define to 1 if you have the header file. */ 37 | #undef HAVE_SYS_TYPES_H 38 | 39 | /* Define to 1 if you have the header file. */ 40 | #undef HAVE_UNISTD_H 41 | 42 | /* Define to the sub-directory in which libtool stores uninstalled libraries. 43 | */ 44 | #undef LT_OBJDIR 45 | 46 | /* Name of package */ 47 | #undef PACKAGE 48 | 49 | /* Define to the address where bug reports for this package should be sent. */ 50 | #undef PACKAGE_BUGREPORT 51 | 52 | /* Define to the full name of this package. */ 53 | #undef PACKAGE_NAME 54 | 55 | /* Define to the full name and version of this package. */ 56 | #undef PACKAGE_STRING 57 | 58 | /* Define to the one symbol short name of this package. */ 59 | #undef PACKAGE_TARNAME 60 | 61 | /* Define to the home page for this package. */ 62 | #undef PACKAGE_URL 63 | 64 | /* Define to the version of this package. */ 65 | #undef PACKAGE_VERSION 66 | 67 | /* Define to 1 if you have the ANSI C header files. */ 68 | #undef STDC_HEADERS 69 | 70 | /* Version number of package */ 71 | #undef VERSION 72 | 73 | /* Define to empty if `const' does not conform to ANSI C. */ 74 | #undef const 75 | 76 | /* Define to `unsigned int' if does not define. */ 77 | #undef size_t 78 | -------------------------------------------------------------------------------- /src/median.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | #include "array.h" 3 | 4 | struct Buffer { 5 | struct array values; 6 | }; 7 | 8 | DLLEXPORT my_bool median_init(UDF_INIT *initid, UDF_ARGS *args, char *message) { 9 | struct Buffer *data; 10 | 11 | if (1 != args->arg_count) { 12 | snprintf(message, MYSQL_ERRMSG_SIZE, 13 | "median must have exactly one argument"); 14 | return 1; 15 | } 16 | 17 | args->arg_type[0] = REAL_RESULT; 18 | 19 | data = calloc(1, sizeof (*data)); 20 | if (NULL == data) { 21 | snprintf(message, MYSQL_ERRMSG_SIZE, "Memory allocation failed"); 22 | return 1; 23 | } 24 | 25 | if (NULL == array_init(&data->values, sizeof (double), 32)) { 26 | snprintf(message, MYSQL_ERRMSG_SIZE, "Memory allocation failed"); 27 | return 1; 28 | } 29 | 30 | initid->decimals = NOT_FIXED_DEC; 31 | initid->maybe_null = 1; 32 | initid->ptr = (char*) data; 33 | 34 | return 0; 35 | } 36 | 37 | DLLEXPORT void median_clear(UDF_INIT* initid, char* is_null, char *error) { 38 | struct Buffer *data = (struct Buffer *) initid->ptr; 39 | array_truncate(&data->values); 40 | } 41 | 42 | DLLEXPORT void median_add(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char *error) { 43 | struct Buffer *data = (struct Buffer *) initid->ptr; 44 | 45 | if (NULL == args->args[0]) 46 | return; 47 | 48 | if (NULL == array_append(&data->values, args->args[0])) { 49 | *error = 1; 50 | return; 51 | } 52 | } 53 | 54 | DLLEXPORT void median_deinit(UDF_INIT *initid) { 55 | struct Buffer *data = (struct Buffer *) initid->ptr; 56 | if (NULL != data) { 57 | array_free(&data->values); 58 | free(data); 59 | data = NULL; 60 | } 61 | } 62 | 63 | DLLEXPORT double median(UDF_INIT *initid, UDF_ARGS *args, 64 | char *is_null, 65 | char *error __attribute__((unused))) { 66 | struct Buffer *data = (struct Buffer *) initid->ptr; 67 | 68 | if (data->values.n == 0) { 69 | *is_null = 1; 70 | return 0; 71 | } 72 | 73 | if (data->values.n % 2 == 0) { 74 | return _quantile(data->values.p, data->values.n, 0.5); 75 | } else { 76 | size_t k = (data->values.n - 1) / 2; 77 | return _quantile_disc(data->values.p, data->values.n, k); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /m4/ax_mysql_bin.m4: -------------------------------------------------------------------------------- 1 | ##### 2 | # 3 | # SYNOPSIS 4 | # 5 | # AX_MYSQL_BIN() 6 | # 7 | # DESCRIPTION 8 | # 9 | # This macro defines location of MySQL client (mysql), mysqladmin and mysqltest 10 | # 11 | # This macro calls: 12 | # 13 | # AC_SUBST(MYSQL) 14 | # AC_SUBST(MYSQLADMIN) 15 | # AC_SUBST(MYSQLTEST) 16 | # 17 | ##### 18 | 19 | AC_DEFUN([AX_MYSQL_BIN], [ 20 | AC_MSG_CHECKING(for mysqlbin) 21 | AC_ARG_WITH(mysqlbin, 22 | [[ --with-mysqlbin[=CMD] command to run mysql.]], 23 | [withmysqlbin="$withval"], 24 | [withmysqlbin="yes"] 25 | ) 26 | 27 | AC_ARG_WITH(mysqladmin, 28 | [[ --with-mysqladmin[=CMD] command to run mysqladmin.]], 29 | [withmysqladmin="$withval"], 30 | [withmysqladmin="yes"] 31 | ) 32 | 33 | AC_ARG_WITH(mysqltest, 34 | [[ --with-mysqltest[=CMD] command to run mysqltest.]], 35 | [withmysqltest="$withval"], 36 | [withmysqltest="yes"] 37 | ) 38 | 39 | if test -f /etc/mysql/debian.cnf ; then 40 | MYSQL_ARGS="--defaults-file=/etc/mysql/debian.cnf" 41 | else 42 | MYSQL_ARGS="-p" 43 | fi 44 | 45 | if test -z "$withmysqlbin" -o "$withmysqlbin" = "yes"; then 46 | MYSQL=`which mysql`; 47 | if test -n "$MYSQL"; then MYSQL="$MYSQL $MYSQL_ARGS"; fi 48 | elif test "$withmysqlbin" != "no"; then 49 | MYSQL="$withmysqlbin" 50 | fi 51 | 52 | if test -n "$MYSQL" ; then 53 | MYSQLBIN_PATH=`dirname "$MYSQL"` 54 | fi 55 | 56 | if test -z "$withmysqladmin" -o "$withmysqladmin" = "yes"; then 57 | if test -n "$MYSQLBIN_PATH" -a -f "$MYSQLBIN_PATH/mysqladmin"; then 58 | MYSQLADMIN="$MYSQLBIN_PATH/mysqladmin"; 59 | else 60 | MYSQLADMIN=`which mysqladmin`; 61 | fi 62 | 63 | if test -n "$MYSQLADMIN"; then MYSQLADMIN="$MYSQLADMIN $MYSQL_ARGS"; fi 64 | elif test "$withmysqladmin" != "no"; then 65 | MYSQLADMIN="$withmysqladmin" 66 | fi 67 | 68 | if test -z "$withmysqltest" -o "$withmysqltest" = "yes"; then 69 | if test -n "$MYSQLBIN_PATH" -a -f "$MYSQLBIN_PATH/mysqltest"; then 70 | MYSQLTEST="$MYSQLBIN_PATH/mysqltest"; 71 | else 72 | MYSQLTEST=`which mysqltest`; 73 | fi 74 | 75 | if test -n "$MYSQLTEST"; then MYSQLTEST="$MYSQLTEST $MYSQL_ARGS"; fi 76 | elif test "$withmysqltest" != "no"; then 77 | MYSQLTEST="$withmysqltest" 78 | fi 79 | 80 | AC_SUBST(MYSQL) 81 | AC_SUBST(MYSQLADMIN) 82 | AC_SUBST(MYSQLTEST) 83 | ]) -------------------------------------------------------------------------------- /src/kurtosis.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | 3 | DLLEXPORT my_bool kurtosis_init(UDF_INIT *initid, UDF_ARGS *args, char *message) { 4 | 5 | struct StatBuffer *data; 6 | 7 | if (1 != args->arg_count) { 8 | strcpy(message, "kurtosis must have exaclty one argument"); 9 | return 1; 10 | } 11 | 12 | args->arg_type[0] = REAL_RESULT; 13 | 14 | if (NULL == (data = malloc(sizeof (*data)))) { 15 | strcpy(message, "Memory allocation failed"); 16 | return 1; 17 | } 18 | 19 | initid->decimals = NOT_FIXED_DEC; 20 | initid->maybe_null = 1; 21 | initid->ptr = (char*) data; 22 | 23 | return 0; 24 | } 25 | 26 | DLLEXPORT void kurtosis_clear(UDF_INIT* initid, char* is_null, char *error) { 27 | struct StatBuffer *data = (struct StatBuffer *) initid->ptr; 28 | 29 | data->count = 0; 30 | data->mean = 0; 31 | data->M2 = 0; 32 | data->M3 = 0; 33 | data->M4 = 0; 34 | } 35 | 36 | DLLEXPORT void kurtosis_add(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char *error) { 37 | struct StatBuffer *data = (struct StatBuffer *) initid->ptr; 38 | 39 | if (NULL == args->args[0]) 40 | return; 41 | 42 | // http://people.xiph.org/~tterribe/notes/homs.html 43 | 44 | double value = *((double *) args->args[0]); 45 | 46 | data->count++; 47 | 48 | double n = data->count; 49 | 50 | double delta = value - data->mean; 51 | 52 | double delta_n = delta / n; 53 | double shorten = delta * delta_n * (n - 1); 54 | 55 | data->mean = data->mean + delta_n; 56 | data->M4 = data->M4 + delta_n * (shorten * delta_n * (3 + n * (n - 3)) + 6 * delta_n * data->M2 - 4 * data->M3); 57 | data->M3 = data->M3 + shorten * delta_n * (n - 2) - 3 * delta_n * data->M2; 58 | data->M2 = data->M2 + shorten; 59 | } 60 | 61 | DLLEXPORT void kurtosis_deinit(UDF_INIT *initid) { 62 | struct StatBuffer *data = (struct StatBuffer *) initid->ptr; 63 | 64 | if (data) { 65 | free(data); 66 | } 67 | } 68 | 69 | DLLEXPORT double kurtosis(UDF_INIT *initid __attribute__((unused)), UDF_ARGS *args, 70 | char *is_null, 71 | char *error __attribute__((unused))) { 72 | 73 | struct StatBuffer *data = (struct StatBuffer *) initid->ptr; 74 | 75 | if (data->count < 2) { 76 | *is_null = 1; 77 | return 0; 78 | } 79 | 80 | return data->count * data->M4 / (data->M2 * data->M2) - 3; 81 | } 82 | -------------------------------------------------------------------------------- /src/group_last.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | 3 | struct Buffer { 4 | longlong length; 5 | char *string; 6 | char state; 7 | }; 8 | 9 | DLLEXPORT my_bool group_last_init(UDF_INIT *initid, UDF_ARGS *args, char *message) { 10 | struct Buffer* data; 11 | 12 | if (1 != args->arg_count) { 13 | strcpy(message, "group_last must have exaclty one argument"); 14 | return 1; 15 | } 16 | 17 | args->arg_type[0] = STRING_RESULT; 18 | 19 | if (NULL == (data = malloc(sizeof (*data)))) { 20 | strcpy(message, "Memory allocation failed"); 21 | return 1; 22 | } 23 | 24 | if (NULL == (data->string = malloc(65535))) { 25 | strcpy(message, "Memory allocation failed"); 26 | free(data); 27 | return 1; 28 | } 29 | data->length = 0; 30 | data->state = 0; 31 | 32 | initid->max_length = 65535; 33 | initid->maybe_null = 1; 34 | initid->ptr = (char*) data; 35 | 36 | return 0; 37 | } 38 | 39 | DLLEXPORT void group_last_clear(UDF_INIT* initid, char* is_null, char *error) { 40 | struct Buffer* data = (struct Buffer *) initid->ptr; 41 | 42 | data->length = 0; 43 | data->state = 0; 44 | } 45 | 46 | DLLEXPORT void group_last_add(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char *error) { 47 | struct Buffer *data = (struct Buffer *) initid->ptr; 48 | 49 | if (NULL != args->args[0]) { 50 | memcpy(data->string, args->args[0], args->lengths[0]); 51 | data->length = args->lengths[0]; 52 | data->state = 1; 53 | } else if (data->state == 0) { 54 | data->state = 2; 55 | } 56 | } 57 | 58 | DLLEXPORT void group_last_deinit(UDF_INIT *initid) { 59 | struct Buffer *data = (struct Buffer *) initid->ptr; 60 | 61 | if (data) { 62 | 63 | if (data->string) { 64 | free(data->string); 65 | } 66 | free(data); 67 | } 68 | } 69 | 70 | DLLEXPORT char *group_last(UDF_INIT *initid, UDF_ARGS *args, 71 | char *result, unsigned long *length, 72 | char *is_null, char *error __attribute__((unused))) { 73 | struct Buffer* data = (struct Buffer *) initid->ptr; 74 | 75 | if (data->state == 2 || data->string == NULL) { 76 | *is_null = 1; 77 | (*length) = 0; 78 | return NULL; 79 | } 80 | 81 | initid->max_length = data->length; 82 | result = data->string; 83 | 84 | (*length) = data->length; 85 | 86 | return result; 87 | } 88 | -------------------------------------------------------------------------------- /src/percentile_cont.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | #include "array.h" 3 | 4 | struct Buffer { 5 | struct array values; 6 | double percentile; 7 | }; 8 | 9 | DLLEXPORT my_bool percentile_cont_init(UDF_INIT *initid, UDF_ARGS *args, char *message) { 10 | struct Buffer *data; 11 | 12 | if (2 != args->arg_count) { 13 | snprintf(message, MYSQL_ERRMSG_SIZE, 14 | "percentile_cont must have exactly two arguments"); 15 | return 1; 16 | } 17 | 18 | args->arg_type[0] = REAL_RESULT; 19 | args->arg_type[1] = REAL_RESULT; 20 | 21 | data = calloc(1, sizeof (*data)); 22 | if (NULL == data) { 23 | snprintf(message, MYSQL_ERRMSG_SIZE, "Memory allocation failed"); 24 | return 1; 25 | } 26 | 27 | if (NULL == array_init(&data->values, sizeof (double), 32)) { 28 | snprintf(message, MYSQL_ERRMSG_SIZE, "Memory allocation failed"); 29 | return 1; 30 | } 31 | 32 | initid->decimals = NOT_FIXED_DEC; 33 | initid->maybe_null = 1; 34 | initid->ptr = (char*) data; 35 | 36 | return 0; 37 | } 38 | 39 | DLLEXPORT void percentile_cont_clear(UDF_INIT* initid, char* is_null, char *error) { 40 | struct Buffer *data = (struct Buffer *) initid->ptr; 41 | array_truncate(&data->values); 42 | } 43 | 44 | DLLEXPORT void percentile_cont_add(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char *error) { 45 | struct Buffer *data = (struct Buffer *) initid->ptr; 46 | 47 | double percentile = *((double *) args->args[1]); 48 | if (!(isfinite(percentile) && percentile >= 0 && percentile <= 1)) { 49 | *error = 1; 50 | return; 51 | } 52 | data->percentile = percentile; 53 | 54 | if (NULL == args->args[0]) 55 | return; 56 | 57 | if (NULL == array_append(&data->values, args->args[0])) { 58 | *error = 1; 59 | return; 60 | } 61 | } 62 | 63 | DLLEXPORT void percentile_cont_deinit(UDF_INIT *initid) { 64 | struct Buffer *data = (struct Buffer *) initid->ptr; 65 | if (NULL != data) { 66 | array_free(&data->values); 67 | free(data); 68 | data = NULL; 69 | } 70 | } 71 | 72 | DLLEXPORT double percentile_cont(UDF_INIT *initid, UDF_ARGS *args, 73 | char *is_null, 74 | char *error __attribute__((unused))) { 75 | struct Buffer *data = (struct Buffer *) initid->ptr; 76 | 77 | if (data->values.n == 0) { 78 | *is_null = 1; 79 | return 0; 80 | } 81 | 82 | return _quantile(data->values.p, data->values.n, data->percentile); 83 | } 84 | -------------------------------------------------------------------------------- /load.sql.sh: -------------------------------------------------------------------------------- 1 | mysql_version="$1" 2 | mysql_version_major=`expr $mysql_version : '\([[0-9]]*\)'` 3 | shift 4 | 5 | [ $# -eq 0 ] && enable_all=1 6 | enable_functions="$@" 7 | 8 | if_enable() { 9 | [ "$enable_all" = 1 ] && return 0 10 | for func in $enable_functions; do 11 | [ "$func" = "$1" ] && return 0 12 | done 13 | return 1 14 | } 15 | 16 | create_agg_function() { 17 | echo "CREATE AGGREGATE FUNCTION $1 RETURNS $2 SONAME 'udf_infusion.so';" 18 | } 19 | 20 | create_function() { 21 | echo "CREATE FUNCTION $1 RETURNS $2 SONAME 'udf_infusion.so';" 22 | } 23 | 24 | sh unload.sql.sh $mysql_version $enable_functions 25 | 26 | if_enable "bound" && create_function "bound" "real" 27 | if_enable "bround" && create_function "bround" "real" 28 | if_enable "corr" && create_agg_function "corr" "real" 29 | if_enable "covariance" && create_agg_function "covariance" "real" 30 | if_enable "cut" && create_function "cut" "string" 31 | if_enable "fnv" && create_function "fnv" "integer" 32 | if_enable "getint" && create_function "getint" "integer" 33 | if_enable "group_first" && create_agg_function "group_first" "string" 34 | if_enable "group_last" && create_agg_function "group_last" "string" 35 | if_enable "invbit" && create_function "invbit" "integer" 36 | if_enable "isbit" && create_function "isbit" "integer" 37 | if_enable "kurtosis" && create_agg_function "kurtosis" "real" 38 | if_enable "lessavg" && create_agg_function "lessavg" "integer" 39 | if_enable "lesspartpct" && create_agg_function "lesspartpct" "integer" 40 | if_enable "lesspart" && create_agg_function "lesspart" "integer" 41 | if_enable "median" && create_agg_function "median" "real" 42 | if_enable "stats_mode" && create_agg_function "stats_mode" "real" 43 | if_enable "ngram" && create_function "ngram" "string" 44 | if_enable "noverk" && create_function "noverk" "integer" 45 | if_enable "percentile_cont" && create_agg_function "percentile_cont" "real" 46 | if_enable "percentile_disc" && create_agg_function "percentile_disc" "real" 47 | if_enable "rotbit" && create_function "rotbit" "integer" 48 | if_enable "rotint" && create_function "rotint" "integer" 49 | if_enable "rsumd" && create_function "rsumd" "real" 50 | if_enable "rsumi" && create_function "rsumi" "integer" 51 | if_enable "setbit" && create_function "setbit" "integer" 52 | if_enable "setint" && create_function "setint" "integer" 53 | if_enable "skewness" && create_agg_function "skewness" "real" 54 | if_enable "slug" && create_function "slug" "string" 55 | if_enable "xround" && create_function "xround" "integer" 56 | 57 | true 58 | -------------------------------------------------------------------------------- /src/group_first.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | 3 | struct Buffer { 4 | longlong length; 5 | char *string; 6 | char state; 7 | }; 8 | 9 | DLLEXPORT my_bool group_first_init(UDF_INIT *initid, UDF_ARGS *args, char *message) { 10 | struct Buffer* data; 11 | 12 | if (1 != args->arg_count) { 13 | strcpy(message, "group_first must have exaclty one argument"); 14 | return 1; 15 | } 16 | 17 | args->arg_type[0] = STRING_RESULT; 18 | 19 | if (NULL == (data = malloc(sizeof (*data)))) { 20 | strcpy(message, "Memory allocation failed"); 21 | return 1; 22 | } 23 | 24 | if (NULL == (data->string = malloc(65535))) { 25 | strcpy(message, "Memory allocation failed"); 26 | free(data); 27 | return 1; 28 | } 29 | data->length = 0; 30 | data->state = 0; 31 | 32 | initid->max_length = 65535; 33 | initid->maybe_null = 1; 34 | initid->ptr = (char*) data; 35 | 36 | return 0; 37 | } 38 | 39 | DLLEXPORT void group_first_clear(UDF_INIT* initid, char* is_null, char *error) { 40 | struct Buffer* data = (struct Buffer *) initid->ptr; 41 | 42 | data->length = 0; 43 | data->state = 0; 44 | } 45 | 46 | DLLEXPORT void group_first_add(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char *error) { 47 | struct Buffer *data = (struct Buffer *) initid->ptr; 48 | 49 | switch (data->state) { 50 | case 0: 51 | 52 | if (NULL == args->args[0]) { 53 | data->state = 2; 54 | } else { 55 | memcpy(data->string, args->args[0], args->lengths[0]); 56 | data->length = args->lengths[0]; 57 | data->state = 1; 58 | } 59 | break; 60 | } 61 | } 62 | 63 | DLLEXPORT void group_first_deinit(UDF_INIT *initid) { 64 | struct Buffer *data = (struct Buffer *) initid->ptr; 65 | 66 | if (data) { 67 | 68 | if (data->string) { 69 | free(data->string); 70 | } 71 | free(data); 72 | } 73 | } 74 | 75 | DLLEXPORT char *group_first(UDF_INIT *initid, UDF_ARGS *args, 76 | char *result, unsigned long *length, 77 | char *is_null, char *error __attribute__((unused))) { 78 | struct Buffer* data = (struct Buffer *) initid->ptr; 79 | 80 | if (data->state == 2 || data->string == NULL) { 81 | *is_null = 1; 82 | (*length) = 0; 83 | return NULL; 84 | } 85 | 86 | initid->max_length = data->length; 87 | result = data->string; 88 | 89 | (*length) = data->length; 90 | 91 | return result; 92 | } 93 | -------------------------------------------------------------------------------- /src/percentile_disc.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | #include "array.h" 3 | 4 | struct Buffer { 5 | struct array values; 6 | double percentile; 7 | }; 8 | 9 | DLLEXPORT my_bool percentile_disc_init(UDF_INIT *initid, UDF_ARGS *args, char *message) { 10 | struct Buffer *data; 11 | 12 | if (2 != args->arg_count) { 13 | snprintf(message, MYSQL_ERRMSG_SIZE, 14 | "percentile_disc must have exactly two arguments"); 15 | return 1; 16 | } 17 | 18 | args->arg_type[0] = REAL_RESULT; 19 | args->arg_type[1] = REAL_RESULT; 20 | 21 | data = calloc(1, sizeof (*data)); 22 | if (NULL == data) { 23 | snprintf(message, MYSQL_ERRMSG_SIZE, "Memory allocation failed"); 24 | return 1; 25 | } 26 | 27 | if (NULL == array_init(&data->values, sizeof (double), 32)) { 28 | snprintf(message, MYSQL_ERRMSG_SIZE, "Memory allocation failed"); 29 | return 1; 30 | } 31 | 32 | initid->decimals = NOT_FIXED_DEC; 33 | initid->maybe_null = 1; 34 | initid->ptr = (char*) data; 35 | 36 | return 0; 37 | } 38 | 39 | DLLEXPORT void percentile_disc_clear(UDF_INIT* initid, char* is_null, char *error) { 40 | struct Buffer *data = (struct Buffer *) initid->ptr; 41 | array_truncate(&data->values); 42 | } 43 | 44 | DLLEXPORT void percentile_disc_add(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char *error) { 45 | struct Buffer *data = (struct Buffer *) initid->ptr; 46 | 47 | double percentile = *((double *) args->args[1]); 48 | if (!(isfinite(percentile) && percentile >= 0 && percentile <= 1)) { 49 | *error = 1; 50 | return; 51 | } 52 | data->percentile = percentile; 53 | 54 | if (NULL == args->args[0]) 55 | return; 56 | 57 | if (NULL == array_append(&data->values, args->args[0])) { 58 | *error = 1; 59 | return; 60 | } 61 | } 62 | 63 | DLLEXPORT void percentile_disc_deinit(UDF_INIT *initid) { 64 | struct Buffer *data = (struct Buffer *) initid->ptr; 65 | if (NULL != data) { 66 | array_free(&data->values); 67 | free(data); 68 | data = NULL; 69 | } 70 | } 71 | 72 | DLLEXPORT double percentile_disc(UDF_INIT *initid, UDF_ARGS *args, 73 | char *is_null, 74 | char *error __attribute__((unused))) { 75 | struct Buffer *data = (struct Buffer *) initid->ptr; 76 | 77 | if (data->values.n == 0) { 78 | *is_null = 1; 79 | return 0; 80 | } 81 | 82 | size_t k = fmax(0, ceil(data->values.n * data->percentile) - 1); 83 | return _quantile_disc(data->values.p, data->values.n, k); 84 | } 85 | -------------------------------------------------------------------------------- /src/ngram.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | 3 | 4 | #define MAX_GRAM 10 5 | 6 | DLLEXPORT my_bool ngram_init(UDF_INIT *initid, UDF_ARGS *args, char *message) { 7 | 8 | switch (args->arg_count) { 9 | case 2: 10 | args->arg_type[1] = INT_RESULT; 11 | case 1: 12 | args->arg_type[0] = STRING_RESULT; 13 | break; 14 | default: 15 | strcpy(message, "ngram must have one or two arguments"); 16 | return 1; 17 | } 18 | 19 | initid->max_length = (args->lengths[0] + 1) * MAX_GRAM; 20 | initid->ptr = NULL; 21 | initid->const_item = 1; 22 | initid->maybe_null = 1; 23 | 24 | return 0; 25 | } 26 | 27 | DLLEXPORT char *ngram(UDF_INIT *initid, UDF_ARGS *args, 28 | char *result, unsigned long *length, 29 | char *is_null, char *error __attribute__((unused))) { 30 | 31 | char *tmp, *ptr, *start; 32 | 33 | long i = -1, j, l, n = 2; 34 | 35 | if (NULL == args->args[0]) { 36 | *is_null = 1; 37 | return result; 38 | } 39 | 40 | if (2 == args->arg_count) { 41 | if ((n = (unsigned) *((longlong *) args->args[1])) > MAX_GRAM) 42 | n = MAX_GRAM; 43 | } 44 | 45 | if (args->lengths[0] < 1 || n < 1) { 46 | *length = 0; 47 | return result; 48 | } 49 | 50 | if (initid->max_length * n <= 255 * MAX_GRAM) { 51 | ptr = result; 52 | } else if (NULL != initid->ptr) { 53 | ptr = initid->ptr; 54 | } else if (NULL == (ptr = malloc(initid->max_length))) { 55 | *is_null = 1; 56 | return result; 57 | } else { 58 | initid->ptr = ptr; 59 | } 60 | 61 | start = ptr; 62 | 63 | _translate_string(args, ptr, length, '_'); 64 | 65 | l = *length; 66 | 67 | if (l < 1 || l < n) { 68 | return ptr; 69 | } 70 | 71 | tmp = strndup(ptr, l); 72 | 73 | for (; i < l; i++) { 74 | if (i < l - n + 2) { 75 | for (j = 0; j < n; j++) { 76 | if (i + j >= 0 && i + j < l) { 77 | *(ptr++) = tmp[i + j]; 78 | } else { 79 | *(ptr++) = '_'; 80 | } 81 | } 82 | *(ptr++) = ' '; 83 | } 84 | } 85 | free(tmp); 86 | 87 | *(--ptr) = 0; 88 | 89 | *length = ptr - start; 90 | 91 | return start; 92 | } 93 | 94 | DLLEXPORT void ngram_deinit(UDF_INIT *initid, UDF_ARGS *args, char *message) { 95 | char *ptr = (char *) initid->ptr; 96 | 97 | if (NULL != ptr) { 98 | free(ptr); 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /src/corr.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | 3 | struct Buffer { 4 | size_t n; 5 | double x; 6 | double y; 7 | double xy; 8 | double xx; 9 | double yy; 10 | }; 11 | 12 | DLLEXPORT my_bool corr_init(UDF_INIT *initid, UDF_ARGS *args, char *message) { 13 | struct Buffer *data; 14 | 15 | if (2 != args->arg_count) { 16 | snprintf(message, MYSQL_ERRMSG_SIZE, 17 | "corr must have exactly two arguments"); 18 | return 1; 19 | } 20 | 21 | args->arg_type[0] = REAL_RESULT; 22 | args->arg_type[1] = REAL_RESULT; 23 | 24 | data = calloc(1, sizeof (*data)); 25 | if (NULL == data) { 26 | snprintf(message, MYSQL_ERRMSG_SIZE, "Memory allocation failed"); 27 | return 1; 28 | } 29 | 30 | initid->decimals = NOT_FIXED_DEC; 31 | initid->maybe_null = 1; 32 | initid->ptr = (char*) data; 33 | 34 | return 0; 35 | } 36 | 37 | DLLEXPORT void corr_clear(UDF_INIT* initid, char* is_null, char *error) { 38 | struct Buffer *data = (struct Buffer *) initid->ptr; 39 | 40 | data->n = 0; 41 | data->x = 0; 42 | data->y = 0; 43 | data->xy = 0; 44 | data->xx = 0; 45 | data->yy = 0; 46 | } 47 | 48 | DLLEXPORT void corr_add(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char *error) { 49 | struct Buffer *data = (struct Buffer *) initid->ptr; 50 | 51 | if (NULL == args->args[0] || NULL == args->args[1]) 52 | return; 53 | 54 | double x = *((double *) args->args[0]); 55 | double y = *((double *) args->args[1]); 56 | 57 | data->n++; 58 | data->x += x; 59 | data->y += y; 60 | data->xy += x*y; 61 | data->xx += x*x; 62 | data->yy += y*y; 63 | } 64 | 65 | DLLEXPORT void corr_deinit(UDF_INIT *initid) { 66 | struct Buffer *data = (struct Buffer *) initid->ptr; 67 | 68 | if (NULL != data) { 69 | free(data); 70 | data = NULL; 71 | } 72 | } 73 | 74 | DLLEXPORT double corr(UDF_INIT *initid __attribute__((unused)), UDF_ARGS *args, 75 | char *is_null, 76 | char *error __attribute__((unused))) { 77 | struct Buffer *data = (struct Buffer *) initid->ptr; 78 | 79 | if (data->n == 0 || data->xx == 0 || data->yy == 0) { 80 | *is_null = 1; 81 | return 0; 82 | } 83 | 84 | /* 85 | * Corr(X, Y) = Cov(X, Y)/sqrt(D(x)D(Y)) 86 | * Cov(X, Y) = E((X - E(X))(Y - E(Y))) = E(XY) - E(X)E(Y)) 87 | * D(X) = Cov(X, X) = E(XX) - E(X)^2 88 | */ 89 | double n_inv = 1. / data->n; 90 | double cov_xy = n_inv * (data->xy - n_inv * data->x * data->y); 91 | double dx = n_inv * (data->xx - n_inv * data->x * data->x); 92 | double dy = n_inv * (data->yy - n_inv * data->y * data->y); 93 | return cov_xy / sqrt(dx * dy); 94 | } 95 | -------------------------------------------------------------------------------- /src/xround.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | 3 | DLLEXPORT my_bool xround_init(UDF_INIT *initid, UDF_ARGS *args, char *message) { 4 | if (1 != args->arg_count) { 5 | strcpy(message, "xround must have exactly one single argument"); 6 | return 1; 7 | } 8 | 9 | switch (args->arg_type[0]) { 10 | case STRING_RESULT: 11 | case DECIMAL_RESULT: 12 | args->arg_type[0] = REAL_RESULT; 13 | default: 14 | break; 15 | } 16 | initid->const_item = 1; 17 | initid->maybe_null = 0; 18 | 19 | return 0; 20 | } 21 | 22 | #define RET_NEG(s) return (((s) ^ -f) + f) 23 | 24 | DLLEXPORT longlong xround(UDF_INIT *initid __attribute__((unused)), UDF_ARGS *args, 25 | char *is_null, 26 | char *error __attribute__((unused))) { 27 | 28 | longlong n, f = 0; 29 | double d; 30 | 31 | if (NULL == args->args[0]) { 32 | *is_null = 1; 33 | return 0; 34 | } 35 | 36 | if (INT_RESULT == args->arg_type[0]) { 37 | 38 | n = *((longlong *) args->args[0]); 39 | 40 | } else { 41 | 42 | d = *((double *) args->args[0]); 43 | n = (longlong) d; 44 | 45 | n = n + (n < d) - (d < n); 46 | } 47 | 48 | if (n < 0) { 49 | n = -n; 50 | f = 1; 51 | } 52 | 53 | if (n > 1000000000LL) { 54 | 55 | if (n > 100000000000000LL) { 56 | if (n > 10000000000000000LL) { 57 | if (n <= 100000000000000000LL) RET_NEG(100000000000000000LL); 58 | if (n <= 1000000000000000000LL) RET_NEG(1000000000000000000LL); 59 | RET_NEG(1000000000000000000LL); 60 | } else { 61 | if (n <= 1000000000000000LL) RET_NEG(1000000000000000LL); 62 | RET_NEG(10000000000000000LL); 63 | } 64 | } else { 65 | if (n > 100000000000LL) { 66 | if (n <= 1000000000000LL) RET_NEG(1000000000000LL); 67 | if (n <= 10000000000000LL) RET_NEG(10000000000000LL); 68 | RET_NEG(100000000000000LL); 69 | } else { 70 | if (n <= 10000000000LL) RET_NEG(10000000000LL); 71 | RET_NEG(100000000000LL); 72 | } 73 | } 74 | } else if (n > 10000LL) { 75 | if (n > 1000000LL) { 76 | if (n <= 10000000LL) RET_NEG(10000000LL); 77 | if (n <= 100000000LL) RET_NEG(100000000LL); 78 | RET_NEG(1000000000LL); 79 | } else { 80 | if (n <= 100000LL) RET_NEG(100000LL); 81 | RET_NEG(1000000LL); 82 | } 83 | } else { 84 | if (n > 100LL) { 85 | if (n <= 1000LL) RET_NEG(1000LL); 86 | RET_NEG(10000LL); 87 | } else { 88 | if (n <= 1LL) RET_NEG(1LL); 89 | if (n <= 10LL) RET_NEG(10LL); 90 | RET_NEG(100LL); 91 | } 92 | } 93 | RET_NEG(1LL); 94 | } 95 | #undef RET_NEG 96 | -------------------------------------------------------------------------------- /src/stats_mode.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | #include "array.h" 3 | 4 | struct Buffer { 5 | struct array values; 6 | }; 7 | 8 | DLLEXPORT my_bool stats_mode_init(UDF_INIT *initid, UDF_ARGS *args, char *message) { 9 | struct Buffer *data; 10 | 11 | if (1 != args->arg_count) { 12 | snprintf(message, MYSQL_ERRMSG_SIZE, 13 | "stats_mode must have exaclty one argument"); 14 | return 1; 15 | } 16 | 17 | args->arg_type[0] = REAL_RESULT; 18 | 19 | data = calloc(1, sizeof (*data)); 20 | if (NULL == data) { 21 | snprintf(message, MYSQL_ERRMSG_SIZE, "Memory allocation failed"); 22 | return 1; 23 | } 24 | 25 | if (NULL == array_init(&data->values, sizeof (double), 32)) { 26 | snprintf(message, MYSQL_ERRMSG_SIZE, "Memory allocation failed"); 27 | return 1; 28 | } 29 | 30 | initid->decimals = NOT_FIXED_DEC; 31 | initid->maybe_null = 1; 32 | initid->ptr = (char*) data; 33 | 34 | return 0; 35 | } 36 | 37 | DLLEXPORT void stats_mode_clear(UDF_INIT* initid, char* is_null, char *error) { 38 | struct Buffer *data = (struct Buffer *) initid->ptr; 39 | array_truncate(&data->values); 40 | } 41 | 42 | DLLEXPORT void stats_mode_add(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char *error) { 43 | struct Buffer *data = (struct Buffer *) initid->ptr; 44 | 45 | if (NULL == args->args[0]) 46 | return; 47 | 48 | if (NULL == array_append(&data->values, args->args[0])) { 49 | *error = 1; 50 | return; 51 | } 52 | } 53 | 54 | DLLEXPORT void stats_mode_deinit(UDF_INIT *initid) { 55 | struct Buffer *data = (struct Buffer *) initid->ptr; 56 | if (NULL != data) { 57 | array_free(&data->values); 58 | free(data); 59 | data = NULL; 60 | } 61 | } 62 | 63 | static int compar(const void *pa, const void *pb) { 64 | double a = *((double *) pa); 65 | double b = *((double *) pb); 66 | return a > b ? 1 : (a < b ? -1 : 0); 67 | } 68 | 69 | DLLEXPORT double stats_mode(UDF_INIT *initid, UDF_ARGS *args, 70 | char *is_null, 71 | char *error __attribute__((unused))) { 72 | struct Buffer *data = (struct Buffer *) initid->ptr; 73 | 74 | if (data->values.n == 0) { 75 | *is_null = 1; 76 | return 0; 77 | } 78 | 79 | qsort(data->values.p, data->values.n, sizeof (double), compar); 80 | 81 | double mode = 0; 82 | double value = 0; 83 | size_t n = 0; 84 | size_t k = 0; 85 | size_t i = 0; 86 | 87 | for (i = 0; i < data->values.n; i++) { 88 | 89 | if (ARRAY_GET_DOUBLE(data->values, i) != value) { 90 | value = ARRAY_GET_DOUBLE(data->values, i); 91 | k = 0; 92 | } 93 | k++; 94 | if (k > n) { 95 | mode = value; 96 | n = k; 97 | } 98 | } 99 | 100 | if (n == 0) { 101 | *is_null = 1; 102 | return 0; 103 | } 104 | 105 | return mode; 106 | } 107 | -------------------------------------------------------------------------------- /src/cut.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | 3 | DLLEXPORT my_bool cut_init(UDF_INIT *initid, UDF_ARGS *args, char *message) { 4 | 5 | switch (args->arg_count) { 6 | case 3: 7 | args->arg_type[2] = STRING_RESULT; 8 | // no break 9 | case 2: 10 | args->arg_type[0] = STRING_RESULT; 11 | args->arg_type[1] = INT_RESULT; 12 | break; 13 | default: 14 | strcpy(message, "cut must have two or three arguments"); 15 | return 1; 16 | } 17 | 18 | initid->max_length = args->lengths[0]; 19 | initid->const_item = 1; 20 | initid->maybe_null = 1; 21 | initid->ptr = NULL; 22 | 23 | return 0; 24 | } 25 | 26 | DLLEXPORT char *cut(UDF_INIT *initid, UDF_ARGS *args, 27 | char *result, unsigned long *length, 28 | char *is_null, char *error __attribute__((unused))) { 29 | 30 | char *str = args->args[0], *c = "..."; 31 | long sl = args->lengths[0], cl = 3, max = *((longlong *) args->args[1]), i; 32 | 33 | int space = -1, p = 0, len = 0; 34 | 35 | 36 | if (3 == args->arg_count && NULL != args->args[2]) { 37 | c = args->args[2]; 38 | cl = args->lengths[2]; 39 | } 40 | 41 | if (NULL == str) { 42 | *is_null = 1; 43 | return result; 44 | } 45 | 46 | for (; p < sl; len++) { 47 | 48 | const unsigned char c = str[p]; 49 | 50 | switch (c) { 51 | case ' ': 52 | case '\t': 53 | case '\n': 54 | case '\r': 55 | space = p; 56 | } 57 | 58 | if (len == max) { 59 | break; 60 | } 61 | 62 | if ((c & 0x80) == 0) 63 | p += 1; 64 | else if ((c & 0xE0) == 0xC0) 65 | p += 2; 66 | else if ((c & 0xF0) == 0xE0) 67 | p += 3; 68 | else if ((c & 0xF8) == 0xF0) 69 | p += 4; 70 | else { 71 | // Broken UTF8 72 | *is_null = 1; 73 | return result; 74 | } 75 | } 76 | 77 | // Calculate alloc size 78 | int tmp_p = p; // Needed to check if resulting string is same as the original => omit ... 79 | int mem_size = p; 80 | char *ptr = result; 81 | if (len == max && tmp_p != sl) { 82 | 83 | if (space != -1) { 84 | p = mem_size = space; 85 | } 86 | mem_size += cl; 87 | } 88 | 89 | // Alloc new memory if needed 90 | if (mem_size >= 254) { 91 | 92 | if (NULL == (ptr = malloc(mem_size + 1))) { 93 | *is_null = 1; 94 | return result; 95 | } else { 96 | initid->ptr = ptr; 97 | } 98 | } 99 | 100 | // Copy argument 101 | memcpy(ptr, str, p); 102 | 103 | // Append dots 104 | if (len == max && tmp_p != sl) { 105 | memcpy(ptr + p, c, cl); 106 | } 107 | 108 | ptr[mem_size] = 0; 109 | *length = mem_size; 110 | 111 | return ptr; 112 | } 113 | 114 | DLLEXPORT void cut_deinit(UDF_INIT *initid, UDF_ARGS *args, char *message) { 115 | char *ptr = (char *) initid->ptr; 116 | 117 | if (NULL != ptr) { 118 | free(ptr); 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /load.win.sql: -------------------------------------------------------------------------------- 1 | USE mysql; 2 | 3 | DROP FUNCTION IF EXISTS bound; 4 | DROP FUNCTION IF EXISTS bround; 5 | DROP FUNCTION IF EXISTS corr; 6 | DROP FUNCTION IF EXISTS covariance; 7 | DROP FUNCTION IF EXISTS cut; 8 | DROP FUNCTION IF EXISTS fnv; 9 | DROP FUNCTION IF EXISTS getint; 10 | DROP FUNCTION IF EXISTS group_first; 11 | DROP FUNCTION IF EXISTS group_last; 12 | DROP FUNCTION IF EXISTS invbit; 13 | DROP FUNCTION IF EXISTS isbit; 14 | DROP FUNCTION IF EXISTS kurtosis; 15 | DROP FUNCTION IF EXISTS lessavg; 16 | DROP FUNCTION IF EXISTS lesspartpct; 17 | DROP FUNCTION IF EXISTS lesspart; 18 | DROP FUNCTION IF EXISTS median; 19 | DROP FUNCTION IF EXISTS stats_mode; 20 | DROP FUNCTION IF EXISTS ngram; 21 | DROP FUNCTION IF EXISTS noverk; 22 | DROP FUNCTION IF EXISTS percentile_cont; 23 | DROP FUNCTION IF EXISTS percentile_disc; 24 | DROP FUNCTION IF EXISTS rotbit; 25 | DROP FUNCTION IF EXISTS rotint; 26 | DROP FUNCTION IF EXISTS rsumd; 27 | DROP FUNCTION IF EXISTS rsumi; 28 | DROP FUNCTION IF EXISTS setbit; 29 | DROP FUNCTION IF EXISTS setint; 30 | DROP FUNCTION IF EXISTS skewness; 31 | DROP FUNCTION IF EXISTS slug; 32 | DROP FUNCTION IF EXISTS xround; 33 | 34 | CREATE FUNCTION bound RETURNS real SONAME 'udf_infusion.dll'; 35 | CREATE FUNCTION bround RETURNS real SONAME 'udf_infusion.dll'; 36 | CREATE AGGREGATE FUNCTION corr RETURNS real SONAME 'udf_infusion.dll'; 37 | CREATE AGGREGATE FUNCTION covariance RETURNS real SONAME 'udf_infusion.dll'; 38 | CREATE FUNCTION cut RETURNS string SONAME 'udf_infusion.dll'; 39 | CREATE FUNCTION fnv RETURNS integer SONAME 'udf_infusion.dll'; 40 | CREATE FUNCTION getint RETURNS integer SONAME 'udf_infusion.dll'; 41 | CREATE AGGREGATE FUNCTION group_first RETURNS string SONAME 'udf_infusion.dll'; 42 | CREATE AGGREGATE FUNCTION group_last RETURNS string SONAME 'udf_infusion.dll'; 43 | CREATE FUNCTION invbit RETURNS integer SONAME 'udf_infusion.dll'; 44 | CREATE FUNCTION isbit RETURNS integer SONAME 'udf_infusion.dll'; 45 | CREATE AGGREGATE FUNCTION kurtosis RETURNS real SONAME 'udf_infusion.dll'; 46 | CREATE AGGREGATE FUNCTION lessavg RETURNS integer SONAME 'udf_infusion.dll'; 47 | CREATE AGGREGATE FUNCTION lesspartpct RETURNS integer SONAME 'udf_infusion.dll'; 48 | CREATE AGGREGATE FUNCTION lesspart RETURNS integer SONAME 'udf_infusion.dll'; 49 | CREATE AGGREGATE FUNCTION median RETURNS real SONAME 'udf_infusion.dll'; 50 | CREATE AGGREGATE FUNCTION stats_mode RETURNS real SONAME 'udf_infusion.dll'; 51 | CREATE FUNCTION ngram RETURNS string SONAME 'udf_infusion.dll'; 52 | CREATE FUNCTION noverk RETURNS integer SONAME 'udf_infusion.dll'; 53 | CREATE AGGREGATE FUNCTION percentile_cont RETURNS real SONAME 'udf_infusion.dll'; 54 | CREATE AGGREGATE FUNCTION percentile_disc RETURNS real SONAME 'udf_infusion.dll'; 55 | CREATE FUNCTION rotbit RETURNS integer SONAME 'udf_infusion.dll'; 56 | CREATE FUNCTION rotint RETURNS integer SONAME 'udf_infusion.dll'; 57 | CREATE FUNCTION rsumd RETURNS real SONAME 'udf_infusion.dll'; 58 | CREATE FUNCTION rsumi RETURNS integer SONAME 'udf_infusion.dll'; 59 | CREATE FUNCTION setbit RETURNS integer SONAME 'udf_infusion.dll'; 60 | CREATE FUNCTION setint RETURNS integer SONAME 'udf_infusion.dll'; 61 | CREATE AGGREGATE FUNCTION skewness RETURNS real SONAME 'udf_infusion.dll'; 62 | CREATE FUNCTION slug RETURNS string SONAME 'udf_infusion.dll'; 63 | CREATE FUNCTION xround RETURNS integer SONAME 'udf_infusion.dll'; 64 | -------------------------------------------------------------------------------- /README.win_x64.txt: -------------------------------------------------------------------------------- 1 | This is a build of version 1.0 of udf_infusion for 64-bit MySQL 5.1+. 2 | It is licensed under the terms of the GNU General Public License 3 | version 2. See the LICENSE file. 4 | 5 | IMPORTANT NOTE: If you are running 32-bit MySQL, then you need the 32-bit version 6 | of udf_infusion, not the 64-bit version. 7 | 8 | All source code for this project is downloadable from GitHub: 9 | https://github.com/infusion/udf_infusion 10 | 11 | 12 | INSTALLATION 13 | ================================================================================ 14 | To install the udf_infusion UDFs: 15 | 16 | 1. Make sure that you are running 64-bit Windows and that you have installed 17 | the 64-bit build of MySQL 5.1 or later. 18 | 19 | Note: The udf_infusion.dll binary has only been tested with MySQL version 20 | 5.7, but should work with MySQL 5.6, 5.5, 5.1 and 5.0 as well. It is, however, 21 | incompatible with MySQL 3.23/4.0/4.1. 22 | 23 | 2. Look for a file named msvcr120.dll in your System32 folder. If this file is 24 | not present, then install the latest Visual C++ Redistributable for Visual Studio 2013 25 | vcredist_x64.exe: 26 | https://www.microsoft.com/en-us/download/details.aspx?id=40784 27 | 28 | 3. Copy udf_infusion.dll to the MySQL installation's lib\plugin folder. 29 | 30 | With a default installation, this is C:\Program Files\MySQL\MySQL Server 5.7\lib\plugin\ 31 | 32 | Note: You do NOT need to re-start MySQL after copying udf_infusion.dll 33 | into the plugin directory. 34 | 35 | 4. As root, source load.win.sql or simply paste the contents into the CLI client. 36 | 37 | 38 | TROUBLESHOOTING 39 | ================================================================================ 40 | * ERROR 1126 (HY000): Can't open shared library 'udf_infusion' (errno: 0 ) 41 | Or, 42 | ERROR 1126 (HY000): Can't open shared library 'udf_infusion.dll' (errno: 126 The specified module could not be found.) 43 | 44 | This either means that the Visual C++ Redistributable for Visual Studio 2013 45 | is not installed or that MySQL could not find udf_infusion.dll in the 46 | plugin directory. 47 | 48 | Look for a file named msvcr120.dll in your System32 folder. If this file is 49 | not present, then install the latest Visual C++ Redistributable for Visual Studio 2013 50 | vcredist_x64.exe. 51 | 52 | Verify that udf_infusion.dll was copied into the plugin directory by 53 | executing: 54 | SHOW VARIABLES LIKE 'plugin_dir'; 55 | 56 | The result should be: 57 | +---------------+-----------------------------------------------------+ 58 | | Variable_name | Value | 59 | +---------------+-----------------------------------------------------+ 60 | | plugin_dir | C:\Program Files\MySQL\MySQL Server 5.7\lib\plugin\ | 61 | +---------------+-----------------------------------------------------+ 62 | 63 | If it's not, then copy udf_infusion.dll to the listed directory. 64 | 65 | * ERROR 1126 (HY000): Can't open shared library 'udf_infusion.dll' (errno: 193 ) 66 | 67 | This error can happen when you try to use the 64-bit version of udf_infusion 68 | with a 32-bit MySQL server. Either use the 32-bit version of udf_infusion 69 | or install 64-bit MySQL. 70 | 71 | * ERROR 1127 (HY000): Can't find symbol in library 72 | 73 | This means that MySQL was able to find udf_infusion.dll, but for some 74 | reason, it could not "see" the UDF in the DLL module. 75 | 76 | If you are typing the CREATE FUNCTION statements manually, make sure that 77 | you have typed the UDF name exactly as listed in load.win.sql. For example, 78 | instead of "GROUP_FIRST", you must type "group_first" (all lowercase). 79 | 80 | 81 | If you encounter any other problem, please feel free to contact me at: 82 | dtrebbien@gmail.com 83 | -------------------------------------------------------------------------------- /README.win_x86.txt: -------------------------------------------------------------------------------- 1 | This is a build of version 1.0 of udf_infusion for 32-bit MySQL 5.1+. 2 | It is licensed under the terms of the GNU General Public License 3 | version 2. See the LICENSE file. 4 | 5 | All source code for this project is downloadable from GitHub: 6 | https://github.com/infusion/udf_infusion 7 | 8 | 9 | INSTALLATION 10 | ================================================================================ 11 | To install the udf_infusion UDFs: 12 | 13 | 1. Make sure that you have installed the 32-bit build of MySQL 5.1 or later. 14 | 15 | Note: The udf_infusion.dll binary has only been tested with MySQL version 16 | 5.7, but should work with MySQL 5.6, 5.5, 5.1 and 5.0 as well. It is, however, 17 | incompatible with MySQL 3.23/4.0/4.1. 18 | 19 | 2. Look for a file named msvcr120.dll in your System32 folder (on a 64-bit Windows 20 | machine, look for this file in the SysWOW64 folder instead). If this file is 21 | not present, then install the latest Visual C++ Redistributable for Visual Studio 2013 22 | vcredist_x86.exe: 23 | https://www.microsoft.com/en-us/download/details.aspx?id=40784 24 | 25 | 3. Copy udf_infusion.dll to the MySQL installation's lib\plugin folder. 26 | 27 | With a default installation, this is C:\Program Files\MySQL\MySQL Server 5.7\lib\plugin\ 28 | 29 | Note: You do NOT need to re-start MySQL after copying udf_infusion.dll 30 | into the plugin directory. 31 | 32 | 4. As root, source load.win.sql or simply paste the contents into the CLI client. 33 | 34 | 35 | TROUBLESHOOTING 36 | ================================================================================ 37 | * ERROR 1126 (HY000): Can't open shared library 'udf_infusion' (errno: 0 ) 38 | Or, 39 | ERROR 1126 (HY000): Can't open shared library 'udf_infusion.dll' (errno: 126 The specified module could not be found.) 40 | 41 | This either means that the Visual C++ Redistributable for Visual Studio 2013 42 | is not installed or that MySQL could not find udf_infusion.dll in the 43 | plugin directory. 44 | 45 | Look for a file named msvcr120.dll in your System32 folder. If this file is 46 | not present, then install the latest Visual C++ Redistributable for Visual Studio 2013 47 | vcredist_x86.exe. 48 | 49 | Verify that udf_infusion.dll was copied into the plugin directory by 50 | executing: 51 | SHOW VARIABLES LIKE 'plugin_dir'; 52 | 53 | The result should be: 54 | +---------------+-----------------------------------------------------+ 55 | | Variable_name | Value | 56 | +---------------+-----------------------------------------------------+ 57 | | plugin_dir | C:\Program Files\MySQL\MySQL Server 5.7\lib\plugin\ | 58 | +---------------+-----------------------------------------------------+ 59 | 60 | If it's not, then copy udf_infusion.dll to the listed directory. 61 | 62 | * ERROR 1126 (HY000): Can't open shared library 'udf_infusion.dll' (errno: 126 ) 63 | 64 | This error can happen when you don't have the 32-bit Visual C++ Redistributable for Visual Studio 2013 65 | installed. 66 | 67 | On a 64-bit Windows machine, look for a file named msvcr120.dll in the 68 | SysWOW64 folder. You need to install vcredist_x86.exe from https://www.microsoft.com/en-us/download/details.aspx?id=40784 69 | 70 | * ERROR 1126 (HY000): Can't open shared library 'udf_infusion.dll' (errno: 193 ) 71 | 72 | This error can happen when you try to use the 32-bit version of udf_infusion 73 | with a 64-bit MySQL server. Either use the 64-bit version of udf_infusion 74 | or install 32-bit MySQL. 75 | 76 | * ERROR 1127 (HY000): Can't find symbol in library 77 | 78 | This means that MySQL was able to find udf_infusion.dll, but for some 79 | reason, it could not "see" the UDF in the DLL module. 80 | 81 | If you are typing the CREATE FUNCTION statements manually, make sure that 82 | you have typed the UDF name exactly as listed in load.win.sql. For example, 83 | instead of "GROUP_FIRST", you must type "group_first" (all lowercase). 84 | 85 | 86 | If you encounter any other problem, please feel free to contact me at: 87 | dtrebbien@gmail.com 88 | -------------------------------------------------------------------------------- /udf_infusion.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | Source Files 23 | 24 | 25 | Source Files 26 | 27 | 28 | Source Files 29 | 30 | 31 | Source Files 32 | 33 | 34 | Source Files 35 | 36 | 37 | Source Files 38 | 39 | 40 | Source Files 41 | 42 | 43 | Source Files 44 | 45 | 46 | Source Files 47 | 48 | 49 | Source Files 50 | 51 | 52 | Source Files 53 | 54 | 55 | Source Files 56 | 57 | 58 | Source Files 59 | 60 | 61 | Source Files 62 | 63 | 64 | Source Files 65 | 66 | 67 | Source Files 68 | 69 | 70 | Source Files 71 | 72 | 73 | Source Files 74 | 75 | 76 | Source Files 77 | 78 | 79 | Source Files 80 | 81 | 82 | Source Files 83 | 84 | 85 | Source Files 86 | 87 | 88 | Source Files 89 | 90 | 91 | Source Files 92 | 93 | 94 | Source Files 95 | 96 | 97 | Source Files 98 | 99 | 100 | Source Files 101 | 102 | 103 | Source Files 104 | 105 | 106 | Source Files 107 | 108 | 109 | Source Files 110 | 111 | 112 | Source Files 113 | 114 | 115 | Source Files 116 | 117 | 118 | 119 | 120 | Header Files 121 | 122 | 123 | Header Files 124 | 125 | 126 | Header Files 127 | 128 | 129 | 130 | -------------------------------------------------------------------------------- /m4/ltsugar.m4: -------------------------------------------------------------------------------- 1 | # ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*- 2 | # 3 | # Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc. 4 | # Written by Gary V. Vaughan, 2004 5 | # 6 | # This file is free software; the Free Software Foundation gives 7 | # unlimited permission to copy and/or distribute it, with or without 8 | # modifications, as long as this notice is preserved. 9 | 10 | # serial 6 ltsugar.m4 11 | 12 | # This is to help aclocal find these macros, as it can't see m4_define. 13 | AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])]) 14 | 15 | 16 | # lt_join(SEP, ARG1, [ARG2...]) 17 | # ----------------------------- 18 | # Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their 19 | # associated separator. 20 | # Needed until we can rely on m4_join from Autoconf 2.62, since all earlier 21 | # versions in m4sugar had bugs. 22 | m4_define([lt_join], 23 | [m4_if([$#], [1], [], 24 | [$#], [2], [[$2]], 25 | [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])]) 26 | m4_define([_lt_join], 27 | [m4_if([$#$2], [2], [], 28 | [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])]) 29 | 30 | 31 | # lt_car(LIST) 32 | # lt_cdr(LIST) 33 | # ------------ 34 | # Manipulate m4 lists. 35 | # These macros are necessary as long as will still need to support 36 | # Autoconf-2.59 which quotes differently. 37 | m4_define([lt_car], [[$1]]) 38 | m4_define([lt_cdr], 39 | [m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])], 40 | [$#], 1, [], 41 | [m4_dquote(m4_shift($@))])]) 42 | m4_define([lt_unquote], $1) 43 | 44 | 45 | # lt_append(MACRO-NAME, STRING, [SEPARATOR]) 46 | # ------------------------------------------ 47 | # Redefine MACRO-NAME to hold its former content plus `SEPARATOR'`STRING'. 48 | # Note that neither SEPARATOR nor STRING are expanded; they are appended 49 | # to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked). 50 | # No SEPARATOR is output if MACRO-NAME was previously undefined (different 51 | # than defined and empty). 52 | # 53 | # This macro is needed until we can rely on Autoconf 2.62, since earlier 54 | # versions of m4sugar mistakenly expanded SEPARATOR but not STRING. 55 | m4_define([lt_append], 56 | [m4_define([$1], 57 | m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])]) 58 | 59 | 60 | 61 | # lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...]) 62 | # ---------------------------------------------------------- 63 | # Produce a SEP delimited list of all paired combinations of elements of 64 | # PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list 65 | # has the form PREFIXmINFIXSUFFIXn. 66 | # Needed until we can rely on m4_combine added in Autoconf 2.62. 67 | m4_define([lt_combine], 68 | [m4_if(m4_eval([$# > 3]), [1], 69 | [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl 70 | [[m4_foreach([_Lt_prefix], [$2], 71 | [m4_foreach([_Lt_suffix], 72 | ]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[, 73 | [_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])]) 74 | 75 | 76 | # lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ]) 77 | # ----------------------------------------------------------------------- 78 | # Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited 79 | # by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ. 80 | m4_define([lt_if_append_uniq], 81 | [m4_ifdef([$1], 82 | [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1], 83 | [lt_append([$1], [$2], [$3])$4], 84 | [$5])], 85 | [lt_append([$1], [$2], [$3])$4])]) 86 | 87 | 88 | # lt_dict_add(DICT, KEY, VALUE) 89 | # ----------------------------- 90 | m4_define([lt_dict_add], 91 | [m4_define([$1($2)], [$3])]) 92 | 93 | 94 | # lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE) 95 | # -------------------------------------------- 96 | m4_define([lt_dict_add_subkey], 97 | [m4_define([$1($2:$3)], [$4])]) 98 | 99 | 100 | # lt_dict_fetch(DICT, KEY, [SUBKEY]) 101 | # ---------------------------------- 102 | m4_define([lt_dict_fetch], 103 | [m4_ifval([$3], 104 | m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]), 105 | m4_ifdef([$1($2)], [m4_defn([$1($2)])]))]) 106 | 107 | 108 | # lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE]) 109 | # ----------------------------------------------------------------- 110 | m4_define([lt_if_dict_fetch], 111 | [m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4], 112 | [$5], 113 | [$6])]) 114 | 115 | 116 | # lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...]) 117 | # -------------------------------------------------------------- 118 | m4_define([lt_dict_filter], 119 | [m4_if([$5], [], [], 120 | [lt_join(m4_quote(m4_default([$4], [[, ]])), 121 | lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]), 122 | [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl 123 | ]) 124 | -------------------------------------------------------------------------------- /m4/ax_lib_mysql.m4: -------------------------------------------------------------------------------- 1 | ##### http://autoconf-archive.cryp.to/ax_lib_mysql.html 2 | # 3 | # SYNOPSIS 4 | # 5 | # AX_LIB_MYSQL([MINIMUM-VERSION]) 6 | # 7 | # DESCRIPTION 8 | # 9 | # This macro provides tests of availability of MySQL client library 10 | # of particular version or newer. 11 | # 12 | # AX_LIB_MYSQL macro takes only one argument which is optional. If 13 | # there is no required version passed, then macro does not run 14 | # version test. 15 | # 16 | # The --with-mysql option takes one of three possible values: 17 | # 18 | # no - do not check for MySQL client library 19 | # 20 | # yes - do check for MySQL library in standard locations 21 | # (mysql_config should be in the PATH) 22 | # 23 | # path - complete path to mysql_config utility, use this option if 24 | # mysql_config can't be found in the PATH 25 | # 26 | # This macro calls: 27 | # 28 | # AC_SUBST(MYSQL_CFLAGS) 29 | # AC_SUBST(MYSQL_LDFLAGS) 30 | # AC_SUBST(MYSQL_VERSION) 31 | # AC_SUBST(MYSQL_PLUGINDIR) 32 | # 33 | # And sets: 34 | # 35 | # HAVE_MYSQL 36 | # 37 | # LAST MODIFICATION 38 | # 39 | # 2006-07-16 40 | # 41 | # COPYLEFT 42 | # 43 | # Copyright (c) 2006 Mateusz Loskot 44 | # 45 | # Copying and distribution of this file, with or without 46 | # modification, are permitted in any medium without royalty provided 47 | # the copyright notice and this notice are preserved. 48 | 49 | AC_DEFUN([AX_LIB_MYSQL], 50 | [ 51 | AC_ARG_WITH([mysql], 52 | AC_HELP_STRING([--with-mysql=@<:@ARG@:>@], 53 | [use MySQL client library @<:@default=yes@:>@, optionally specify path to mysql_config] 54 | ), 55 | [ 56 | if test "$withval" = "no"; then 57 | want_mysql="no" 58 | elif test "$withval" = "yes"; then 59 | want_mysql="yes" 60 | else 61 | want_mysql="yes" 62 | MYSQL_CONFIG="$withval" 63 | fi 64 | ], 65 | [want_mysql="yes"] 66 | ) 67 | 68 | MYSQL_CFLAGS="" 69 | MYSQL_LDFLAGS="" 70 | MYSQL_VERSION="" 71 | MYSQL_PLUGINDIR="" 72 | 73 | dnl 74 | dnl Check MySQL libraries (libpq) 75 | dnl 76 | 77 | if test "$want_mysql" = "yes"; then 78 | 79 | if test -z "$MYSQL_CONFIG" -o test; then 80 | AC_PATH_PROG([MYSQL_CONFIG], [mysql_config], [no]) 81 | fi 82 | 83 | if test "$MYSQL_CONFIG" != "no"; then 84 | AC_MSG_CHECKING([for MySQL libraries]) 85 | 86 | MYSQL_CFLAGS="`$MYSQL_CONFIG --cflags`" 87 | MYSQL_LDFLAGS="`$MYSQL_CONFIG --libs`" 88 | 89 | MYSQL_VERSION=`$MYSQL_CONFIG --version` 90 | if $MYSQL_CONFIG --plugindir > /dev/null; then 91 | MYSQL_PLUGINDIR=`$MYSQL_CONFIG --plugindir` 92 | fi 93 | 94 | AC_DEFINE([HAVE_MYSQL], [1], 95 | [Define to 1 if MySQL libraries are available]) 96 | 97 | found_mysql="yes" 98 | AC_MSG_RESULT([yes]) 99 | m4_ifval($2,$2) 100 | else 101 | found_mysql="no" 102 | AC_MSG_RESULT([no]) 103 | m4_ifval($3,$3) 104 | fi 105 | fi 106 | 107 | dnl 108 | dnl Check if required version of MySQL is available 109 | dnl 110 | 111 | 112 | mysql_version_req=ifelse([$1], [], [], [$1]) 113 | 114 | if test "$found_mysql" = "yes" -a -n "$mysql_version_req"; then 115 | 116 | AC_MSG_CHECKING([if MySQL version is >= $mysql_version_req]) 117 | 118 | dnl Decompose required version string of MySQL 119 | dnl and calculate its number representation 120 | mysql_version_req_major=`expr $mysql_version_req : '\([[0-9]]*\)'` 121 | mysql_version_req_minor=`expr $mysql_version_req : '[[0-9]]*\.\([[0-9]]*\)'` 122 | mysql_version_req_micro=`expr $mysql_version_req : '[[0-9]]*\.[[0-9]]*\.\([[0-9]]*\)'` 123 | if test "x$mysql_version_req_micro" = "x"; then 124 | mysql_version_req_micro="0" 125 | fi 126 | 127 | mysql_version_req_number=`expr $mysql_version_req_major \* 1000000 \ 128 | \+ $mysql_version_req_minor \* 1000 \ 129 | \+ $mysql_version_req_micro` 130 | 131 | dnl Decompose version string of installed MySQL 132 | dnl and calculate its number representation 133 | mysql_version_major=`expr $MYSQL_VERSION : '\([[0-9]]*\)'` 134 | mysql_version_minor=`expr $MYSQL_VERSION : '[[0-9]]*\.\([[0-9]]*\)'` 135 | mysql_version_micro=`expr $MYSQL_VERSION : '[[0-9]]*\.[[0-9]]*\.\([[0-9]]*\)'` 136 | if test "x$mysql_version_micro" = "x"; then 137 | mysql_version_micro="0" 138 | fi 139 | 140 | mysql_version_number=`expr $mysql_version_major \* 1000000 \ 141 | \+ $mysql_version_minor \* 1000 \ 142 | \+ $mysql_version_micro` 143 | 144 | mysql_version_check=`expr $mysql_version_number \>\= $mysql_version_req_number` 145 | if test "$mysql_version_check" = "1"; then 146 | AC_MSG_RESULT([yes]) 147 | m4_ifval($2,$2) 148 | else 149 | AC_MSG_RESULT([no]) 150 | m4_ifval($3,$3) 151 | fi 152 | fi 153 | 154 | AC_SUBST([MYSQL_VERSION]) 155 | AC_SUBST([MYSQL_CFLAGS]) 156 | AC_SUBST([MYSQL_LDFLAGS]) 157 | AC_SUBST([MYSQL_PLUGINDIR]) 158 | ]) 159 | -------------------------------------------------------------------------------- /m4/lt~obsolete.m4: -------------------------------------------------------------------------------- 1 | # lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*- 2 | # 3 | # Copyright (C) 2004, 2005, 2007, 2009 Free Software Foundation, Inc. 4 | # Written by Scott James Remnant, 2004. 5 | # 6 | # This file is free software; the Free Software Foundation gives 7 | # unlimited permission to copy and/or distribute it, with or without 8 | # modifications, as long as this notice is preserved. 9 | 10 | # serial 5 lt~obsolete.m4 11 | 12 | # These exist entirely to fool aclocal when bootstrapping libtool. 13 | # 14 | # In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN) 15 | # which have later been changed to m4_define as they aren't part of the 16 | # exported API, or moved to Autoconf or Automake where they belong. 17 | # 18 | # The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN 19 | # in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us 20 | # using a macro with the same name in our local m4/libtool.m4 it'll 21 | # pull the old libtool.m4 in (it doesn't see our shiny new m4_define 22 | # and doesn't know about Autoconf macros at all.) 23 | # 24 | # So we provide this file, which has a silly filename so it's always 25 | # included after everything else. This provides aclocal with the 26 | # AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything 27 | # because those macros already exist, or will be overwritten later. 28 | # We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. 29 | # 30 | # Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here. 31 | # Yes, that means every name once taken will need to remain here until 32 | # we give up compatibility with versions before 1.7, at which point 33 | # we need to keep only those names which we still refer to. 34 | 35 | # This is to help aclocal find these macros, as it can't see m4_define. 36 | AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])]) 37 | 38 | m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])]) 39 | m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])]) 40 | m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])]) 41 | m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])]) 42 | m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])]) 43 | m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])]) 44 | m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])]) 45 | m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])]) 46 | m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])]) 47 | m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])]) 48 | m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])]) 49 | m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])]) 50 | m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])]) 51 | m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])]) 52 | m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])]) 53 | m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])]) 54 | m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])]) 55 | m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])]) 56 | m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])]) 57 | m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])]) 58 | m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])]) 59 | m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])]) 60 | m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])]) 61 | m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])]) 62 | m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])]) 63 | m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])]) 64 | m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])]) 65 | m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])]) 66 | m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])]) 67 | m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])]) 68 | m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])]) 69 | m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])]) 70 | m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])]) 71 | m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])]) 72 | m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])]) 73 | m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])]) 74 | m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])]) 75 | m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])]) 76 | m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])]) 77 | m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])]) 78 | m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])]) 79 | m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])]) 80 | m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])]) 81 | m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])]) 82 | m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])]) 83 | m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])]) 84 | m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])]) 85 | m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])]) 86 | m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])]) 87 | m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])]) 88 | m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])]) 89 | m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])]) 90 | m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])]) 91 | m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])]) 92 | m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS], [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])]) 93 | m4_ifndef([_LT_AC_PROG_CXXCPP], [AC_DEFUN([_LT_AC_PROG_CXXCPP])]) 94 | m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS], [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])]) 95 | m4_ifndef([_LT_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])]) 96 | m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])]) 97 | m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])]) 98 | m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])]) 99 | -------------------------------------------------------------------------------- /src/common.h: -------------------------------------------------------------------------------- 1 | #ifndef COMMON_H 2 | #define COMMON_H 3 | 4 | #ifdef _MSC_VER 5 | #define DLLEXPORT __declspec(dllexport) 6 | #define __attribute__(x) 7 | #ifndef __cplusplus 8 | #define inline __inline 9 | #endif 10 | #define snprintf _snprintf 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | /* 17 | http://pubs.opengroup.org/onlinepubs/9699919799/functions/strndup.html 18 | */ 19 | inline static char * strndup(const char *s, size_t n) 20 | { 21 | char *result; 22 | size_t len; 23 | 24 | len = strlen(s); 25 | if (n < len) { 26 | len = n; 27 | } 28 | #ifdef __cplusplus 29 | result = static_cast(malloc(len + 1)); 30 | #else 31 | result = malloc(len + 1); 32 | #endif 33 | if (!result) { 34 | return 0; 35 | } 36 | memcpy(result, s, len); 37 | result[len] = '\0'; 38 | return result; 39 | } 40 | #else /* _MSC_VER */ 41 | #define DLLEXPORT 42 | #endif /* _MSC_VER */ 43 | 44 | #ifdef STANDARD 45 | /* STANDARD is defined, don't use any mysql functions */ 46 | #include 47 | #include 48 | #include 49 | #include 50 | #if defined(__WIN__) || defined(_WIN32) 51 | typedef unsigned __int64 ulonglong; /* Microsofts 64 bit types */ 52 | typedef __int64 longlong; 53 | #else 54 | typedef unsigned long long ulonglong; 55 | typedef long long longlong; 56 | #endif /* defined(__WIN__) || defined(_WIN32) */ 57 | #else 58 | #include 59 | #include 60 | #if defined(MYSQL_SERVER) 61 | #include /* To get strmov() */ 62 | #else 63 | /* when compiled as standalone */ 64 | #include 65 | #define strmov(a,b) stpcpy(a,b) 66 | #define bzero(a,b) memset(a,0,b) 67 | #define memcpy_fixed(a,b,c) memcpy(a,b,c) 68 | #endif 69 | #endif 70 | #include 71 | #include 72 | 73 | #ifndef NOT_FIXED_DEC 74 | #define NOT_FIXED_DEC 31 75 | #endif 76 | 77 | #if MYSQL_VERSION_ID >= 80001 78 | #ifdef __cplusplus 79 | #ifndef MARIADB_VERSION_ID 80 | typedef bool my_bool; 81 | #endif 82 | #else 83 | typedef char my_bool; 84 | #endif 85 | #endif 86 | 87 | #ifdef __cplusplus 88 | extern "C" { 89 | #endif 90 | 91 | struct DoubleBuffer { 92 | unsigned long used; 93 | unsigned long size; 94 | double *number; 95 | double sum; 96 | }; 97 | 98 | struct StatBuffer { 99 | unsigned long count; 100 | double mean; 101 | double M2; 102 | double M3; 103 | double M4; 104 | }; 105 | 106 | extern char *_translate_string(UDF_ARGS *, char *, unsigned long *, char); 107 | extern double _quantile(double *, size_t, double); 108 | extern double _quantile_disc(double *, size_t, size_t); 109 | 110 | 111 | #define LESSSIZE() \ 112 | if (data->size == data->used) { \ 113 | data->size<<= 1; \ 114 | data->number = (double *) realloc(data->number, data->size * sizeof(*(data->number))); \ 115 | if (NULL == data->number) { \ 116 | *error = 1; \ 117 | return; \ 118 | } \ 119 | } 120 | 121 | #define LESSINIT() \ 122 | \ 123 | if (NULL == (data = malloc(sizeof (*data)))) { \ 124 | strcpy(message, "Memory allocation failed"); \ 125 | return 1; \ 126 | } \ 127 | data->used = 0; \ 128 | data->sum = 0; \ 129 | data->size = 32; \ 130 | data->number = (double *) malloc(data->size * sizeof(*(data->number))); \ 131 | if (NULL == data->number) { \ 132 | strcpy(message, "Memory allocation failed"); \ 133 | return 1; \ 134 | } \ 135 | \ 136 | initid->maybe_null = 1; \ 137 | initid->ptr = (char*) data 138 | 139 | #define LESSCLEAR() \ 140 | struct DoubleBuffer *data = (struct DoubleBuffer *) initid->ptr; \ 141 | \ 142 | data->used = 0 143 | 144 | 145 | #define LESSADD() \ 146 | struct DoubleBuffer *data = (struct DoubleBuffer *) initid->ptr; \ 147 | double value = *((double*)args->args[0]); \ 148 | \ 149 | unsigned int s = doubleSlot(data, value, 0, data->used - 1); \ 150 | \ 151 | if (NULL == args->args[0]) \ 152 | return; \ 153 | \ 154 | LESSSIZE(); \ 155 | \ 156 | switch (type) { \ 157 | case 1: \ 158 | data->sum = data->sum + value; \ 159 | break; \ 160 | } \ 161 | \ 162 | doublePush(data, s, value); \ 163 | data->used++ 164 | 165 | 166 | #define LESSDEINIT() \ 167 | struct DoubleBuffer *data = (struct DoubleBuffer *) initid->ptr; \ 168 | \ 169 | if (NULL != data->number) { \ 170 | free(data->number); \ 171 | } \ 172 | \ 173 | if (NULL != data) { \ 174 | free(data); \ 175 | } 176 | 177 | 178 | #define LESS() \ 179 | do { \ 180 | psum+= data->number[count]; \ 181 | \ 182 | if (psum < limit) { \ 183 | count++; \ 184 | \ 185 | if (count >= data->used) \ 186 | break; \ 187 | \ 188 | continue; \ 189 | } \ 190 | break; \ 191 | \ 192 | } while (1) 193 | 194 | inline static unsigned int doubleSlot(struct DoubleBuffer *buffer, double value, int m, int n) { 195 | 196 | double *data = buffer->number; 197 | 198 | unsigned int i; 199 | 200 | if (0 == buffer->used) { 201 | return 0; 202 | } 203 | 204 | // TODO: Use binary search 205 | 206 | if (value >= data[buffer->used - 1]) { 207 | return buffer->used; 208 | } 209 | 210 | if (value <= data[0]) { 211 | return 0; 212 | } 213 | 214 | for (i = 0; i < buffer->used - 1; i++) { 215 | 216 | if (data[i] <= value && value <= data[1 + i]) { 217 | return i + 1; 218 | } 219 | } 220 | return buffer->used; 221 | } 222 | 223 | inline static void doublePush(struct DoubleBuffer *buffer, unsigned int step, double value) { 224 | 225 | double *data = buffer->number; 226 | 227 | /* About zero length of memmove() 228 | 7.21.1.2 229 | "Where an argument declared as size_t n specifies the length of the array 230 | for a function, n can have the value zero on a call to that function. 231 | Unless explicitly stated otherwise in the description of a particular 232 | function in this subclause, pointer arguments on such a call shall still 233 | have valid values, as described in 7.1.4." 234 | */ 235 | memmove(&data[1 + step], &data[step], sizeof (*data) * (buffer->used - step)); 236 | 237 | data[step] = value; 238 | } 239 | 240 | #ifdef __cplusplus 241 | } 242 | #endif 243 | 244 | #endif /* COMMON_H */ 245 | -------------------------------------------------------------------------------- /src/_translate_string.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | 3 | 4 | #if 1 5 | #define EN(n) (n) 6 | #else 7 | #define EN(n) (((n) >> 8) | (((n) << 8) & 0xffff)) 8 | #endif 9 | 10 | #define ADD1(s) *(result++) = s[0]; add = 1; 11 | #define ADD1I(s) ADD1(s); ++ptr; 12 | 13 | #define ADD2(s) *(result++) = s[0]; *(result++) = s[1]; add = 1; 14 | #define ADD2I(s) ADD2(s); ++ptr; 15 | 16 | #define BTW(c, a, b) (unsigned)(c) - (unsigned)(a) <= (unsigned)(b) - (unsigned)(a) 17 | 18 | char *_translate_string(UDF_ARGS *args, char *result, unsigned long *length, char separator) { 19 | 20 | char *start_res = result, *ptr = args->args[0], *end_str = ptr + args->lengths[0], add = 0; 21 | 22 | /* My own UTF8 and latin translation table */ 23 | 24 | for (; ptr < end_str; ptr++) { 25 | 26 | unsigned char c = *ptr; 27 | unsigned short s = *((unsigned short *) ptr); 28 | 29 | if (BTW(c, 'a', 'z') || BTW(c, '0', '9')) { 30 | *(result++) = c; 31 | add = 1; 32 | } else if (BTW(c, 'A', 'Z')) { 33 | *(result++) = c | 32; 34 | add = 1; 35 | } else switch (s) { 36 | case EN(0x9fc3): 37 | ADD2I("ss"); 38 | break; 39 | case EN(0x84c3): case EN(0xa4c3): 40 | case EN(0xa6c3): case EN(0x86c3): 41 | ADD2I("ae"); 42 | break; 43 | case EN(0x96c3): case EN(0xb6c3): case EN(0x91c5): 44 | ADD2I("oe"); 45 | break; 46 | case EN(0x9cc3): case EN(0xbcc3): 47 | ADD2I("ue"); 48 | break; 49 | case EN(0xa0c3): case EN(0xa1c3): 50 | case EN(0xa2c3): case EN(0xa3c3): 51 | case EN(0xa5c3): case EN(0x80c3): 52 | case EN(0x81c3): case EN(0x82c3): 53 | case EN(0x83c3): case EN(0x85c3): case EN(0x83c4): 54 | ADD1I("a"); 55 | break; 56 | case EN(0xa8c3): case EN(0xa9c3): 57 | case EN(0xaac3): case EN(0xabc3): 58 | case EN(0x88c3): case EN(0x89c3): 59 | case EN(0x8ac3): case EN(0x8bc3): 60 | case EN(0x9BC4): case EN(0x99c4): 61 | ADD1I("e"); 62 | break; 63 | case EN(0xacc3): case EN(0xadc3): 64 | case EN(0xaec3): case EN(0xafc3): 65 | case EN(0x8cc3): case EN(0x8dc3): 66 | case EN(0x8ec3): case EN(0x8fc3): 67 | ADD1I("i"); 68 | break; 69 | case EN(0xb0c3): case EN(0xb2c3): 70 | case EN(0xb3c3): case EN(0xb4c3): 71 | case EN(0xb5c3): case EN(0x92c3): 72 | case EN(0x93c3): case EN(0x94c3): 73 | case EN(0x95c3): case EN(0x98c3): 74 | case EN(0xb8c3): 75 | ADD1I("o"); 76 | break; 77 | case EN(0xb9c3): case EN(0xbac3): 78 | case EN(0xbbc3): case EN(0x99c3): 79 | case EN(0x9ac3): case EN(0x9bc3): 80 | case EN(0xb5c2): case EN(0xafc5): 81 | ADD1I("u"); 82 | break; 83 | case EN(0x91c3): case EN(0xb1c3): 84 | ADD1I("n"); 85 | break; 86 | case EN(0x87c3): case EN(0xa7c2): 87 | case EN(0xa2c2): case EN(0xa7c3): 88 | case EN(0x87c4): case EN(0x8dc4): 89 | ADD1I("c"); 90 | break; 91 | case EN(0x9ec3): case EN(0xbec3): 92 | ADD1I("p"); 93 | break; 94 | case EN(0xbfc3): case EN(0xa5c2): 95 | case EN(0x9dc3): case EN(0xbdc3): 96 | ADD1I("y"); 97 | break; 98 | case EN(0x97c3): 99 | ADD1I("x"); 100 | break; 101 | case EN(0xaec2): case EN(0x99c5): 102 | ADD1I("r"); 103 | break; 104 | case EN(0x90c3): 105 | ADD1I("d"); 106 | break; 107 | case EN(0x81c5): case EN(0x82c5): 108 | ADD1I("l"); 109 | break; 110 | case EN(0x9fc4): 111 | ADD1I("g"); 112 | break; 113 | case EN(0x84c5): case EN(0x83c5): 114 | ADD1I("n"); 115 | break; 116 | case EN(0x99c8): case EN(0xa1c5): 117 | ADD1I("s"); 118 | break; 119 | case EN(0xa0c5): case EN(0x9ec5): case EN(0x9ac5): 120 | ADD1I("S"); 121 | break; 122 | case EN(0xbec5): 123 | ADD1I("z"); 124 | break; 125 | default: 126 | switch (c) { 127 | case 223: 128 | ADD2("ss"); 129 | break; 130 | case 196: case 198: 131 | case 228: case 230: 132 | ADD2("ae"); 133 | break; 134 | case 214: case 246: 135 | ADD2("oe"); 136 | break; 137 | case 220: case 252: 138 | ADD2("ue"); 139 | break; 140 | case 192: case 193: 141 | case 194: case 195: 142 | case 197: case 224: 143 | case 225: case 226: 144 | case 227: case 229: 145 | ADD1("a"); 146 | break; 147 | case 200: case 201: 148 | case 202: case 203: 149 | case 232: case 233: 150 | case 234: case 235: 151 | ADD1("e"); 152 | break; 153 | case 161: case 204: 154 | case 205: case 206: 155 | case 207: case 236: 156 | case 237: case 238: 157 | case 239: 158 | ADD1("i"); 159 | break; 160 | case 210: case 211: 161 | case 212: case 213: 162 | case 240: case 242: 163 | case 243: case 244: 164 | case 245: 165 | ADD1("o"); 166 | break; 167 | case 181: case 217: 168 | case 218: case 219: 169 | case 249: case 250: 170 | case 251: 171 | ADD1("u"); 172 | break; 173 | case 209: case 241: 174 | ADD1("n"); 175 | break; 176 | case 162: case 169: 177 | case 199: case 231: 178 | ADD1("c"); 179 | break; 180 | case 222: case 254: 181 | ADD1("p"); 182 | break; 183 | case 165: case 221: 184 | case 253: case 255: 185 | ADD1("y"); 186 | break; 187 | case 215: 188 | ADD1("x"); 189 | break; 190 | case 174: 191 | ADD1("r"); 192 | break; 193 | case 208: 194 | ADD1("d"); 195 | break; 196 | default: 197 | if (add) { 198 | *(result++) = separator; 199 | add = 0; 200 | } 201 | } 202 | } 203 | } 204 | 205 | if ((*length = result - start_res) > 0 && *(result - 1) == separator) { 206 | result--; 207 | (*length)--; 208 | } 209 | 210 | *result = 0; 211 | 212 | return start_res; 213 | } 214 | -------------------------------------------------------------------------------- /udf_infusion.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Debug 10 | x64 11 | 12 | 13 | Release 14 | Win32 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {CC50FDE6-5D58-4D30-B3D7-8C79C94E3B61} 23 | Win32Proj 24 | udf_infusion 25 | 26 | 27 | 28 | DynamicLibrary 29 | true 30 | v120 31 | Unicode 32 | 33 | 34 | DynamicLibrary 35 | true 36 | v120 37 | Unicode 38 | 39 | 40 | DynamicLibrary 41 | false 42 | v120 43 | true 44 | Unicode 45 | 46 | 47 | DynamicLibrary 48 | false 49 | v120 50 | true 51 | Unicode 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | true 71 | 72 | 73 | true 74 | 75 | 76 | false 77 | 78 | 79 | false 80 | 81 | 82 | 83 | 84 | 85 | Level3 86 | Disabled 87 | STANDARD;MYSQL_SERVER;WIN32;_DEBUG;_WINDOWS;_USRDLL;UDF_INFUSION_EXPORTS;%(PreprocessorDefinitions) 88 | false 89 | C:\Program Files %28x86%29\MySQL\MySQL Server 5.7\include;%(AdditionalIncludeDirectories) 90 | Default 91 | 92 | 93 | Windows 94 | true 95 | mysqlclient.lib;kernel32.lib;%(AdditionalDependencies) 96 | C:\Program Files %28x86%29\MySQL\MySQL Server 5.7\lib;%(AdditionalLibraryDirectories) 97 | 98 | 99 | 100 | 101 | 102 | 103 | Level3 104 | Disabled 105 | STANDARD;MYSQL_SERVER;WIN32;_DEBUG;_WINDOWS;_USRDLL;UDF_INFUSION_EXPORTS;%(PreprocessorDefinitions) 106 | false 107 | C:\Program Files\MySQL\MySQL Server 5.7\include;%(AdditionalIncludeDirectories) 108 | Default 109 | 110 | 111 | Windows 112 | true 113 | mysqlclient.lib;kernel32.lib;%(AdditionalDependencies) 114 | C:\Program Files\MySQL\MySQL Server 5.7\lib;%(AdditionalLibraryDirectories) 115 | 116 | 117 | 118 | 119 | Level3 120 | 121 | 122 | MaxSpeed 123 | true 124 | true 125 | STANDARD;MYSQL_SERVER;WIN32;NDEBUG;_WINDOWS;_USRDLL;UDF_INFUSION_EXPORTS;%(PreprocessorDefinitions) 126 | false 127 | C:\Program Files %28x86%29\MySQL\MySQL Server 5.7\include;%(AdditionalIncludeDirectories) 128 | Default 129 | 130 | 131 | Windows 132 | true 133 | true 134 | true 135 | mysqlclient.lib;kernel32.lib;%(AdditionalDependencies) 136 | C:\Program Files %28x86%29\MySQL\MySQL Server 5.7\lib;%(AdditionalLibraryDirectories) 137 | 138 | 139 | 140 | 141 | Level3 142 | 143 | 144 | MaxSpeed 145 | true 146 | true 147 | STANDARD;MYSQL_SERVER;WIN32;NDEBUG;_WINDOWS;_USRDLL;UDF_INFUSION_EXPORTS;%(PreprocessorDefinitions) 148 | false 149 | C:\Program Files\MySQL\MySQL Server 5.7\include;%(AdditionalIncludeDirectories) 150 | Default 151 | 152 | 153 | Windows 154 | true 155 | true 156 | true 157 | mysqlclient.lib;kernel32.lib;%(AdditionalDependencies) 158 | C:\Program Files\MySQL\MySQL Server 5.7\lib;%(AdditionalLibraryDirectories) 159 | 160 | 161 | 162 | 163 | CppCode 164 | 165 | 166 | CppCode 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | CppCode 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | MySQL Infusion UDF 2 | ================== 3 | 4 | Description 5 | ----------- 6 | 7 | The MySQL Infusion UDF is a functionality enhancement for MySQL. 8 | It provides a variety of new string, math and aggregate functions. 9 | 10 | Installation 11 | ------------ 12 | 13 | Please make sure you have the following required software on your system 14 | before installation: 15 | 16 | * C and C++ compiler 17 | * MySQL server, client and development files 18 | 19 | ## Installation of prerequisites 20 | 21 | Ubuntu 22 | 23 | ``` 24 | apt-get install libmysqlclient-dev build-essential 25 | ``` 26 | 27 | Debian (uses MariaDB) 28 | 29 | ``` 30 | apt-get install default-libmysqlclient-dev build-essential 31 | ``` 32 | 33 | On CentOS / Fedora 34 | 35 | ``` 36 | yum install libtool 37 | yum install mysql-community-devel 38 | ``` 39 | 40 | 41 | To install MySQL Infusion UDF: 42 | 43 | ```sh 44 | git clone https://github.com/infusion/udf_infusion.git 45 | cd udf_infusion 46 | ./configure 47 | make 48 | sudo make install 49 | mysql < load.sql 50 | ``` 51 | 52 | You can choose to install only given UDF functions with the 53 | `--enable-functions` option: 54 | 55 | ```sh 56 | ./configure --enable-functions="" 57 | ``` 58 | 59 | where `` is a list of function names separated by space. 60 | 61 | To uninstall: 62 | 63 | ```sh 64 | mysql < unload.sql 65 | make uninstall 66 | ``` 67 | 68 | Aggregate Functions 69 | ------------------- 70 | 71 | Get the median of a set 72 | ``` 73 | double median(double n); 74 | 75 | mysql> SELECT median(weight) from t1; 76 | ``` 77 | 78 | 79 | Calculate the co-variance of two random variables 80 | ``` 81 | double covariance(double x, double y); 82 | 83 | mysql> SELECT covariance(a, b) from t1; 84 | ``` 85 | 86 | 87 | Calculate the correlation of two random variables 88 | ``` 89 | double corr(double x, double y); 90 | 91 | mysql> SELECT corr(a, b) from t1; 92 | ``` 93 | 94 | 95 | Get the first element of a group 96 | ``` 97 | string group_first(string s); 98 | 99 | mysql> SELECT group_first(s) from t1; 100 | ``` 101 | 102 | 103 | Get the last element of a group 104 | ``` 105 | string group_last(string s); 106 | 107 | mysql> SELECT group_last(s) from t1; 108 | ``` 109 | 110 | 111 | Get the maximum number of elements less than a certain partial sum 112 | ``` 113 | int lesspart(double m, double psum); 114 | 115 | mysql> SELECT lesspart(m, 1000) from t1; 116 | ``` 117 | 118 | 119 | Get the maximum number of elements less than a certain percentage of the partial sum 120 | ``` 121 | int lesspartpct(double m, double pct); 122 | 123 | mysql> SELECT lesspartpct(m, 0.4) from t1; 124 | ``` 125 | 126 | 127 | Get the maximum number of elements less than average 128 | ``` 129 | int lessavg(double m); 130 | 131 | mysql> SELECT lessavg(double m) from t1; 132 | ``` 133 | 134 | 135 | Calculate continuous percentile. Returns the value at a relative position 136 | specified by the fraction, interpolating between input values if needed. 137 | ``` 138 | double percentile_cont(double x, double fraction); 139 | 140 | mysql> SELECT percentile_cont(x, 0.5) from t1; 141 | ``` 142 | 143 | 144 | Calculate discrete percentile. Returns the first input value whose relative 145 | position is greater than or equal to the specified fraction. 146 | ``` 147 | double percentile_disc(double x, double fraction); 148 | 149 | mysql> SELECT percentile_disc(x, 0.5) from t1; 150 | ``` 151 | 152 | 153 | Calculates the 3th statistical moment of a data set: skewness 154 | See: http://geography.uoregon.edu/geogr/topics/moments.htm 155 | ``` 156 | double skewness(double m); 157 | 158 | mysql> SELECT skewness(double m) from t1; 159 | ``` 160 | 161 | 162 | Find statistical mode, i.e. the most frequent input value. 163 | ``` 164 | double stats_mode(double x); 165 | 166 | mysql> SELECT stats_mode(double x) from t1; 167 | ``` 168 | 169 | 170 | Calculates the 4th statistical moment of a data set: kurtosis 171 | See: http://geography.uoregon.edu/geogr/topics/moments.htm 172 | ``` 173 | double kurtosis(double m); 174 | 175 | mysql> SELECT kurtosis(double m) from t1; 176 | ``` 177 | 178 | 179 | Misc Functions 180 | -------------- 181 | 182 | A running SUM() for int and double/real values. Same as @x:= @x + value, but much faster and cleaner to code. The names are built up of R(unning)-SUM-(Int|Double) 183 | ``` 184 | int rsumi(int col); 185 | double rsumd(double col); 186 | 187 | 188 | mysql> SELECT rsumi(int_col) FROM t1; 189 | mysql> SELECT rsumd(double_col) FROM t1; 190 | ``` 191 | 192 | 193 | A 64 bit hash function for MySQL, implementing a FNV algorithm 194 | ``` 195 | int fnv(string str); 196 | 197 | mysql> SELECT cast( fnv( str ) as unsigned ) from t1; 198 | ``` 199 | 200 | Unfortunately, the UDF API doesn't support unsigned int return values. If you don't like the cast approach above, just add a stored function on your own: 201 | 202 | ``` 203 | CREATE FUNCTION ufnv(str TEXT) RETURNS INT UNSIGNED 204 | RETURN cast( fnv( str ) as unsigned ); 205 | ``` 206 | 207 | String Functions 208 | ---------------- 209 | 210 | All string functions operate on UTF8 strings. 211 | 212 | Cuts a string if it's longer then a max value and appends "...". Words are not chopped as long as white spaces are present. 213 | ``` 214 | string cut(string str, int num[, string x='...']); 215 | 216 | mysql> SELECT cut('This is the funny world of MySQL...', 15); 217 | +------------------------------------------------+ 218 | | cut('This is the funny world of MySQL...', 15) | 219 | +------------------------------------------------+ 220 | | This is the... | 221 | +------------------------------------------------+ 222 | 1 row in set (0.00 sec) 223 | ``` 224 | 225 | 226 | The old name of this function was makeurl but I renamed it to slug, because this seems to be the more official term for this one. The Wordpress Codex says this: A slug is a few words that describe a post or a page. Slugs are usually a URL friendly version of the post title [...], but a slug can be anything you like. Slugs are meant to be used with permalinks as they help describe what the content at the URL is. 227 | ``` 228 | string slug(string str[, char separator='_']); 229 | 230 | mysql> SELECT slug('Max Müller Straße!', '-'); 231 | +----------------------------+ 232 | | slug('Max Müller Straße!') | 233 | +----------------------------+ 234 | | max-mueller-strasse | 235 | +----------------------------+ 236 | 1 row in set (0.00 sec) 237 | ``` 238 | 239 | 240 | Generates a list of ngrams from a given string. 241 | ``` 242 | string ngram(string str[, int size=2]); 243 | 244 | mysql> SELECT ngram('Lorem ipsum dolor'); 245 | +-------------------------------------------------------+ 246 | | ngram('Lorem ipsum dolor') | 247 | +-------------------------------------------------------+ 248 | | _l lo or re em m_ _i ip ps su um m_ _d do ol lo or r_ | 249 | +-------------------------------------------------------+ 250 | 1 row in set (0.01 sec) 251 | ``` 252 | 253 | 254 | Math Functions 255 | -------------- 256 | 257 | Round to the next multiple of a base. 258 | ``` 259 | int bround(int num, int base); 260 | 261 | mysql> SELECT bround(13, 3); 262 | +---------------+ 263 | | bround(13, 3) | 264 | +---------------+ 265 | | 15 | 266 | +---------------+ 267 | 1 row in set (0.00 sec) 268 | ``` 269 | 270 | 271 | Round to the next power of 10. This breaks down 10^ceil(log(n) / log(10)) 272 | ``` 273 | int xround(int num); 274 | 275 | mysql> SELECT xround(55); 276 | +------------+ 277 | | xround(55) | 278 | +------------+ 279 | | 100 | 280 | +------------+ 281 | 1 row in set (0.00 sec) 282 | ``` 283 | 284 | 285 | Limits a number to a specified lower min- and/or a upper max value. Not used min/max can be ignored with NULL 286 | ``` 287 | double bound(double num, double min, double max); 288 | 289 | mysql> SELECT bound(12, 0, 4); 290 | +-----------------+ 291 | | bound(12, 0, 4) | 292 | +-----------------+ 293 | | 4.00000000 | 294 | +-----------------+ 295 | 1 row in set (0.00 sec) 296 | ``` 297 | 298 | 299 | Calculates N over K 300 | ``` 301 | int noverk(int n, int k); 302 | 303 | mysql> select noverk(49, 6); 304 | +---------------+ 305 | | noverk(49, 6) | 306 | +---------------+ 307 | | 13983816 | 308 | +---------------+ 309 | 1 row in set (0.00 sec) 310 | ``` 311 | 312 | 313 | Binary Functions 314 | ---------------- 315 | 316 | Check if a bit-flag is set in the number. 317 | ``` 318 | bool isbit(int mask, int n); 319 | 320 | mysql> SELECT isbit(5, 2); 321 | +-------------+ 322 | | isbit(5, 2) | 323 | +-------------+ 324 | | 1 | 325 | +-------------+ 326 | 1 row in set (0.00 sec) 327 | ``` 328 | 329 | 330 | Set a bit-flag at the position to 1 (or optionally 0). 331 | ``` 332 | int setbit(int mask, int n[, bool init=1]); 333 | 334 | mysql> SELECT setbit(8, 4, 1); 335 | +-----------------+ 336 | | setbit(8, 4, 1) | 337 | +-----------------+ 338 | | 24 | 339 | +-----------------+ 340 | 1 row in set (0.00 sec) 341 | ``` 342 | 343 | 344 | Toggle/invert a bit-flag at the given position. 345 | ``` 346 | int invbit(int mask, int n); 347 | 348 | mysql> SELECT invbit(8, 2); 349 | +--------------+ 350 | | invbit(8, 2) | 351 | +--------------+ 352 | | 12 | 353 | +--------------+ 354 | 1 row in set (0.00 sec) 355 | ``` 356 | 357 | 358 | Rotate (=shift to the left and append shifted-out bits to the right) the bits within the number 359 | ``` 360 | int rotbit(int mask, int n); 361 | 362 | mysql> select rotbit(13, 1); 363 | +---------------+ 364 | | rotbit(13, 1) | 365 | +---------------+ 366 | | 26 | 367 | +---------------+ 368 | 1 row in set (0.00 sec) 369 | ``` 370 | 371 | 372 | Get a smaller integer from a bigger integer. 373 | See: https://raw.org/article/store-small-numbers-in-big-numbers/ 374 | ``` 375 | int getint(int mask, int x, int y); 376 | 377 | mysql> SELECT GETINT(4283942, 4, 8); 378 | +-----------------------+ 379 | | getint(4283942, 4, 8) | 380 | +-----------------------+ 381 | | 2 | 382 | +-----------------------+ 383 | 1 row in set (0.00 sec) 384 | ``` 385 | 386 | Set a smaller integer into a bigger integer. 387 | See: https://raw.org/article/store-small-numbers-in-big-numbers/ 388 | ``` 389 | int setint(int mask, int x, int y, int m); 390 | 391 | mysql> SELECT SETINT(4283942, 4, 8, 10); 392 | +---------------------------+ 393 | | setint(4283942, 4, 8, 10) | 394 | +---------------------------+ 395 | | 4284070 | 396 | +---------------------------+ 397 | 1 row in set (0.00 sec) 398 | ``` 399 | 400 | Testing 401 | ======= 402 | 403 | udf_infusion contains a set of unit tests to verify the correctness 404 | of the provided UDF functions. Running them after installation is optional. 405 | 406 | Prerequisites: 407 | 408 | * Python 2.7 409 | * [numpy](http://www.numpy.org/) 410 | * [scipy](http://scipy.org/) 411 | 412 | **Note**: The testing framework requires all UDF functions to be enabled 413 | during installation. 414 | 415 | First, it is recommended you set connection details (incl. password) in 416 | `~/.my.cnf`, e.g.: 417 | 418 | ``` 419 | [client] 420 | user= 421 | password= 422 | ``` 423 | 424 | Alternatively, you can set options to be passed to the MySQL client 425 | in the `MYSQL_OPTIONS` environment variable. 426 | 427 | To prepare the testing environment (requires administrator rights in MySQL): 428 | 429 | ``` 430 | make test_prepare 431 | ``` 432 | 433 | This may take a while as sample data is generated and imported. 434 | Database `udf_infusion_test` is created and populated with generated data. 435 | 436 | Run tests with: 437 | 438 | ``` 439 | make test 440 | ``` 441 | 442 | After completion, the temporary database can be dropped with `test_clean`: 443 | 444 | ``` 445 | make test_clean 446 | ``` 447 | 448 | License 449 | ====== 450 | Copyright (c) 2015, [Robert Eisele](https://raw.org/) 451 | Licensed under GPL Version 2 license. 452 | -------------------------------------------------------------------------------- /config/missing: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # Common stub for a few missing GNU programs while installing. 3 | 4 | scriptversion=2012-01-06.13; # UTC 5 | 6 | # Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005, 2006, 7 | # 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. 8 | # Originally by Fran,cois Pinard , 1996. 9 | 10 | # This program is free software; you can redistribute it and/or modify 11 | # it under the terms of the GNU General Public License as published by 12 | # the Free Software Foundation; either version 2, or (at your option) 13 | # any later version. 14 | 15 | # This program is distributed in the hope that it will be useful, 16 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | # GNU General Public License for more details. 19 | 20 | # You should have received a copy of the GNU General Public License 21 | # along with this program. If not, see . 22 | 23 | # As a special exception to the GNU General Public License, if you 24 | # distribute this file as part of a program that contains a 25 | # configuration script generated by Autoconf, you may include it under 26 | # the same distribution terms that you use for the rest of that program. 27 | 28 | if test $# -eq 0; then 29 | echo 1>&2 "Try \`$0 --help' for more information" 30 | exit 1 31 | fi 32 | 33 | run=: 34 | sed_output='s/.* --output[ =]\([^ ]*\).*/\1/p' 35 | sed_minuso='s/.* -o \([^ ]*\).*/\1/p' 36 | 37 | # In the cases where this matters, `missing' is being run in the 38 | # srcdir already. 39 | if test -f configure.ac; then 40 | configure_ac=configure.ac 41 | else 42 | configure_ac=configure.in 43 | fi 44 | 45 | msg="missing on your system" 46 | 47 | case $1 in 48 | --run) 49 | # Try to run requested program, and just exit if it succeeds. 50 | run= 51 | shift 52 | "$@" && exit 0 53 | # Exit code 63 means version mismatch. This often happens 54 | # when the user try to use an ancient version of a tool on 55 | # a file that requires a minimum version. In this case we 56 | # we should proceed has if the program had been absent, or 57 | # if --run hadn't been passed. 58 | if test $? = 63; then 59 | run=: 60 | msg="probably too old" 61 | fi 62 | ;; 63 | 64 | -h|--h|--he|--hel|--help) 65 | echo "\ 66 | $0 [OPTION]... PROGRAM [ARGUMENT]... 67 | 68 | Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an 69 | error status if there is no known handling for PROGRAM. 70 | 71 | Options: 72 | -h, --help display this help and exit 73 | -v, --version output version information and exit 74 | --run try to run the given command, and emulate it if it fails 75 | 76 | Supported PROGRAM values: 77 | aclocal touch file \`aclocal.m4' 78 | autoconf touch file \`configure' 79 | autoheader touch file \`config.h.in' 80 | autom4te touch the output file, or create a stub one 81 | automake touch all \`Makefile.in' files 82 | bison create \`y.tab.[ch]', if possible, from existing .[ch] 83 | flex create \`lex.yy.c', if possible, from existing .c 84 | help2man touch the output file 85 | lex create \`lex.yy.c', if possible, from existing .c 86 | makeinfo touch the output file 87 | yacc create \`y.tab.[ch]', if possible, from existing .[ch] 88 | 89 | Version suffixes to PROGRAM as well as the prefixes \`gnu-', \`gnu', and 90 | \`g' are ignored when checking the name. 91 | 92 | Send bug reports to ." 93 | exit $? 94 | ;; 95 | 96 | -v|--v|--ve|--ver|--vers|--versi|--versio|--version) 97 | echo "missing $scriptversion (GNU Automake)" 98 | exit $? 99 | ;; 100 | 101 | -*) 102 | echo 1>&2 "$0: Unknown \`$1' option" 103 | echo 1>&2 "Try \`$0 --help' for more information" 104 | exit 1 105 | ;; 106 | 107 | esac 108 | 109 | # normalize program name to check for. 110 | program=`echo "$1" | sed ' 111 | s/^gnu-//; t 112 | s/^gnu//; t 113 | s/^g//; t'` 114 | 115 | # Now exit if we have it, but it failed. Also exit now if we 116 | # don't have it and --version was passed (most likely to detect 117 | # the program). This is about non-GNU programs, so use $1 not 118 | # $program. 119 | case $1 in 120 | lex*|yacc*) 121 | # Not GNU programs, they don't have --version. 122 | ;; 123 | 124 | *) 125 | if test -z "$run" && ($1 --version) > /dev/null 2>&1; then 126 | # We have it, but it failed. 127 | exit 1 128 | elif test "x$2" = "x--version" || test "x$2" = "x--help"; then 129 | # Could not run --version or --help. This is probably someone 130 | # running `$TOOL --version' or `$TOOL --help' to check whether 131 | # $TOOL exists and not knowing $TOOL uses missing. 132 | exit 1 133 | fi 134 | ;; 135 | esac 136 | 137 | # If it does not exist, or fails to run (possibly an outdated version), 138 | # try to emulate it. 139 | case $program in 140 | aclocal*) 141 | echo 1>&2 "\ 142 | WARNING: \`$1' is $msg. You should only need it if 143 | you modified \`acinclude.m4' or \`${configure_ac}'. You might want 144 | to install the \`Automake' and \`Perl' packages. Grab them from 145 | any GNU archive site." 146 | touch aclocal.m4 147 | ;; 148 | 149 | autoconf*) 150 | echo 1>&2 "\ 151 | WARNING: \`$1' is $msg. You should only need it if 152 | you modified \`${configure_ac}'. You might want to install the 153 | \`Autoconf' and \`GNU m4' packages. Grab them from any GNU 154 | archive site." 155 | touch configure 156 | ;; 157 | 158 | autoheader*) 159 | echo 1>&2 "\ 160 | WARNING: \`$1' is $msg. You should only need it if 161 | you modified \`acconfig.h' or \`${configure_ac}'. You might want 162 | to install the \`Autoconf' and \`GNU m4' packages. Grab them 163 | from any GNU archive site." 164 | files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}` 165 | test -z "$files" && files="config.h" 166 | touch_files= 167 | for f in $files; do 168 | case $f in 169 | *:*) touch_files="$touch_files "`echo "$f" | 170 | sed -e 's/^[^:]*://' -e 's/:.*//'`;; 171 | *) touch_files="$touch_files $f.in";; 172 | esac 173 | done 174 | touch $touch_files 175 | ;; 176 | 177 | automake*) 178 | echo 1>&2 "\ 179 | WARNING: \`$1' is $msg. You should only need it if 180 | you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'. 181 | You might want to install the \`Automake' and \`Perl' packages. 182 | Grab them from any GNU archive site." 183 | find . -type f -name Makefile.am -print | 184 | sed 's/\.am$/.in/' | 185 | while read f; do touch "$f"; done 186 | ;; 187 | 188 | autom4te*) 189 | echo 1>&2 "\ 190 | WARNING: \`$1' is needed, but is $msg. 191 | You might have modified some files without having the 192 | proper tools for further handling them. 193 | You can get \`$1' as part of \`Autoconf' from any GNU 194 | archive site." 195 | 196 | file=`echo "$*" | sed -n "$sed_output"` 197 | test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` 198 | if test -f "$file"; then 199 | touch $file 200 | else 201 | test -z "$file" || exec >$file 202 | echo "#! /bin/sh" 203 | echo "# Created by GNU Automake missing as a replacement of" 204 | echo "# $ $@" 205 | echo "exit 0" 206 | chmod +x $file 207 | exit 1 208 | fi 209 | ;; 210 | 211 | bison*|yacc*) 212 | echo 1>&2 "\ 213 | WARNING: \`$1' $msg. You should only need it if 214 | you modified a \`.y' file. You may need the \`Bison' package 215 | in order for those modifications to take effect. You can get 216 | \`Bison' from any GNU archive site." 217 | rm -f y.tab.c y.tab.h 218 | if test $# -ne 1; then 219 | eval LASTARG=\${$#} 220 | case $LASTARG in 221 | *.y) 222 | SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` 223 | if test -f "$SRCFILE"; then 224 | cp "$SRCFILE" y.tab.c 225 | fi 226 | SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` 227 | if test -f "$SRCFILE"; then 228 | cp "$SRCFILE" y.tab.h 229 | fi 230 | ;; 231 | esac 232 | fi 233 | if test ! -f y.tab.h; then 234 | echo >y.tab.h 235 | fi 236 | if test ! -f y.tab.c; then 237 | echo 'main() { return 0; }' >y.tab.c 238 | fi 239 | ;; 240 | 241 | lex*|flex*) 242 | echo 1>&2 "\ 243 | WARNING: \`$1' is $msg. You should only need it if 244 | you modified a \`.l' file. You may need the \`Flex' package 245 | in order for those modifications to take effect. You can get 246 | \`Flex' from any GNU archive site." 247 | rm -f lex.yy.c 248 | if test $# -ne 1; then 249 | eval LASTARG=\${$#} 250 | case $LASTARG in 251 | *.l) 252 | SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` 253 | if test -f "$SRCFILE"; then 254 | cp "$SRCFILE" lex.yy.c 255 | fi 256 | ;; 257 | esac 258 | fi 259 | if test ! -f lex.yy.c; then 260 | echo 'main() { return 0; }' >lex.yy.c 261 | fi 262 | ;; 263 | 264 | help2man*) 265 | echo 1>&2 "\ 266 | WARNING: \`$1' is $msg. You should only need it if 267 | you modified a dependency of a manual page. You may need the 268 | \`Help2man' package in order for those modifications to take 269 | effect. You can get \`Help2man' from any GNU archive site." 270 | 271 | file=`echo "$*" | sed -n "$sed_output"` 272 | test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` 273 | if test -f "$file"; then 274 | touch $file 275 | else 276 | test -z "$file" || exec >$file 277 | echo ".ab help2man is required to generate this page" 278 | exit $? 279 | fi 280 | ;; 281 | 282 | makeinfo*) 283 | echo 1>&2 "\ 284 | WARNING: \`$1' is $msg. You should only need it if 285 | you modified a \`.texi' or \`.texinfo' file, or any other file 286 | indirectly affecting the aspect of the manual. The spurious 287 | call might also be the consequence of using a buggy \`make' (AIX, 288 | DU, IRIX). You might want to install the \`Texinfo' package or 289 | the \`GNU make' package. Grab either from any GNU archive site." 290 | # The file to touch is that specified with -o ... 291 | file=`echo "$*" | sed -n "$sed_output"` 292 | test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` 293 | if test -z "$file"; then 294 | # ... or it is the one specified with @setfilename ... 295 | infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` 296 | file=`sed -n ' 297 | /^@setfilename/{ 298 | s/.* \([^ ]*\) *$/\1/ 299 | p 300 | q 301 | }' $infile` 302 | # ... or it is derived from the source name (dir/f.texi becomes f.info) 303 | test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info 304 | fi 305 | # If the file does not exist, the user really needs makeinfo; 306 | # let's fail without touching anything. 307 | test -f $file || exit 1 308 | touch $file 309 | ;; 310 | 311 | *) 312 | echo 1>&2 "\ 313 | WARNING: \`$1' is needed, and is $msg. 314 | You might have modified some files without having the 315 | proper tools for further handling them. Check the \`README' file, 316 | it often tells you about the needed prerequisites for installing 317 | this package. You may also peek at any GNU archive site, in case 318 | some other package would contain this missing \`$1' program." 319 | exit 1 320 | ;; 321 | esac 322 | 323 | exit 0 324 | 325 | # Local variables: 326 | # eval: (add-hook 'write-file-hooks 'time-stamp) 327 | # time-stamp-start: "scriptversion=" 328 | # time-stamp-format: "%:y-%02m-%02d.%02H" 329 | # time-stamp-time-zone: "UTC" 330 | # time-stamp-end: "; # UTC" 331 | # End: 332 | -------------------------------------------------------------------------------- /test/Makefile.in: -------------------------------------------------------------------------------- 1 | # Makefile.in generated by automake 1.11.6 from Makefile.am. 2 | # @configure_input@ 3 | 4 | # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 5 | # 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software 6 | # Foundation, Inc. 7 | # This Makefile.in is free software; the Free Software Foundation 8 | # gives unlimited permission to copy and/or distribute it, 9 | # with or without modifications, as long as this notice is preserved. 10 | 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY, to the extent permitted by law; without 13 | # even the implied warranty of MERCHANTABILITY or FITNESS FOR A 14 | # PARTICULAR PURPOSE. 15 | 16 | @SET_MAKE@ 17 | VPATH = @srcdir@ 18 | am__make_dryrun = \ 19 | { \ 20 | am__dry=no; \ 21 | case $$MAKEFLAGS in \ 22 | *\\[\ \ ]*) \ 23 | echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ 24 | | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ 25 | *) \ 26 | for am__flg in $$MAKEFLAGS; do \ 27 | case $$am__flg in \ 28 | *=*|--*) ;; \ 29 | *n*) am__dry=yes; break;; \ 30 | esac; \ 31 | done;; \ 32 | esac; \ 33 | test $$am__dry = yes; \ 34 | } 35 | pkgdatadir = $(datadir)/@PACKAGE@ 36 | pkgincludedir = $(includedir)/@PACKAGE@ 37 | pkglibdir = $(libdir)/@PACKAGE@ 38 | pkglibexecdir = $(libexecdir)/@PACKAGE@ 39 | am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd 40 | install_sh_DATA = $(install_sh) -c -m 644 41 | install_sh_PROGRAM = $(install_sh) -c 42 | install_sh_SCRIPT = $(install_sh) -c 43 | INSTALL_HEADER = $(INSTALL_DATA) 44 | transform = $(program_transform_name) 45 | NORMAL_INSTALL = : 46 | PRE_INSTALL = : 47 | POST_INSTALL = : 48 | NORMAL_UNINSTALL = : 49 | PRE_UNINSTALL = : 50 | POST_UNINSTALL = : 51 | build_triplet = @build@ 52 | host_triplet = @host@ 53 | subdir = test 54 | DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in 55 | ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 56 | am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ 57 | $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ 58 | $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ 59 | $(top_srcdir)/m4/ax_lib_mysql.m4 \ 60 | $(top_srcdir)/m4/ax_mysql_bin.m4 $(top_srcdir)/configure.ac 61 | am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ 62 | $(ACLOCAL_M4) 63 | mkinstalldirs = $(install_sh) -d 64 | CONFIG_HEADER = $(top_builddir)/config.h 65 | CONFIG_CLEAN_FILES = 66 | CONFIG_CLEAN_VPATH_FILES = 67 | SOURCES = 68 | DIST_SOURCES = 69 | am__can_run_installinfo = \ 70 | case $$AM_UPDATE_INFO_DIR in \ 71 | n|no|NO) false;; \ 72 | *) (install-info --version) >/dev/null 2>&1;; \ 73 | esac 74 | DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) 75 | ACLOCAL = @ACLOCAL@ 76 | AMTAR = @AMTAR@ 77 | AR = @AR@ 78 | AUTOCONF = @AUTOCONF@ 79 | AUTOHEADER = @AUTOHEADER@ 80 | AUTOMAKE = @AUTOMAKE@ 81 | AWK = @AWK@ 82 | CC = @CC@ 83 | CCDEPMODE = @CCDEPMODE@ 84 | CFLAGS = @CFLAGS@ 85 | CPP = @CPP@ 86 | CPPFLAGS = @CPPFLAGS@ 87 | CXX = @CXX@ 88 | CXXCPP = @CXXCPP@ 89 | CXXDEPMODE = @CXXDEPMODE@ 90 | CXXFLAGS = @CXXFLAGS@ 91 | CYGPATH_W = @CYGPATH_W@ 92 | DEFS = @DEFS@ 93 | DEPDIR = @DEPDIR@ 94 | DLLTOOL = @DLLTOOL@ 95 | DSYMUTIL = @DSYMUTIL@ 96 | DUMPBIN = @DUMPBIN@ 97 | ECHO_C = @ECHO_C@ 98 | ECHO_N = @ECHO_N@ 99 | ECHO_T = @ECHO_T@ 100 | EGREP = @EGREP@ 101 | EXEEXT = @EXEEXT@ 102 | FGREP = @FGREP@ 103 | GREP = @GREP@ 104 | INSTALL = @INSTALL@ 105 | INSTALL_DATA = @INSTALL_DATA@ 106 | INSTALL_PROGRAM = @INSTALL_PROGRAM@ 107 | INSTALL_SCRIPT = @INSTALL_SCRIPT@ 108 | INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ 109 | LD = @LD@ 110 | LDFLAGS = @LDFLAGS@ 111 | LIBOBJS = @LIBOBJS@ 112 | LIBS = @LIBS@ 113 | LIBTOOL = @LIBTOOL@ 114 | LIPO = @LIPO@ 115 | LN_S = @LN_S@ 116 | LTLIBOBJS = @LTLIBOBJS@ 117 | MAKEINFO = @MAKEINFO@ 118 | MANIFEST_TOOL = @MANIFEST_TOOL@ 119 | MKDIR_P = @MKDIR_P@ 120 | MYSQL = mysql 121 | MYSQLADMIN = @MYSQLADMIN@ 122 | MYSQLTEST = mysqltest 123 | MYSQL_CFLAGS = @MYSQL_CFLAGS@ 124 | MYSQL_CONFIG = @MYSQL_CONFIG@ 125 | MYSQL_LDFLAGS = @MYSQL_LDFLAGS@ 126 | MYSQL_PLUGINDIR = @MYSQL_PLUGINDIR@ 127 | MYSQL_VERSION = @MYSQL_VERSION@ 128 | NM = @NM@ 129 | NMEDIT = @NMEDIT@ 130 | OBJDUMP = @OBJDUMP@ 131 | OBJEXT = @OBJEXT@ 132 | OTOOL = @OTOOL@ 133 | OTOOL64 = @OTOOL64@ 134 | PACKAGE = @PACKAGE@ 135 | PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ 136 | PACKAGE_NAME = @PACKAGE_NAME@ 137 | PACKAGE_STRING = @PACKAGE_STRING@ 138 | PACKAGE_TARNAME = @PACKAGE_TARNAME@ 139 | PACKAGE_URL = @PACKAGE_URL@ 140 | PACKAGE_VERSION = @PACKAGE_VERSION@ 141 | PATH_SEPARATOR = @PATH_SEPARATOR@ 142 | RANLIB = @RANLIB@ 143 | SED = @SED@ 144 | SET_MAKE = @SET_MAKE@ 145 | SHELL = @SHELL@ 146 | STRIP = @STRIP@ 147 | VERSION = @VERSION@ 148 | abs_builddir = @abs_builddir@ 149 | abs_srcdir = @abs_srcdir@ 150 | abs_top_builddir = @abs_top_builddir@ 151 | abs_top_srcdir = @abs_top_srcdir@ 152 | ac_ct_AR = @ac_ct_AR@ 153 | ac_ct_CC = @ac_ct_CC@ 154 | ac_ct_CXX = @ac_ct_CXX@ 155 | ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ 156 | am__include = @am__include@ 157 | am__leading_dot = @am__leading_dot@ 158 | am__quote = @am__quote@ 159 | am__tar = @am__tar@ 160 | am__untar = @am__untar@ 161 | bindir = @bindir@ 162 | build = @build@ 163 | build_alias = @build_alias@ 164 | build_cpu = @build_cpu@ 165 | build_os = @build_os@ 166 | build_vendor = @build_vendor@ 167 | builddir = @builddir@ 168 | datadir = @datadir@ 169 | datarootdir = @datarootdir@ 170 | docdir = @docdir@ 171 | dvidir = @dvidir@ 172 | enable_functions = @enable_functions@ 173 | exec_prefix = @exec_prefix@ 174 | host = @host@ 175 | host_alias = @host_alias@ 176 | host_cpu = @host_cpu@ 177 | host_os = @host_os@ 178 | host_vendor = @host_vendor@ 179 | htmldir = @htmldir@ 180 | includedir = @includedir@ 181 | infodir = @infodir@ 182 | install_sh = @install_sh@ 183 | libdir = @libdir@ 184 | libexecdir = @libexecdir@ 185 | localedir = @localedir@ 186 | localstatedir = @localstatedir@ 187 | mandir = @mandir@ 188 | mkdir_p = @mkdir_p@ 189 | oldincludedir = @oldincludedir@ 190 | pdfdir = @pdfdir@ 191 | prefix = @prefix@ 192 | program_transform_name = @program_transform_name@ 193 | psdir = @psdir@ 194 | sbindir = @sbindir@ 195 | sharedstatedir = @sharedstatedir@ 196 | srcdir = @srcdir@ 197 | sysconfdir = @sysconfdir@ 198 | target_alias = @target_alias@ 199 | top_build_prefix = @top_build_prefix@ 200 | top_builddir = @top_builddir@ 201 | top_srcdir = @top_srcdir@ 202 | CLEANFILES = *.log *.reject *.result example_table 203 | EXTRA_DIST = *.test *.sql test2result generate_random_data 204 | ALL_TESTS = $(wildcard *.test) 205 | all: all-am 206 | 207 | .SUFFIXES: 208 | $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) 209 | @for dep in $?; do \ 210 | case '$(am__configure_deps)' in \ 211 | *$$dep*) \ 212 | ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ 213 | && { if test -f $@; then exit 0; else break; fi; }; \ 214 | exit 1;; \ 215 | esac; \ 216 | done; \ 217 | echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign test/Makefile'; \ 218 | $(am__cd) $(top_srcdir) && \ 219 | $(AUTOMAKE) --foreign test/Makefile 220 | .PRECIOUS: Makefile 221 | Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status 222 | @case '$?' in \ 223 | *config.status*) \ 224 | cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ 225 | *) \ 226 | echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ 227 | cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ 228 | esac; 229 | 230 | $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) 231 | cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh 232 | 233 | $(top_srcdir)/configure: $(am__configure_deps) 234 | cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh 235 | $(ACLOCAL_M4): $(am__aclocal_m4_deps) 236 | cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh 237 | $(am__aclocal_m4_deps): 238 | 239 | mostlyclean-libtool: 240 | -rm -f *.lo 241 | 242 | clean-libtool: 243 | -rm -rf .libs _libs 244 | tags: TAGS 245 | TAGS: 246 | 247 | ctags: CTAGS 248 | CTAGS: 249 | 250 | 251 | distdir: $(DISTFILES) 252 | @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ 253 | topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ 254 | list='$(DISTFILES)'; \ 255 | dist_files=`for file in $$list; do echo $$file; done | \ 256 | sed -e "s|^$$srcdirstrip/||;t" \ 257 | -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ 258 | case $$dist_files in \ 259 | */*) $(MKDIR_P) `echo "$$dist_files" | \ 260 | sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ 261 | sort -u` ;; \ 262 | esac; \ 263 | for file in $$dist_files; do \ 264 | if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ 265 | if test -d $$d/$$file; then \ 266 | dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ 267 | if test -d "$(distdir)/$$file"; then \ 268 | find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ 269 | fi; \ 270 | if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ 271 | cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ 272 | find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ 273 | fi; \ 274 | cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ 275 | else \ 276 | test -f "$(distdir)/$$file" \ 277 | || cp -p $$d/$$file "$(distdir)/$$file" \ 278 | || exit 1; \ 279 | fi; \ 280 | done 281 | check-am: all-am 282 | check: check-am 283 | all-am: Makefile 284 | installdirs: 285 | install: install-am 286 | install-exec: install-exec-am 287 | install-data: install-data-am 288 | uninstall: uninstall-am 289 | 290 | install-am: all-am 291 | @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am 292 | 293 | installcheck: installcheck-am 294 | install-strip: 295 | if test -z '$(STRIP)'; then \ 296 | $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ 297 | install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ 298 | install; \ 299 | else \ 300 | $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ 301 | install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ 302 | "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ 303 | fi 304 | mostlyclean-generic: 305 | 306 | clean-generic: 307 | -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) 308 | 309 | distclean-generic: 310 | -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) 311 | -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) 312 | 313 | maintainer-clean-generic: 314 | @echo "This command is intended for maintainers to use" 315 | @echo "it deletes files that may require special tools to rebuild." 316 | clean: clean-am 317 | 318 | clean-am: clean-generic clean-libtool mostlyclean-am 319 | 320 | distclean: distclean-am 321 | -rm -f Makefile 322 | distclean-am: clean-am distclean-generic 323 | 324 | dvi: dvi-am 325 | 326 | dvi-am: 327 | 328 | html: html-am 329 | 330 | html-am: 331 | 332 | info: info-am 333 | 334 | info-am: 335 | 336 | install-data-am: 337 | 338 | install-dvi: install-dvi-am 339 | 340 | install-dvi-am: 341 | 342 | install-exec-am: 343 | 344 | install-html: install-html-am 345 | 346 | install-html-am: 347 | 348 | install-info: install-info-am 349 | 350 | install-info-am: 351 | 352 | install-man: 353 | 354 | install-pdf: install-pdf-am 355 | 356 | install-pdf-am: 357 | 358 | install-ps: install-ps-am 359 | 360 | install-ps-am: 361 | 362 | installcheck-am: 363 | 364 | maintainer-clean: maintainer-clean-am 365 | -rm -f Makefile 366 | maintainer-clean-am: distclean-am maintainer-clean-generic 367 | 368 | mostlyclean: mostlyclean-am 369 | 370 | mostlyclean-am: mostlyclean-generic mostlyclean-libtool 371 | 372 | pdf: pdf-am 373 | 374 | pdf-am: 375 | 376 | ps: ps-am 377 | 378 | ps-am: 379 | 380 | uninstall-am: 381 | 382 | .MAKE: install-am install-strip 383 | 384 | .PHONY: all all-am check check-am clean clean-generic clean-libtool \ 385 | distclean distclean-generic distclean-libtool distdir dvi \ 386 | dvi-am html html-am info info-am install install-am \ 387 | install-data install-data-am install-dvi install-dvi-am \ 388 | install-exec install-exec-am install-html install-html-am \ 389 | install-info install-info-am install-man install-pdf \ 390 | install-pdf-am install-ps install-ps-am install-strip \ 391 | installcheck installcheck-am installdirs maintainer-clean \ 392 | maintainer-clean-generic mostlyclean mostlyclean-generic \ 393 | mostlyclean-libtool pdf pdf-am ps ps-am uninstall uninstall-am 394 | 395 | 396 | test_prepare: test_prepare_start example_table test_prepare_sql test_results 397 | @echo "$@: Test environment ready!" 398 | @echo "$@: You can now run \`make test\`" 399 | 400 | test_prepare_start: 401 | @echo "$@: Preparing test environment (this may take a while)..." 402 | 403 | test_prepare_sql: 404 | $(MYSQL) --local-infile=1 $(MYSQL_OPTIONS) < test_prepare.sql 405 | 406 | example_table: 407 | ./generate_random_data 1000000 > example_table 408 | 409 | test_results: $(ALL_TESTS:%.test=%.result) 410 | 411 | %.result: %.test 412 | ./test2result < $*.test > $@ 413 | 414 | test_clean: 415 | $(MYSQL) $(MYSQL_OPTIONS) < test_clean.sql 416 | 417 | %.run : %.test 418 | $(MYSQLTEST) $(MYSQL_OPTIONS) -R $*.result < $*.test 419 | 420 | test: $(ALL_TESTS:%.test=%.run) 421 | 422 | .PHONY: test_prepare test_prepare_start example_table test_prepare_sql test_results test 423 | 424 | # Tell versions [3.59,3.63) of GNU make to not export all variables. 425 | # Otherwise a system limit (for SysV at least) may be exceeded. 426 | .NOEXPORT: 427 | -------------------------------------------------------------------------------- /m4/ltoptions.m4: -------------------------------------------------------------------------------- 1 | # Helper functions for option handling. -*- Autoconf -*- 2 | # 3 | # Copyright (C) 2004, 2005, 2007, 2008, 2009 Free Software Foundation, 4 | # Inc. 5 | # Written by Gary V. Vaughan, 2004 6 | # 7 | # This file is free software; the Free Software Foundation gives 8 | # unlimited permission to copy and/or distribute it, with or without 9 | # modifications, as long as this notice is preserved. 10 | 11 | # serial 7 ltoptions.m4 12 | 13 | # This is to help aclocal find these macros, as it can't see m4_define. 14 | AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])]) 15 | 16 | 17 | # _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME) 18 | # ------------------------------------------ 19 | m4_define([_LT_MANGLE_OPTION], 20 | [[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])]) 21 | 22 | 23 | # _LT_SET_OPTION(MACRO-NAME, OPTION-NAME) 24 | # --------------------------------------- 25 | # Set option OPTION-NAME for macro MACRO-NAME, and if there is a 26 | # matching handler defined, dispatch to it. Other OPTION-NAMEs are 27 | # saved as a flag. 28 | m4_define([_LT_SET_OPTION], 29 | [m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl 30 | m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]), 31 | _LT_MANGLE_DEFUN([$1], [$2]), 32 | [m4_warning([Unknown $1 option `$2'])])[]dnl 33 | ]) 34 | 35 | 36 | # _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET]) 37 | # ------------------------------------------------------------ 38 | # Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. 39 | m4_define([_LT_IF_OPTION], 40 | [m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])]) 41 | 42 | 43 | # _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET) 44 | # ------------------------------------------------------- 45 | # Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME 46 | # are set. 47 | m4_define([_LT_UNLESS_OPTIONS], 48 | [m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), 49 | [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option), 50 | [m4_define([$0_found])])])[]dnl 51 | m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3 52 | ])[]dnl 53 | ]) 54 | 55 | 56 | # _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST) 57 | # ---------------------------------------- 58 | # OPTION-LIST is a space-separated list of Libtool options associated 59 | # with MACRO-NAME. If any OPTION has a matching handler declared with 60 | # LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about 61 | # the unknown option and exit. 62 | m4_defun([_LT_SET_OPTIONS], 63 | [# Set options 64 | m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), 65 | [_LT_SET_OPTION([$1], _LT_Option)]) 66 | 67 | m4_if([$1],[LT_INIT],[ 68 | dnl 69 | dnl Simply set some default values (i.e off) if boolean options were not 70 | dnl specified: 71 | _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no 72 | ]) 73 | _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no 74 | ]) 75 | dnl 76 | dnl If no reference was made to various pairs of opposing options, then 77 | dnl we run the default mode handler for the pair. For example, if neither 78 | dnl `shared' nor `disable-shared' was passed, we enable building of shared 79 | dnl archives by default: 80 | _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED]) 81 | _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC]) 82 | _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC]) 83 | _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install], 84 | [_LT_ENABLE_FAST_INSTALL]) 85 | ]) 86 | ])# _LT_SET_OPTIONS 87 | 88 | 89 | ## --------------------------------- ## 90 | ## Macros to handle LT_INIT options. ## 91 | ## --------------------------------- ## 92 | 93 | # _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME) 94 | # ----------------------------------------- 95 | m4_define([_LT_MANGLE_DEFUN], 96 | [[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])]) 97 | 98 | 99 | # LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE) 100 | # ----------------------------------------------- 101 | m4_define([LT_OPTION_DEFINE], 102 | [m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl 103 | ])# LT_OPTION_DEFINE 104 | 105 | 106 | # dlopen 107 | # ------ 108 | LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes 109 | ]) 110 | 111 | AU_DEFUN([AC_LIBTOOL_DLOPEN], 112 | [_LT_SET_OPTION([LT_INIT], [dlopen]) 113 | AC_DIAGNOSE([obsolete], 114 | [$0: Remove this warning and the call to _LT_SET_OPTION when you 115 | put the `dlopen' option into LT_INIT's first parameter.]) 116 | ]) 117 | 118 | dnl aclocal-1.4 backwards compatibility: 119 | dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], []) 120 | 121 | 122 | # win32-dll 123 | # --------- 124 | # Declare package support for building win32 dll's. 125 | LT_OPTION_DEFINE([LT_INIT], [win32-dll], 126 | [enable_win32_dll=yes 127 | 128 | case $host in 129 | *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*) 130 | AC_CHECK_TOOL(AS, as, false) 131 | AC_CHECK_TOOL(DLLTOOL, dlltool, false) 132 | AC_CHECK_TOOL(OBJDUMP, objdump, false) 133 | ;; 134 | esac 135 | 136 | test -z "$AS" && AS=as 137 | _LT_DECL([], [AS], [1], [Assembler program])dnl 138 | 139 | test -z "$DLLTOOL" && DLLTOOL=dlltool 140 | _LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl 141 | 142 | test -z "$OBJDUMP" && OBJDUMP=objdump 143 | _LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl 144 | ])# win32-dll 145 | 146 | AU_DEFUN([AC_LIBTOOL_WIN32_DLL], 147 | [AC_REQUIRE([AC_CANONICAL_HOST])dnl 148 | _LT_SET_OPTION([LT_INIT], [win32-dll]) 149 | AC_DIAGNOSE([obsolete], 150 | [$0: Remove this warning and the call to _LT_SET_OPTION when you 151 | put the `win32-dll' option into LT_INIT's first parameter.]) 152 | ]) 153 | 154 | dnl aclocal-1.4 backwards compatibility: 155 | dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], []) 156 | 157 | 158 | # _LT_ENABLE_SHARED([DEFAULT]) 159 | # ---------------------------- 160 | # implement the --enable-shared flag, and supports the `shared' and 161 | # `disable-shared' LT_INIT options. 162 | # DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. 163 | m4_define([_LT_ENABLE_SHARED], 164 | [m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl 165 | AC_ARG_ENABLE([shared], 166 | [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@], 167 | [build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])], 168 | [p=${PACKAGE-default} 169 | case $enableval in 170 | yes) enable_shared=yes ;; 171 | no) enable_shared=no ;; 172 | *) 173 | enable_shared=no 174 | # Look at the argument we got. We use all the common list separators. 175 | lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," 176 | for pkg in $enableval; do 177 | IFS="$lt_save_ifs" 178 | if test "X$pkg" = "X$p"; then 179 | enable_shared=yes 180 | fi 181 | done 182 | IFS="$lt_save_ifs" 183 | ;; 184 | esac], 185 | [enable_shared=]_LT_ENABLE_SHARED_DEFAULT) 186 | 187 | _LT_DECL([build_libtool_libs], [enable_shared], [0], 188 | [Whether or not to build shared libraries]) 189 | ])# _LT_ENABLE_SHARED 190 | 191 | LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])]) 192 | LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])]) 193 | 194 | # Old names: 195 | AC_DEFUN([AC_ENABLE_SHARED], 196 | [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared]) 197 | ]) 198 | 199 | AC_DEFUN([AC_DISABLE_SHARED], 200 | [_LT_SET_OPTION([LT_INIT], [disable-shared]) 201 | ]) 202 | 203 | AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) 204 | AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) 205 | 206 | dnl aclocal-1.4 backwards compatibility: 207 | dnl AC_DEFUN([AM_ENABLE_SHARED], []) 208 | dnl AC_DEFUN([AM_DISABLE_SHARED], []) 209 | 210 | 211 | 212 | # _LT_ENABLE_STATIC([DEFAULT]) 213 | # ---------------------------- 214 | # implement the --enable-static flag, and support the `static' and 215 | # `disable-static' LT_INIT options. 216 | # DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. 217 | m4_define([_LT_ENABLE_STATIC], 218 | [m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl 219 | AC_ARG_ENABLE([static], 220 | [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@], 221 | [build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])], 222 | [p=${PACKAGE-default} 223 | case $enableval in 224 | yes) enable_static=yes ;; 225 | no) enable_static=no ;; 226 | *) 227 | enable_static=no 228 | # Look at the argument we got. We use all the common list separators. 229 | lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," 230 | for pkg in $enableval; do 231 | IFS="$lt_save_ifs" 232 | if test "X$pkg" = "X$p"; then 233 | enable_static=yes 234 | fi 235 | done 236 | IFS="$lt_save_ifs" 237 | ;; 238 | esac], 239 | [enable_static=]_LT_ENABLE_STATIC_DEFAULT) 240 | 241 | _LT_DECL([build_old_libs], [enable_static], [0], 242 | [Whether or not to build static libraries]) 243 | ])# _LT_ENABLE_STATIC 244 | 245 | LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])]) 246 | LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])]) 247 | 248 | # Old names: 249 | AC_DEFUN([AC_ENABLE_STATIC], 250 | [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static]) 251 | ]) 252 | 253 | AC_DEFUN([AC_DISABLE_STATIC], 254 | [_LT_SET_OPTION([LT_INIT], [disable-static]) 255 | ]) 256 | 257 | AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) 258 | AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) 259 | 260 | dnl aclocal-1.4 backwards compatibility: 261 | dnl AC_DEFUN([AM_ENABLE_STATIC], []) 262 | dnl AC_DEFUN([AM_DISABLE_STATIC], []) 263 | 264 | 265 | 266 | # _LT_ENABLE_FAST_INSTALL([DEFAULT]) 267 | # ---------------------------------- 268 | # implement the --enable-fast-install flag, and support the `fast-install' 269 | # and `disable-fast-install' LT_INIT options. 270 | # DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. 271 | m4_define([_LT_ENABLE_FAST_INSTALL], 272 | [m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl 273 | AC_ARG_ENABLE([fast-install], 274 | [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], 275 | [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], 276 | [p=${PACKAGE-default} 277 | case $enableval in 278 | yes) enable_fast_install=yes ;; 279 | no) enable_fast_install=no ;; 280 | *) 281 | enable_fast_install=no 282 | # Look at the argument we got. We use all the common list separators. 283 | lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," 284 | for pkg in $enableval; do 285 | IFS="$lt_save_ifs" 286 | if test "X$pkg" = "X$p"; then 287 | enable_fast_install=yes 288 | fi 289 | done 290 | IFS="$lt_save_ifs" 291 | ;; 292 | esac], 293 | [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT) 294 | 295 | _LT_DECL([fast_install], [enable_fast_install], [0], 296 | [Whether or not to optimize for fast installation])dnl 297 | ])# _LT_ENABLE_FAST_INSTALL 298 | 299 | LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])]) 300 | LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])]) 301 | 302 | # Old names: 303 | AU_DEFUN([AC_ENABLE_FAST_INSTALL], 304 | [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install]) 305 | AC_DIAGNOSE([obsolete], 306 | [$0: Remove this warning and the call to _LT_SET_OPTION when you put 307 | the `fast-install' option into LT_INIT's first parameter.]) 308 | ]) 309 | 310 | AU_DEFUN([AC_DISABLE_FAST_INSTALL], 311 | [_LT_SET_OPTION([LT_INIT], [disable-fast-install]) 312 | AC_DIAGNOSE([obsolete], 313 | [$0: Remove this warning and the call to _LT_SET_OPTION when you put 314 | the `disable-fast-install' option into LT_INIT's first parameter.]) 315 | ]) 316 | 317 | dnl aclocal-1.4 backwards compatibility: 318 | dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], []) 319 | dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], []) 320 | 321 | 322 | # _LT_WITH_PIC([MODE]) 323 | # -------------------- 324 | # implement the --with-pic flag, and support the `pic-only' and `no-pic' 325 | # LT_INIT options. 326 | # MODE is either `yes' or `no'. If omitted, it defaults to `both'. 327 | m4_define([_LT_WITH_PIC], 328 | [AC_ARG_WITH([pic], 329 | [AS_HELP_STRING([--with-pic@<:@=PKGS@:>@], 330 | [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], 331 | [lt_p=${PACKAGE-default} 332 | case $withval in 333 | yes|no) pic_mode=$withval ;; 334 | *) 335 | pic_mode=default 336 | # Look at the argument we got. We use all the common list separators. 337 | lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," 338 | for lt_pkg in $withval; do 339 | IFS="$lt_save_ifs" 340 | if test "X$lt_pkg" = "X$lt_p"; then 341 | pic_mode=yes 342 | fi 343 | done 344 | IFS="$lt_save_ifs" 345 | ;; 346 | esac], 347 | [pic_mode=default]) 348 | 349 | test -z "$pic_mode" && pic_mode=m4_default([$1], [default]) 350 | 351 | _LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl 352 | ])# _LT_WITH_PIC 353 | 354 | LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])]) 355 | LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])]) 356 | 357 | # Old name: 358 | AU_DEFUN([AC_LIBTOOL_PICMODE], 359 | [_LT_SET_OPTION([LT_INIT], [pic-only]) 360 | AC_DIAGNOSE([obsolete], 361 | [$0: Remove this warning and the call to _LT_SET_OPTION when you 362 | put the `pic-only' option into LT_INIT's first parameter.]) 363 | ]) 364 | 365 | dnl aclocal-1.4 backwards compatibility: 366 | dnl AC_DEFUN([AC_LIBTOOL_PICMODE], []) 367 | 368 | ## ----------------- ## 369 | ## LTDL_INIT Options ## 370 | ## ----------------- ## 371 | 372 | m4_define([_LTDL_MODE], []) 373 | LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive], 374 | [m4_define([_LTDL_MODE], [nonrecursive])]) 375 | LT_OPTION_DEFINE([LTDL_INIT], [recursive], 376 | [m4_define([_LTDL_MODE], [recursive])]) 377 | LT_OPTION_DEFINE([LTDL_INIT], [subproject], 378 | [m4_define([_LTDL_MODE], [subproject])]) 379 | 380 | m4_define([_LTDL_TYPE], []) 381 | LT_OPTION_DEFINE([LTDL_INIT], [installable], 382 | [m4_define([_LTDL_TYPE], [installable])]) 383 | LT_OPTION_DEFINE([LTDL_INIT], [convenience], 384 | [m4_define([_LTDL_TYPE], [convenience])]) 385 | -------------------------------------------------------------------------------- /config/install-sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # install - install a program, script, or datafile 3 | 4 | scriptversion=2011-01-19.21; # UTC 5 | 6 | # This originates from X11R5 (mit/util/scripts/install.sh), which was 7 | # later released in X11R6 (xc/config/util/install.sh) with the 8 | # following copyright and license. 9 | # 10 | # Copyright (C) 1994 X Consortium 11 | # 12 | # Permission is hereby granted, free of charge, to any person obtaining a copy 13 | # of this software and associated documentation files (the "Software"), to 14 | # deal in the Software without restriction, including without limitation the 15 | # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 16 | # sell copies of the Software, and to permit persons to whom the Software is 17 | # furnished to do so, subject to the following conditions: 18 | # 19 | # The above copyright notice and this permission notice shall be included in 20 | # all copies or substantial portions of the Software. 21 | # 22 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | # X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 26 | # AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- 27 | # TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 28 | # 29 | # Except as contained in this notice, the name of the X Consortium shall not 30 | # be used in advertising or otherwise to promote the sale, use or other deal- 31 | # ings in this Software without prior written authorization from the X Consor- 32 | # tium. 33 | # 34 | # 35 | # FSF changes to this file are in the public domain. 36 | # 37 | # Calling this script install-sh is preferred over install.sh, to prevent 38 | # `make' implicit rules from creating a file called install from it 39 | # when there is no Makefile. 40 | # 41 | # This script is compatible with the BSD install script, but was written 42 | # from scratch. 43 | 44 | nl=' 45 | ' 46 | IFS=" "" $nl" 47 | 48 | # set DOITPROG to echo to test this script 49 | 50 | # Don't use :- since 4.3BSD and earlier shells don't like it. 51 | doit=${DOITPROG-} 52 | if test -z "$doit"; then 53 | doit_exec=exec 54 | else 55 | doit_exec=$doit 56 | fi 57 | 58 | # Put in absolute file names if you don't have them in your path; 59 | # or use environment vars. 60 | 61 | chgrpprog=${CHGRPPROG-chgrp} 62 | chmodprog=${CHMODPROG-chmod} 63 | chownprog=${CHOWNPROG-chown} 64 | cmpprog=${CMPPROG-cmp} 65 | cpprog=${CPPROG-cp} 66 | mkdirprog=${MKDIRPROG-mkdir} 67 | mvprog=${MVPROG-mv} 68 | rmprog=${RMPROG-rm} 69 | stripprog=${STRIPPROG-strip} 70 | 71 | posix_glob='?' 72 | initialize_posix_glob=' 73 | test "$posix_glob" != "?" || { 74 | if (set -f) 2>/dev/null; then 75 | posix_glob= 76 | else 77 | posix_glob=: 78 | fi 79 | } 80 | ' 81 | 82 | posix_mkdir= 83 | 84 | # Desired mode of installed file. 85 | mode=0755 86 | 87 | chgrpcmd= 88 | chmodcmd=$chmodprog 89 | chowncmd= 90 | mvcmd=$mvprog 91 | rmcmd="$rmprog -f" 92 | stripcmd= 93 | 94 | src= 95 | dst= 96 | dir_arg= 97 | dst_arg= 98 | 99 | copy_on_change=false 100 | no_target_directory= 101 | 102 | usage="\ 103 | Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE 104 | or: $0 [OPTION]... SRCFILES... DIRECTORY 105 | or: $0 [OPTION]... -t DIRECTORY SRCFILES... 106 | or: $0 [OPTION]... -d DIRECTORIES... 107 | 108 | In the 1st form, copy SRCFILE to DSTFILE. 109 | In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. 110 | In the 4th, create DIRECTORIES. 111 | 112 | Options: 113 | --help display this help and exit. 114 | --version display version info and exit. 115 | 116 | -c (ignored) 117 | -C install only if different (preserve the last data modification time) 118 | -d create directories instead of installing files. 119 | -g GROUP $chgrpprog installed files to GROUP. 120 | -m MODE $chmodprog installed files to MODE. 121 | -o USER $chownprog installed files to USER. 122 | -s $stripprog installed files. 123 | -t DIRECTORY install into DIRECTORY. 124 | -T report an error if DSTFILE is a directory. 125 | 126 | Environment variables override the default commands: 127 | CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG 128 | RMPROG STRIPPROG 129 | " 130 | 131 | while test $# -ne 0; do 132 | case $1 in 133 | -c) ;; 134 | 135 | -C) copy_on_change=true;; 136 | 137 | -d) dir_arg=true;; 138 | 139 | -g) chgrpcmd="$chgrpprog $2" 140 | shift;; 141 | 142 | --help) echo "$usage"; exit $?;; 143 | 144 | -m) mode=$2 145 | case $mode in 146 | *' '* | *' '* | *' 147 | '* | *'*'* | *'?'* | *'['*) 148 | echo "$0: invalid mode: $mode" >&2 149 | exit 1;; 150 | esac 151 | shift;; 152 | 153 | -o) chowncmd="$chownprog $2" 154 | shift;; 155 | 156 | -s) stripcmd=$stripprog;; 157 | 158 | -t) dst_arg=$2 159 | # Protect names problematic for `test' and other utilities. 160 | case $dst_arg in 161 | -* | [=\(\)!]) dst_arg=./$dst_arg;; 162 | esac 163 | shift;; 164 | 165 | -T) no_target_directory=true;; 166 | 167 | --version) echo "$0 $scriptversion"; exit $?;; 168 | 169 | --) shift 170 | break;; 171 | 172 | -*) echo "$0: invalid option: $1" >&2 173 | exit 1;; 174 | 175 | *) break;; 176 | esac 177 | shift 178 | done 179 | 180 | if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then 181 | # When -d is used, all remaining arguments are directories to create. 182 | # When -t is used, the destination is already specified. 183 | # Otherwise, the last argument is the destination. Remove it from $@. 184 | for arg 185 | do 186 | if test -n "$dst_arg"; then 187 | # $@ is not empty: it contains at least $arg. 188 | set fnord "$@" "$dst_arg" 189 | shift # fnord 190 | fi 191 | shift # arg 192 | dst_arg=$arg 193 | # Protect names problematic for `test' and other utilities. 194 | case $dst_arg in 195 | -* | [=\(\)!]) dst_arg=./$dst_arg;; 196 | esac 197 | done 198 | fi 199 | 200 | if test $# -eq 0; then 201 | if test -z "$dir_arg"; then 202 | echo "$0: no input file specified." >&2 203 | exit 1 204 | fi 205 | # It's OK to call `install-sh -d' without argument. 206 | # This can happen when creating conditional directories. 207 | exit 0 208 | fi 209 | 210 | if test -z "$dir_arg"; then 211 | do_exit='(exit $ret); exit $ret' 212 | trap "ret=129; $do_exit" 1 213 | trap "ret=130; $do_exit" 2 214 | trap "ret=141; $do_exit" 13 215 | trap "ret=143; $do_exit" 15 216 | 217 | # Set umask so as not to create temps with too-generous modes. 218 | # However, 'strip' requires both read and write access to temps. 219 | case $mode in 220 | # Optimize common cases. 221 | *644) cp_umask=133;; 222 | *755) cp_umask=22;; 223 | 224 | *[0-7]) 225 | if test -z "$stripcmd"; then 226 | u_plus_rw= 227 | else 228 | u_plus_rw='% 200' 229 | fi 230 | cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; 231 | *) 232 | if test -z "$stripcmd"; then 233 | u_plus_rw= 234 | else 235 | u_plus_rw=,u+rw 236 | fi 237 | cp_umask=$mode$u_plus_rw;; 238 | esac 239 | fi 240 | 241 | for src 242 | do 243 | # Protect names problematic for `test' and other utilities. 244 | case $src in 245 | -* | [=\(\)!]) src=./$src;; 246 | esac 247 | 248 | if test -n "$dir_arg"; then 249 | dst=$src 250 | dstdir=$dst 251 | test -d "$dstdir" 252 | dstdir_status=$? 253 | else 254 | 255 | # Waiting for this to be detected by the "$cpprog $src $dsttmp" command 256 | # might cause directories to be created, which would be especially bad 257 | # if $src (and thus $dsttmp) contains '*'. 258 | if test ! -f "$src" && test ! -d "$src"; then 259 | echo "$0: $src does not exist." >&2 260 | exit 1 261 | fi 262 | 263 | if test -z "$dst_arg"; then 264 | echo "$0: no destination specified." >&2 265 | exit 1 266 | fi 267 | dst=$dst_arg 268 | 269 | # If destination is a directory, append the input filename; won't work 270 | # if double slashes aren't ignored. 271 | if test -d "$dst"; then 272 | if test -n "$no_target_directory"; then 273 | echo "$0: $dst_arg: Is a directory" >&2 274 | exit 1 275 | fi 276 | dstdir=$dst 277 | dst=$dstdir/`basename "$src"` 278 | dstdir_status=0 279 | else 280 | # Prefer dirname, but fall back on a substitute if dirname fails. 281 | dstdir=` 282 | (dirname "$dst") 2>/dev/null || 283 | expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ 284 | X"$dst" : 'X\(//\)[^/]' \| \ 285 | X"$dst" : 'X\(//\)$' \| \ 286 | X"$dst" : 'X\(/\)' \| . 2>/dev/null || 287 | echo X"$dst" | 288 | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ 289 | s//\1/ 290 | q 291 | } 292 | /^X\(\/\/\)[^/].*/{ 293 | s//\1/ 294 | q 295 | } 296 | /^X\(\/\/\)$/{ 297 | s//\1/ 298 | q 299 | } 300 | /^X\(\/\).*/{ 301 | s//\1/ 302 | q 303 | } 304 | s/.*/./; q' 305 | ` 306 | 307 | test -d "$dstdir" 308 | dstdir_status=$? 309 | fi 310 | fi 311 | 312 | obsolete_mkdir_used=false 313 | 314 | if test $dstdir_status != 0; then 315 | case $posix_mkdir in 316 | '') 317 | # Create intermediate dirs using mode 755 as modified by the umask. 318 | # This is like FreeBSD 'install' as of 1997-10-28. 319 | umask=`umask` 320 | case $stripcmd.$umask in 321 | # Optimize common cases. 322 | *[2367][2367]) mkdir_umask=$umask;; 323 | .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; 324 | 325 | *[0-7]) 326 | mkdir_umask=`expr $umask + 22 \ 327 | - $umask % 100 % 40 + $umask % 20 \ 328 | - $umask % 10 % 4 + $umask % 2 329 | `;; 330 | *) mkdir_umask=$umask,go-w;; 331 | esac 332 | 333 | # With -d, create the new directory with the user-specified mode. 334 | # Otherwise, rely on $mkdir_umask. 335 | if test -n "$dir_arg"; then 336 | mkdir_mode=-m$mode 337 | else 338 | mkdir_mode= 339 | fi 340 | 341 | posix_mkdir=false 342 | case $umask in 343 | *[123567][0-7][0-7]) 344 | # POSIX mkdir -p sets u+wx bits regardless of umask, which 345 | # is incompatible with FreeBSD 'install' when (umask & 300) != 0. 346 | ;; 347 | *) 348 | tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ 349 | trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 350 | 351 | if (umask $mkdir_umask && 352 | exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 353 | then 354 | if test -z "$dir_arg" || { 355 | # Check for POSIX incompatibilities with -m. 356 | # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or 357 | # other-writeable bit of parent directory when it shouldn't. 358 | # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. 359 | ls_ld_tmpdir=`ls -ld "$tmpdir"` 360 | case $ls_ld_tmpdir in 361 | d????-?r-*) different_mode=700;; 362 | d????-?--*) different_mode=755;; 363 | *) false;; 364 | esac && 365 | $mkdirprog -m$different_mode -p -- "$tmpdir" && { 366 | ls_ld_tmpdir_1=`ls -ld "$tmpdir"` 367 | test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" 368 | } 369 | } 370 | then posix_mkdir=: 371 | fi 372 | rmdir "$tmpdir/d" "$tmpdir" 373 | else 374 | # Remove any dirs left behind by ancient mkdir implementations. 375 | rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null 376 | fi 377 | trap '' 0;; 378 | esac;; 379 | esac 380 | 381 | if 382 | $posix_mkdir && ( 383 | umask $mkdir_umask && 384 | $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" 385 | ) 386 | then : 387 | else 388 | 389 | # The umask is ridiculous, or mkdir does not conform to POSIX, 390 | # or it failed possibly due to a race condition. Create the 391 | # directory the slow way, step by step, checking for races as we go. 392 | 393 | case $dstdir in 394 | /*) prefix='/';; 395 | [-=\(\)!]*) prefix='./';; 396 | *) prefix='';; 397 | esac 398 | 399 | eval "$initialize_posix_glob" 400 | 401 | oIFS=$IFS 402 | IFS=/ 403 | $posix_glob set -f 404 | set fnord $dstdir 405 | shift 406 | $posix_glob set +f 407 | IFS=$oIFS 408 | 409 | prefixes= 410 | 411 | for d 412 | do 413 | test X"$d" = X && continue 414 | 415 | prefix=$prefix$d 416 | if test -d "$prefix"; then 417 | prefixes= 418 | else 419 | if $posix_mkdir; then 420 | (umask=$mkdir_umask && 421 | $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break 422 | # Don't fail if two instances are running concurrently. 423 | test -d "$prefix" || exit 1 424 | else 425 | case $prefix in 426 | *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; 427 | *) qprefix=$prefix;; 428 | esac 429 | prefixes="$prefixes '$qprefix'" 430 | fi 431 | fi 432 | prefix=$prefix/ 433 | done 434 | 435 | if test -n "$prefixes"; then 436 | # Don't fail if two instances are running concurrently. 437 | (umask $mkdir_umask && 438 | eval "\$doit_exec \$mkdirprog $prefixes") || 439 | test -d "$dstdir" || exit 1 440 | obsolete_mkdir_used=true 441 | fi 442 | fi 443 | fi 444 | 445 | if test -n "$dir_arg"; then 446 | { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && 447 | { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && 448 | { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || 449 | test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 450 | else 451 | 452 | # Make a couple of temp file names in the proper directory. 453 | dsttmp=$dstdir/_inst.$$_ 454 | rmtmp=$dstdir/_rm.$$_ 455 | 456 | # Trap to clean up those temp files at exit. 457 | trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 458 | 459 | # Copy the file name to the temp name. 460 | (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && 461 | 462 | # and set any options; do chmod last to preserve setuid bits. 463 | # 464 | # If any of these fail, we abort the whole thing. If we want to 465 | # ignore errors from any of these, just make sure not to ignore 466 | # errors from the above "$doit $cpprog $src $dsttmp" command. 467 | # 468 | { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && 469 | { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && 470 | { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && 471 | { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && 472 | 473 | # If -C, don't bother to copy if it wouldn't change the file. 474 | if $copy_on_change && 475 | old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && 476 | new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && 477 | 478 | eval "$initialize_posix_glob" && 479 | $posix_glob set -f && 480 | set X $old && old=:$2:$4:$5:$6 && 481 | set X $new && new=:$2:$4:$5:$6 && 482 | $posix_glob set +f && 483 | 484 | test "$old" = "$new" && 485 | $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 486 | then 487 | rm -f "$dsttmp" 488 | else 489 | # Rename the file to the real destination. 490 | $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || 491 | 492 | # The rename failed, perhaps because mv can't rename something else 493 | # to itself, or perhaps because mv is so ancient that it does not 494 | # support -f. 495 | { 496 | # Now remove or move aside any old file at destination location. 497 | # We try this two ways since rm can't unlink itself on some 498 | # systems and the destination file might be busy for other 499 | # reasons. In this case, the final cleanup might fail but the new 500 | # file should still install successfully. 501 | { 502 | test ! -f "$dst" || 503 | $doit $rmcmd -f "$dst" 2>/dev/null || 504 | { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && 505 | { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } 506 | } || 507 | { echo "$0: cannot unlink or rename $dst" >&2 508 | (exit 1); exit 1 509 | } 510 | } && 511 | 512 | # Now rename the file to the real destination. 513 | $doit $mvcmd "$dsttmp" "$dst" 514 | } 515 | fi || exit 1 516 | 517 | trap '' 0 518 | fi 519 | done 520 | 521 | # Local variables: 522 | # eval: (add-hook 'write-file-hooks 'time-stamp) 523 | # time-stamp-start: "scriptversion=" 524 | # time-stamp-format: "%:y-%02m-%02d.%02H" 525 | # time-stamp-time-zone: "UTC" 526 | # time-stamp-end: "; # UTC" 527 | # End: 528 | --------------------------------------------------------------------------------