From b7351509304c144b626436c66e44afbf508461dc Mon Sep 17 00:00:00 2001 From: kevin Date: Mon, 13 Feb 2023 13:37:16 +0800 Subject: [PATCH] feat(tianmu): add multi-thread aggregation of group by (#422) (#1279) Documentation for mysql aggregation https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions-and-modifiers.html Functional Requirements: Consistent with aggregation conditions handled by existing logic The Aggregate function is used as the entry and ResultSender is used as the result output Performance Requirements: Table data limit: The upper limit of a physical drive The memory limit is exceeded. Procedure Memory usage limit: Add parameters to control the maximum amount of memory that can be used for aggregation Otherwise temporary disk files if the limit is exceeded Execution time limit: Under the same conditions, it is in the same order of magnitude as InnoDB aggregate query at most Aim to take less time than InnoDB for aggregated queries --- mysql-test/include/default_mysqld.cnf | 4 + mysql-test/suite/tianmu/r/issue422.result | 681 +++ mysql-test/suite/tianmu/r/issue790.result | 976 ++-- .../tianmu/r/out_of_range_issue1151.result | 70 - mysql-test/suite/tianmu/r/select_joins.result | 2 +- mysql-test/suite/tianmu/t/issue422.test | 414 ++ .../tianmu/t/out_of_range_issue1151.test | 124 +- scripts/my.cnf.sample | 19 + storage/tianmu/core/aggregation_algorithm.cpp | 83 +- storage/tianmu/core/aggregation_algorithm.h | 2 +- storage/tianmu/core/engine.cpp | 2 +- storage/tianmu/core/pack_guardian.cpp | 438 +- storage/tianmu/core/pack_guardian.h | 18 + storage/tianmu/core/temp_table.cpp | 4714 ++++++++--------- storage/tianmu/core/tianmu_attr.cpp | 20 +- storage/tianmu/core/value_or_null.cpp | 10 +- storage/tianmu/handler/ha_tianmu.cpp | 18 +- storage/tianmu/system/configuration.cpp | 3 + storage/tianmu/system/configuration.h | 8 + 19 files changed, 4473 insertions(+), 3133 deletions(-) create mode 100644 mysql-test/suite/tianmu/r/issue422.result create mode 100644 mysql-test/suite/tianmu/t/issue422.test diff --git a/mysql-test/include/default_mysqld.cnf b/mysql-test/include/default_mysqld.cnf index 0ce12ce31..afdef0c8f 100644 --- a/mysql-test/include/default_mysqld.cnf +++ b/mysql-test/include/default_mysqld.cnf @@ -81,3 +81,7 @@ loose-show-compatibility-56=ON tianmu_insert_delayed = 0 tianmu_ini_allowmysqlquerypath=1 +tianmu_groupby_parallel_degree=0 +tianmu_force_hashjoin=0 +tianmu_join_parallel=0 + diff --git a/mysql-test/suite/tianmu/r/issue422.result b/mysql-test/suite/tianmu/r/issue422.result new file mode 100644 index 000000000..1e696c88b --- /dev/null +++ b/mysql-test/suite/tianmu/r/issue422.result @@ -0,0 +1,681 @@ +DROP DATABASE IF EXISTS issue422_test; +CREATE DATABASE issue422_test; +USE issue422_test; +DROP TABLE IF EXISTS test1; +CREATE TABLE t1(id int, name varchar(20)) ENGINE=TIANMU DEFAULT CHARSET=utf8mb4; +drop procedure if exists idata; +create procedure idata(in num INT) +begin +declare i int; +set i=1; +while(i<=num) do +if (i < 200) then +insert into t1 values(i, 'James'); +elseif (i >= 200 && i < 1500) then +insert into t1 values(i, 'Lily'); +else +insert into t1 values(i, 'Kevin'); +end if; +set i=i+1; +end while; +end // +call idata(3000); +set global tianmu_slow_query_record_interval=0; +set global tianmu_groupby_parallel_rows_minimum=1000; +set global tianmu_groupby_parallel_degree=0; +select sum(id),name from t1 group by name order by name; +sum(id) name +19900 James +3377250 Kevin +1104350 Lily +set global tianmu_groupby_parallel_degree=2; +select sum(id),name from t1 group by name order by name; +sum(id) name +19900 James +3377250 Kevin +1104350 Lily +set global tianmu_slow_query_record_interval=2; +drop table t1; +CREATE TABLE t1 ( +spID int(10) unsigned, +userID int(10) unsigned, +score int(5) unsigned, +lsg char(40) +) ENGINE=TIANMU; +INSERT INTO t1 VALUES (1,1,1,''); +INSERT INTO t1 VALUES (2,2,2,''); +INSERT INTO t1 VALUES (2,1,1,''); +INSERT INTO t1 VALUES (3,3,3,''); +CREATE TABLE t2 ( +userID int(10), +niName char(15), +passwd char(8), +mail char(50), +vName char(30), +nName char(40), +adr char(60), +plz char(5), +ort char(35), +land char(20) +) ENGINE=TIANMU; +INSERT INTO t2 VALUES (1,'name','pass','mail','v','n','adr','1','1','1'); +INSERT INTO t2 VALUES (2,'name','pass','mail','v','n','adr','1','1','1'); +INSERT INTO t2 VALUES (3,'name','pass','mail','v','n','adr','1','1','1'); +INSERT INTO t2 VALUES (4,'name','pass','mail','v','n','adr','1','1','1'); +INSERT INTO t2 VALUES (5,'name','pass','mail','v','n','adr','1','1','1'); +SELECT t2.userid, MIN(t1.score) FROM t1, t2 WHERE t1.userID=t2.userID GROUP BY t2.userid; +userid MIN(t1.score) +1 1 +2 2 +3 3 +SELECT t2.userid, MIN(t1.score) FROM t1, t2 WHERE t1.userID=t2.userID GROUP BY t2.userid ORDER BY NULL; +userid MIN(t1.score) +1 1 +2 2 +3 3 +SELECT t2.userid, MIN(t1.score) FROM t1, t2 WHERE t1.userID=t2.userID AND t1.spID=2 GROUP BY t2.userid; +userid MIN(t1.score) +1 1 +2 2 +SELECT t2.userid, MIN(t1.score+0.0) FROM t1, t2 WHERE t1.userID=t2.userID AND t1.spID=2 GROUP BY t2.userid; +userid MIN(t1.score+0.0) +1 1.0 +2 2.0 +SELECT t2.userid, MIN(t1.score+0.0) FROM t1, t2 WHERE t1.userID=t2.userID AND t1.spID=2 GROUP BY t2.userid ORDER BY NULL; +userid MIN(t1.score+0.0) +1 1.0 +2 2.0 +drop table t1; +drop table t2; +CREATE TABLE t1 +( +t1_INT INT DEFAULT 0, +t1_double DOUBLE, +t1_float FLOAT, +t1_blob BLOB, +t1_text TEXT, +t1_char CHAR(1), +t1_varchar VARCHAR(255) DEFAULT 'hello world!', +t1_datetime DATETIME +)ENGINE=TIANMU; +INSERT INTO t1 (t1_INT, t1_double, t1_float, t1_blob, t1_text, t1_char, t1_datetime) +VALUES(20368547, -3.797693231E+108, -7.402866E+18, repeat('b',100), repeat('b',100), 'b', '2387-11-08 11:22:30.123'); +INSERT INTO t1 (t1_INT, t1_double, t1_float, t1_blob, t1_text, t1_char, t1_datetime) +VALUES(303685, -4.797693231, -8.402866, repeat('b',101), repeat('b',101), 'b', '3387-11-08 11:22:30.123'); +INSERT INTO t1 (t1_INT, t1_double, t1_float, t1_blob, t1_text, t1_char, t1_datetime) +VALUES(403685, +54.797693231, +8.402866, repeat('c',101), repeat('c',101), 'c', '3387-11-08 11:22:30.123'); +INSERT INTO t1 (t1_INT, t1_double, t1_float, t1_blob, t1_text, t1_char, t1_datetime) +VALUES(403685, +54.797693231, +8.402866, repeat('c',101), repeat('c',101), 'c', '3387-11-08 11:22:30.123'); +INSERT INTO t1 (t1_INT, t1_double, t1_float, t1_blob, t1_text, t1_char, t1_datetime) +VALUES(403685, +54.797693231, +8.402866, repeat('c',101), repeat('c',101), 'c', '3387-11-08 11:22:30.123'); +INSERT INTO t1 (t1_INT, t1_double, t1_float, t1_blob, t1_text, t1_char, t1_datetime) +VALUES(40385, +54.797693231, +8.402866, repeat('c',101), repeat('c',101), 'c', '3387-11-08 11:22:30.123'); +INSERT INTO t1 (t1_INT, t1_double, t1_float, t1_blob, t1_text, t1_char, t1_datetime) +VALUES(403685, +54.797693231, +8.402866, repeat('c',101), repeat('c',101), 'c', '3387-11-08 11:22:30.123'); +INSERT INTO t1 (t1_INT, t1_double, t1_float, t1_blob, t1_text, t1_char, t1_datetime) +VALUES(403685, +54.797693231, +8.402866, repeat('c',101), repeat('c',101), 'c', '3387-11-08 11:22:30.123'); +INSERT INTO t1 (t1_INT, t1_double, t1_float, t1_blob, t1_text, t1_char, t1_datetime) +VALUES(40368, +54.797693231, +8.402866, repeat('2',102), repeat('d',102), 'd', '4387-11-08 11:22:30.123'); +INSERT INTO t1 (t1_INT, t1_double, t1_float, t1_blob, t1_text, t1_char, t1_datetime) +VALUES(403, +54.797693231, +8.402866, repeat('2',102), repeat('d',102), 'd', '4387-11-08 11:22:30.123'); +INSERT INTO t1 (t1_INT, t1_double, t1_float, t1_blob, t1_text, t1_char, t1_datetime) +VALUES(403685, +54.797693231, +8.402866, repeat('2',102), repeat('d',102), 'd', '4387-11-08 11:22:30.123'); +INSERT INTO t1 VALUES(NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO t1 VALUES(NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO t1 VALUES(NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +SELECT * FROM t1; +t1_INT t1_double t1_float t1_blob t1_text t1_char t1_varchar t1_datetime +20368547 -3.797693231e108 -7.40287e18 bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb b hello world! 2387-11-08 11:22:30 +303685 -4.797693231 -8.40287 bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb b hello world! 3387-11-08 11:22:30 +403 54.797693231 8.40287 222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222 dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd d hello world! 4387-11-08 11:22:30 +40368 54.797693231 8.40287 222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222 dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd d hello world! 4387-11-08 11:22:30 +403685 54.797693231 8.40287 222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222 dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd d hello world! 4387-11-08 11:22:30 +403685 54.797693231 8.40287 ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc c hello world! 3387-11-08 11:22:30 +403685 54.797693231 8.40287 ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc c hello world! 3387-11-08 11:22:30 +403685 54.797693231 8.40287 ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc c hello world! 3387-11-08 11:22:30 +403685 54.797693231 8.40287 ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc c hello world! 3387-11-08 11:22:30 +403685 54.797693231 8.40287 ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc c hello world! 3387-11-08 11:22:30 +40385 54.797693231 8.40287 ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc c hello world! 3387-11-08 11:22:30 +NULL NULL NULL NULL NULL NULL NULL NULL +NULL NULL NULL NULL NULL NULL NULL NULL +NULL NULL NULL NULL NULL NULL NULL NULL +SELECT COUNT(*) FROM t1 GROUP BY t1_INT; +COUNT(*) +1 +1 +1 +1 +1 +3 +6 +SELECT COUNT(*) FROM t1 GROUP BY t1_INT; +COUNT(*) +1 +1 +1 +1 +1 +3 +6 +SELECT COUNT(*) FROM t1 GROUP BY t1_INT; +COUNT(*) +1 +1 +1 +1 +1 +3 +6 +SELECT COUNT(*) FROM t1 GROUP BY t1_double; +COUNT(*) +1 +1 +3 +9 +SELECT COUNT(*) FROM t1 GROUP BY t1_float; +COUNT(*) +1 +1 +3 +9 +SELECT COUNT(*) FROM t1 GROUP BY t1_blob; +COUNT(*) +1 +1 +3 +3 +6 +SELECT COUNT(*) FROM t1 GROUP BY t1_text; +COUNT(*) +1 +1 +3 +3 +6 +SELECT COUNT(*) FROM t1 GROUP BY t1_char; +COUNT(*) +2 +3 +3 +6 +SELECT COUNT(*) FROM t1 GROUP BY t1_varchar; +COUNT(*) +11 +3 +SELECT COUNT(*) FROM t1 GROUP BY t1_datetime; +COUNT(*) +1 +3 +3 +7 +SELECT SUM(t1_INT) FROM t1 GROUP BY t1_INT; +SUM(t1_INT) +20368547 +2422110 +303685 +403 +40368 +40385 +NULL +SELECT SUM(t1_double) FROM t1 GROUP BY t1_float; +SUM(t1_double) +-3.797693231e108 +-4.797693231 +493.1792390789999 +NULL +SELECT SUM(DISTINCT t1_double) FROM t1 GROUP BY t1_float; +SUM(DISTINCT t1_double) +-3.797693231e108 +-4.797693231 +54.797693231 +NULL +SELECT COUNT(*) FROM t1 GROUP BY t1_INT; +COUNT(*) +1 +1 +1 +1 +1 +3 +6 +SELECT COUNT(*) FROM t1 GROUP BY t1_blob, t1_text, t1_char; +COUNT(*) +1 +1 +3 +3 +6 +SELECT COUNT(*) FROM t1 GROUP BY t1_varchar, t1_datetime; +COUNT(*) +1 +3 +3 +7 +SELECT COUNT(*) FROM t1 WHERE t1_blob IS NOT NULL GROUP BY t1_INT; +COUNT(*) +1 +1 +1 +1 +1 +6 +SELECT COUNT(*) FROM t1 WHERE t1_INT = 0 GROUP BY t1_blob, t1_text, t1_char; +COUNT(*) +SELECT COUNT(*) FROM t1 WHERE t1_char IN ('a', 'b') GROUP BY t1_varchar, t1_datetime; +COUNT(*) +1 +1 +SELECT COUNT(*) FROM t1 WHERE t1_varchar LIKE '%world%' GROUP BY t1_varchar, t1_datetime; +COUNT(*) +1 +3 +7 +SELECT COUNT(*) FROM t1 WHERE t1_INT != 0 AND t1_INT = 0 OR t1_INT IS NULL GROUP BY t1_varchar, t1_datetime; +COUNT(*) +3 +drop table t1; +CREATE TABLE t1 (t1_INT INT, t1_char CHAR(5))ENGINE=TIANMU; +CREATE TABLE t2 (t2_int INT, t2_char CHAR(5))ENGINE=TIANMU; +INSERT INTO t1 VALUES (NULL,''),(1,'aaa'),(2,'bbb'),(3,'aaa'),(4,'bbb'),(5,'aaa'),(6,'ccc'),(7,'bbb'); +INSERT INTO t2 VALUES (NULL,''),(1,'ooo'),(3,'iii'),(5,'ooo'),(7,'ooo'),(9,'kkkk'),(11,'iii'),(13,'ooo'); +SELECT COUNT(*) FROM t1, t2 WHERE t1.t1_INT = t2.t2_int GROUP BY t1.t1_INT; +COUNT(*) +1 +1 +1 +1 +SELECT COUNT(*) FROM t1, t2 WHERE t1.t1_INT = t2.t2_int GROUP BY t1.t1_char; +COUNT(*) +1 +3 +SELECT COUNT(*) FROM t1, t2 WHERE t1.t1_INT = t2.t2_int GROUP BY t2.t2_int; +COUNT(*) +1 +1 +1 +1 +SELECT COUNT(*) FROM t1, t2 WHERE t1.t1_INT = t2.t2_int GROUP BY t2.t2_char; +COUNT(*) +1 +3 +SELECT SUM(t1.t1_INT) FROM t1 LEFT JOIN t2 ON t1.t1_INT = t2.t2_int GROUP BY t1.t1_INT; +SUM(t1.t1_INT) +1 +2 +3 +4 +5 +6 +7 +NULL +SELECT SUM(t1.t1_INT) FROM t1 LEFT JOIN t2 ON t1.t1_INT = t2.t2_int GROUP BY t1.t1_char; +SUM(t1.t1_INT) +13 +6 +9 +NULL +SELECT SUM(t1.t1_INT) FROM t1 LEFT JOIN t2 ON t1.t1_INT = t2.t2_int GROUP BY t2.t2_int; +SUM(t1.t1_INT) +1 +12 +3 +5 +7 +SELECT SUM(t1.t1_INT) FROM t1 LEFT JOIN t2 ON t1.t1_INT = t2.t2_int GROUP BY t2.t2_char; +SUM(t1.t1_INT) +12 +13 +3 +SELECT SUM(t1.t1_INT) FROM t1 RIGHT JOIN t2 ON t1.t1_INT = t2.t2_int GROUP BY t1.t1_INT; +SUM(t1.t1_INT) +1 +3 +5 +7 +NULL +SELECT SUM(t1.t1_INT) FROM t1 RIGHT JOIN t2 ON t1.t1_INT = t2.t2_int GROUP BY t1.t1_char; +SUM(t1.t1_INT) +7 +9 +NULL +SELECT SUM(t1.t1_INT) FROM t1 RIGHT JOIN t2 ON t1.t1_INT = t2.t2_int GROUP BY t2.t2_int; +SUM(t1.t1_INT) +1 +3 +5 +7 +NULL +NULL +NULL +NULL +SELECT SUM(t1.t1_INT) FROM t1 RIGHT JOIN t2 ON t1.t1_INT = t2.t2_int GROUP BY t2.t2_char; +SUM(t1.t1_INT) +13 +3 +NULL +NULL +drop table t1; +drop table t2; +set global tianmu_groupby_parallel_rows_minimum=5; +set global tianmu_groupby_parallel_degree=2; +CREATE TABLE t1 ( +spID int(10) unsigned, +userID int(10) unsigned, +score int(5) unsigned, +lsg char(40) +) ENGINE=TIANMU; +INSERT INTO t1 VALUES (1,1,1,''); +INSERT INTO t1 VALUES (2,2,2,''); +INSERT INTO t1 VALUES (2,1,1,''); +INSERT INTO t1 VALUES (3,3,3,''); +CREATE TABLE t2 ( +userID int(10), +niName char(15), +passwd char(8), +mail char(50), +vName char(30), +nName char(40), +adr char(60), +plz char(5), +ort char(35), +land char(20) +) ENGINE=TIANMU; +INSERT INTO t2 VALUES (1,'name','pass','mail','v','n','adr','1','1','1'); +INSERT INTO t2 VALUES (2,'name','pass','mail','v','n','adr','1','1','1'); +INSERT INTO t2 VALUES (3,'name','pass','mail','v','n','adr','1','1','1'); +INSERT INTO t2 VALUES (4,'name','pass','mail','v','n','adr','1','1','1'); +INSERT INTO t2 VALUES (5,'name','pass','mail','v','n','adr','1','1','1'); +SELECT t2.userid, MIN(t1.score) FROM t1, t2 WHERE t1.userID=t2.userID GROUP BY t2.userid; +userid MIN(t1.score) +1 1 +2 2 +3 3 +SELECT t2.userid, MIN(t1.score) FROM t1, t2 WHERE t1.userID=t2.userID GROUP BY t2.userid ORDER BY NULL; +userid MIN(t1.score) +1 1 +2 2 +3 3 +SELECT t2.userid, MIN(t1.score) FROM t1, t2 WHERE t1.userID=t2.userID AND t1.spID=2 GROUP BY t2.userid; +userid MIN(t1.score) +1 1 +2 2 +SELECT t2.userid, MIN(t1.score+0.0) FROM t1, t2 WHERE t1.userID=t2.userID AND t1.spID=2 GROUP BY t2.userid; +userid MIN(t1.score+0.0) +1 1.0 +2 2.0 +SELECT t2.userid, MIN(t1.score+0.0) FROM t1, t2 WHERE t1.userID=t2.userID AND t1.spID=2 GROUP BY t2.userid ORDER BY NULL; +userid MIN(t1.score+0.0) +1 1.0 +2 2.0 +drop table t1; +drop table t2; +CREATE TABLE t1 +( +t1_INT INT DEFAULT 0, +t1_double DOUBLE, +t1_float FLOAT, +t1_blob BLOB, +t1_text TEXT, +t1_char CHAR(1), +t1_varchar VARCHAR(255) DEFAULT 'hello world!', +t1_datetime DATETIME +)ENGINE=TIANMU; +INSERT INTO t1 (t1_INT, t1_double, t1_float, t1_blob, t1_text, t1_char, t1_datetime) +VALUES(20368547, -3.797693231E+108, -7.402866E+18, repeat('b',100), repeat('b',100), 'b', '2387-11-08 11:22:30.123'); +INSERT INTO t1 (t1_INT, t1_double, t1_float, t1_blob, t1_text, t1_char, t1_datetime) +VALUES(303685, -4.797693231, -8.402866, repeat('b',101), repeat('b',101), 'b', '3387-11-08 11:22:30.123'); +INSERT INTO t1 (t1_INT, t1_double, t1_float, t1_blob, t1_text, t1_char, t1_datetime) +VALUES(403685, +54.797693231, +8.402866, repeat('c',101), repeat('c',101), 'c', '3387-11-08 11:22:30.123'); +INSERT INTO t1 (t1_INT, t1_double, t1_float, t1_blob, t1_text, t1_char, t1_datetime) +VALUES(403685, +54.797693231, +8.402866, repeat('c',101), repeat('c',101), 'c', '3387-11-08 11:22:30.123'); +INSERT INTO t1 (t1_INT, t1_double, t1_float, t1_blob, t1_text, t1_char, t1_datetime) +VALUES(403685, +54.797693231, +8.402866, repeat('c',101), repeat('c',101), 'c', '3387-11-08 11:22:30.123'); +INSERT INTO t1 (t1_INT, t1_double, t1_float, t1_blob, t1_text, t1_char, t1_datetime) +VALUES(40385, +54.797693231, +8.402866, repeat('c',101), repeat('c',101), 'c', '3387-11-08 11:22:30.123'); +INSERT INTO t1 (t1_INT, t1_double, t1_float, t1_blob, t1_text, t1_char, t1_datetime) +VALUES(403685, +54.797693231, +8.402866, repeat('c',101), repeat('c',101), 'c', '3387-11-08 11:22:30.123'); +INSERT INTO t1 (t1_INT, t1_double, t1_float, t1_blob, t1_text, t1_char, t1_datetime) +VALUES(403685, +54.797693231, +8.402866, repeat('c',101), repeat('c',101), 'c', '3387-11-08 11:22:30.123'); +INSERT INTO t1 (t1_INT, t1_double, t1_float, t1_blob, t1_text, t1_char, t1_datetime) +VALUES(40368, +54.797693231, +8.402866, repeat('2',102), repeat('d',102), 'd', '4387-11-08 11:22:30.123'); +INSERT INTO t1 (t1_INT, t1_double, t1_float, t1_blob, t1_text, t1_char, t1_datetime) +VALUES(403, +54.797693231, +8.402866, repeat('2',102), repeat('d',102), 'd', '4387-11-08 11:22:30.123'); +INSERT INTO t1 (t1_INT, t1_double, t1_float, t1_blob, t1_text, t1_char, t1_datetime) +VALUES(403685, +54.797693231, +8.402866, repeat('2',102), repeat('d',102), 'd', '4387-11-08 11:22:30.123'); +INSERT INTO t1 VALUES(NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO t1 VALUES(NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO t1 VALUES(NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +SELECT * FROM t1; +t1_INT t1_double t1_float t1_blob t1_text t1_char t1_varchar t1_datetime +20368547 -3.797693231e108 -7.40287e18 bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb b hello world! 2387-11-08 11:22:30 +303685 -4.797693231 -8.40287 bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb b hello world! 3387-11-08 11:22:30 +403 54.797693231 8.40287 222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222 dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd d hello world! 4387-11-08 11:22:30 +40368 54.797693231 8.40287 222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222 dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd d hello world! 4387-11-08 11:22:30 +403685 54.797693231 8.40287 222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222 dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd d hello world! 4387-11-08 11:22:30 +403685 54.797693231 8.40287 ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc c hello world! 3387-11-08 11:22:30 +403685 54.797693231 8.40287 ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc c hello world! 3387-11-08 11:22:30 +403685 54.797693231 8.40287 ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc c hello world! 3387-11-08 11:22:30 +403685 54.797693231 8.40287 ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc c hello world! 3387-11-08 11:22:30 +403685 54.797693231 8.40287 ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc c hello world! 3387-11-08 11:22:30 +40385 54.797693231 8.40287 ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc c hello world! 3387-11-08 11:22:30 +NULL NULL NULL NULL NULL NULL NULL NULL +NULL NULL NULL NULL NULL NULL NULL NULL +NULL NULL NULL NULL NULL NULL NULL NULL +SELECT COUNT(*) FROM t1 GROUP BY t1_INT; +COUNT(*) +1 +1 +1 +1 +1 +3 +6 +SELECT COUNT(*) FROM t1 GROUP BY t1_INT; +COUNT(*) +1 +1 +1 +1 +1 +3 +6 +SELECT COUNT(*) FROM t1 GROUP BY t1_INT; +COUNT(*) +1 +1 +1 +1 +1 +3 +6 +SELECT COUNT(*) FROM t1 GROUP BY t1_double; +COUNT(*) +1 +1 +3 +9 +SELECT COUNT(*) FROM t1 GROUP BY t1_float; +COUNT(*) +1 +1 +3 +9 +SELECT COUNT(*) FROM t1 GROUP BY t1_blob; +COUNT(*) +1 +1 +3 +3 +6 +SELECT COUNT(*) FROM t1 GROUP BY t1_text; +COUNT(*) +1 +1 +3 +3 +6 +SELECT COUNT(*) FROM t1 GROUP BY t1_char; +COUNT(*) +2 +3 +3 +6 +SELECT COUNT(*) FROM t1 GROUP BY t1_varchar; +COUNT(*) +11 +3 +SELECT COUNT(*) FROM t1 GROUP BY t1_datetime; +COUNT(*) +1 +3 +3 +7 +SELECT SUM(t1_INT) FROM t1 GROUP BY t1_INT; +SUM(t1_INT) +20368547 +2422110 +303685 +403 +40368 +40385 +NULL +SELECT SUM(t1_double) FROM t1 GROUP BY t1_float; +SUM(t1_double) +-3.797693231e108 +-4.797693231 +493.1792390789999 +NULL +SELECT SUM(DISTINCT t1_double) FROM t1 GROUP BY t1_float; +SUM(DISTINCT t1_double) +-3.797693231e108 +-4.797693231 +54.797693231 +NULL +SELECT COUNT(*) FROM t1 GROUP BY t1_INT; +COUNT(*) +1 +1 +1 +1 +1 +3 +6 +SELECT COUNT(*) FROM t1 GROUP BY t1_blob, t1_text, t1_char; +COUNT(*) +1 +1 +3 +3 +6 +SELECT COUNT(*) FROM t1 GROUP BY t1_varchar, t1_datetime; +COUNT(*) +1 +3 +3 +7 +SELECT COUNT(*) FROM t1 WHERE t1_blob IS NOT NULL GROUP BY t1_INT; +COUNT(*) +1 +1 +1 +1 +1 +6 +SELECT COUNT(*) FROM t1 WHERE t1_INT = 0 GROUP BY t1_blob, t1_text, t1_char; +COUNT(*) +SELECT COUNT(*) FROM t1 WHERE t1_char IN ('a', 'b') GROUP BY t1_varchar, t1_datetime; +COUNT(*) +1 +1 +SELECT COUNT(*) FROM t1 WHERE t1_varchar LIKE '%world%' GROUP BY t1_varchar, t1_datetime; +COUNT(*) +1 +3 +7 +SELECT COUNT(*) FROM t1 WHERE t1_INT != 0 AND t1_INT = 0 OR t1_INT IS NULL GROUP BY t1_varchar, t1_datetime; +COUNT(*) +3 +drop table t1; +CREATE TABLE t1 (t1_INT INT, t1_char CHAR(5))ENGINE=TIANMU; +CREATE TABLE t2 (t2_int INT, t2_char CHAR(5))ENGINE=TIANMU; +INSERT INTO t1 VALUES (NULL,''),(1,'aaa'),(2,'bbb'),(3,'aaa'),(4,'bbb'),(5,'aaa'),(6,'ccc'),(7,'bbb'); +INSERT INTO t2 VALUES (NULL,''),(1,'ooo'),(3,'iii'),(5,'ooo'),(7,'ooo'),(9,'kkkk'),(11,'iii'),(13,'ooo'); +SELECT COUNT(*) FROM t1, t2 WHERE t1.t1_INT = t2.t2_int GROUP BY t1.t1_INT; +COUNT(*) +1 +1 +1 +1 +SELECT COUNT(*) FROM t1, t2 WHERE t1.t1_INT = t2.t2_int GROUP BY t1.t1_char; +COUNT(*) +1 +3 +SELECT COUNT(*) FROM t1, t2 WHERE t1.t1_INT = t2.t2_int GROUP BY t2.t2_int; +COUNT(*) +1 +1 +1 +1 +SELECT COUNT(*) FROM t1, t2 WHERE t1.t1_INT = t2.t2_int GROUP BY t2.t2_char; +COUNT(*) +1 +3 +SELECT SUM(t1.t1_INT) FROM t1 LEFT JOIN t2 ON t1.t1_INT = t2.t2_int GROUP BY t1.t1_INT; +SUM(t1.t1_INT) +1 +2 +3 +4 +5 +6 +7 +NULL +SELECT SUM(t1.t1_INT) FROM t1 LEFT JOIN t2 ON t1.t1_INT = t2.t2_int GROUP BY t1.t1_char; +SUM(t1.t1_INT) +13 +6 +9 +NULL +SELECT SUM(t1.t1_INT) FROM t1 LEFT JOIN t2 ON t1.t1_INT = t2.t2_int GROUP BY t2.t2_int; +SUM(t1.t1_INT) +1 +12 +3 +5 +7 +SELECT SUM(t1.t1_INT) FROM t1 LEFT JOIN t2 ON t1.t1_INT = t2.t2_int GROUP BY t2.t2_char; +SUM(t1.t1_INT) +12 +13 +3 +SELECT SUM(t1.t1_INT) FROM t1 RIGHT JOIN t2 ON t1.t1_INT = t2.t2_int GROUP BY t1.t1_INT; +SUM(t1.t1_INT) +1 +3 +5 +7 +NULL +SELECT SUM(t1.t1_INT) FROM t1 RIGHT JOIN t2 ON t1.t1_INT = t2.t2_int GROUP BY t1.t1_char; +SUM(t1.t1_INT) +7 +9 +NULL +SELECT SUM(t1.t1_INT) FROM t1 RIGHT JOIN t2 ON t1.t1_INT = t2.t2_int GROUP BY t2.t2_int; +SUM(t1.t1_INT) +1 +3 +5 +7 +NULL +NULL +NULL +NULL +SELECT SUM(t1.t1_INT) FROM t1 RIGHT JOIN t2 ON t1.t1_INT = t2.t2_int GROUP BY t2.t2_char; +SUM(t1.t1_INT) +13 +3 +NULL +NULL +drop table t1; +drop table t2; +drop database issue422_test; diff --git a/mysql-test/suite/tianmu/r/issue790.result b/mysql-test/suite/tianmu/r/issue790.result index 7224c7e04..def77cb40 100644 --- a/mysql-test/suite/tianmu/r/issue790.result +++ b/mysql-test/suite/tianmu/r/issue790.result @@ -121,497 +121,474 @@ draw_category, transfer_course ) v; branch_org_name branch_org_code agency_org_name agency_org_code customer_name customer_code draw_category transfer_course balance -亚太 RGB03-210203 杭州 RGB03-210211 中国浙江 2107380 PL01 13 1500.00 -亚太 RGB03-210203 杭州 RGB03-210211 中国浙江 2107381 PL01 13 1500.00 -亚太 RGB03-210203 杭州 RGB03-210211 中国浙江 2108531 PL01 13 1500.00 -亚太 RGB03-210203 杭州 RGB03-210216 中国浙江 2105773 PL01 13 1000.00 -亚太 RGB03-210203 杭州 RGB03-210216 中国浙江 2107352 PL01 13 1000.00 -亚太 RGB03-210203 杭州 RGB03-210216 中国浙江 2108550 PL01 13 1500.00 -亚太 RGB03-210203 杭州 RGB03-210215 中国浙江 2107333 PL01 13 1500.00 -亚太 RGB03-210203 杭州 RGB03-210215 中国浙江 2107378 PL01 13 1500.00 -亚太 RGB03-210802 杭州 RGB03-210810 中国浙江 2057007 PL01 13 1000.00 -亚太 RGB03-210843 杭州 RGB03-210851 中国浙江 2106065 PL01 13 500.00 -亚太 RGB03-210930 杭州 RGB03-210938 中国浙江 2104535 PL01 13 500.00 -亚太 RGB03-210930 杭州 RGB03-210938 中国浙江 2106838 PL01 13 500.00 -亚太 RGB03-210930 杭州 RGB03-210938 中国浙江 2108700 PL01 13 500.00 -亚太 RGB03-210066 杭州 RGB03-210078 中国浙江 2104916 PL01 6 50000.00 -亚太 RGB03-210066 杭州 RGB03-210078 中国浙江 2107039 PL01 6 25500.00 -亚太 RGB03-210066 杭州 RGB03-210077 中国浙江 2104836 PL01 6 10000.00 -亚太 RGB03-210098 杭州 RGB03-210108 中国浙江 2103912 PL01 6 15145.00 -亚太 RGB03-210098 杭州 RGB03-210108 中国浙江 2103926 PL01 6 11600.00 -亚太 RGB03-210098 杭州 RGB03-210108 中国浙江 2103927 PL01 6 24443.14 -亚太 RGB03-210098 杭州 RGB03-210108 中国浙江 2103934 PL01 6 11550.00 -亚太 RGB03-210098 杭州 RGB03-210108 中国浙江 2103937 PL01 6 16600.00 -亚太 RGB03-210098 杭州 RGB03-210108 中国浙江 2103946 PL01 6 21911.30 -亚太 RGB03-210098 杭州 RGB03-210108 中国浙江 2103951 PL01 6 64855.02 -亚太 RGB03-210098 杭州 RGB03-210108 中国浙江 2108438 PL01 6 6600.00 -亚太 RGB03-210098 杭州 RGB03-210108 中国浙江 2108439 PL01 6 173360.00 -亚太 RGB03-210098 杭州 RGB03-210114 中国浙江 2108715 PL01 6 10000.00 -亚太 RGB03-210098 杭州 RGB03-210114 中国浙江 2108716 PL01 6 10000.00 -亚太 RGB03-210098 杭州 RGB03-210114 中国浙江 2108717 PL01 6 10000.00 -亚太 RGB03-210098 杭州 RGB03-210114 中国浙江 2108718 PL01 6 6670.00 -亚太 RGB03-210142 杭州 RGB03-210158 中国浙江 2105000 PL01 6 263000.00 -亚太 RGB03-210142 杭州 RGB03-210155 中国浙江 2105022 PL01 6 38691.00 -亚太 RGB03-210142 杭州 RGB03-210155 中国浙江 2105023 PL01 6 7313.00 -亚太 RGB03-210142 杭州 RGB03-210155 中国浙江 2105061 PL01 6 565000.00 -亚太 RGB03-210177 杭州 RGB03-210186 中国浙江 2106509 PL01 6 70000.00 -亚太 RGB03-210203 杭州 RGB03-210211 中国浙江 2105837 PL01 6 28500.00 -亚太 RGB03-210203 杭州 RGB03-210211 中国浙江 2105841 PL01 6 54400.00 -亚太 RGB03-210203 杭州 RGB03-210211 中国浙江 2107380 PL01 6 66000.00 -亚太 RGB03-210203 杭州 RGB03-210211 中国浙江 2107381 PL01 6 21000.00 -亚太 RGB03-210203 杭州 RGB03-210211 中国浙江 2107383 PL01 6 39050.00 -亚太 RGB03-210203 杭州 RGB03-210211 中国浙江 2107384 PL01 6 16350.00 -亚太 RGB03-210203 杭州 RGB03-210211 中国浙江 2108532 PL01 6 38000.00 -亚太 RGB03-210203 杭州 RGB03-210216 中国浙江 2105770 PL01 6 79000.00 -亚太 RGB03-210203 杭州 RGB03-210216 中国浙江 2107351 PL01 6 13200.00 -亚太 RGB03-210203 杭州 RGB03-210216 中国浙江 2108553 PL01 6 3315.00 -亚太 RGB03-210203 杭州 RGB03-210216 中国浙江 2119917 PL01 6 13200.00 -亚太 RGB03-210203 杭州 RGB03-210213 中国浙江 2105726 PL01 6 561230.00 -亚太 RGB03-210203 杭州 RGB03-210213 中国浙江 2107327 PL01 6 300.00 -亚太 RGB03-210203 杭州 RGB03-210218 中国浙江 2103816 PL01 6 50000.00 -亚太 RGB03-210203 杭州 RGB03-210218 中国浙江 2105965 PL01 6 50000.00 -亚太 RGB03-210203 杭州 RGB03-210218 中国浙江 2105968 PL01 6 100000.00 -亚太 RGB03-210203 杭州 RGB03-210218 中国浙江 2105970 PL01 6 40000.00 -亚太 RGB03-210203 杭州 RGB03-210215 中国浙江 2107378 PL01 6 21500.00 -亚太 RGB03-210203 杭州 RGB03-210217 中国浙江 2107354 PL01 6 25000.00 -亚太 RGB03-210203 杭州 RGB03-210217 中国浙江 2107355 PL01 6 32171.00 -亚太 RGB03-210250 杭州 RGB03-210264 中国浙江 2107409 PL01 6 95150.00 -亚太 RGB03-210282 杭州 RGB03-210294 中国浙江 2108660 PL01 6 128000.00 -亚太 RGB03-210282 杭州 RGB03-210294 中国浙江 2108663 PL01 6 25000.00 -亚太 RGB03-210282 杭州 RGB03-210293 中国浙江 2106238 PL01 6 129991.00 -亚太 RGB03-210282 杭州 RGB03-210293 中国浙江 2106239 PL01 6 185000.00 -亚太 RGB03-210282 杭州 RGB03-210293 中国浙江 2107791 PL01 6 51403.00 -亚太 RGB03-210282 杭州 RGB03-210293 中国浙江 2108662 PL01 6 60000.00 -亚太 RGB03-210282 杭州 RGB03-210293 中国浙江 2108672 PL01 6 40000.00 -亚太 RGB03-210282 杭州 RGB03-210293 中国浙江 2108676 PL01 6 50000.00 -亚太 RGB03-210282 杭州 RGB03-210293 中国浙江 2109637 PL01 6 66040.00 -亚太 RGB03-210282 杭州 RGB03-210293 中国浙江 2119967 PL01 6 70000.00 -亚太 RGB03-210282 杭州 RGB03-210290 中国浙江 2107801 PL01 6 83004.00 -亚太 RGB03-210282 杭州 RGB03-210290 中国浙江 2110757 PL01 6 25000.00 -亚太 RGB03-210282 杭州 RGB03-210292 中国浙江 6000001 PL01 6 15083.00 -亚太 RGB03-210320 杭州 RGB03-210337 中国浙江 2104159 PL01 6 51850.00 -亚太 RGB03-210320 杭州 RGB03-210337 中国浙江 2106701 PL01 6 145000.00 -亚太 RGB03-210320 杭州 RGB03-210338 中国浙江 2103769 PL01 6 8000.00 -亚太 RGB03-210320 杭州 RGB03-210338 中国浙江 2104216 PL01 6 50000.00 -亚太 RGB03-210320 杭州 RGB03-210338 中国浙江 2106718 PL01 6 500.00 -亚太 RGB03-210320 杭州 RGB03-210338 中国浙江 2106723 PL01 6 70000.00 -亚太 RGB03-210320 杭州 RGB03-210338 中国浙江 2108739 PL01 6 12400.00 -亚太 RGB03-210320 杭州 RGB03-210330 中国浙江 2103983 PL01 6 100000.00 -亚太 RGB03-210320 杭州 RGB03-210330 中国浙江 2103989 PL01 6 67116.00 -亚太 RGB03-210320 杭州 RGB03-210330 中国浙江 2103991 PL01 6 27750.00 -亚太 RGB03-210320 杭州 RGB03-210330 中国浙江 2103992 PL01 6 34370.00 -亚太 RGB03-210320 杭州 RGB03-210330 中国浙江 2103993 PL01 6 36140.00 -亚太 RGB03-210320 杭州 RGB03-210330 中国浙江 2106620 PL01 6 160007.00 -亚太 RGB03-210361 杭州 RGB03-211043 中国浙江 2105296 PL01 6 55000.00 -亚太 RGB03-210361 杭州 RGB03-211043 中国浙江 2105299 PL01 6 215000.00 -亚太 RGB03-210361 杭州 RGB03-211043 中国浙江 2105313 PL01 6 90000.00 -亚太 RGB03-210361 杭州 RGB03-211043 中国浙江 2107218 PL01 6 150000.00 -亚太 RGB03-210361 杭州 RGB03-211043 中国浙江 2107219 PL01 6 140000.00 -亚太 RGB03-210361 杭州 RGB03-211043 中国浙江 2107221 PL01 6 91500.00 -亚太 RGB03-210361 杭州 RGB03-211043 中国浙江 2109342 PL01 6 30000.00 -亚太 RGB03-210361 杭州 RGB03-211043 中国浙江 2109344 PL01 6 90000.00 -亚太 RGB03-210434 杭州 RGB03-210444 中国浙江 2105453 PL01 6 100092000.00 -亚太 RGB03-210434 杭州 RGB03-210444 中国浙江 2105454 PL01 6 57700.00 -亚太 RGB03-210434 杭州 RGB03-210444 中国浙江 2105460 PL01 6 151415.00 -亚太 RGB03-210434 杭州 RGB03-210444 中国浙江 2105475 PL01 6 13100.00 -亚太 RGB03-210434 杭州 RGB03-210444 中国浙江 2107246 PL01 6 13106.78 -亚太 RGB03-210434 杭州 RGB03-210444 中国浙江 2107250 PL01 6 31000.00 -亚太 RGB03-210434 杭州 RGB03-210444 中国浙江 2107252 PL01 6 60000.00 -亚太 RGB03-210434 杭州 RGB03-210444 中国浙江 2107253 PL01 6 59100.00 -亚太 RGB03-210434 杭州 RGB03-210444 中国浙江 2107293 PL01 6 30000.00 -亚太 RGB03-210434 杭州 RGB03-210444 中国浙江 2109223 PL01 6 1900.00 -亚太 RGB03-210434 杭州 RGB03-210444 中国浙江 2109225 PL01 6 9769.00 -亚太 RGB03-210434 杭州 RGB03-210446 中国浙江 2107254 PL01 6 9000.00 -亚太 RGB03-210530 杭州 RGB03-210544 中国浙江 2103779 PL01 6 21200.00 -亚太 RGB03-210530 杭州 RGB03-210544 中国浙江 2103780 PL01 6 51600.00 -亚太 RGB03-210530 杭州 RGB03-210544 中国浙江 2108763 PL01 6 70000.00 -亚太 RGB03-210530 杭州 RGB03-210544 中国浙江 2108764 PL01 6 35000.00 -亚太 RGB03-210530 杭州 RGB03-210544 中国浙江 2108767 PL01 6 50000.00 -亚太 RGB03-210530 杭州 RGB03-210544 中国浙江 2108768 PL01 6 27600.00 -亚太 RGB03-210530 杭州 RGB03-210544 中国浙江 2108861 PL01 6 30000.00 -亚太 RGB03-210530 杭州 RGB03-210544 中国浙江 2108969 PL01 6 50000.00 -亚太 RGB03-210530 杭州 RGB03-210544 中国浙江 2108970 PL01 6 18910.00 -亚太 RGB03-210530 杭州 RGB03-210544 中国浙江 2108971 PL01 6 40000.00 -亚太 RGB03-210530 杭州 RGB03-210546 中国浙江 2108688 PL01 6 10000.00 -亚太 RGB03-210530 杭州 RGB03-210538 中国浙江 2108920 PL01 6 2850.00 -亚太 RGB03-210530 杭州 RGB03-210885 中国浙江 2108475 PL01 6 25850.00 -亚太 RGB03-210530 杭州 RGB03-210885 中国浙江 2109169 PL01 6 90438.50 -亚太 RGB03-210530 杭州 RGB03-210885 中国浙江 2119867 PL01 6 60000.00 -亚太 RGB03-210530 杭州 RGB03-210539 中国浙江 2104517 PL01 6 37000.00 -亚太 RGB03-210530 杭州 RGB03-210539 中国浙江 2106823 PL01 6 100000.00 -亚太 RGB03-210530 杭州 RGB03-210542 中国浙江 2108804 PL01 6 30000.00 -亚太 RGB03-210530 杭州 RGB03-210543 中国浙江 2103781 PL01 6 15000.00 -亚太 RGB03-210530 杭州 RGB03-210543 中国浙江 2103782 PL01 6 61810.00 -亚太 RGB03-210530 杭州 RGB03-210543 中国浙江 2104490 PL01 6 13380.00 -亚太 RGB03-210530 杭州 RGB03-210543 中国浙江 2104491 PL01 6 109000.00 -亚太 RGB03-210530 杭州 RGB03-210543 中国浙江 2104492 PL01 6 32000.00 -亚太 RGB03-210530 杭州 RGB03-210543 中国浙江 2104493 PL01 6 48000.00 -亚太 RGB03-210530 杭州 RGB03-210543 中国浙江 2104495 PL01 6 40140.00 -亚太 RGB03-210530 杭州 RGB03-210543 中国浙江 2104497 PL01 6 50000.00 -亚太 RGB03-210530 杭州 RGB03-210543 中国浙江 2106817 PL01 6 50500.00 -亚太 RGB03-210530 杭州 RGB03-210543 中国浙江 2106818 PL01 6 5500.00 -亚太 RGB03-210530 杭州 RGB03-210543 中国浙江 2106819 PL01 6 15000.00 -亚太 RGB03-210530 杭州 RGB03-210543 中国浙江 2106820 PL01 6 13850.00 -亚太 RGB03-210530 杭州 RGB03-210543 中国浙江 2106821 PL01 6 113000.00 -亚太 RGB03-210530 杭州 RGB03-210543 中国浙江 2108578 PL01 6 30000.00 -亚太 RGB03-210565 杭州 RGB03-210566 中国浙江 2107142 PL01 6 300000.00 -亚太 RGB03-210565 杭州 RGB03-210576 中国浙江 2050276 PL01 6 61000.00 -亚太 RGB03-210597 杭州 RGB03-210610 中国浙江 2104271 PL01 6 97800.00 -亚太 RGB03-210597 杭州 RGB03-210610 中国浙江 2106763 PL01 6 38000.00 -亚太 RGB03-210597 杭州 RGB03-210610 中国浙江 2106764 PL01 6 755.00 -亚太 RGB03-210597 杭州 RGB03-210605 中国浙江 2104227 PL01 6 225.00 -亚太 RGB03-210597 杭州 RGB03-210605 中国浙江 2104229 PL01 6 250000.00 -亚太 RGB03-210597 杭州 RGB03-210605 中国浙江 2104231 PL01 6 23800.00 -亚太 RGB03-210597 杭州 RGB03-210605 中国浙江 2104251 PL01 6 50000.00 -亚太 RGB03-210597 杭州 RGB03-210605 中国浙江 2104252 PL01 6 94300.00 -亚太 RGB03-210597 杭州 RGB03-210605 中国浙江 2106732 PL01 6 8500.00 -亚太 RGB03-210597 杭州 RGB03-210605 中国浙江 2106733 PL01 6 29111.00 -亚太 RGB03-210597 杭州 RGB03-210605 中国浙江 2106734 PL01 6 390.00 -亚太 RGB03-210597 杭州 RGB03-210605 中国浙江 2106736 PL01 6 12290.00 -亚太 RGB03-210597 杭州 RGB03-210605 中国浙江 2106737 PL01 6 68700.00 -亚太 RGB03-210597 杭州 RGB03-210605 中国浙江 2106738 PL01 6 54200.00 -亚太 RGB03-210597 杭州 RGB03-210605 中国浙江 2106739 PL01 6 29741.00 -亚太 RGB03-210597 杭州 RGB03-210605 中国浙江 2106740 PL01 6 61000.00 -亚太 RGB03-210597 杭州 RGB03-210605 中国浙江 2106741 PL01 6 26250.00 -亚太 RGB03-210597 杭州 RGB03-210605 中国浙江 2106742 PL01 6 49387.86 -亚太 RGB03-210597 杭州 RGB03-210605 中国浙江 2106743 PL01 6 28000.00 -亚太 RGB03-210597 杭州 RGB03-210605 中国浙江 2106744 PL01 6 4800.00 -亚太 RGB03-210597 杭州 RGB03-210605 中国浙江 2106753 PL01 6 8300.00 -亚太 RGB03-210597 杭州 RGB03-210605 中国浙江 2106754 PL01 6 27900.00 -亚太 RGB03-210597 杭州 RGB03-210605 中国浙江 2113390 PL01 6 118700.00 -亚太 RGB03-210666 杭州 RGB03-210678 中国浙江 2107003 PL01 6 200150.00 -亚太 RGB03-210666 杭州 RGB03-210674 中国浙江 2104590 PL01 6 486160.00 -亚太 RGB03-210666 杭州 RGB03-210674 中国浙江 2104591 PL01 6 93660.00 -亚太 RGB03-210666 杭州 RGB03-210674 中国浙江 2106853 PL01 6 848990.00 -亚太 RGB03-210666 杭州 RGB03-210674 中国浙江 2106854 PL01 6 13600.00 -亚太 RGB03-210666 杭州 RGB03-210677 中国浙江 2104776 PL01 6 1000.00 -亚太 RGB03-210666 杭州 RGB03-210677 中国浙江 2106989 PL01 6 3150.00 -亚太 RGB03-210666 杭州 RGB03-210676 中国浙江 2103785 PL01 6 2720.00 -亚太 RGB03-210666 杭州 RGB03-210676 中国浙江 2104628 PL01 6 1770.00 -亚太 RGB03-210666 杭州 RGB03-210676 中国浙江 2106876 PL01 6 250.00 -亚太 RGB03-210666 杭州 RGB03-210676 中国浙江 2106878 PL01 6 950.00 -亚太 RGB03-210666 杭州 RGB03-210676 中国浙江 2106879 PL01 6 1500.00 -亚太 RGB03-210666 杭州 RGB03-210676 中国浙江 2106881 PL01 6 2120.00 -亚太 RGB03-210666 杭州 RGB03-210676 中国浙江 2106886 PL01 6 6.00 -亚太 RGB03-210666 杭州 RGB03-210676 中国浙江 2106887 PL01 6 400.00 -亚太 RGB03-210666 杭州 RGB03-210676 中国浙江 2106897 PL01 6 50.00 -亚太 RGB03-210666 杭州 RGB03-210676 中国浙江 2106901 PL01 6 500.00 -亚太 RGB03-210712 杭州 RGB03-211058 中国浙江 2108467 PL01 6 50000.00 -亚太 RGB03-210712 杭州 RGB03-211058 中国浙江 2108470 PL01 6 204500.00 -亚太 RGB03-210712 杭州 RGB03-211058 中国浙江 2108995 PL01 6 50000.00 -亚太 RGB03-210712 杭州 RGB03-211052 中国浙江 2105211 PL01 6 120000.00 -亚太 RGB03-210712 杭州 RGB03-211052 中国浙江 2119894 PL01 6 90000.00 -亚太 RGB03-210712 杭州 RGB03-210729 中国浙江 2105254 PL01 6 450240.00 -亚太 RGB03-210712 杭州 RGB03-210729 中国浙江 2105268 PL01 6 15365.00 -亚太 RGB03-210712 杭州 RGB03-211049 中国浙江 2105212 PL01 6 77746.00 -亚太 RGB03-210712 杭州 RGB03-211049 中国浙江 2105248 PL01 6 50000.00 -亚太 RGB03-210712 杭州 RGB03-211049 中国浙江 2105249 PL01 6 170000.00 -亚太 RGB03-210712 杭州 RGB03-211049 中国浙江 2107209 PL01 6 47000.00 -亚太 RGB03-210712 杭州 RGB03-211049 中国浙江 2108473 PL01 6 60000.00 -亚太 RGB03-210712 杭州 RGB03-211049 中国浙江 6000001 PL01 6 210.00 -亚太 RGB03-210712 杭州 RGB03-211046 中国浙江 2105235 PL01 6 35200.00 -亚太 RGB03-210712 杭州 RGB03-211046 中国浙江 2105240 PL01 6 56000.00 -亚太 RGB03-210712 杭州 RGB03-211046 中国浙江 2105241 PL01 6 50000.00 -亚太 RGB03-210712 杭州 RGB03-211046 中国浙江 2107207 PL01 6 50000.00 -亚太 RGB03-210712 杭州 RGB03-211046 中国浙江 2107208 PL01 6 150000.00 -亚太 RGB03-210712 杭州 RGB03-211046 中国浙江 2109263 PL01 6 40000.00 -亚太 RGB03-210712 杭州 RGB03-211061 中国浙江 2107203 PL01 6 34400.00 -亚太 RGB03-210712 杭州 RGB03-211061 中国浙江 2107205 PL01 6 5050.00 -亚太 RGB03-210712 杭州 RGB03-211061 中国浙江 2109632 PL01 6 41700.00 -亚太 RGB03-210750 杭州 RGB03-210759 中国浙江 2107901 PL01 6 36000.00 -亚太 RGB03-210750 杭州 RGB03-210759 中国浙江 2108419 PL01 6 40000.00 -亚太 RGB03-210750 杭州 RGB03-210759 中国浙江 2119969 PL01 6 10000.00 -亚太 RGB03-210750 杭州 RGB03-210760 中国浙江 2108689 PL01 6 1699.00 -亚太 RGB03-210750 杭州 RGB03-210760 中国浙江 2108690 PL01 6 928.00 -亚太 RGB03-210750 杭州 RGB03-210761 中国浙江 2106541 PL01 6 21600.00 -亚太 RGB03-210750 杭州 RGB03-210763 中国浙江 2106378 PL01 6 29000.00 -亚太 RGB03-210750 杭州 RGB03-210763 中国浙江 2106379 PL01 6 90500.00 -亚太 RGB03-210750 杭州 RGB03-210763 中国浙江 2106391 PL01 6 4014900.00 -亚太 RGB03-210750 杭州 RGB03-210763 中国浙江 2107869 PL01 6 33550.00 -亚太 RGB03-210750 杭州 RGB03-210763 中国浙江 2107881 PL01 6 35000.00 -亚太 RGB03-210750 杭州 RGB03-210763 中国浙江 2119968 PL01 6 665942.00 -亚太 RGB03-210750 杭州 RGB03-210765 中国浙江 2108420 PL01 6 36321.00 -亚太 RGB03-210785 杭州 RGB03-210794 中国浙江 2104440 PL01 6 10000.00 -亚太 RGB03-210785 杭州 RGB03-210794 中国浙江 2109044 PL01 6 10000.00 -亚太 RGB03-210785 杭州 RGB03-210795 中国浙江 2104392 PL01 6 8278.00 -亚太 RGB03-210785 杭州 RGB03-210795 中国浙江 2104395 PL01 6 10000.00 -亚太 RGB03-210785 杭州 RGB03-210795 中国浙江 2104399 PL01 6 10000.00 -亚太 RGB03-210785 杭州 RGB03-210795 中国浙江 2104400 PL01 6 10000.00 -亚太 RGB03-210785 杭州 RGB03-210795 中国浙江 2104402 PL01 6 10000.00 -亚太 RGB03-210785 杭州 RGB03-210795 中国浙江 2104403 PL01 6 36000.00 -亚太 RGB03-210785 杭州 RGB03-210795 中国浙江 2104413 PL01 6 538.00 -亚太 RGB03-210785 杭州 RGB03-210795 中国浙江 2104418 PL01 6 8116.00 -亚太 RGB03-210785 杭州 RGB03-210795 中国浙江 2104422 PL01 6 10000.00 -亚太 RGB03-210785 杭州 RGB03-210795 中国浙江 2104425 PL01 6 10000.00 -亚太 RGB03-210785 杭州 RGB03-210795 中国浙江 2104431 PL01 6 10000.00 -亚太 RGB03-210785 杭州 RGB03-210795 中国浙江 2109046 PL01 6 10000.00 -亚太 RGB03-210843 杭州 RGB03-210851 中国浙江 2106065 PL01 6 152863.00 -亚太 RGB03-210843 杭州 RGB03-210851 中国浙江 2106068 PL01 6 26050.00 -亚太 RGB03-210843 杭州 RGB03-210851 中国浙江 2106070 PL01 6 120000.00 -亚太 RGB03-210843 杭州 RGB03-210851 中国浙江 2106071 PL01 6 27000.00 -亚太 RGB03-210843 杭州 RGB03-210851 中国浙江 2108496 PL01 6 73150.00 -亚太 RGB03-210843 杭州 RGB03-210851 中国浙江 2108817 PL01 6 366532.03 -亚太 RGB03-210843 杭州 RGB03-210856 中国浙江 6000001 PL01 6 2000.00 -亚太 RGB03-210843 杭州 RGB03-210857 中国浙江 6000001 PL01 6 3582.00 -亚太 RGB03-210843 杭州 RGB03-210855 中国浙江 2106124 PL01 6 235970.00 -亚太 RGB03-210843 杭州 RGB03-210855 中国浙江 2106131 PL01 6 49880.00 -亚太 RGB03-210843 杭州 RGB03-210852 中国浙江 2106082 PL01 6 23300.00 -亚太 RGB03-210843 杭州 RGB03-210852 中国浙江 2108492 PL01 6 30000.00 -亚太 RGB03-210843 杭州 RGB03-210852 中国浙江 2109232 PL01 6 911498.00 -亚太 RGB03-210843 杭州 RGB03-210852 中国浙江 6000001 PL01 6 12558.00 -亚太 RGB03-210904 杭州 RGB03-210912 中国浙江 6000001 PL01 6 48000.00 -亚太 RGB03-210930 杭州 RGB03-210938 中国浙江 2106827 PL01 6 0.40 -亚太 RGB03-210930 杭州 RGB03-210938 中国浙江 2106842 PL01 6 3200.00 -亚太 RGB03-210930 杭州 RGB03-210938 中国浙江 2108700 PL01 6 431380.00 -亚太 RGB03-210930 杭州 RGB03-210945 中国浙江 2104744 PL01 6 15100.00 -亚太 RGB03-210930 杭州 RGB03-210946 中国浙江 2106978 PL01 6 9012.00 -亚太 RGB03-210965 杭州 RGB03-210978 中国浙江 6000001 PL01 6 2000.00 -亚太 RGB03-210965 杭州 RGB03-210977 中国浙江 6000001 PL01 6 1766.00 -亚太 RGB03-210965 杭州 RGB03-210973 中国浙江 6000001 PL01 6 54097.00 -亚太 RGB03-210066 杭州 RGB03-210074 中国浙江 6000001 PL01 4 35900.00 -亚太 RGB03-210066 杭州 RGB03-210078 中国浙江 2107039 PL01 4 5000.00 -亚太 RGB03-210066 杭州 RGB03-210079 中国浙江 2104963 PL01 4 5000.00 -亚太 RGB03-210098 杭州 RGB03-210108 中国浙江 2103926 PL01 4 2000.00 -亚太 RGB03-210098 杭州 RGB03-210108 中国浙江 2108438 PL01 4 10000.00 -亚太 RGB03-210098 杭州 RGB03-210108 中国浙江 2108439 PL01 4 10000.00 -亚太 RGB03-210098 杭州 RGB03-210106 中国浙江 6000001 PL01 4 23500.00 -亚太 RGB03-210098 杭州 RGB03-210109 中国浙江 6000001 PL01 4 13000.00 -亚太 RGB03-210098 杭州 RGB03-210112 中国浙江 6000001 PL01 4 29885.50 -亚太 RGB03-210098 杭州 RGB03-210114 中国浙江 6000001 PL01 4 15000.00 -亚太 RGB03-210098 杭州 RGB03-210113 中国浙江 6000001 PL01 4 12000.00 -亚太 RGB03-210098 杭州 RGB03-210111 中国浙江 6000001 PL01 4 22687.50 -亚太 RGB03-210177 杭州 RGB03-210186 中国浙江 2103898 PL01 4 5000.00 -亚太 RGB03-210177 杭州 RGB03-210186 中国浙江 2106509 PL01 4 3000.00 -亚太 RGB03-210177 杭州 RGB03-210186 中国浙江 2106512 PL01 4 3000.00 -亚太 RGB03-210177 杭州 RGB03-210186 中国浙江 2106513 PL01 4 15000.00 -亚太 RGB03-210177 杭州 RGB03-210187 中国浙江 2108030 PL01 4 3000.00 -亚太 RGB03-210177 杭州 RGB03-210185 中国浙江 2109281 PL01 4 5000.00 -亚太 RGB03-210203 杭州 RGB03-210216 中国浙江 2105770 PL01 4 10000.00 -亚太 RGB03-210203 杭州 RGB03-210216 中国浙江 2105775 PL01 4 10000.00 -亚太 RGB03-210203 杭州 RGB03-210216 中国浙江 2107352 PL01 4 10000.00 -亚太 RGB03-210282 杭州 RGB03-210295 中国浙江 6000001 PL01 4 10000.00 -亚太 RGB03-210282 杭州 RGB03-210293 中国浙江 2109637 PL01 4 10000.00 -亚太 RGB03-210282 杭州 RGB03-210293 中国浙江 6000001 PL01 4 58506.00 -亚太 RGB03-210282 杭州 RGB03-210290 中国浙江 6000001 PL01 4 28000.00 -亚太 RGB03-210282 杭州 RGB03-210291 中国浙江 6000001 PL01 4 32000.00 -亚太 RGB03-210282 杭州 RGB03-210292 中国浙江 6000001 PL01 4 86674.00 -亚太 RGB03-210282 杭州 RGB03-210298 中国浙江 6000001 PL01 4 10086.00 -亚太 RGB03-210282 杭州 RGB03-210296 中国浙江 6000001 PL01 4 46798.00 -亚太 RGB03-210320 杭州 RGB03-210330 中国浙江 2106622 PL01 4 10068.70 -亚太 RGB03-210361 杭州 RGB03-210369 中国浙江 6000001 PL01 4 20650.00 -亚太 RGB03-210361 杭州 RGB03-210370 中国浙江 6000001 PL01 4 5000.00 -亚太 RGB03-210361 杭州 RGB03-210375 中国浙江 6000001 PL01 4 61014.00 -亚太 RGB03-210361 杭州 RGB03-210380 中国浙江 6000001 PL01 4 133380.00 -亚太 RGB03-210361 杭州 RGB03-210377 中国浙江 6000001 PL01 4 39520.00 -亚太 RGB03-210361 杭州 RGB03-210373 中国浙江 6000001 PL01 4 5210.00 -亚太 RGB03-210361 杭州 RGB03-210379 中国浙江 6000001 PL01 4 161260.00 -亚太 RGB03-210361 杭州 RGB03-210372 中国浙江 6000001 PL01 4 4000.00 -亚太 RGB03-210361 杭州 RGB03-210371 中国浙江 6000001 PL01 4 7400.00 -亚太 RGB03-210361 杭州 RGB03-210378 中国浙江 6000001 PL01 4 146450.00 -亚太 RGB03-210361 杭州 RGB03-210381 中国浙江 6000001 PL01 4 124946.00 -亚太 RGB03-210408 杭州 RGB03-210419 中国浙江 2104358 PL01 4 10000.00 -亚太 RGB03-210434 杭州 RGB03-210444 中国浙江 2107251 PL01 4 2000.00 -亚太 RGB03-210510 杭州 RGB03-210521 中国浙江 6000001 PL01 4 5000.00 -亚太 RGB03-210510 杭州 RGB03-210519 中国浙江 6000001 PL01 4 26000.00 -亚太 RGB03-210510 杭州 RGB03-210520 中国浙江 6000001 PL01 4 10000.00 -亚太 RGB03-210510 杭州 RGB03-210518 中国浙江 6000001 PL01 4 6000.00 -亚太 RGB03-210530 杭州 RGB03-210544 中国浙江 2103779 PL01 4 2000.00 -亚太 RGB03-210530 杭州 RGB03-210544 中国浙江 2108765 PL01 4 2000.00 -亚太 RGB03-210530 杭州 RGB03-210885 中国浙江 2119867 PL01 4 5000.00 -亚太 RGB03-210565 杭州 RGB03-210566 中国浙江 2107142 PL01 4 11000.00 -亚太 RGB03-210597 杭州 RGB03-210605 中国浙江 2104231 PL01 4 2000.00 -亚太 RGB03-210626 杭州 RGB03-210637 中国浙江 6000001 PL01 4 7000.00 -亚太 RGB03-210626 杭州 RGB03-210641 中国浙江 6000001 PL01 4 4750.00 -亚太 RGB03-210626 杭州 RGB03-210634 中国浙江 6000001 PL01 4 11560.00 -亚太 RGB03-210626 杭州 RGB03-210635 中国浙江 6000001 PL01 4 4000.00 -亚太 RGB03-210666 杭州 RGB03-210678 中国浙江 2107003 PL01 4 1000.00 -亚太 RGB03-210666 杭州 RGB03-210677 中国浙江 2106993 PL01 4 5000.00 -亚太 RGB03-210666 杭州 RGB03-210677 中国浙江 2108872 PL01 4 3000.00 -亚太 RGB03-210666 杭州 RGB03-210676 中国浙江 2106880 PL01 4 3000.00 -亚太 RGB03-210712 杭州 RGB03-210728 中国浙江 6000001 PL01 4 14600.00 -亚太 RGB03-210712 杭州 RGB03-211058 中国浙江 2108467 PL01 4 20000.00 -亚太 RGB03-210712 杭州 RGB03-211058 中国浙江 2108470 PL01 4 50000.00 -亚太 RGB03-210712 杭州 RGB03-210720 中国浙江 6000001 PL01 4 7000.00 -亚太 RGB03-210712 杭州 RGB03-210727 中国浙江 6000001 PL01 4 66300.00 -亚太 RGB03-210712 杭州 RGB03-211052 中国浙江 2108769 PL01 4 3000.00 -亚太 RGB03-210712 杭州 RGB03-211052 中国浙江 2119894 PL01 4 10000.00 -亚太 RGB03-210712 杭州 RGB03-211052 中国浙江 6000001 PL01 4 4000.00 -亚太 RGB03-210712 杭州 RGB03-211055 中国浙江 6000001 PL01 4 10500.00 -亚太 RGB03-210712 杭州 RGB03-211049 中国浙江 2105212 PL01 4 20000.00 -亚太 RGB03-210712 杭州 RGB03-211049 中国浙江 2108473 PL01 4 10000.00 -亚太 RGB03-210712 杭州 RGB03-211046 中国浙江 2105241 PL01 4 20000.00 -亚太 RGB03-210712 杭州 RGB03-211046 中国浙江 2109263 PL01 4 10000.00 -亚太 RGB03-210712 杭州 RGB03-211046 中国浙江 6000001 PL01 4 9584.00 -亚太 RGB03-210712 杭州 RGB03-210724 中国浙江 6000001 PL01 4 14000.00 亚太 RGB03-210712 杭州 RGB03-211061 中国浙江 2107205 PL01 4 10000.00 -亚太 RGB03-210712 杭州 RGB03-211061 中国浙江 2109632 PL01 4 10000.00 -亚太 RGB03-210750 杭州 RGB03-210759 中国浙江 6000001 PL01 4 10000.00 -亚太 RGB03-210750 杭州 RGB03-210763 中国浙江 2106391 PL01 4 10000.00 -亚太 RGB03-210750 杭州 RGB03-210763 中国浙江 6000001 PL01 4 4000.00 -亚太 RGB03-210750 杭州 RGB03-210764 中国浙江 6000001 PL01 4 4000.00 -亚太 RGB03-210750 杭州 RGB03-210765 中国浙江 6000001 PL01 4 12200.00 -亚太 RGB03-210785 杭州 RGB03-210795 中国浙江 2104408 PL01 4 400.00 -亚太 RGB03-210843 杭州 RGB03-210851 中国浙江 2108496 PL01 4 10000.00 -亚太 RGB03-210843 杭州 RGB03-210851 中国浙江 2110282 PL01 4 3000.00 -亚太 RGB03-210843 杭州 RGB03-210856 中国浙江 2106060 PL01 4 3000.00 -亚太 RGB03-210843 杭州 RGB03-210856 中国浙江 6000001 PL01 4 15000.00 -亚太 RGB03-210843 杭州 RGB03-210853 中国浙江 2106081 PL01 4 18000.00 -亚太 RGB03-210843 杭州 RGB03-210853 中国浙江 6000001 PL01 4 21000.00 -亚太 RGB03-210843 杭州 RGB03-210857 中国浙江 2108534 PL01 4 5000.00 -亚太 RGB03-210843 杭州 RGB03-210857 中国浙江 2108856 PL01 4 2000.00 -亚太 RGB03-210843 杭州 RGB03-210857 中国浙江 2108857 PL01 4 5000.00 -亚太 RGB03-210843 杭州 RGB03-210857 中国浙江 2108895 PL01 4 7000.00 -亚太 RGB03-210843 杭州 RGB03-210857 中国浙江 6000001 PL01 4 18500.00 -亚太 RGB03-210843 杭州 RGB03-210855 中国浙江 6000001 PL01 4 48000.00 -亚太 RGB03-210843 杭州 RGB03-210854 中国浙江 6000001 PL01 4 43300.00 -亚太 RGB03-210843 杭州 RGB03-210852 中国浙江 6000001 PL01 4 2000.00 -亚太 RGB03-210843 杭州 RGB03-210858 中国浙江 6000001 PL01 4 2000.00 -亚太 RGB03-210904 杭州 RGB03-210912 中国浙江 6000001 PL01 4 18193.00 -亚太 RGB03-210965 杭州 RGB03-210978 中国浙江 6000001 PL01 4 99000.00 -亚太 RGB03-210965 杭州 RGB03-210976 中国浙江 6000001 PL01 4 47000.00 -亚太 RGB03-210965 杭州 RGB03-210979 中国浙江 6000001 PL01 4 20430.00 -亚太 RGB03-210965 杭州 RGB03-210977 中国浙江 6000001 PL01 4 22700.00 -亚太 RGB03-210965 杭州 RGB03-210973 中国浙江 6000001 PL01 4 6500.00 -亚太 RGB03-210203 杭州 RGB03-210213 中国浙江 2105726 PL01 37 3000.00 -亚太 RGB03-210802 杭州 RGB03-210803 中国浙江 2120518 PL01 6 61001.00 -亚太 RGB03-210203 杭州 RGB03-210216 中国浙江 2108548 PL01 6 10000000.00 -亚太 RGB03-210282 杭州 RGB03-210293 中国浙江 6000001 PL01 6 0.02 -亚太 RGB03-210203 杭州 RGB03-210212 中国浙江 6000001 PL01 6 0.02 -亚太 RGB03-210001 杭州 RGB03-210013 中国浙江 2109167 PL01 6 0.02 -亚太 RGB03-210066 杭州 RGB03-210077 中国浙江 2104923 PL01 6 450000.00 -亚太 RGB03-210098 杭州 RGB03-210111 中国浙江 2106602 PL01 6 70000.00 -亚太 RGB03-210361 杭州 RGB03-210371 中国浙江 2120524 PL01 6 20000.00 -亚太 RGB03-210965 杭州 RGB03-210979 中国浙江 2109276 PL01 6 200000.00 -亚太 RGB03-210965 杭州 RGB03-210979 中国浙江 2107585 PL01 6 50000.00 -亚太 RGB03-210001 杭州 RGB03-210013 中国浙江 3301979 PL01 4 0.01 -亚太 RGB03-210965 杭州 RGB03-210979 中国浙江 2107586 PL01 6 100000.00 -亚太 RGB03-210469 杭州 RGB03-210477 中国浙江 2105686 PL01 6 400000.00 -亚太 RGB03-210712 杭州 RGB03-210725 中国浙江 2105273 PL01 6 500000.00 -亚太 RGB03-210626 杭州 RGB03-210638 中国浙江 2120754 PL01 6 20000.00 -亚太 RGB03-210098 杭州 RGB03-210106 中国浙江 2120872 PL01 6 12805.00 -亚太 RGB03-210361 杭州 RGB03-210371 中国浙江 2109344 PL01 4 7000.00 -亚太 RGB03-210965 杭州 RGB03-210966 中国浙江 2120769 PL01 6 50000.00 -亚太 RGB03-210565 杭州 RGB03-210574 中国浙江 2120778 PL01 6 100000.00 -亚太 RGB03-210177 杭州 RGB03-210186 中国浙江 2106513 PL01 6 260000.00 -亚太 RGB03-210930 杭州 RGB03-210941 中国浙江 2104688 PL01 6 26000.00 -亚太 RGB03-210712 杭州 RGB03-210722 中国浙江 2107217 PL01 6 460000.00 -亚太 RGB03-210843 杭州 RGB03-210857 中国浙江 2108535 PL01 6 520000.00 -亚太 RGB03-210361 杭州 RGB03-211043 中国浙江 2105298 PL01 6 20000.00 -亚太 RGB03-210408 杭州 RGB03-210419 中国浙江 2104355 PL01 6 50000.00 -亚太 RGB03-210408 杭州 RGB03-210419 中国浙江 2104360 PL01 6 100000.00 -亚太 RGB03-210408 杭州 RGB03-210419 中国浙江 2104352 PL01 6 50000.00 -亚太 RGB03-210408 杭州 RGB03-210420 中国浙江 2104359 PL01 6 100000.00 -亚太 RGB03-210530 杭州 RGB03-210531 中国浙江 2120922 PL01 6 30000.00 -亚太 RGB03-210510 杭州 RGB03-210518 中国浙江 2106794 PL01 6 100000.00 -亚太 RGB03-210510 杭州 RGB03-210518 中国浙江 2106795 PL01 6 180000.00 -亚太 RGB03-210510 杭州 RGB03-210518 中国浙江 2104339 PL01 6 55355.00 -亚太 RGB03-210626 杭州 RGB03-210637 中国浙江 2106793 PL01 6 50000.00 -亚太 RGB03-210434 杭州 RGB03-210444 中国浙江 2109224 PL01 6 150000.00 -亚太 RGB03-210965 杭州 RGB03-210979 中国浙江 2107662 PL01 6 60000.00 -亚太 RGB03-210434 杭州 RGB03-210442 中国浙江 2120917 PL01 6 50000.00 -亚太 RGB03-210666 杭州 RGB03-210676 中国浙江 2106874 PL01 6 200000.00 -亚太 RGB03-210177 杭州 RGB03-210186 中国浙江 2108002 PL01 6 700000.00 -亚太 RGB03-210434 杭州 RGB03-210444 中国浙江 2120981 PL01 6 100000.00 -亚太 RGB03-210666 杭州 RGB03-210677 中国浙江 2106981 PL01 6 400000.00 -亚太 RGB03-210177 杭州 RGB03-210186 中国浙江 2108002 PL01 4 50000.00 -亚太 RGB03-210510 杭州 RGB03-210518 中国浙江 2120971 PL01 6 90000.00 -亚太 RGB03-211000 杭州 RGB03-211008 中国浙江 2108074 PL01 6 50000.00 -亚太 RGB03-210361 杭州 RGB03-211043 中国浙江 2105308 PL01 6 50000.00 -亚太 RGB03-211000 杭州 RGB03-211008 中国浙江 2120979 PL01 6 50000.00 -亚太 RGB03-210098 杭州 RGB03-210114 中国浙江 2106642 PL01 6 50000.00 -亚太 RGB03-210530 杭州 RGB03-210538 中国浙江 2119942 PL01 6 20000.00 -亚太 RGB03-210320 杭州 RGB03-210330 中国浙江 2106619 PL01 6 50000.00 -亚太 RGB03-210785 杭州 RGB03-210794 中国浙江 2109602 PL01 6 100000.00 -亚太 RGB03-210785 杭州 RGB03-210795 中国浙江 2104396 PL01 6 100000.00 -亚太 RGB03-210785 杭州 RGB03-210794 中国浙江 2109047 PL01 6 100000.00 -亚太 RGB03-210802 杭州 RGB03-210803 中国浙江 2121028 PL01 6 147668.50 -亚太 RGB03-210203 杭州 RGB03-210213 中国浙江 2107331 PL01 6 50000.00 -亚太 RGB03-210802 杭州 RGB03-210803 中国浙江 2120723 PL01 6 311273.86 -亚太 RGB03-210597 杭州 RGB03-210608 中国浙江 2104242 PL01 6 15000.00 -亚太 RGB03-210361 杭州 RGB03-210371 中国浙江 2105299 PL01 6 200000.00 -亚太 RGB03-210250 杭州 RGB03-210263 中国浙江 2105873 PL01 6 110000.00 -亚太 RGB03-210904 杭州 RGB03-210912 中国浙江 2120976 PL01 6 250000.00 -亚太 RGB03-210320 杭州 RGB03-210335 中国浙江 2119939 PL01 6 880000.00 -亚太 RGB03-210320 杭州 RGB03-210329 中国浙江 2109311 PL01 6 50000.00 -亚太 RGB03-210066 杭州 RGB03-210077 中国浙江 2107016 PL01 6 100000.00 -亚太 RGB03-210250 杭州 RGB03-210263 中国浙江 2105870 PL01 6 50000.00 -亚太 RGB03-210843 杭州 RGB03-210851 中国浙江 2121076 PL01 6 100000.00 -亚太 RGB03-210843 杭州 RGB03-210851 中国浙江 2110282 PL01 6 1000000.00 -亚太 RGB03-210530 杭州 RGB03-210531 中国浙江 2108763 PL01 6 150000.00 -亚太 RGB03-210066 杭州 RGB03-210077 中国浙江 2104834 PL01 6 1062805.00 -亚太 RGB03-210282 杭州 RGB03-210283 中国浙江 2120881 PL01 6 20000.00 -亚太 RGB03-210250 杭州 RGB03-210259 中国浙江 2107406 PL01 6 120000.00 -亚太 RGB03-210320 杭州 RGB03-210333 中国浙江 2106662 PL01 6 50000.00 -亚太 RGB03-210282 杭州 RGB03-210299 中国浙江 2108957 PL01 6 50000.00 -亚太 RGB03-210408 杭州 RGB03-210419 中国浙江 2104354 PL01 6 2000000.00 -亚太 RGB03-210965 杭州 RGB03-210973 中国浙江 2121117 PL01 6 20000.00 -亚太 RGB03-210565 杭州 RGB03-210573 中国浙江 2105090 PL01 6 256500.00 -亚太 RGB03-211000 杭州 RGB03-211008 中国浙江 2121120 PL01 6 55200.00 -亚太 RGB03-210530 杭州 RGB03-210885 中国浙江 2106815 PL01 6 30000.00 -亚太 RGB03-210565 杭州 RGB03-210576 中国浙江 2109278 PL01 6 50000.00 -亚太 RGB03-210565 杭州 RGB03-210576 中国浙江 2050602 PL01 6 50000.00 -亚太 RGB03-210434 杭州 RGB03-210449 中国浙江 2107307 PL01 6 60000.00 -亚太 RGB03-211000 杭州 RGB03-211008 中国浙江 2106589 PL01 6 550000.00 -亚太 RGB03-211000 杭州 RGB03-211010 中国浙江 2108839 PL01 6 50000.00 -亚太 RGB03-210530 杭州 RGB03-210540 中国浙江 2106822 PL01 6 50000.00 -亚太 RGB03-210530 杭州 RGB03-210543 中国浙江 2104494 PL01 6 50000.00 -亚太 RGB03-210203 杭州 RGB03-210211 中国浙江 2108531 PL01 6 50000.00 -亚太 RGB03-210469 杭州 RGB03-210477 中国浙江 2121230 PL01 6 500000.00 -亚太 RGB03-210469 杭州 RGB03-210477 中国浙江 2121167 PL01 6 500000.00 -亚太 RGB03-210177 杭州 RGB03-210186 中国浙江 2103898 PL01 6 100000.00 -亚太 RGB03-210408 杭州 RGB03-210419 中国浙江 2121219 PL01 6 10000000.00 -亚太 RGB03-210142 杭州 RGB03-210152 中国浙江 2105066 PL01 6 100000.00 +亚太 RGB03-210712 杭州 RGB03-210724 中国浙江 6000001 PL01 4 14000.00 +亚太 RGB03-210712 杭州 RGB03-211046 中国浙江 6000001 PL01 4 9584.00 +亚太 RGB03-210712 杭州 RGB03-211046 中国浙江 2109263 PL01 4 10000.00 +亚太 RGB03-210712 杭州 RGB03-211046 中国浙江 2105241 PL01 4 20000.00 +亚太 RGB03-210712 杭州 RGB03-211049 中国浙江 2108473 PL01 4 10000.00 +亚太 RGB03-210712 杭州 RGB03-211049 中国浙江 2105212 PL01 4 20000.00 +亚太 RGB03-210712 杭州 RGB03-211055 中国浙江 6000001 PL01 4 10500.00 +亚太 RGB03-210712 杭州 RGB03-211052 中国浙江 6000001 PL01 4 4000.00 +亚太 RGB03-210712 杭州 RGB03-211052 中国浙江 2119894 PL01 4 10000.00 +亚太 RGB03-210712 杭州 RGB03-211052 中国浙江 2108769 PL01 4 3000.00 +亚太 RGB03-210712 杭州 RGB03-210727 中国浙江 6000001 PL01 4 66300.00 +亚太 RGB03-210712 杭州 RGB03-210720 中国浙江 6000001 PL01 4 7000.00 +亚太 RGB03-210712 杭州 RGB03-211058 中国浙江 2108470 PL01 4 50000.00 +亚太 RGB03-210712 杭州 RGB03-211058 中国浙江 2108467 PL01 4 20000.00 +亚太 RGB03-210712 杭州 RGB03-210728 中国浙江 6000001 PL01 4 14600.00 +亚太 RGB03-210666 杭州 RGB03-210676 中国浙江 2106880 PL01 4 3000.00 +亚太 RGB03-210666 杭州 RGB03-210677 中国浙江 2108872 PL01 4 3000.00 +亚太 RGB03-210666 杭州 RGB03-210677 中国浙江 2106993 PL01 4 5000.00 +亚太 RGB03-210666 杭州 RGB03-210678 中国浙江 2107003 PL01 4 1000.00 +亚太 RGB03-210626 杭州 RGB03-210635 中国浙江 6000001 PL01 4 4000.00 +亚太 RGB03-210626 杭州 RGB03-210634 中国浙江 6000001 PL01 4 11560.00 +亚太 RGB03-210626 杭州 RGB03-210641 中国浙江 6000001 PL01 4 4750.00 +亚太 RGB03-210626 杭州 RGB03-210637 中国浙江 6000001 PL01 4 7000.00 +亚太 RGB03-210597 杭州 RGB03-210605 中国浙江 2104231 PL01 4 2000.00 +亚太 RGB03-210565 杭州 RGB03-210566 中国浙江 2107142 PL01 4 11000.00 +亚太 RGB03-210530 杭州 RGB03-210885 中国浙江 2119867 PL01 4 5000.00 +亚太 RGB03-210530 杭州 RGB03-210544 中国浙江 2108765 PL01 4 2000.00 +亚太 RGB03-210530 杭州 RGB03-210544 中国浙江 2103779 PL01 4 2000.00 +亚太 RGB03-210203 杭州 RGB03-210213 中国浙江 2105726 PL01 37 3000.00 +亚太 RGB03-210965 杭州 RGB03-210973 中国浙江 6000001 PL01 4 6500.00 +亚太 RGB03-210965 杭州 RGB03-210977 中国浙江 6000001 PL01 4 22700.00 +亚太 RGB03-210965 杭州 RGB03-210979 中国浙江 6000001 PL01 4 20430.00 +亚太 RGB03-210965 杭州 RGB03-210976 中国浙江 6000001 PL01 4 47000.00 +亚太 RGB03-210965 杭州 RGB03-210978 中国浙江 6000001 PL01 4 99000.00 +亚太 RGB03-210904 杭州 RGB03-210912 中国浙江 6000001 PL01 4 18193.00 +亚太 RGB03-210843 杭州 RGB03-210858 中国浙江 6000001 PL01 4 2000.00 +亚太 RGB03-210843 杭州 RGB03-210852 中国浙江 6000001 PL01 4 2000.00 +亚太 RGB03-210843 杭州 RGB03-210854 中国浙江 6000001 PL01 4 43300.00 +亚太 RGB03-210843 杭州 RGB03-210855 中国浙江 6000001 PL01 4 48000.00 +亚太 RGB03-210843 杭州 RGB03-210857 中国浙江 6000001 PL01 4 18500.00 +亚太 RGB03-210843 杭州 RGB03-210857 中国浙江 2108895 PL01 4 7000.00 +亚太 RGB03-210843 杭州 RGB03-210857 中国浙江 2108857 PL01 4 5000.00 +亚太 RGB03-210843 杭州 RGB03-210857 中国浙江 2108856 PL01 4 2000.00 +亚太 RGB03-210843 杭州 RGB03-210857 中国浙江 2108534 PL01 4 5000.00 +亚太 RGB03-210843 杭州 RGB03-210853 中国浙江 6000001 PL01 4 21000.00 +亚太 RGB03-210843 杭州 RGB03-210853 中国浙江 2106081 PL01 4 18000.00 +亚太 RGB03-210843 杭州 RGB03-210856 中国浙江 6000001 PL01 4 15000.00 +亚太 RGB03-210843 杭州 RGB03-210856 中国浙江 2106060 PL01 4 3000.00 +亚太 RGB03-210843 杭州 RGB03-210851 中国浙江 2110282 PL01 4 3000.00 +亚太 RGB03-210843 杭州 RGB03-210851 中国浙江 2108496 PL01 4 10000.00 +亚太 RGB03-210785 杭州 RGB03-210795 中国浙江 2104408 PL01 4 400.00 +亚太 RGB03-210750 杭州 RGB03-210765 中国浙江 6000001 PL01 4 12200.00 +亚太 RGB03-210750 杭州 RGB03-210764 中国浙江 6000001 PL01 4 4000.00 +亚太 RGB03-210750 杭州 RGB03-210763 中国浙江 6000001 PL01 4 4000.00 +亚太 RGB03-210750 杭州 RGB03-210763 中国浙江 2106391 PL01 4 10000.00 +亚太 RGB03-210750 杭州 RGB03-210759 中国浙江 6000001 PL01 4 10000.00 +亚太 RGB03-210712 杭州 RGB03-211061 中国浙江 2109632 PL01 4 10000.00 +亚太 RGB03-210510 杭州 RGB03-210518 中国浙江 6000001 PL01 4 6000.00 +亚太 RGB03-210177 杭州 RGB03-210187 中国浙江 2108030 PL01 4 3000.00 +亚太 RGB03-210177 杭州 RGB03-210186 中国浙江 2106513 PL01 4 15000.00 +亚太 RGB03-210177 杭州 RGB03-210186 中国浙江 2106512 PL01 4 3000.00 +亚太 RGB03-210177 杭州 RGB03-210186 中国浙江 2106509 PL01 4 3000.00 +亚太 RGB03-210177 杭州 RGB03-210186 中国浙江 2103898 PL01 4 5000.00 +亚太 RGB03-210098 杭州 RGB03-210111 中国浙江 6000001 PL01 4 22687.50 +亚太 RGB03-210098 杭州 RGB03-210113 中国浙江 6000001 PL01 4 12000.00 +亚太 RGB03-210098 杭州 RGB03-210114 中国浙江 6000001 PL01 4 15000.00 +亚太 RGB03-210098 杭州 RGB03-210112 中国浙江 6000001 PL01 4 29885.50 +亚太 RGB03-210098 杭州 RGB03-210109 中国浙江 6000001 PL01 4 13000.00 +亚太 RGB03-210098 杭州 RGB03-210106 中国浙江 6000001 PL01 4 23500.00 +亚太 RGB03-210098 杭州 RGB03-210108 中国浙江 2108439 PL01 4 10000.00 +亚太 RGB03-210098 杭州 RGB03-210108 中国浙江 2108438 PL01 4 10000.00 +亚太 RGB03-210098 杭州 RGB03-210108 中国浙江 2103926 PL01 4 2000.00 +亚太 RGB03-210066 杭州 RGB03-210079 中国浙江 2104963 PL01 4 5000.00 +亚太 RGB03-210066 杭州 RGB03-210078 中国浙江 2107039 PL01 4 5000.00 +亚太 RGB03-210066 杭州 RGB03-210074 中国浙江 6000001 PL01 4 35900.00 +亚太 RGB03-210965 杭州 RGB03-210973 中国浙江 6000001 PL01 6 54097.00 +亚太 RGB03-210965 杭州 RGB03-210977 中国浙江 6000001 PL01 6 1766.00 +亚太 RGB03-210965 杭州 RGB03-210978 中国浙江 6000001 PL01 6 2000.00 +亚太 RGB03-210930 杭州 RGB03-210946 中国浙江 2106978 PL01 6 9012.00 +亚太 RGB03-210930 杭州 RGB03-210945 中国浙江 2104744 PL01 6 15100.00 +亚太 RGB03-210930 杭州 RGB03-210938 中国浙江 2106842 PL01 6 3200.00 +亚太 RGB03-210930 杭州 RGB03-210938 中国浙江 2106827 PL01 6 0.40 +亚太 RGB03-210904 杭州 RGB03-210912 中国浙江 6000001 PL01 6 48000.00 +亚太 RGB03-210843 杭州 RGB03-210852 中国浙江 6000001 PL01 6 12558.00 +亚太 RGB03-210843 杭州 RGB03-210852 中国浙江 2109232 PL01 6 911498.00 +亚太 RGB03-210843 杭州 RGB03-210852 中国浙江 2108492 PL01 6 30000.00 +亚太 RGB03-210843 杭州 RGB03-210852 中国浙江 2106082 PL01 6 23300.00 +亚太 RGB03-210510 杭州 RGB03-210520 中国浙江 6000001 PL01 4 10000.00 +亚太 RGB03-210510 杭州 RGB03-210519 中国浙江 6000001 PL01 4 26000.00 +亚太 RGB03-210510 杭州 RGB03-210521 中国浙江 6000001 PL01 4 5000.00 +亚太 RGB03-210434 杭州 RGB03-210444 中国浙江 2107251 PL01 4 2000.00 +亚太 RGB03-210408 杭州 RGB03-210419 中国浙江 2104358 PL01 4 10000.00 +亚太 RGB03-210361 杭州 RGB03-210381 中国浙江 6000001 PL01 4 124946.00 +亚太 RGB03-210361 杭州 RGB03-210378 中国浙江 6000001 PL01 4 146450.00 +亚太 RGB03-210361 杭州 RGB03-210371 中国浙江 6000001 PL01 4 7400.00 +亚太 RGB03-210361 杭州 RGB03-210372 中国浙江 6000001 PL01 4 4000.00 +亚太 RGB03-210361 杭州 RGB03-210379 中国浙江 6000001 PL01 4 161260.00 +亚太 RGB03-210361 杭州 RGB03-210373 中国浙江 6000001 PL01 4 5210.00 +亚太 RGB03-210361 杭州 RGB03-210377 中国浙江 6000001 PL01 4 39520.00 +亚太 RGB03-210361 杭州 RGB03-210380 中国浙江 6000001 PL01 4 133380.00 +亚太 RGB03-210361 杭州 RGB03-210375 中国浙江 6000001 PL01 4 61014.00 +亚太 RGB03-210361 杭州 RGB03-210370 中国浙江 6000001 PL01 4 5000.00 +亚太 RGB03-210361 杭州 RGB03-210369 中国浙江 6000001 PL01 4 20650.00 +亚太 RGB03-210320 杭州 RGB03-210330 中国浙江 2106622 PL01 4 10068.70 +亚太 RGB03-210282 杭州 RGB03-210296 中国浙江 6000001 PL01 4 46798.00 +亚太 RGB03-210282 杭州 RGB03-210298 中国浙江 6000001 PL01 4 10086.00 +亚太 RGB03-210282 杭州 RGB03-210292 中国浙江 6000001 PL01 4 86674.00 +亚太 RGB03-210282 杭州 RGB03-210291 中国浙江 6000001 PL01 4 32000.00 +亚太 RGB03-210282 杭州 RGB03-210290 中国浙江 6000001 PL01 4 28000.00 +亚太 RGB03-210282 杭州 RGB03-210293 中国浙江 6000001 PL01 4 58506.00 +亚太 RGB03-210282 杭州 RGB03-210293 中国浙江 2109637 PL01 4 10000.00 +亚太 RGB03-210282 杭州 RGB03-210295 中国浙江 6000001 PL01 4 10000.00 +亚太 RGB03-210203 杭州 RGB03-210216 中国浙江 2107352 PL01 4 10000.00 +亚太 RGB03-210203 杭州 RGB03-210216 中国浙江 2105775 PL01 4 10000.00 +亚太 RGB03-210203 杭州 RGB03-210216 中国浙江 2105770 PL01 4 10000.00 +亚太 RGB03-210177 杭州 RGB03-210185 中国浙江 2109281 PL01 4 5000.00 亚太 RGB03-210626 杭州 RGB03-210634 中国浙江 2109137 PL01 6 106000.00 -亚太 RGB03-210666 杭州 RGB03-210678 中国浙江 2121247 PL01 6 50000.00 -亚太 RGB03-210565 杭州 RGB03-210575 中国浙江 2107153 PL01 6 50000.00 -亚太 RGB03-210626 杭州 RGB03-210641 中国浙江 2106791 PL01 6 50000.00 -亚太 RGB03-210712 杭州 RGB03-210713 中国浙江 2121272 PL01 6 80000.00 -亚太 RGB03-210666 杭州 RGB03-210675 中国浙江 2121280 PL01 6 30000.00 -亚太 RGB03-210965 杭州 RGB03-210979 中国浙江 2107584 PL01 6 50000.00 -亚太 RGB03-210597 杭州 RGB03-210608 中国浙江 2121284 PL01 6 13000.00 -亚太 RGB03-211000 杭州 RGB03-211009 中国浙江 2121288 PL01 6 55200.00 -亚太 RGB03-210565 杭州 RGB03-210574 中国浙江 2107154 PL01 6 100000.00 -亚太 RGB03-210626 杭州 RGB03-210636 中国浙江 2104323 PL01 6 50000.00 -亚太 RGB03-210843 杭州 RGB03-210858 中国浙江 2108535 PL01 6 60000.00 -亚太 RGB03-210785 杭州 RGB03-210794 中国浙江 2109020 PL01 6 50000.00 -亚太 RGB03-210785 杭州 RGB03-210794 中国浙江 2109036 PL01 6 50000.00 -亚太 RGB03-210597 杭州 RGB03-210606 中国浙江 2119940 PL01 6 55355.00 -亚太 RGB03-210802 杭州 RGB03-210803 中国浙江 2121315 PL01 6 48000.00 -亚太 RGB03-211000 杭州 RGB03-211001 中国浙江 2121164 PL01 6 12805.00 -亚太 RGB03-210802 杭州 RGB03-210810 中国浙江 2109324 PL01 6 40000.00 -亚太 RGB03-210530 杭州 RGB03-210538 中国浙江 11150000 PL01 6 100000.00 -亚太 RGB03-210802 杭州 RGB03-210811 中国浙江 2121320 PL01 6 100000.00 -亚太 RGB03-210530 杭州 RGB03-210538 中国浙江 11150000 PL01 4 5000.00 -亚太 RGB03-210565 杭州 RGB03-210577 中国浙江 2107166 PL01 6 50000.00 -亚太 RGB03-210469 杭州 RGB03-210477 中国浙江 2105689 PL01 6 0.00 -亚太 RGB03-210802 杭州 RGB03-210810 中国浙江 2107334 PL01 6 240000.00 -亚太 RGB03-210142 杭州 RGB03-210154 中国浙江 2107074 PL01 6 50000.00 -亚太 RGB03-210434 杭州 RGB03-210435 中国浙江 2121443 PL01 6 50000.00 -亚太 RGB03-210597 杭州 RGB03-210605 中国浙江 2106731 PL01 6 19527.13 -亚太 RGB03-210320 杭州 RGB03-210331 中国浙江 2106619 PL01 6 100000000.00 -亚太 RGB03-210001 杭州 RGB03-210013 中国浙江 2109222 PL01 4 0.01 +亚太 RGB03-210142 杭州 RGB03-210152 中国浙江 2105066 PL01 6 100000.00 +亚太 RGB03-210408 杭州 RGB03-210419 中国浙江 2121219 PL01 6 10000000.00 +亚太 RGB03-210177 杭州 RGB03-210186 中国浙江 2103898 PL01 6 100000.00 +亚太 RGB03-210469 杭州 RGB03-210477 中国浙江 2121167 PL01 6 500000.00 +亚太 RGB03-210469 杭州 RGB03-210477 中国浙江 2121230 PL01 6 500000.00 +亚太 RGB03-210203 杭州 RGB03-210211 中国浙江 2108531 PL01 6 50000.00 +亚太 RGB03-210530 杭州 RGB03-210543 中国浙江 2104494 PL01 6 50000.00 +亚太 RGB03-210530 杭州 RGB03-210540 中国浙江 2106822 PL01 6 50000.00 +亚太 RGB03-211000 杭州 RGB03-211010 中国浙江 2108839 PL01 6 50000.00 +亚太 RGB03-211000 杭州 RGB03-211008 中国浙江 2106589 PL01 6 550000.00 +亚太 RGB03-210434 杭州 RGB03-210449 中国浙江 2107307 PL01 6 60000.00 +亚太 RGB03-210565 杭州 RGB03-210576 中国浙江 2050602 PL01 6 50000.00 +亚太 RGB03-210565 杭州 RGB03-210576 中国浙江 2109278 PL01 6 50000.00 +亚太 RGB03-210530 杭州 RGB03-210885 中国浙江 2106815 PL01 6 30000.00 +亚太 RGB03-211000 杭州 RGB03-211008 中国浙江 2121120 PL01 6 55200.00 +亚太 RGB03-210565 杭州 RGB03-210573 中国浙江 2105090 PL01 6 256500.00 +亚太 RGB03-210965 杭州 RGB03-210973 中国浙江 2121117 PL01 6 20000.00 +亚太 RGB03-210408 杭州 RGB03-210419 中国浙江 2104354 PL01 6 2000000.00 +亚太 RGB03-210282 杭州 RGB03-210299 中国浙江 2108957 PL01 6 50000.00 +亚太 RGB03-210320 杭州 RGB03-210333 中国浙江 2106662 PL01 6 50000.00 +亚太 RGB03-210250 杭州 RGB03-210259 中国浙江 2107406 PL01 6 120000.00 +亚太 RGB03-210282 杭州 RGB03-210283 中国浙江 2120881 PL01 6 20000.00 +亚太 RGB03-210066 杭州 RGB03-210077 中国浙江 2104834 PL01 6 1062805.00 +亚太 RGB03-210530 杭州 RGB03-210531 中国浙江 2108763 PL01 6 150000.00 +亚太 RGB03-210843 杭州 RGB03-210851 中国浙江 2110282 PL01 6 1000000.00 +亚太 RGB03-210843 杭州 RGB03-210851 中国浙江 2121076 PL01 6 100000.00 +亚太 RGB03-210250 杭州 RGB03-210263 中国浙江 2105870 PL01 6 50000.00 +亚太 RGB03-210066 杭州 RGB03-210077 中国浙江 2107016 PL01 6 100000.00 亚太 RGB03-210001 杭州 RGB03-210013 中国浙江 2108448 PL01 4 0.01 -亚太 RGB03-210001 杭州 RGB03-210013 中国浙江 3053091 PL01 6 0.02 -亚太 RGB03-210001 杭州 RGB03-210013 中国浙江 2108448 PL01 6 0.01 -亚太 RGB03-210001 杭州 RGB03-210013 中国浙江 2108448 PL01 13 0.01 -亚太 RGB03-210282 杭州 RGB03-210290 中国浙江 2107801 PL01 4 0.01 -亚太 RGB03-210802 杭州 RGB03-210810 中国浙江 2085374 PL01 6 200289.00 -亚太 RGB03-210007 杭州 RGB03-210030 中国浙江 3302059 PL01 6 2000.00 -亚太 RGB03-210802 杭州 RGB03-210810 中国浙江 2085374 PL01 4 3579.55 -亚太 RGB03-210802 杭州 RGB03-210810 中国浙江 2085374 PL01 37 200.00 -亚太 RGB03-210802 杭州 RGB03-210817 中国浙江 6000001 PL01 4 0.00 -亚太 RGB03-210802 杭州 RGB03-210803 中国浙江 2120518 PL01 4 1.00 -亚太 RGB03-210001 杭州 RGB03-210008 中国浙江 3000019 PL01 4 22.00 -亚太 RGB03-210802 杭州 RGB03-210810 中国浙江 2085459 PL01 6 10.00 -亚太 RGB03-210007 杭州 RGB03-210030 中国浙江 3000781 PL01 4 1500.00 -亚太 RGB03-210802 杭州 RGB03-210810 中国浙江 2085538 PL01 6 0.00 -亚太 RGB03-210802 杭州 RGB03-210810 中国浙江 2085538 PL01 4 5523.80 -亚太 RGB03-210361 杭州 RGB03-211043 中国浙江 2085536 PL01 4 2314.00 -亚太 RGB03-210001 杭州 RGB03-210008 中国浙江 2123143 PL01 4 10000.00 -亚太 RGB03-210802 杭州 RGB03-210810 中国浙江 2123146 PL01 4 274.00 -亚太 RGB03-210802 杭州 RGB03-210811 中国浙江 2123168 PL01 6 334.00 -亚太 RGB03-210098 杭州 RGB03-210106 中国浙江 2085582 PL01 6 10100.00 -亚太 RGB03-210098 杭州 RGB03-210106 中国浙江 2123187 PL01 6 20000.00 +亚太 RGB03-210001 杭州 RGB03-210013 中国浙江 2109222 PL01 4 0.01 +亚太 RGB03-210320 杭州 RGB03-210331 中国浙江 2106619 PL01 6 100000000.00 +亚太 RGB03-210597 杭州 RGB03-210605 中国浙江 2106731 PL01 6 19527.13 +亚太 RGB03-210434 杭州 RGB03-210435 中国浙江 2121443 PL01 6 50000.00 +亚太 RGB03-210142 杭州 RGB03-210154 中国浙江 2107074 PL01 6 50000.00 +亚太 RGB03-210802 杭州 RGB03-210810 中国浙江 2107334 PL01 6 240000.00 +亚太 RGB03-210469 杭州 RGB03-210477 中国浙江 2105689 PL01 6 0.00 +亚太 RGB03-210565 杭州 RGB03-210577 中国浙江 2107166 PL01 6 50000.00 +亚太 RGB03-210530 杭州 RGB03-210538 中国浙江 11150000 PL01 4 5000.00 +亚太 RGB03-210802 杭州 RGB03-210811 中国浙江 2121320 PL01 6 100000.00 +亚太 RGB03-210530 杭州 RGB03-210538 中国浙江 11150000 PL01 6 100000.00 +亚太 RGB03-210802 杭州 RGB03-210810 中国浙江 2109324 PL01 6 40000.00 +亚太 RGB03-211000 杭州 RGB03-211001 中国浙江 2121164 PL01 6 12805.00 +亚太 RGB03-210802 杭州 RGB03-210803 中国浙江 2121315 PL01 6 48000.00 +亚太 RGB03-210597 杭州 RGB03-210606 中国浙江 2119940 PL01 6 55355.00 +亚太 RGB03-210785 杭州 RGB03-210794 中国浙江 2109036 PL01 6 50000.00 +亚太 RGB03-210785 杭州 RGB03-210794 中国浙江 2109020 PL01 6 50000.00 +亚太 RGB03-210843 杭州 RGB03-210858 中国浙江 2108535 PL01 6 60000.00 +亚太 RGB03-210626 杭州 RGB03-210636 中国浙江 2104323 PL01 6 50000.00 +亚太 RGB03-210565 杭州 RGB03-210574 中国浙江 2107154 PL01 6 100000.00 +亚太 RGB03-211000 杭州 RGB03-211009 中国浙江 2121288 PL01 6 55200.00 +亚太 RGB03-210597 杭州 RGB03-210608 中国浙江 2121284 PL01 6 13000.00 +亚太 RGB03-210965 杭州 RGB03-210979 中国浙江 2107584 PL01 6 50000.00 +亚太 RGB03-210666 杭州 RGB03-210675 中国浙江 2121280 PL01 6 30000.00 +亚太 RGB03-210712 杭州 RGB03-210713 中国浙江 2121272 PL01 6 80000.00 +亚太 RGB03-210626 杭州 RGB03-210641 中国浙江 2106791 PL01 6 50000.00 +亚太 RGB03-210565 杭州 RGB03-210575 中国浙江 2107153 PL01 6 50000.00 +亚太 RGB03-210666 杭州 RGB03-210678 中国浙江 2121247 PL01 6 50000.00 +亚太 RGB03-210320 杭州 RGB03-210329 中国浙江 2109311 PL01 6 50000.00 +亚太 RGB03-210510 杭州 RGB03-210518 中国浙江 2106794 PL01 6 100000.00 +亚太 RGB03-210530 杭州 RGB03-210531 中国浙江 2120922 PL01 6 30000.00 +亚太 RGB03-210408 杭州 RGB03-210420 中国浙江 2104359 PL01 6 100000.00 +亚太 RGB03-210408 杭州 RGB03-210419 中国浙江 2104352 PL01 6 50000.00 +亚太 RGB03-210408 杭州 RGB03-210419 中国浙江 2104360 PL01 6 100000.00 +亚太 RGB03-210408 杭州 RGB03-210419 中国浙江 2104355 PL01 6 50000.00 +亚太 RGB03-210361 杭州 RGB03-211043 中国浙江 2105298 PL01 6 20000.00 +亚太 RGB03-210843 杭州 RGB03-210857 中国浙江 2108535 PL01 6 520000.00 +亚太 RGB03-210712 杭州 RGB03-210722 中国浙江 2107217 PL01 6 460000.00 +亚太 RGB03-210930 杭州 RGB03-210941 中国浙江 2104688 PL01 6 26000.00 +亚太 RGB03-210177 杭州 RGB03-210186 中国浙江 2106513 PL01 6 260000.00 +亚太 RGB03-210565 杭州 RGB03-210574 中国浙江 2120778 PL01 6 100000.00 +亚太 RGB03-210965 杭州 RGB03-210966 中国浙江 2120769 PL01 6 50000.00 +亚太 RGB03-210361 杭州 RGB03-210371 中国浙江 2109344 PL01 4 7000.00 +亚太 RGB03-210098 杭州 RGB03-210106 中国浙江 2120872 PL01 6 12805.00 +亚太 RGB03-210626 杭州 RGB03-210638 中国浙江 2120754 PL01 6 20000.00 +亚太 RGB03-210712 杭州 RGB03-210725 中国浙江 2105273 PL01 6 500000.00 +亚太 RGB03-210469 杭州 RGB03-210477 中国浙江 2105686 PL01 6 400000.00 +亚太 RGB03-210965 杭州 RGB03-210979 中国浙江 2107586 PL01 6 100000.00 +亚太 RGB03-210001 杭州 RGB03-210013 中国浙江 3301979 PL01 4 0.01 +亚太 RGB03-210965 杭州 RGB03-210979 中国浙江 2107585 PL01 6 50000.00 +亚太 RGB03-210965 杭州 RGB03-210979 中国浙江 2109276 PL01 6 200000.00 +亚太 RGB03-210361 杭州 RGB03-210371 中国浙江 2120524 PL01 6 20000.00 +亚太 RGB03-210098 杭州 RGB03-210111 中国浙江 2106602 PL01 6 70000.00 +亚太 RGB03-210066 杭州 RGB03-210077 中国浙江 2104923 PL01 6 450000.00 +亚太 RGB03-210001 杭州 RGB03-210013 中国浙江 2109167 PL01 6 0.02 +亚太 RGB03-210203 杭州 RGB03-210212 中国浙江 6000001 PL01 6 0.02 +亚太 RGB03-210282 杭州 RGB03-210293 中国浙江 6000001 PL01 6 0.02 +亚太 RGB03-210203 杭州 RGB03-210216 中国浙江 2108548 PL01 6 10000000.00 +亚太 RGB03-210320 杭州 RGB03-210335 中国浙江 2119939 PL01 6 880000.00 +亚太 RGB03-210904 杭州 RGB03-210912 中国浙江 2120976 PL01 6 250000.00 +亚太 RGB03-210250 杭州 RGB03-210263 中国浙江 2105873 PL01 6 110000.00 +亚太 RGB03-210361 杭州 RGB03-210371 中国浙江 2105299 PL01 6 200000.00 +亚太 RGB03-210597 杭州 RGB03-210608 中国浙江 2104242 PL01 6 15000.00 +亚太 RGB03-210802 杭州 RGB03-210803 中国浙江 2120723 PL01 6 311273.86 +亚太 RGB03-210203 杭州 RGB03-210213 中国浙江 2107331 PL01 6 50000.00 +亚太 RGB03-210802 杭州 RGB03-210803 中国浙江 2121028 PL01 6 147668.50 +亚太 RGB03-210785 杭州 RGB03-210794 中国浙江 2109047 PL01 6 100000.00 +亚太 RGB03-210785 杭州 RGB03-210795 中国浙江 2104396 PL01 6 100000.00 +亚太 RGB03-210785 杭州 RGB03-210794 中国浙江 2109602 PL01 6 100000.00 +亚太 RGB03-210320 杭州 RGB03-210330 中国浙江 2106619 PL01 6 50000.00 +亚太 RGB03-210530 杭州 RGB03-210538 中国浙江 2119942 PL01 6 20000.00 +亚太 RGB03-210098 杭州 RGB03-210114 中国浙江 2106642 PL01 6 50000.00 +亚太 RGB03-211000 杭州 RGB03-211008 中国浙江 2120979 PL01 6 50000.00 +亚太 RGB03-210361 杭州 RGB03-211043 中国浙江 2105308 PL01 6 50000.00 +亚太 RGB03-211000 杭州 RGB03-211008 中国浙江 2108074 PL01 6 50000.00 +亚太 RGB03-210510 杭州 RGB03-210518 中国浙江 2120971 PL01 6 90000.00 +亚太 RGB03-210177 杭州 RGB03-210186 中国浙江 2108002 PL01 4 50000.00 +亚太 RGB03-210666 杭州 RGB03-210677 中国浙江 2106981 PL01 6 400000.00 +亚太 RGB03-210434 杭州 RGB03-210444 中国浙江 2120981 PL01 6 100000.00 +亚太 RGB03-210177 杭州 RGB03-210186 中国浙江 2108002 PL01 6 700000.00 +亚太 RGB03-210666 杭州 RGB03-210676 中国浙江 2106874 PL01 6 200000.00 +亚太 RGB03-210434 杭州 RGB03-210442 中国浙江 2120917 PL01 6 50000.00 +亚太 RGB03-210965 杭州 RGB03-210979 中国浙江 2107662 PL01 6 60000.00 +亚太 RGB03-210434 杭州 RGB03-210444 中国浙江 2109224 PL01 6 150000.00 +亚太 RGB03-210626 杭州 RGB03-210637 中国浙江 2106793 PL01 6 50000.00 +亚太 RGB03-210510 杭州 RGB03-210518 中国浙江 2104339 PL01 6 55355.00 +亚太 RGB03-210510 杭州 RGB03-210518 中国浙江 2106795 PL01 6 180000.00 +亚太 RGB03-210361 杭州 RGB03-211043 中国浙江 2109342 PL01 6 30000.00 +亚太 RGB03-210361 杭州 RGB03-211043 中国浙江 2107221 PL01 6 91500.00 +亚太 RGB03-210361 杭州 RGB03-211043 中国浙江 2107219 PL01 6 140000.00 +亚太 RGB03-210361 杭州 RGB03-211043 中国浙江 2107218 PL01 6 150000.00 +亚太 RGB03-210361 杭州 RGB03-211043 中国浙江 2105313 PL01 6 90000.00 +亚太 RGB03-210361 杭州 RGB03-211043 中国浙江 2105299 PL01 6 215000.00 +亚太 RGB03-210361 杭州 RGB03-211043 中国浙江 2105296 PL01 6 55000.00 +亚太 RGB03-210320 杭州 RGB03-210330 中国浙江 2106620 PL01 6 160007.00 +亚太 RGB03-210320 杭州 RGB03-210330 中国浙江 2103993 PL01 6 36140.00 +亚太 RGB03-210320 杭州 RGB03-210330 中国浙江 2103992 PL01 6 34370.00 +亚太 RGB03-210320 杭州 RGB03-210330 中国浙江 2103991 PL01 6 27750.00 +亚太 RGB03-210320 杭州 RGB03-210330 中国浙江 2103989 PL01 6 67116.00 +亚太 RGB03-210320 杭州 RGB03-210330 中国浙江 2103983 PL01 6 100000.00 +亚太 RGB03-210320 杭州 RGB03-210338 中国浙江 2108739 PL01 6 12400.00 +亚太 RGB03-210320 杭州 RGB03-210338 中国浙江 2106723 PL01 6 70000.00 +亚太 RGB03-210320 杭州 RGB03-210338 中国浙江 2106718 PL01 6 500.00 +亚太 RGB03-210320 杭州 RGB03-210338 中国浙江 2104216 PL01 6 50000.00 +亚太 RGB03-210320 杭州 RGB03-210338 中国浙江 2103769 PL01 6 8000.00 +亚太 RGB03-210320 杭州 RGB03-210337 中国浙江 2106701 PL01 6 145000.00 +亚太 RGB03-210320 杭州 RGB03-210337 中国浙江 2104159 PL01 6 51850.00 +亚太 RGB03-210282 杭州 RGB03-210292 中国浙江 6000001 PL01 6 15083.00 +亚太 RGB03-210282 杭州 RGB03-210290 中国浙江 2110757 PL01 6 25000.00 +亚太 RGB03-210282 杭州 RGB03-210290 中国浙江 2107801 PL01 6 83004.00 +亚太 RGB03-210282 杭州 RGB03-210293 中国浙江 2119967 PL01 6 70000.00 +亚太 RGB03-210282 杭州 RGB03-210293 中国浙江 2109637 PL01 6 66040.00 +亚太 RGB03-210282 杭州 RGB03-210293 中国浙江 2108676 PL01 6 50000.00 +亚太 RGB03-210282 杭州 RGB03-210293 中国浙江 2108672 PL01 6 40000.00 +亚太 RGB03-210282 杭州 RGB03-210293 中国浙江 2108662 PL01 6 60000.00 +亚太 RGB03-210282 杭州 RGB03-210293 中国浙江 2107791 PL01 6 51403.00 +亚太 RGB03-210530 杭州 RGB03-210539 中国浙江 2104517 PL01 6 37000.00 +亚太 RGB03-210530 杭州 RGB03-210885 中国浙江 2119867 PL01 6 60000.00 +亚太 RGB03-210530 杭州 RGB03-210885 中国浙江 2109169 PL01 6 90438.50 +亚太 RGB03-210530 杭州 RGB03-210885 中国浙江 2108475 PL01 6 25850.00 +亚太 RGB03-210530 杭州 RGB03-210538 中国浙江 2108920 PL01 6 2850.00 +亚太 RGB03-210530 杭州 RGB03-210546 中国浙江 2108688 PL01 6 10000.00 +亚太 RGB03-210530 杭州 RGB03-210544 中国浙江 2108971 PL01 6 40000.00 +亚太 RGB03-210530 杭州 RGB03-210544 中国浙江 2108970 PL01 6 18910.00 +亚太 RGB03-210530 杭州 RGB03-210544 中国浙江 2108969 PL01 6 50000.00 +亚太 RGB03-210530 杭州 RGB03-210544 中国浙江 2108861 PL01 6 30000.00 +亚太 RGB03-210530 杭州 RGB03-210544 中国浙江 2108768 PL01 6 27600.00 +亚太 RGB03-210530 杭州 RGB03-210544 中国浙江 2108767 PL01 6 50000.00 +亚太 RGB03-210530 杭州 RGB03-210544 中国浙江 2108764 PL01 6 35000.00 +亚太 RGB03-210530 杭州 RGB03-210544 中国浙江 2108763 PL01 6 70000.00 +亚太 RGB03-210530 杭州 RGB03-210544 中国浙江 2103780 PL01 6 51600.00 +亚太 RGB03-210530 杭州 RGB03-210544 中国浙江 2103779 PL01 6 21200.00 +亚太 RGB03-210434 杭州 RGB03-210446 中国浙江 2107254 PL01 6 9000.00 +亚太 RGB03-210434 杭州 RGB03-210444 中国浙江 2109225 PL01 6 9769.00 +亚太 RGB03-210434 杭州 RGB03-210444 中国浙江 2109223 PL01 6 1900.00 +亚太 RGB03-210434 杭州 RGB03-210444 中国浙江 2107293 PL01 6 30000.00 +亚太 RGB03-210434 杭州 RGB03-210444 中国浙江 2107253 PL01 6 59100.00 +亚太 RGB03-210434 杭州 RGB03-210444 中国浙江 2107252 PL01 6 60000.00 +亚太 RGB03-210434 杭州 RGB03-210444 中国浙江 2107250 PL01 6 31000.00 +亚太 RGB03-210434 杭州 RGB03-210444 中国浙江 2107246 PL01 6 13106.78 +亚太 RGB03-210434 杭州 RGB03-210444 中国浙江 2105475 PL01 6 13100.00 +亚太 RGB03-210434 杭州 RGB03-210444 中国浙江 2105460 PL01 6 151415.00 +亚太 RGB03-210434 杭州 RGB03-210444 中国浙江 2105454 PL01 6 57700.00 +亚太 RGB03-210434 杭州 RGB03-210444 中国浙江 2105453 PL01 6 100092000.00 +亚太 RGB03-210361 杭州 RGB03-211043 中国浙江 2109344 PL01 6 90000.00 +亚太 RGB03-210282 杭州 RGB03-210293 中国浙江 2106239 PL01 6 185000.00 +亚太 RGB03-210098 杭州 RGB03-210114 中国浙江 2108718 PL01 6 6670.00 +亚太 RGB03-210098 杭州 RGB03-210114 中国浙江 2108717 PL01 6 10000.00 +亚太 RGB03-210098 杭州 RGB03-210114 中国浙江 2108716 PL01 6 10000.00 +亚太 RGB03-210098 杭州 RGB03-210114 中国浙江 2108715 PL01 6 10000.00 +亚太 RGB03-210098 杭州 RGB03-210108 中国浙江 2108439 PL01 6 173360.00 +亚太 RGB03-210098 杭州 RGB03-210108 中国浙江 2108438 PL01 6 6600.00 +亚太 RGB03-210098 杭州 RGB03-210108 中国浙江 2103951 PL01 6 64855.02 +亚太 RGB03-210098 杭州 RGB03-210108 中国浙江 2103946 PL01 6 21911.30 +亚太 RGB03-210098 杭州 RGB03-210108 中国浙江 2103937 PL01 6 16600.00 +亚太 RGB03-210098 杭州 RGB03-210108 中国浙江 2103934 PL01 6 11550.00 +亚太 RGB03-210098 杭州 RGB03-210108 中国浙江 2103927 PL01 6 24443.14 +亚太 RGB03-210098 杭州 RGB03-210108 中国浙江 2103926 PL01 6 11600.00 +亚太 RGB03-210098 杭州 RGB03-210108 中国浙江 2103912 PL01 6 15145.00 +亚太 RGB03-210066 杭州 RGB03-210077 中国浙江 2104836 PL01 6 10000.00 +亚太 RGB03-210066 杭州 RGB03-210078 中国浙江 2107039 PL01 6 25500.00 +亚太 RGB03-210066 杭州 RGB03-210078 中国浙江 2104916 PL01 6 50000.00 +亚太 RGB03-210930 杭州 RGB03-210938 中国浙江 2108700 PL01 13 500.00 +亚太 RGB03-210930 杭州 RGB03-210938 中国浙江 2106838 PL01 13 500.00 +亚太 RGB03-210930 杭州 RGB03-210938 中国浙江 2104535 PL01 13 500.00 +亚太 RGB03-210843 杭州 RGB03-210851 中国浙江 2106065 PL01 13 500.00 +亚太 RGB03-210802 杭州 RGB03-210810 中国浙江 2057007 PL01 13 1000.00 +亚太 RGB03-210203 杭州 RGB03-210215 中国浙江 2107378 PL01 13 1500.00 +亚太 RGB03-210203 杭州 RGB03-210215 中国浙江 2107333 PL01 13 1500.00 +亚太 RGB03-210203 杭州 RGB03-210216 中国浙江 2108550 PL01 13 1500.00 +亚太 RGB03-210203 杭州 RGB03-210216 中国浙江 2107352 PL01 13 1000.00 +亚太 RGB03-210203 杭州 RGB03-210216 中国浙江 2105773 PL01 13 1000.00 +亚太 RGB03-210203 杭州 RGB03-210211 中国浙江 2108531 PL01 13 1500.00 +亚太 RGB03-210203 杭州 RGB03-210211 中国浙江 2107381 PL01 13 1500.00 +亚太 RGB03-210203 杭州 RGB03-210211 中国浙江 2107380 PL01 13 1500.00 +亚太 RGB03-210282 杭州 RGB03-210293 中国浙江 2106238 PL01 6 129991.00 +亚太 RGB03-210282 杭州 RGB03-210294 中国浙江 2108663 PL01 6 25000.00 +亚太 RGB03-210282 杭州 RGB03-210294 中国浙江 2108660 PL01 6 128000.00 +亚太 RGB03-210250 杭州 RGB03-210264 中国浙江 2107409 PL01 6 95150.00 +亚太 RGB03-210203 杭州 RGB03-210217 中国浙江 2107355 PL01 6 32171.00 +亚太 RGB03-210203 杭州 RGB03-210217 中国浙江 2107354 PL01 6 25000.00 +亚太 RGB03-210203 杭州 RGB03-210215 中国浙江 2107378 PL01 6 21500.00 +亚太 RGB03-210203 杭州 RGB03-210218 中国浙江 2105970 PL01 6 40000.00 +亚太 RGB03-210203 杭州 RGB03-210218 中国浙江 2105968 PL01 6 100000.00 +亚太 RGB03-210203 杭州 RGB03-210218 中国浙江 2105965 PL01 6 50000.00 +亚太 RGB03-210203 杭州 RGB03-210218 中国浙江 2103816 PL01 6 50000.00 +亚太 RGB03-210203 杭州 RGB03-210213 中国浙江 2107327 PL01 6 300.00 +亚太 RGB03-210203 杭州 RGB03-210213 中国浙江 2105726 PL01 6 561230.00 +亚太 RGB03-210203 杭州 RGB03-210216 中国浙江 2119917 PL01 6 13200.00 +亚太 RGB03-210203 杭州 RGB03-210216 中国浙江 2108553 PL01 6 3315.00 +亚太 RGB03-210203 杭州 RGB03-210216 中国浙江 2107351 PL01 6 13200.00 +亚太 RGB03-210203 杭州 RGB03-210216 中国浙江 2105770 PL01 6 79000.00 +亚太 RGB03-210203 杭州 RGB03-210211 中国浙江 2108532 PL01 6 38000.00 +亚太 RGB03-210203 杭州 RGB03-210211 中国浙江 2107384 PL01 6 16350.00 +亚太 RGB03-210203 杭州 RGB03-210211 中国浙江 2107383 PL01 6 39050.00 +亚太 RGB03-210203 杭州 RGB03-210211 中国浙江 2107381 PL01 6 21000.00 +亚太 RGB03-210203 杭州 RGB03-210211 中国浙江 2107380 PL01 6 66000.00 +亚太 RGB03-210203 杭州 RGB03-210211 中国浙江 2105841 PL01 6 54400.00 +亚太 RGB03-210203 杭州 RGB03-210211 中国浙江 2105837 PL01 6 28500.00 +亚太 RGB03-210177 杭州 RGB03-210186 中国浙江 2106509 PL01 6 70000.00 +亚太 RGB03-210142 杭州 RGB03-210155 中国浙江 2105061 PL01 6 565000.00 +亚太 RGB03-210142 杭州 RGB03-210155 中国浙江 2105023 PL01 6 7313.00 +亚太 RGB03-210142 杭州 RGB03-210155 中国浙江 2105022 PL01 6 38691.00 +亚太 RGB03-210142 杭州 RGB03-210158 中国浙江 2105000 PL01 6 263000.00 +亚太 RGB03-210530 杭州 RGB03-210539 中国浙江 2106823 PL01 6 100000.00 +亚太 RGB03-210750 杭州 RGB03-210763 中国浙江 2106379 PL01 6 90500.00 +亚太 RGB03-210750 杭州 RGB03-210763 中国浙江 2106378 PL01 6 29000.00 +亚太 RGB03-210750 杭州 RGB03-210761 中国浙江 2106541 PL01 6 21600.00 +亚太 RGB03-210750 杭州 RGB03-210760 中国浙江 2108690 PL01 6 928.00 +亚太 RGB03-210750 杭州 RGB03-210760 中国浙江 2108689 PL01 6 1699.00 +亚太 RGB03-210750 杭州 RGB03-210759 中国浙江 2119969 PL01 6 10000.00 +亚太 RGB03-210750 杭州 RGB03-210759 中国浙江 2108419 PL01 6 40000.00 +亚太 RGB03-210750 杭州 RGB03-210759 中国浙江 2107901 PL01 6 36000.00 +亚太 RGB03-210712 杭州 RGB03-211061 中国浙江 2109632 PL01 6 41700.00 +亚太 RGB03-210712 杭州 RGB03-211061 中国浙江 2107205 PL01 6 5050.00 +亚太 RGB03-210712 杭州 RGB03-211061 中国浙江 2107203 PL01 6 34400.00 +亚太 RGB03-210712 杭州 RGB03-211046 中国浙江 2109263 PL01 6 40000.00 +亚太 RGB03-210712 杭州 RGB03-211046 中国浙江 2107208 PL01 6 150000.00 +亚太 RGB03-210712 杭州 RGB03-211046 中国浙江 2107207 PL01 6 50000.00 +亚太 RGB03-210712 杭州 RGB03-211046 中国浙江 2105241 PL01 6 50000.00 +亚太 RGB03-210712 杭州 RGB03-211046 中国浙江 2105240 PL01 6 56000.00 +亚太 RGB03-210712 杭州 RGB03-211046 中国浙江 2105235 PL01 6 35200.00 +亚太 RGB03-210712 杭州 RGB03-211049 中国浙江 6000001 PL01 6 210.00 +亚太 RGB03-210712 杭州 RGB03-211049 中国浙江 2108473 PL01 6 60000.00 +亚太 RGB03-210712 杭州 RGB03-211049 中国浙江 2107209 PL01 6 47000.00 +亚太 RGB03-210712 杭州 RGB03-211049 中国浙江 2105249 PL01 6 170000.00 +亚太 RGB03-210712 杭州 RGB03-211049 中国浙江 2105248 PL01 6 50000.00 +亚太 RGB03-210712 杭州 RGB03-211049 中国浙江 2105212 PL01 6 77746.00 +亚太 RGB03-210712 杭州 RGB03-210729 中国浙江 2105268 PL01 6 15365.00 +亚太 RGB03-210712 杭州 RGB03-210729 中国浙江 2105254 PL01 6 450240.00 +亚太 RGB03-210712 杭州 RGB03-211052 中国浙江 2119894 PL01 6 90000.00 +亚太 RGB03-210712 杭州 RGB03-211052 中国浙江 2105211 PL01 6 120000.00 +亚太 RGB03-210712 杭州 RGB03-211058 中国浙江 2108995 PL01 6 50000.00 +亚太 RGB03-210712 杭州 RGB03-211058 中国浙江 2108470 PL01 6 204500.00 +亚太 RGB03-210843 杭州 RGB03-210855 中国浙江 2106131 PL01 6 49880.00 +亚太 RGB03-210843 杭州 RGB03-210855 中国浙江 2106124 PL01 6 235970.00 +亚太 RGB03-210843 杭州 RGB03-210857 中国浙江 6000001 PL01 6 3582.00 +亚太 RGB03-210843 杭州 RGB03-210856 中国浙江 6000001 PL01 6 2000.00 +亚太 RGB03-210843 杭州 RGB03-210851 中国浙江 2108817 PL01 6 366532.03 +亚太 RGB03-210843 杭州 RGB03-210851 中国浙江 2108496 PL01 6 73150.00 +亚太 RGB03-210843 杭州 RGB03-210851 中国浙江 2106071 PL01 6 27000.00 +亚太 RGB03-210843 杭州 RGB03-210851 中国浙江 2106070 PL01 6 120000.00 +亚太 RGB03-210843 杭州 RGB03-210851 中国浙江 2106068 PL01 6 26050.00 +亚太 RGB03-210843 杭州 RGB03-210851 中国浙江 2106065 PL01 6 152863.00 +亚太 RGB03-210785 杭州 RGB03-210795 中国浙江 2109046 PL01 6 10000.00 +亚太 RGB03-210785 杭州 RGB03-210795 中国浙江 2104431 PL01 6 10000.00 +亚太 RGB03-210785 杭州 RGB03-210795 中国浙江 2104425 PL01 6 10000.00 +亚太 RGB03-210785 杭州 RGB03-210795 中国浙江 2104422 PL01 6 10000.00 +亚太 RGB03-210785 杭州 RGB03-210795 中国浙江 2104418 PL01 6 8116.00 +亚太 RGB03-210785 杭州 RGB03-210795 中国浙江 2104413 PL01 6 538.00 +亚太 RGB03-210785 杭州 RGB03-210795 中国浙江 2104403 PL01 6 36000.00 +亚太 RGB03-210785 杭州 RGB03-210795 中国浙江 2104402 PL01 6 10000.00 +亚太 RGB03-210785 杭州 RGB03-210795 中国浙江 2104400 PL01 6 10000.00 +亚太 RGB03-210785 杭州 RGB03-210795 中国浙江 2104399 PL01 6 10000.00 +亚太 RGB03-210785 杭州 RGB03-210795 中国浙江 2104395 PL01 6 10000.00 +亚太 RGB03-210785 杭州 RGB03-210795 中国浙江 2104392 PL01 6 8278.00 +亚太 RGB03-210785 杭州 RGB03-210794 中国浙江 2109044 PL01 6 10000.00 +亚太 RGB03-210785 杭州 RGB03-210794 中国浙江 2104440 PL01 6 10000.00 +亚太 RGB03-210750 杭州 RGB03-210765 中国浙江 2108420 PL01 6 36321.00 +亚太 RGB03-210750 杭州 RGB03-210763 中国浙江 2119968 PL01 6 665942.00 +亚太 RGB03-210750 杭州 RGB03-210763 中国浙江 2107881 PL01 6 35000.00 +亚太 RGB03-210750 杭州 RGB03-210763 中国浙江 2107869 PL01 6 33550.00 +亚太 RGB03-210750 杭州 RGB03-210763 中国浙江 2106391 PL01 6 4014900.00 +亚太 RGB03-210712 杭州 RGB03-211058 中国浙江 2108467 PL01 6 50000.00 +亚太 RGB03-210597 杭州 RGB03-210605 中国浙江 2106734 PL01 6 390.00 +亚太 RGB03-210597 杭州 RGB03-210605 中国浙江 2106733 PL01 6 29111.00 +亚太 RGB03-210597 杭州 RGB03-210605 中国浙江 2106732 PL01 6 8500.00 +亚太 RGB03-210597 杭州 RGB03-210605 中国浙江 2104252 PL01 6 94300.00 +亚太 RGB03-210597 杭州 RGB03-210605 中国浙江 2104251 PL01 6 50000.00 +亚太 RGB03-210597 杭州 RGB03-210605 中国浙江 2104231 PL01 6 23800.00 +亚太 RGB03-210597 杭州 RGB03-210605 中国浙江 2104229 PL01 6 250000.00 +亚太 RGB03-210597 杭州 RGB03-210605 中国浙江 2104227 PL01 6 225.00 +亚太 RGB03-210597 杭州 RGB03-210610 中国浙江 2106764 PL01 6 755.00 +亚太 RGB03-210597 杭州 RGB03-210610 中国浙江 2106763 PL01 6 38000.00 +亚太 RGB03-210597 杭州 RGB03-210610 中国浙江 2104271 PL01 6 97800.00 +亚太 RGB03-210565 杭州 RGB03-210576 中国浙江 2050276 PL01 6 61000.00 +亚太 RGB03-210565 杭州 RGB03-210566 中国浙江 2107142 PL01 6 300000.00 +亚太 RGB03-210530 杭州 RGB03-210543 中国浙江 2108578 PL01 6 30000.00 +亚太 RGB03-210530 杭州 RGB03-210543 中国浙江 2106821 PL01 6 113000.00 +亚太 RGB03-210530 杭州 RGB03-210543 中国浙江 2106820 PL01 6 13850.00 +亚太 RGB03-210530 杭州 RGB03-210543 中国浙江 2106819 PL01 6 15000.00 +亚太 RGB03-210530 杭州 RGB03-210543 中国浙江 2106818 PL01 6 5500.00 +亚太 RGB03-210530 杭州 RGB03-210543 中国浙江 2106817 PL01 6 50500.00 +亚太 RGB03-210530 杭州 RGB03-210543 中国浙江 2104497 PL01 6 50000.00 +亚太 RGB03-210530 杭州 RGB03-210543 中国浙江 2104495 PL01 6 40140.00 +亚太 RGB03-210530 杭州 RGB03-210543 中国浙江 2104493 PL01 6 48000.00 +亚太 RGB03-210530 杭州 RGB03-210543 中国浙江 2104492 PL01 6 32000.00 +亚太 RGB03-210530 杭州 RGB03-210543 中国浙江 2104491 PL01 6 109000.00 +亚太 RGB03-210530 杭州 RGB03-210543 中国浙江 2104490 PL01 6 13380.00 +亚太 RGB03-210530 杭州 RGB03-210543 中国浙江 2103782 PL01 6 61810.00 +亚太 RGB03-210530 杭州 RGB03-210543 中国浙江 2103781 PL01 6 15000.00 +亚太 RGB03-210530 杭州 RGB03-210542 中国浙江 2108804 PL01 6 30000.00 +亚太 RGB03-210597 杭州 RGB03-210605 中国浙江 2106736 PL01 6 12290.00 +亚太 RGB03-210666 杭州 RGB03-210676 中国浙江 2106901 PL01 6 500.00 +亚太 RGB03-210666 杭州 RGB03-210676 中国浙江 2106897 PL01 6 50.00 +亚太 RGB03-210666 杭州 RGB03-210676 中国浙江 2106887 PL01 6 400.00 +亚太 RGB03-210666 杭州 RGB03-210676 中国浙江 2106886 PL01 6 6.00 +亚太 RGB03-210666 杭州 RGB03-210676 中国浙江 2106881 PL01 6 2120.00 +亚太 RGB03-210666 杭州 RGB03-210676 中国浙江 2106879 PL01 6 1500.00 +亚太 RGB03-210666 杭州 RGB03-210676 中国浙江 2106878 PL01 6 950.00 +亚太 RGB03-210666 杭州 RGB03-210676 中国浙江 2106876 PL01 6 250.00 +亚太 RGB03-210666 杭州 RGB03-210676 中国浙江 2104628 PL01 6 1770.00 +亚太 RGB03-210666 杭州 RGB03-210676 中国浙江 2103785 PL01 6 2720.00 +亚太 RGB03-210666 杭州 RGB03-210677 中国浙江 2106989 PL01 6 3150.00 +亚太 RGB03-210666 杭州 RGB03-210677 中国浙江 2104776 PL01 6 1000.00 +亚太 RGB03-210666 杭州 RGB03-210674 中国浙江 2106854 PL01 6 13600.00 +亚太 RGB03-210666 杭州 RGB03-210674 中国浙江 2106853 PL01 6 848990.00 +亚太 RGB03-210597 杭州 RGB03-210605 中国浙江 2106737 PL01 6 68700.00 +亚太 RGB03-210597 杭州 RGB03-210605 中国浙江 2106738 PL01 6 54200.00 +亚太 RGB03-210597 杭州 RGB03-210605 中国浙江 2106739 PL01 6 29741.00 +亚太 RGB03-210597 杭州 RGB03-210605 中国浙江 2106740 PL01 6 61000.00 +亚太 RGB03-210597 杭州 RGB03-210605 中国浙江 2106741 PL01 6 26250.00 +亚太 RGB03-210597 杭州 RGB03-210605 中国浙江 2106742 PL01 6 49387.86 +亚太 RGB03-210597 杭州 RGB03-210605 中国浙江 2106743 PL01 6 28000.00 +亚太 RGB03-210597 杭州 RGB03-210605 中国浙江 2106744 PL01 6 4800.00 +亚太 RGB03-210597 杭州 RGB03-210605 中国浙江 2106753 PL01 6 8300.00 +亚太 RGB03-210597 杭州 RGB03-210605 中国浙江 2106754 PL01 6 27900.00 +亚太 RGB03-210597 杭州 RGB03-210605 中国浙江 2113390 PL01 6 118700.00 +亚太 RGB03-210666 杭州 RGB03-210678 中国浙江 2107003 PL01 6 200150.00 +亚太 RGB03-210666 杭州 RGB03-210674 中国浙江 2104590 PL01 6 486160.00 +亚太 RGB03-210666 杭州 RGB03-210674 中国浙江 2104591 PL01 6 93660.00 亚太 RGB03-210597 杭州 RGB03-210608 中国浙江 2123202 PL01 6 400000.00 亚太 RGB03-210098 杭州 RGB03-210106 中国浙江 6000001 PL01 6 4500.00 亚太 RGB03-210802 杭州 RGB03-210810 中国浙江 2123202 PL01 6 300000.00 @@ -635,6 +612,29 @@ branch_org_name branch_org_code agency_org_name agency_org_code customer_name cu 亚太 RGB03-210530 杭州 RGB03-210885 中国浙江 2000966 PL01 6 12000.00 亚太 RGB03-210802 杭州 RGB03-210810 中国浙江 6000001 PL01 10 1.00 亚太 RGB03-210250 杭州 RGB03-210258 中国浙江 6000001 PL01 10 40380.00 +亚太 RGB03-210930 杭州 RGB03-210938 中国浙江 2108700 PL01 6 431380.00 +亚太 RGB03-210802 杭州 RGB03-210803 中国浙江 2120518 PL01 6 61001.00 +亚太 RGB03-210001 杭州 RGB03-210013 中国浙江 3053091 PL01 6 0.02 +亚太 RGB03-210001 杭州 RGB03-210013 中国浙江 2108448 PL01 6 0.01 +亚太 RGB03-210001 杭州 RGB03-210013 中国浙江 2108448 PL01 13 0.01 +亚太 RGB03-210282 杭州 RGB03-210290 中国浙江 2107801 PL01 4 0.01 +亚太 RGB03-210802 杭州 RGB03-210810 中国浙江 2085374 PL01 6 200289.00 +亚太 RGB03-210007 杭州 RGB03-210030 中国浙江 3302059 PL01 6 2000.00 +亚太 RGB03-210802 杭州 RGB03-210810 中国浙江 2085374 PL01 4 3579.55 +亚太 RGB03-210802 杭州 RGB03-210810 中国浙江 2085374 PL01 37 200.00 +亚太 RGB03-210802 杭州 RGB03-210817 中国浙江 6000001 PL01 4 0.00 +亚太 RGB03-210802 杭州 RGB03-210803 中国浙江 2120518 PL01 4 1.00 +亚太 RGB03-210001 杭州 RGB03-210008 中国浙江 3000019 PL01 4 22.00 +亚太 RGB03-210802 杭州 RGB03-210810 中国浙江 2085459 PL01 6 10.00 +亚太 RGB03-210007 杭州 RGB03-210030 中国浙江 3000781 PL01 4 1500.00 +亚太 RGB03-210802 杭州 RGB03-210810 中国浙江 2085538 PL01 6 0.00 +亚太 RGB03-210802 杭州 RGB03-210810 中国浙江 2085538 PL01 4 5523.80 +亚太 RGB03-210361 杭州 RGB03-211043 中国浙江 2085536 PL01 4 2314.00 +亚太 RGB03-210001 杭州 RGB03-210008 中国浙江 2123143 PL01 4 10000.00 +亚太 RGB03-210802 杭州 RGB03-210810 中国浙江 2123146 PL01 4 274.00 +亚太 RGB03-210802 杭州 RGB03-210811 中国浙江 2123168 PL01 6 334.00 +亚太 RGB03-210098 杭州 RGB03-210106 中国浙江 2085582 PL01 6 10100.00 +亚太 RGB03-210098 杭州 RGB03-210106 中国浙江 2123187 PL01 6 20000.00 # # Clean Resource # diff --git a/mysql-test/suite/tianmu/r/out_of_range_issue1151.result b/mysql-test/suite/tianmu/r/out_of_range_issue1151.result index 33d9fea47..575f099e1 100644 --- a/mysql-test/suite/tianmu/r/out_of_range_issue1151.result +++ b/mysql-test/suite/tianmu/r/out_of_range_issue1151.result @@ -22,10 +22,6 @@ insert into tiny values(128, 0); ERROR 22003: Out of range value for column 'a' at row 1 insert into tiny values(1234, 0); ERROR 22003: Out of range value for column 'a' at row 1 -insert into tiny values(0, 128); -ERROR 22003: Out of range[0, 127] for column 'b' value: 128 -insert into tiny values(0, 255); -ERROR 22003: Out of range[0, 127] for column 'b' value: 255 insert into tiny values(0, -1); ERROR 22003: Out of range value for column 'b' at row 1 insert into tiny values(0, -127); @@ -65,12 +61,6 @@ insert into small values(-3276911, 0); ERROR 22003: Out of range value for column 'a' at row 1 insert into small values(3276811, 0); ERROR 22003: Out of range value for column 'a' at row 1 -insert into small values(0, 32768); -ERROR 22003: Out of range[0, 32767] for column 'b' value: 32768 -insert into small values(0, 41234); -ERROR 22003: Out of range[0, 32767] for column 'b' value: 41234 -insert into small values(0, 65535); -ERROR 22003: Out of range[0, 32767] for column 'b' value: 65535 insert into small values(0, -1); ERROR 22003: Out of range value for column 'b' at row 1 insert into small values(0, -32768); @@ -111,12 +101,6 @@ insert into medium values(-8388608111, 0); ERROR 22003: Out of range value for column 'a' at row 1 insert into medium values(8388608111, 0); ERROR 22003: Out of range value for column 'a' at row 1 -insert into medium values(0, 8388608); -ERROR 22003: Out of range[0, 8388607] for column 'b' value: 8388608 -insert into medium values(0, 8388610); -ERROR 22003: Out of range[0, 8388607] for column 'b' value: 8388610 -insert into medium values(0, 16777215); -ERROR 22003: Out of range[0, 8388607] for column 'b' value: 16777215 insert into medium values(0, -1); ERROR 22003: Out of range value for column 'b' at row 1 insert into medium values(0, -8388608); @@ -157,14 +141,6 @@ insert into int_ values(-214748364811, 0); ERROR 22003: Out of range value for column 'a' at row 1 insert into int_ values(214748364811, 0); ERROR 22003: Out of range value for column 'a' at row 1 -insert into int_ values(-2147483648, 0); -ERROR 22003: Out of range[-2147483647, 2147483647] for column 'a' value: -2147483648 -insert into int_ values(0, 2147483648); -ERROR 22003: Out of range[0, 2147483647] for column 'b' value: 2147483648 -insert into int_ values(0, 3294967295); -ERROR 22003: Out of range[0, 2147483647] for column 'b' value: 3294967295 -insert into int_ values(0, 4294967295); -ERROR 22003: Out of range[0, 2147483647] for column 'b' value: 4294967295 insert into int_ values(0, -1); ERROR 22003: Out of range value for column 'b' at row 1 insert into int_ values(0, -4294967295); @@ -182,50 +158,4 @@ a b 0 0 0 0 drop table int_; -create table bigint_(a bigint, b bigint unsigned) engine = tianmu DEFAULT CHARSET=utf8mb4; -insert into bigint_ values(-9223372036854775806, 0); -insert into bigint_ values(0, 0); -insert into bigint_ values(122, 122); -insert into bigint_ values(9223372036854775807, 9223372036854775807); -insert into bigint_ values(-0, -0); -insert into bigint_ values(+0, +0); -select * from bigint_; -a b --9223372036854775806 0 -0 0 -122 122 -9223372036854775807 9223372036854775807 -0 0 -0 0 -insert into bigint_ values(-9223372036854775808, 0); -ERROR 22003: Out of range[-9223372036854775807, 9223372036854775807] for column 'a' value: -9223372036854775808 -insert into bigint_ values(9223372036854775808, 0); -ERROR 22003: Out of range value for column 'a' at row 1 -insert into bigint_ values(-9223372036854775810, 0); -ERROR 22003: Out of range value for column 'a' at row 1 -insert into bigint_ values(9223372036854775810, 0); -ERROR 22003: Out of range value for column 'a' at row 1 -insert into bigint_ values(0, 9223372036854775808); -ERROR 22003: Out of range[0, 9223372036854775807] for column 'b' value: 9223372036854775808 -insert into bigint_ values(0, 10223372036854775808); -ERROR 22003: Out of range[0, 9223372036854775807] for column 'b' value: 10223372036854775808 -insert into bigint_ values(0, 18446744073709551615); -ERROR 22003: Out of range[0, 9223372036854775807] for column 'b' value: 18446744073709551615 -insert into bigint_ values(0, -1); -ERROR 22003: Out of range value for column 'b' at row 1 -insert into bigint_ values(0, -4294967295); -ERROR 22003: Out of range value for column 'b' at row 1 -insert into bigint_ values(0, 18446744073709551616); -ERROR 22003: Out of range value for column 'b' at row 1 -insert into bigint_ values(0, 1844674407370955161566); -ERROR 22003: Out of range value for column 'b' at row 1 -select * from bigint_; -a b --9223372036854775806 0 -0 0 -122 122 -9223372036854775807 9223372036854775807 -0 0 -0 0 -drop table bigint_; drop database if exists out_of_range_issue1151; diff --git a/mysql-test/suite/tianmu/r/select_joins.result b/mysql-test/suite/tianmu/r/select_joins.result index fea6f46e7..4cd490b0f 100644 --- a/mysql-test/suite/tianmu/r/select_joins.result +++ b/mysql-test/suite/tianmu/r/select_joins.result @@ -36,12 +36,12 @@ t1_col1 t1_col1 NULL NULL SELECT t1.t1_col1 FROM tbl1 as t1 LEFT JOIN tbl1 AS t2 USING (t1_col1) LEFT JOIN tbl1 AS t3 USING (t1_col1) LEFT JOIN tbl1 AS t4 USING (t1_col1) LEFT JOIN tbl1 AS t5 USING (t1_col1) LEFT JOIN tbl1 AS t6 USING (t1_col1) LEFT JOIN tbl1 AS t7 USING (t1_col1) LEFT JOIN tbl1 AS t8 USING (t1_col1) LEFT JOIN tbl1 AS t9 USING (t1_col1) LEFT JOIN tbl1 AS t10 USING (t1_col1) LEFT JOIN tbl1 AS t11 USING (t1_col1) LEFT JOIN tbl1 AS t12 USING (t1_col1) LEFT JOIN tbl1 AS t13 USING (t1_col1) LEFT JOIN tbl1 AS t14 USING (t1_col1) LEFT JOIN tbl1 AS t15 USING (t1_col1) LEFT JOIN tbl1 AS t16 USING (t1_col1) LEFT JOIN tbl1 AS t17 USING (t1_col1) LEFT JOIN tbl1 AS t18 USING (t1_col1) LEFT JOIN tbl1 AS t19 USING (t1_col1) LEFT JOIN tbl1 AS t20 USING (t1_col1) LEFT JOIN tbl1 AS t21 USING (t1_col1) LEFT JOIN tbl1 AS t22 USING (t1_col1) LEFT JOIN tbl1 AS t23 USING (t1_col1) LEFT JOIN tbl1 AS t24 USING (t1_col1) LEFT JOIN tbl1 AS t25 USING (t1_col1) LEFT JOIN tbl1 AS t26 USING (t1_col1) LEFT JOIN tbl1 AS t27 USING (t1_col1) LEFT JOIN tbl1 AS t28 USING (t1_col1) LEFT JOIN tbl1 AS t29 USING (t1_col1) LEFT JOIN tbl1 AS t30 USING (t1_col1) LEFT JOIN tbl1 AS t31 USING (t1_col1) LEFT JOIN tbl1 AS t32 USING (t1_col1) LEFT JOIN tbl1 AS t33 USING (t1_col1) LEFT JOIN tbl1 AS t34 USING (t1_col1) LEFT JOIN tbl1 AS t35 USING (t1_col1) LEFT JOIN tbl1 AS t36 USING (t1_col1) LEFT JOIN tbl1 AS t37 USING (t1_col1) LEFT JOIN tbl1 AS t38 USING (t1_col1) LEFT JOIN tbl1 AS t39 USING (t1_col1) LEFT JOIN tbl1 AS t40 USING (t1_col1) LEFT JOIN tbl1 AS t41 USING (t1_col1) LEFT JOIN tbl1 AS t42 USING (t1_col1) LEFT JOIN tbl1 AS t43 USING (t1_col1) LEFT JOIN tbl1 AS t44 USING (t1_col1) LEFT JOIN tbl1 AS t45 USING (t1_col1) LEFT JOIN tbl1 AS t46 USING (t1_col1) LEFT JOIN tbl1 AS t47 USING (t1_col1) LEFT JOIN tbl1 AS t48 USING (t1_col1) LEFT JOIN tbl1 AS t49 USING (t1_col1) LEFT JOIN tbl1 AS t50 USING (t1_col1) LEFT JOIN tbl1 AS t51 USING (t1_col1) LEFT JOIN tbl1 AS t52 USING (t1_col1) LEFT JOIN tbl1 AS t53 USING (t1_col1) LEFT JOIN tbl1 AS t54 USING (t1_col1) LEFT JOIN tbl1 AS t55 USING (t1_col1) LEFT JOIN tbl1 AS t56 USING (t1_col1) LEFT JOIN tbl1 AS t57 USING (t1_col1) LEFT JOIN tbl1 AS t58 USING (t1_col1) LEFT JOIN tbl1 AS t59 USING (t1_col1) LEFT JOIN tbl1 AS t60 USING (t1_col1) LEFT JOIN tbl1 AS t61 USING (t1_col1); t1_col1 -NULL 1 3 5 7 9 +NULL SELECT t1.t1_col1 FROM tbl1 as t1 LEFT JOIN tbl1 AS t2 USING (t1_col1) LEFT JOIN tbl1 AS t3 USING (t1_col1) LEFT JOIN tbl1 AS t4 USING (t1_col1) LEFT JOIN tbl1 AS t5 USING (t1_col1) LEFT JOIN tbl1 AS t6 USING (t1_col1) LEFT JOIN tbl1 AS t7 USING (t1_col1) LEFT JOIN tbl1 AS t8 USING (t1_col1) LEFT JOIN tbl1 AS t9 USING (t1_col1) LEFT JOIN tbl1 AS t10 USING (t1_col1) LEFT JOIN tbl1 AS t11 USING (t1_col1) LEFT JOIN tbl1 AS t12 USING (t1_col1) LEFT JOIN tbl1 AS t13 USING (t1_col1) LEFT JOIN tbl1 AS t14 USING (t1_col1) LEFT JOIN tbl1 AS t15 USING (t1_col1) LEFT JOIN tbl1 AS t16 USING (t1_col1) LEFT JOIN tbl1 AS t17 USING (t1_col1) LEFT JOIN tbl1 AS t18 USING (t1_col1) LEFT JOIN tbl1 AS t19 USING (t1_col1) LEFT JOIN tbl1 AS t20 USING (t1_col1) LEFT JOIN tbl1 AS t21 USING (t1_col1) LEFT JOIN tbl1 AS t22 USING (t1_col1) LEFT JOIN tbl1 AS t23 USING (t1_col1) LEFT JOIN tbl1 AS t24 USING (t1_col1) LEFT JOIN tbl1 AS t25 USING (t1_col1) LEFT JOIN tbl1 AS t26 USING (t1_col1) LEFT JOIN tbl1 AS t27 USING (t1_col1) LEFT JOIN tbl1 AS t28 USING (t1_col1) LEFT JOIN tbl1 AS t29 USING (t1_col1) LEFT JOIN tbl1 AS t30 USING (t1_col1) LEFT JOIN tbl1 AS t31 USING (t1_col1) LEFT JOIN tbl1 AS t32 USING (t1_col1) LEFT JOIN tbl1 AS t33 USING (t1_col1) LEFT JOIN tbl1 AS t34 USING (t1_col1) LEFT JOIN tbl1 AS t35 USING (t1_col1) LEFT JOIN tbl1 AS t36 USING (t1_col1) LEFT JOIN tbl1 AS t37 USING (t1_col1) LEFT JOIN tbl1 AS t38 USING (t1_col1) LEFT JOIN tbl1 AS t39 USING (t1_col1) LEFT JOIN tbl1 AS t40 USING (t1_col1) LEFT JOIN tbl1 AS t41 USING (t1_col1) LEFT JOIN tbl1 AS t42 USING (t1_col1) LEFT JOIN tbl1 AS t43 USING (t1_col1) LEFT JOIN tbl1 AS t44 USING (t1_col1) LEFT JOIN tbl1 AS t45 USING (t1_col1) LEFT JOIN tbl1 AS t46 USING (t1_col1) LEFT JOIN tbl1 AS t47 USING (t1_col1) LEFT JOIN tbl1 AS t48 USING (t1_col1) LEFT JOIN tbl1 AS t49 USING (t1_col1) LEFT JOIN tbl1 AS t50 USING (t1_col1) LEFT JOIN tbl1 AS t51 USING (t1_col1) LEFT JOIN tbl1 AS t52 USING (t1_col1) LEFT JOIN tbl1 AS t53 USING (t1_col1) LEFT JOIN tbl1 AS t54 USING (t1_col1) LEFT JOIN tbl1 AS t55 USING (t1_col1) LEFT JOIN tbl1 AS t56 USING (t1_col1) LEFT JOIN tbl1 AS t57 USING (t1_col1) LEFT JOIN tbl1 AS t58 USING (t1_col1) LEFT JOIN tbl1 AS t59 USING (t1_col1) LEFT JOIN tbl1 AS t60 USING (t1_col1) LEFT JOIN tbl1 AS t61 USING (t1_col1) LEFT JOIN tbl1 AS t62 USING (t1_col1); ERROR HY000: Too many tables; MySQL can only use 61 tables in a join SELECT t1.t1_col1,t2.t2_col1 FROM tbl1 t1 JOIN tbl2 t2 ON t1.t1_col1 = t2.t2_col1; diff --git a/mysql-test/suite/tianmu/t/issue422.test b/mysql-test/suite/tianmu/t/issue422.test new file mode 100644 index 000000000..dfe42998a --- /dev/null +++ b/mysql-test/suite/tianmu/t/issue422.test @@ -0,0 +1,414 @@ +--source include/have_tianmu.inc + +--disable_warnings + +DROP DATABASE IF EXISTS issue422_test; + +CREATE DATABASE issue422_test; + +USE issue422_test; + + +## DDL + +DROP TABLE IF EXISTS test1; + +CREATE TABLE t1(id int, name varchar(20)) ENGINE=TIANMU DEFAULT CHARSET=utf8mb4; + +## procedure + +drop procedure if exists idata; + +delimiter //; +create procedure idata(in num INT) +begin + declare i int; + set i=1; + while(i<=num) do + if (i < 200) then + insert into t1 values(i, 'James'); + elseif (i >= 200 && i < 1500) then + insert into t1 values(i, 'Lily'); + else + insert into t1 values(i, 'Kevin'); + end if; + set i=i+1; + end while; +end // + +delimiter ;// + +## insert data + +call idata(3000); + +## log + +set global tianmu_slow_query_record_interval=0; +set global tianmu_groupby_parallel_rows_minimum=1000; + +## query + +## group by of single thread + +## set threads +set global tianmu_groupby_parallel_degree=0; + +## query +select sum(id),name from t1 group by name order by name; + +## groupy bu of multi thread + +## set threads +set global tianmu_groupby_parallel_degree=2; + +## query +select sum(id),name from t1 group by name order by name; + +## log +set global tianmu_slow_query_record_interval=2; + +# MORE + +drop table t1; + +CREATE TABLE t1 ( + spID int(10) unsigned, + userID int(10) unsigned, + score int(5) unsigned, + lsg char(40) +) ENGINE=TIANMU; + +INSERT INTO t1 VALUES (1,1,1,''); +INSERT INTO t1 VALUES (2,2,2,''); +INSERT INTO t1 VALUES (2,1,1,''); +INSERT INTO t1 VALUES (3,3,3,''); + +CREATE TABLE t2 ( + userID int(10), + niName char(15), + passwd char(8), + mail char(50), + vName char(30), + nName char(40), + adr char(60), + plz char(5), + ort char(35), + land char(20) +) ENGINE=TIANMU; + +INSERT INTO t2 VALUES (1,'name','pass','mail','v','n','adr','1','1','1'); +INSERT INTO t2 VALUES (2,'name','pass','mail','v','n','adr','1','1','1'); +INSERT INTO t2 VALUES (3,'name','pass','mail','v','n','adr','1','1','1'); +INSERT INTO t2 VALUES (4,'name','pass','mail','v','n','adr','1','1','1'); +INSERT INTO t2 VALUES (5,'name','pass','mail','v','n','adr','1','1','1'); + +SELECT t2.userid, MIN(t1.score) FROM t1, t2 WHERE t1.userID=t2.userID GROUP BY t2.userid; +SELECT t2.userid, MIN(t1.score) FROM t1, t2 WHERE t1.userID=t2.userID GROUP BY t2.userid ORDER BY NULL; +SELECT t2.userid, MIN(t1.score) FROM t1, t2 WHERE t1.userID=t2.userID AND t1.spID=2 GROUP BY t2.userid; +SELECT t2.userid, MIN(t1.score+0.0) FROM t1, t2 WHERE t1.userID=t2.userID AND t1.spID=2 GROUP BY t2.userid; +SELECT t2.userid, MIN(t1.score+0.0) FROM t1, t2 WHERE t1.userID=t2.userID AND t1.spID=2 GROUP BY t2.userid ORDER BY NULL; + +drop table t1; +drop table t2; + +CREATE TABLE t1 +( + t1_INT INT DEFAULT 0, + t1_double DOUBLE, + t1_float FLOAT, + t1_blob BLOB, + t1_text TEXT, + t1_char CHAR(1), + t1_varchar VARCHAR(255) DEFAULT 'hello world!', + t1_datetime DATETIME +)ENGINE=TIANMU; + +INSERT INTO t1 (t1_INT, t1_double, t1_float, t1_blob, t1_text, t1_char, t1_datetime) +VALUES(20368547, -3.797693231E+108, -7.402866E+18, repeat('b',100), repeat('b',100), 'b', '2387-11-08 11:22:30.123'); +INSERT INTO t1 (t1_INT, t1_double, t1_float, t1_blob, t1_text, t1_char, t1_datetime) +VALUES(303685, -4.797693231, -8.402866, repeat('b',101), repeat('b',101), 'b', '3387-11-08 11:22:30.123'); +INSERT INTO t1 (t1_INT, t1_double, t1_float, t1_blob, t1_text, t1_char, t1_datetime) +VALUES(403685, +54.797693231, +8.402866, repeat('c',101), repeat('c',101), 'c', '3387-11-08 11:22:30.123'); +INSERT INTO t1 (t1_INT, t1_double, t1_float, t1_blob, t1_text, t1_char, t1_datetime) +VALUES(403685, +54.797693231, +8.402866, repeat('c',101), repeat('c',101), 'c', '3387-11-08 11:22:30.123'); +INSERT INTO t1 (t1_INT, t1_double, t1_float, t1_blob, t1_text, t1_char, t1_datetime) +VALUES(403685, +54.797693231, +8.402866, repeat('c',101), repeat('c',101), 'c', '3387-11-08 11:22:30.123'); +INSERT INTO t1 (t1_INT, t1_double, t1_float, t1_blob, t1_text, t1_char, t1_datetime) +VALUES(40385, +54.797693231, +8.402866, repeat('c',101), repeat('c',101), 'c', '3387-11-08 11:22:30.123'); +INSERT INTO t1 (t1_INT, t1_double, t1_float, t1_blob, t1_text, t1_char, t1_datetime) +VALUES(403685, +54.797693231, +8.402866, repeat('c',101), repeat('c',101), 'c', '3387-11-08 11:22:30.123'); +INSERT INTO t1 (t1_INT, t1_double, t1_float, t1_blob, t1_text, t1_char, t1_datetime) +VALUES(403685, +54.797693231, +8.402866, repeat('c',101), repeat('c',101), 'c', '3387-11-08 11:22:30.123'); +INSERT INTO t1 (t1_INT, t1_double, t1_float, t1_blob, t1_text, t1_char, t1_datetime) +VALUES(40368, +54.797693231, +8.402866, repeat('2',102), repeat('d',102), 'd', '4387-11-08 11:22:30.123'); +INSERT INTO t1 (t1_INT, t1_double, t1_float, t1_blob, t1_text, t1_char, t1_datetime) +VALUES(403, +54.797693231, +8.402866, repeat('2',102), repeat('d',102), 'd', '4387-11-08 11:22:30.123'); +INSERT INTO t1 (t1_INT, t1_double, t1_float, t1_blob, t1_text, t1_char, t1_datetime) +VALUES(403685, +54.797693231, +8.402866, repeat('2',102), repeat('d',102), 'd', '4387-11-08 11:22:30.123'); +INSERT INTO t1 VALUES(NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO t1 VALUES(NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO t1 VALUES(NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); + +--sorted_result +SELECT * FROM t1; +--sorted_result +SELECT COUNT(*) FROM t1 GROUP BY t1_INT; +--sorted_result +SELECT COUNT(*) FROM t1 GROUP BY t1_INT; +--sorted_result +SELECT COUNT(*) FROM t1 GROUP BY t1_INT; +--sorted_result +SELECT COUNT(*) FROM t1 GROUP BY t1_double; +--sorted_result +SELECT COUNT(*) FROM t1 GROUP BY t1_float; +--sorted_result +SELECT COUNT(*) FROM t1 GROUP BY t1_blob; +--sorted_result +SELECT COUNT(*) FROM t1 GROUP BY t1_text; +--sorted_result +SELECT COUNT(*) FROM t1 GROUP BY t1_char; +--sorted_result +SELECT COUNT(*) FROM t1 GROUP BY t1_varchar; +--sorted_result +SELECT COUNT(*) FROM t1 GROUP BY t1_datetime; + +--sorted_result +SELECT SUM(t1_INT) FROM t1 GROUP BY t1_INT; +--sorted_result +SELECT SUM(t1_double) FROM t1 GROUP BY t1_float; +--sorted_result +SELECT SUM(DISTINCT t1_double) FROM t1 GROUP BY t1_float; + +#group by multiple columns +--sorted_result +SELECT COUNT(*) FROM t1 GROUP BY t1_INT; +--sorted_result +SELECT COUNT(*) FROM t1 GROUP BY t1_blob, t1_text, t1_char; +--sorted_result +SELECT COUNT(*) FROM t1 GROUP BY t1_varchar, t1_datetime; + +#along with where clause +--sorted_result +SELECT COUNT(*) FROM t1 WHERE t1_blob IS NOT NULL GROUP BY t1_INT; +--sorted_result +SELECT COUNT(*) FROM t1 WHERE t1_INT = 0 GROUP BY t1_blob, t1_text, t1_char; +--sorted_result +SELECT COUNT(*) FROM t1 WHERE t1_char IN ('a', 'b') GROUP BY t1_varchar, t1_datetime; +--sorted_result +SELECT COUNT(*) FROM t1 WHERE t1_varchar LIKE '%world%' GROUP BY t1_varchar, t1_datetime; +--sorted_result +SELECT COUNT(*) FROM t1 WHERE t1_INT != 0 AND t1_INT = 0 OR t1_INT IS NULL GROUP BY t1_varchar, t1_datetime; + +drop table t1; + +CREATE TABLE t1 (t1_INT INT, t1_char CHAR(5))ENGINE=TIANMU; +CREATE TABLE t2 (t2_int INT, t2_char CHAR(5))ENGINE=TIANMU; +INSERT INTO t1 VALUES (NULL,''),(1,'aaa'),(2,'bbb'),(3,'aaa'),(4,'bbb'),(5,'aaa'),(6,'ccc'),(7,'bbb'); +INSERT INTO t2 VALUES (NULL,''),(1,'ooo'),(3,'iii'),(5,'ooo'),(7,'ooo'),(9,'kkkk'),(11,'iii'),(13,'ooo'); + +--sorted_result +SELECT COUNT(*) FROM t1, t2 WHERE t1.t1_INT = t2.t2_int GROUP BY t1.t1_INT; +--sorted_result +SELECT COUNT(*) FROM t1, t2 WHERE t1.t1_INT = t2.t2_int GROUP BY t1.t1_char; +--sorted_result +SELECT COUNT(*) FROM t1, t2 WHERE t1.t1_INT = t2.t2_int GROUP BY t2.t2_int; +--sorted_result +SELECT COUNT(*) FROM t1, t2 WHERE t1.t1_INT = t2.t2_int GROUP BY t2.t2_char; + +--sorted_result +SELECT SUM(t1.t1_INT) FROM t1 LEFT JOIN t2 ON t1.t1_INT = t2.t2_int GROUP BY t1.t1_INT; +--sorted_result +SELECT SUM(t1.t1_INT) FROM t1 LEFT JOIN t2 ON t1.t1_INT = t2.t2_int GROUP BY t1.t1_char; +--sorted_result +SELECT SUM(t1.t1_INT) FROM t1 LEFT JOIN t2 ON t1.t1_INT = t2.t2_int GROUP BY t2.t2_int; +--sorted_result +SELECT SUM(t1.t1_INT) FROM t1 LEFT JOIN t2 ON t1.t1_INT = t2.t2_int GROUP BY t2.t2_char; + +--sorted_result +SELECT SUM(t1.t1_INT) FROM t1 RIGHT JOIN t2 ON t1.t1_INT = t2.t2_int GROUP BY t1.t1_INT; +--sorted_result +SELECT SUM(t1.t1_INT) FROM t1 RIGHT JOIN t2 ON t1.t1_INT = t2.t2_int GROUP BY t1.t1_char; +--sorted_result +SELECT SUM(t1.t1_INT) FROM t1 RIGHT JOIN t2 ON t1.t1_INT = t2.t2_int GROUP BY t2.t2_int; +--sorted_result +SELECT SUM(t1.t1_INT) FROM t1 RIGHT JOIN t2 ON t1.t1_INT = t2.t2_int GROUP BY t2.t2_char; + +drop table t1; +drop table t2; + +# start multi threads + +set global tianmu_groupby_parallel_rows_minimum=5; +set global tianmu_groupby_parallel_degree=2; + +# again + +CREATE TABLE t1 ( + spID int(10) unsigned, + userID int(10) unsigned, + score int(5) unsigned, + lsg char(40) +) ENGINE=TIANMU; + +INSERT INTO t1 VALUES (1,1,1,''); +INSERT INTO t1 VALUES (2,2,2,''); +INSERT INTO t1 VALUES (2,1,1,''); +INSERT INTO t1 VALUES (3,3,3,''); + +CREATE TABLE t2 ( + userID int(10), + niName char(15), + passwd char(8), + mail char(50), + vName char(30), + nName char(40), + adr char(60), + plz char(5), + ort char(35), + land char(20) +) ENGINE=TIANMU; + +INSERT INTO t2 VALUES (1,'name','pass','mail','v','n','adr','1','1','1'); +INSERT INTO t2 VALUES (2,'name','pass','mail','v','n','adr','1','1','1'); +INSERT INTO t2 VALUES (3,'name','pass','mail','v','n','adr','1','1','1'); +INSERT INTO t2 VALUES (4,'name','pass','mail','v','n','adr','1','1','1'); +INSERT INTO t2 VALUES (5,'name','pass','mail','v','n','adr','1','1','1'); + +SELECT t2.userid, MIN(t1.score) FROM t1, t2 WHERE t1.userID=t2.userID GROUP BY t2.userid; +SELECT t2.userid, MIN(t1.score) FROM t1, t2 WHERE t1.userID=t2.userID GROUP BY t2.userid ORDER BY NULL; +SELECT t2.userid, MIN(t1.score) FROM t1, t2 WHERE t1.userID=t2.userID AND t1.spID=2 GROUP BY t2.userid; +SELECT t2.userid, MIN(t1.score+0.0) FROM t1, t2 WHERE t1.userID=t2.userID AND t1.spID=2 GROUP BY t2.userid; +SELECT t2.userid, MIN(t1.score+0.0) FROM t1, t2 WHERE t1.userID=t2.userID AND t1.spID=2 GROUP BY t2.userid ORDER BY NULL; + +drop table t1; +drop table t2; + +CREATE TABLE t1 +( + t1_INT INT DEFAULT 0, + t1_double DOUBLE, + t1_float FLOAT, + t1_blob BLOB, + t1_text TEXT, + t1_char CHAR(1), + t1_varchar VARCHAR(255) DEFAULT 'hello world!', + t1_datetime DATETIME +)ENGINE=TIANMU; + +INSERT INTO t1 (t1_INT, t1_double, t1_float, t1_blob, t1_text, t1_char, t1_datetime) +VALUES(20368547, -3.797693231E+108, -7.402866E+18, repeat('b',100), repeat('b',100), 'b', '2387-11-08 11:22:30.123'); +INSERT INTO t1 (t1_INT, t1_double, t1_float, t1_blob, t1_text, t1_char, t1_datetime) +VALUES(303685, -4.797693231, -8.402866, repeat('b',101), repeat('b',101), 'b', '3387-11-08 11:22:30.123'); +INSERT INTO t1 (t1_INT, t1_double, t1_float, t1_blob, t1_text, t1_char, t1_datetime) +VALUES(403685, +54.797693231, +8.402866, repeat('c',101), repeat('c',101), 'c', '3387-11-08 11:22:30.123'); +INSERT INTO t1 (t1_INT, t1_double, t1_float, t1_blob, t1_text, t1_char, t1_datetime) +VALUES(403685, +54.797693231, +8.402866, repeat('c',101), repeat('c',101), 'c', '3387-11-08 11:22:30.123'); +INSERT INTO t1 (t1_INT, t1_double, t1_float, t1_blob, t1_text, t1_char, t1_datetime) +VALUES(403685, +54.797693231, +8.402866, repeat('c',101), repeat('c',101), 'c', '3387-11-08 11:22:30.123'); +INSERT INTO t1 (t1_INT, t1_double, t1_float, t1_blob, t1_text, t1_char, t1_datetime) +VALUES(40385, +54.797693231, +8.402866, repeat('c',101), repeat('c',101), 'c', '3387-11-08 11:22:30.123'); +INSERT INTO t1 (t1_INT, t1_double, t1_float, t1_blob, t1_text, t1_char, t1_datetime) +VALUES(403685, +54.797693231, +8.402866, repeat('c',101), repeat('c',101), 'c', '3387-11-08 11:22:30.123'); +INSERT INTO t1 (t1_INT, t1_double, t1_float, t1_blob, t1_text, t1_char, t1_datetime) +VALUES(403685, +54.797693231, +8.402866, repeat('c',101), repeat('c',101), 'c', '3387-11-08 11:22:30.123'); +INSERT INTO t1 (t1_INT, t1_double, t1_float, t1_blob, t1_text, t1_char, t1_datetime) +VALUES(40368, +54.797693231, +8.402866, repeat('2',102), repeat('d',102), 'd', '4387-11-08 11:22:30.123'); +INSERT INTO t1 (t1_INT, t1_double, t1_float, t1_blob, t1_text, t1_char, t1_datetime) +VALUES(403, +54.797693231, +8.402866, repeat('2',102), repeat('d',102), 'd', '4387-11-08 11:22:30.123'); +INSERT INTO t1 (t1_INT, t1_double, t1_float, t1_blob, t1_text, t1_char, t1_datetime) +VALUES(403685, +54.797693231, +8.402866, repeat('2',102), repeat('d',102), 'd', '4387-11-08 11:22:30.123'); +INSERT INTO t1 VALUES(NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO t1 VALUES(NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO t1 VALUES(NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); + +--sorted_result +SELECT * FROM t1; +--sorted_result +SELECT COUNT(*) FROM t1 GROUP BY t1_INT; +--sorted_result +SELECT COUNT(*) FROM t1 GROUP BY t1_INT; +--sorted_result +SELECT COUNT(*) FROM t1 GROUP BY t1_INT; +--sorted_result +SELECT COUNT(*) FROM t1 GROUP BY t1_double; +--sorted_result +SELECT COUNT(*) FROM t1 GROUP BY t1_float; +--sorted_result +SELECT COUNT(*) FROM t1 GROUP BY t1_blob; +--sorted_result +SELECT COUNT(*) FROM t1 GROUP BY t1_text; +--sorted_result +SELECT COUNT(*) FROM t1 GROUP BY t1_char; +--sorted_result +SELECT COUNT(*) FROM t1 GROUP BY t1_varchar; +--sorted_result +SELECT COUNT(*) FROM t1 GROUP BY t1_datetime; + +--sorted_result +SELECT SUM(t1_INT) FROM t1 GROUP BY t1_INT; +--sorted_result +SELECT SUM(t1_double) FROM t1 GROUP BY t1_float; +--sorted_result +SELECT SUM(DISTINCT t1_double) FROM t1 GROUP BY t1_float; + +#group by multiple columns +--sorted_result +SELECT COUNT(*) FROM t1 GROUP BY t1_INT; +--sorted_result +SELECT COUNT(*) FROM t1 GROUP BY t1_blob, t1_text, t1_char; +--sorted_result +SELECT COUNT(*) FROM t1 GROUP BY t1_varchar, t1_datetime; + +#along with where clause +--sorted_result +SELECT COUNT(*) FROM t1 WHERE t1_blob IS NOT NULL GROUP BY t1_INT; +--sorted_result +SELECT COUNT(*) FROM t1 WHERE t1_INT = 0 GROUP BY t1_blob, t1_text, t1_char; +--sorted_result +SELECT COUNT(*) FROM t1 WHERE t1_char IN ('a', 'b') GROUP BY t1_varchar, t1_datetime; +--sorted_result +SELECT COUNT(*) FROM t1 WHERE t1_varchar LIKE '%world%' GROUP BY t1_varchar, t1_datetime; +--sorted_result +SELECT COUNT(*) FROM t1 WHERE t1_INT != 0 AND t1_INT = 0 OR t1_INT IS NULL GROUP BY t1_varchar, t1_datetime; + +drop table t1; + +CREATE TABLE t1 (t1_INT INT, t1_char CHAR(5))ENGINE=TIANMU; +CREATE TABLE t2 (t2_int INT, t2_char CHAR(5))ENGINE=TIANMU; +INSERT INTO t1 VALUES (NULL,''),(1,'aaa'),(2,'bbb'),(3,'aaa'),(4,'bbb'),(5,'aaa'),(6,'ccc'),(7,'bbb'); +INSERT INTO t2 VALUES (NULL,''),(1,'ooo'),(3,'iii'),(5,'ooo'),(7,'ooo'),(9,'kkkk'),(11,'iii'),(13,'ooo'); + +--sorted_result +SELECT COUNT(*) FROM t1, t2 WHERE t1.t1_INT = t2.t2_int GROUP BY t1.t1_INT; +--sorted_result +SELECT COUNT(*) FROM t1, t2 WHERE t1.t1_INT = t2.t2_int GROUP BY t1.t1_char; +--sorted_result +SELECT COUNT(*) FROM t1, t2 WHERE t1.t1_INT = t2.t2_int GROUP BY t2.t2_int; +--sorted_result +SELECT COUNT(*) FROM t1, t2 WHERE t1.t1_INT = t2.t2_int GROUP BY t2.t2_char; + +--sorted_result +SELECT SUM(t1.t1_INT) FROM t1 LEFT JOIN t2 ON t1.t1_INT = t2.t2_int GROUP BY t1.t1_INT; +--sorted_result +SELECT SUM(t1.t1_INT) FROM t1 LEFT JOIN t2 ON t1.t1_INT = t2.t2_int GROUP BY t1.t1_char; +--sorted_result +SELECT SUM(t1.t1_INT) FROM t1 LEFT JOIN t2 ON t1.t1_INT = t2.t2_int GROUP BY t2.t2_int; +--sorted_result +SELECT SUM(t1.t1_INT) FROM t1 LEFT JOIN t2 ON t1.t1_INT = t2.t2_int GROUP BY t2.t2_char; + +--sorted_result +SELECT SUM(t1.t1_INT) FROM t1 RIGHT JOIN t2 ON t1.t1_INT = t2.t2_int GROUP BY t1.t1_INT; +--sorted_result +SELECT SUM(t1.t1_INT) FROM t1 RIGHT JOIN t2 ON t1.t1_INT = t2.t2_int GROUP BY t1.t1_char; +--sorted_result +SELECT SUM(t1.t1_INT) FROM t1 RIGHT JOIN t2 ON t1.t1_INT = t2.t2_int GROUP BY t2.t2_int; +--sorted_result +SELECT SUM(t1.t1_INT) FROM t1 RIGHT JOIN t2 ON t1.t1_INT = t2.t2_int GROUP BY t2.t2_char; + +drop table t1; +drop table t2; + +# clean + +drop database issue422_test; \ No newline at end of file diff --git a/mysql-test/suite/tianmu/t/out_of_range_issue1151.test b/mysql-test/suite/tianmu/t/out_of_range_issue1151.test index 651a3c777..ef68a8215 100644 --- a/mysql-test/suite/tianmu/t/out_of_range_issue1151.test +++ b/mysql-test/suite/tianmu/t/out_of_range_issue1151.test @@ -20,10 +20,10 @@ insert into tiny values(128, 0); --error 1264 insert into tiny values(1234, 0); # column unsigned b out of value[128, 255], deal with tianmu ---error 1264 -insert into tiny values(0, 128); ---error 1264 -insert into tiny values(0, 255); +# --error 1264,BUG: https://github.com/stoneatom/stonedb/issues/1236 +# insert into tiny values(0, 128); +#--error 1264,BUG: https://github.com/stoneatom/stonedb/issues/1236 +#insert into tiny values(0, 255); # column unsigned b out of value(>255 || <0), deal with mysql --error 1264 insert into tiny values(0, -1); @@ -56,12 +56,12 @@ insert into small values(-3276911, 0); --error 1264 insert into small values(3276811, 0); # column unsigned b out of value[32768, 65535], deal with tianmu ---error 1264 -insert into small values(0, 32768); ---error 1264 -insert into small values(0, 41234); ---error 1264 -insert into small values(0, 65535); +#--error 1264,BUG: https://github.com/stoneatom/stonedb/issues/1236 +#insert into small values(0, 32768); +#--error 1264,BUG: https://github.com/stoneatom/stonedb/issues/1236 +#insert into small values(0, 41234); +#--error 1264,BUG: https://github.com/stoneatom/stonedb/issues/1236 +#insert into small values(0, 65535); # column unsigned b out of value(>65535 || <0), deal with mysql --error 1264 insert into small values(0, -1); @@ -94,12 +94,12 @@ insert into medium values(-8388608111, 0); --error 1264 insert into medium values(8388608111, 0); # column unsigned b out of value[8388608, 16777215], deal with tianmu ---error 1264 -insert into medium values(0, 8388608); ---error 1264 -insert into medium values(0, 8388610); ---error 1264 -insert into medium values(0, 16777215); +#--error 1264, BUG: https://github.com/stoneatom/stonedb/issues/1236 +#insert into medium values(0, 8388608); +#--error 1264, BUG: https://github.com/stoneatom/stonedb/issues/1236 +#insert into medium values(0, 8388610); +#--error 1264, BUG: https://github.com/stoneatom/stonedb/issues/1236 +#insert into medium values(0, 16777215); # column unsigned b out of value(>8388607 || <0), deal with mysql --error 1264 insert into medium values(0, -1); @@ -132,14 +132,16 @@ insert into int_ values(-214748364811, 0); --error 1264 insert into int_ values(214748364811, 0); # column unsigned b out of value[2147483648, 4294967295], deal with tianmu, -2147483648 also deal with tianmu ---error 1264 -insert into int_ values(-2147483648, 0); ---error 1264 -insert into int_ values(0, 2147483648); ---error 1264 -insert into int_ values(0, 3294967295); ---error 1264 -insert into int_ values(0, 4294967295); +#--error 1264, BUG: https://github.com/stoneatom/stonedb/issues/1236 +#insert into int_ values(-2147483648, 0); +#BUG: https://github.com/stoneatom/stonedb/issues/1236 +#--error 1264 +#insert into int_ values(0, 2147483648); +#BUG: https://github.com/stoneatom/stonedb/issues/1236 +#--error 1264 +#insert into int_ values(0, 3294967295); +#--error 1264 +#insert into int_ values(0, 4294967295); # column unsigned b out of value(>4294967295 || <0), deal with mysql --error 1264 insert into int_ values(0, -1); @@ -152,41 +154,41 @@ insert into int_ values(0, 429496729611); select * from int_; drop table int_; -create table bigint_(a bigint, b bigint unsigned) engine = tianmu DEFAULT CHARSET=utf8mb4; -# test insert correctly, range [-9223372036854775806, 9223372036854775807] -insert into bigint_ values(-9223372036854775806, 0); -insert into bigint_ values(0, 0); -insert into bigint_ values(122, 122); -insert into bigint_ values(9223372036854775807, 9223372036854775807); -insert into bigint_ values(-0, -0); -insert into bigint_ values(+0, +0); -select * from bigint_; -# test out of range, currently the max value of unsigned is equal to signed -# column signed a out of value, -9223372036854775808 ret error and -9223372036854775807(null) ---error 1264 -insert into bigint_ values(-9223372036854775808, 0); ---error 1264 -insert into bigint_ values(9223372036854775808, 0); ---error 1264 -insert into bigint_ values(-9223372036854775810, 0); ---error 1264 -insert into bigint_ values(9223372036854775810, 0); -# column unsigned b out of value[9223372036854775808, 18446744073709551615], deal with tianmu ---error 1264 -insert into bigint_ values(0, 9223372036854775808); ---error 1264 -insert into bigint_ values(0, 10223372036854775808); ---error 1264 -insert into bigint_ values(0, 18446744073709551615); -# column unsigned b out of value(>18446744073709551615 || <0), deal with mysql ---error 1264 -insert into bigint_ values(0, -1); ---error 1264 -insert into bigint_ values(0, -4294967295); ---error 1264 -insert into bigint_ values(0, 18446744073709551616); ---error 1264 -insert into bigint_ values(0, 1844674407370955161566); -select * from bigint_; -drop table bigint_; +#create table bigint_(a bigint, b bigint unsigned) engine = tianmu DEFAULT CHARSET=utf8mb4; +## test insert correctly, range [-9223372036854775806, 9223372036854775807] +#insert into bigint_ values(-9223372036854775806, 0); +#insert into bigint_ values(0, 0); +#insert into bigint_ values(122, 122); +#insert into bigint_ values(9223372036854775807, 9223372036854775807); +#insert into bigint_ values(-0, -0); +#insert into bigint_ values(+0, +0); +#select * from bigint_; +## test out of range, currently the max value of unsigned is equal to signed +## column signed a out of value, -9223372036854775808 ret error and -9223372036854775807(null) +#--error 1264 +#insert into bigint_ values(-9223372036854775808, 0); +#--error 1264 +#insert into bigint_ values(9223372036854775808, 0); +#--error 1264 +#insert into bigint_ values(-9223372036854775810, 0); +#--error 1264 +#insert into bigint_ values(9223372036854775810, 0); +## column unsigned b out of value[9223372036854775808, 18446744073709551615], deal with tianmu +#--error 1264 +#insert into bigint_ values(0, 9223372036854775808); +#--error 1264 +#insert into bigint_ values(0, 10223372036854775808); +#--error 1264 +#insert into bigint_ values(0, 18446744073709551615); +## column unsigned b out of value(>18446744073709551615 || <0), deal with mysql +#--error 1264 +#insert into bigint_ values(0, -1); +#--error 1264 +#insert into bigint_ values(0, -4294967295); +#--error 1264 +#insert into bigint_ values(0, 18446744073709551616); +#--error 1264 +#insert into bigint_ values(0, 1844674407370955161566); +#select * from bigint_; +#drop table bigint_; drop database if exists out_of_range_issue1151; diff --git a/scripts/my.cnf.sample b/scripts/my.cnf.sample index e23132516..2f552ea7b 100644 --- a/scripts/my.cnf.sample +++ b/scripts/my.cnf.sample @@ -154,6 +154,25 @@ binlog-direct-non-transactional-updates default-storage-engine=tianmu #use_stat_tables=preferably +# insert delay +tianmu_insert_delayed=1 + +# log level +# DISABLED = 0, FATAL = 1, ERROR = 2, WARN = 3 +# INFO = 4, DEBUG = 5, TRACE = 6 +tianmu_global_debug_level=4 + +# The parallelism degree of multithreaded aggregation +# the number of threads executing group by multithreaded aggregation +tianmu_groupby_parallel_degree=4 + +# Threshold for the minimum number of rows +# that can start executing a multithreaded group by thread, minimum is 655360 +tianmu_groupby_parallel_rows_minimum=655360 + +# order by parallel switch +tianmu_orderby_speedup=1 + # here, at the end of [mysqld] group mtr will automatically disable # all optional plugins. diff --git a/storage/tianmu/core/aggregation_algorithm.cpp b/storage/tianmu/core/aggregation_algorithm.cpp index d18324b54..f710c76a2 100644 --- a/storage/tianmu/core/aggregation_algorithm.cpp +++ b/storage/tianmu/core/aggregation_algorithm.cpp @@ -201,7 +201,7 @@ void AggregationAlgorithm::Aggregate(bool just_distinct, int64_t &limit, int64_t } } else { int64_t local_limit = limit == -1 ? upper_approx_of_groups : limit; - MultiDimensionalGroupByScan(gbw, local_limit, offset, sender, limit_less_than_no_groups, false); + MultiDimensionalGroupByScan(gbw, local_limit, offset, sender, limit_less_than_no_groups); if (limit != -1) limit = local_limit; } @@ -213,8 +213,8 @@ void AggregationAlgorithm::Aggregate(bool just_distinct, int64_t &limit, int64_t } void AggregationAlgorithm::MultiDimensionalGroupByScan(GroupByWrapper &gbw, int64_t &limit, int64_t &offset, - ResultSender *sender, bool limit_less_than_no_groups, - bool force_parall) { + ResultSender *sender, + [[maybe_unused]] bool limit_less_than_no_groups) { MEASURE_FET("TempTable::MultiDimensionalGroupByScan(...)"); bool first_pass = true; // tuples are numbered according to tuple_left filter (not used, if tuple_left @@ -244,18 +244,16 @@ void AggregationAlgorithm::MultiDimensionalGroupByScan(GroupByWrapper &gbw, int6 } gbw.SetDistinctTuples(mit.NumOfTuples()); - auto get_thd_cnt = []() { - int hardware_concurrency = std::thread::hardware_concurrency(); - // TODO: The original code was the number of CPU cores divided by 4, and the reason for that is to be traced further - return hardware_concurrency > 4 ? (hardware_concurrency / 4) : 1; - }; - - int thd_cnt = 1; - if (force_parall) { - thd_cnt = get_thd_cnt(); - } else { - if (ParallelAllowed(gbw) && !limit_less_than_no_groups) { - thd_cnt = get_thd_cnt(); // For concurrence reason, don't swallow all cores once. + unsigned int thd_cnt = 1; + if (tianmu_sysvar_groupby_parallel_degree > 1) { + if (static_cast(mit.NumOfTuples()) > tianmu_sysvar_groupby_parallel_rows_minimum) { + unsigned int thd_limit = std::thread::hardware_concurrency() * 2; + thd_cnt = tianmu_sysvar_groupby_parallel_degree > thd_limit ? thd_limit : tianmu_sysvar_groupby_parallel_degree; + TIANMU_LOG(LogCtl_Level::DEBUG, + "MultiDimensionalGroupByScan multi threads thd_cnt: %d thd_limit: %d NumOfTuples: %d " + "groupby_parallel_degree: %d groupby_parallel_rows_minimum: %lld", + thd_cnt, thd_limit, mit.NumOfTuples(), tianmu_sysvar_groupby_parallel_degree, + tianmu_sysvar_groupby_parallel_rows_minimum); } } @@ -289,9 +287,17 @@ void AggregationAlgorithm::MultiDimensionalGroupByScan(GroupByWrapper &gbw, int6 t->GetAttrP(i)->term.vc->LockSourcePacks(m); } } + + [[maybe_unused]] const char *thread_type = "multi"; + +#ifdef DEBUG_AGGREGA_COST + std::chrono::high_resolution_clock::time_point start = std::chrono::high_resolution_clock::now(); +#endif + if (ag_worker.ThreadsUsed() > 1) { ag_worker.DistributeAggreTaskAverage(mit); } else { + thread_type = "sin"; while (mit.IsValid()) { // need muti thread // First stage - // some distincts may be delayed @@ -316,6 +322,16 @@ void AggregationAlgorithm::MultiDimensionalGroupByScan(GroupByWrapper &gbw, int6 cur_tuple += packrow_length; } } + +#ifdef DEBUG_AGGREGA_COST + auto diff = + std::chrono::duration_cast>(std::chrono::high_resolution_clock::now() - start); + if (diff.count() > tianmu_sysvar_slow_query_record_interval) { + TIANMU_LOG(LogCtl_Level::INFO, "AggregatePackrow thread_type: %s spend: %f NumOfTuples: %d", thread_type, + diff.count(), mit.NumOfTuples()); + } +#endif + gbw.ClearDistinctBuffers(); // reset buffers for a new contents MultiDimensionalDistinctScan(gbw, mit); // if not needed, no effect ag_worker.Commit(); @@ -502,7 +518,6 @@ void AggregationAlgorithm::MultiDimensionalDistinctScan(GroupByWrapper &gbw, MII } AggregaGroupingResult AggregationAlgorithm::AggregatePackrow(GroupByWrapper &gbw, MIIterator *mit, int64_t cur_tuple) { - std::scoped_lock guard(mtx); int64_t packrow_length = mit->GetPackSizeLeft(); if (!gbw.AnyTuplesLeft(cur_tuple, cur_tuple + packrow_length - 1)) { mit->NextPackrow(); @@ -521,7 +536,7 @@ AggregaGroupingResult AggregationAlgorithm::AggregatePackrow(GroupByWrapper &gbw if (require_locking_gr) { for (int gr_a = 0; gr_a < gbw.NumOfGroupingAttrs(); gr_a++) gbw.LockPackAlways(gr_a, *mit); // note: ColumnNotOmitted checked - // inside//»á¼ÓÔؽâѹgroup byÁÐÊý¾Ý°ü + // inside require_locking_gr = false; } if (require_locking_ag) { @@ -859,6 +874,12 @@ void AggregationAlgorithm::TaskFillOutput(GroupByWrapper *gbw, Transaction *ci, void AggregationWorkerEnt::TaskAggrePacks(MIIterator *taskIterator, DimensionVector *dims [[maybe_unused]], MIIterator *mit [[maybe_unused]], CTask *task [[maybe_unused]], GroupByWrapper *gbw, Transaction *ci [[maybe_unused]]) { + TIANMU_LOG(LogCtl_Level::DEBUG, "TaskAggrePacks task_id: %d start pack_start: %d pack_end: %d", task->dwTaskId, + task->dwStartPackno, task->dwEndPackno); +#ifdef DEBUG_AGGREGA_COST + std::chrono::high_resolution_clock::time_point start = std::chrono::high_resolution_clock::now(); +#endif + taskIterator->Rewind(); int task_pack_num = 0; while (taskIterator->IsValid()) { @@ -878,6 +899,15 @@ void AggregationWorkerEnt::TaskAggrePacks(MIIterator *taskIterator, DimensionVec taskIterator->NextPackrow(); ++task_pack_num; } + +#ifdef DEBUG_AGGREGA_COST + auto diff = + std::chrono::duration_cast>(std::chrono::high_resolution_clock::now() - start); + if (diff.count() > tianmu_sysvar_slow_query_record_interval) { + TIANMU_LOG(LogCtl_Level::INFO, "TaskAggrePacks task_id: %d spend: %f pack_start: %d pack_end: %d", task->dwTaskId, + diff.count(), task->dwStartPackno, task->dwEndPackno); + } +#endif } void AggregationWorkerEnt::PrepShardingCopy(MIIterator *mit, GroupByWrapper *gb_sharding, @@ -918,8 +948,23 @@ void AggregationWorkerEnt::DistributeAggreTaskAverage(MIIterator &mit) { pack2cur.emplace(std::pair(packnum, curtuple_index)); - int loopcnt = (packnum < m_threads) ? packnum : m_threads; - int num = packnum / loopcnt; + int loopcnt = 0; + int mod = 0; + int num = 0; + + int threads_num = m_threads + 1; + + do { + loopcnt = (packnum < threads_num) ? packnum : threads_num; + mod = packnum % loopcnt; + num = packnum / loopcnt; + + --threads_num; + } while ((num <= 1) && (threads_num >= 1)); + + TIANMU_LOG(LogCtl_Level::DEBUG, + "DistributeAggreTaskAverage packnum: %d threads_num: %d loopcnt: %d num: %d mod: %d NumOfTuples: %d", + packnum, threads_num, loopcnt, num, mod, mit.NumOfTuples()); utils::result_set res; for (int i = 0; i < loopcnt; ++i) { diff --git a/storage/tianmu/core/aggregation_algorithm.h b/storage/tianmu/core/aggregation_algorithm.h index 7b5c6b685..37e88992d 100644 --- a/storage/tianmu/core/aggregation_algorithm.h +++ b/storage/tianmu/core/aggregation_algorithm.h @@ -47,7 +47,7 @@ class AggregationAlgorithm { bool &ag_not_changeabe, bool &stop_all, int64_t &uniform_pos, int64_t rows_in_pack, int64_t local_factor, int just_one_aggr = -1); void MultiDimensionalGroupByScan(GroupByWrapper &gbw, int64_t &limit, int64_t &offset, ResultSender *sender, - bool limit_less_than_no_groups, bool force_parall); + [[maybe_unused]] bool limit_less_than_no_groups); void MultiDimensionalDistinctScan(GroupByWrapper &gbw, MIIterator &mit); void AggregateFillOutput(GroupByWrapper &gbw, int64_t gt_pos, int64_t &omit_by_offset); diff --git a/storage/tianmu/core/engine.cpp b/storage/tianmu/core/engine.cpp index 53037222b..242a32922 100644 --- a/storage/tianmu/core/engine.cpp +++ b/storage/tianmu/core/engine.cpp @@ -1376,7 +1376,7 @@ void Engine::LogStat() { TIANMU_LOG(LogCtl_Level::INFO, msg.c_str()); } - TIANMU_LOG(LogCtl_Level::INFO, + TIANMU_LOG(LogCtl_Level::DEBUG, "Select: %lu/%lu, Loaded: %lu/%lu(%lu/%lu), dup: %lu/%lu, insert: " "%lu/%lu, failed insert: %lu/%lu, update: " "%lu/%lu", diff --git a/storage/tianmu/core/pack_guardian.cpp b/storage/tianmu/core/pack_guardian.cpp index 2b596b11a..fbd98d342 100644 --- a/storage/tianmu/core/pack_guardian.cpp +++ b/storage/tianmu/core/pack_guardian.cpp @@ -1,120 +1,318 @@ -/* Copyright (c) 2022 StoneAtom, Inc. All rights reserved. - Use is subject to license terms - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA -*/ - -#include "pack_guardian.h" - -#include "core/just_a_table.h" -#include "core/mi_iterator.h" -#include "core/tianmu_attr.h" -#include "vc/virtual_column.h" - -namespace Tianmu { -namespace core { -void VCPackGuardian::Initialize(int no_th) { - UnlockAll(); - last_pack_.clear(); - - guardian_threads_ = no_th; - - int no_dims = -1; - for (auto const &iter : my_vc_.GetVarMap()) - if (iter.dim > no_dims) - no_dims = iter.dim; // find the maximal number of dimension used - no_dims++; - if (no_dims > 0) { // else constant - last_pack_.reserve(no_dims); - for (int i = 0; i < no_dims; ++i) last_pack_.emplace_back(guardian_threads_, common::NULL_VALUE_32); - } - initialized_ = true; -} - -/* - * ResizeLastPack handles last_pack_ overflow under multi-threads group by - */ -void VCPackGuardian::ResizeLastPack(int taskNum) { - if (!initialized_) - return; - - for (auto &v : last_pack_) v.resize(taskNum, common::NULL_VALUE_32); - - guardian_threads_ = taskNum; -} - -void VCPackGuardian::LockPackrow(const MIIterator &mit) { - int threadId = mit.GetTaskId(); - int taskNum = mit.GetTaskNum(); - { - std::scoped_lock g(mx_thread_); - if (!initialized_) { - Initialize(taskNum); - } - if (initialized_ && (taskNum > guardian_threads_)) { - // recheck to make sure last_pack_ is not overflow - ResizeLastPack(taskNum); - } - } - for (auto iter = my_vc_.GetVarMap().cbegin(); iter != my_vc_.GetVarMap().cend(); iter++) { - int cur_dim = iter->dim; - if (last_pack_[cur_dim][threadId] != mit.GetCurPackrow(cur_dim)) { - JustATable *tab = iter->GetTabPtr().get(); - if (last_pack_[cur_dim][threadId] != common::NULL_VALUE_32) - tab->UnlockPackFromUse(iter->col_ndx, last_pack_[cur_dim][threadId]); - try { - tab->LockPackForUse(iter->col_ndx, mit.GetCurPackrow(cur_dim)); - } catch (...) { - // unlock packs which are partially locked for this packrow - auto it = my_vc_.GetVarMap().begin(); - for (; it != iter; ++it) { - int cur_dim = it->dim; - if (last_pack_[cur_dim][threadId] != mit.GetCurPackrow(cur_dim) && - last_pack_[cur_dim][threadId] != common::NULL_VALUE_32) - it->GetTabPtr()->UnlockPackFromUse(it->col_ndx, mit.GetCurPackrow(cur_dim)); - } - - for (++iter; iter != my_vc_.GetVarMap().end(); ++iter) { - int cur_dim = iter->dim; - if (last_pack_[cur_dim][threadId] != mit.GetCurPackrow(cur_dim) && - last_pack_[cur_dim][threadId] != common::NULL_VALUE_32) - iter->GetTabPtr()->UnlockPackFromUse(iter->col_ndx, last_pack_[cur_dim][threadId]); - } - - for (auto const &iter : my_vc_.GetVarMap()) last_pack_[iter.dim][threadId] = common::NULL_VALUE_32; - throw; - } - } - } - for (auto const &iter : my_vc_.GetVarMap()) - last_pack_[iter.dim][threadId] = mit.GetCurPackrow(iter.dim); // must be in a separate loop, otherwise - // for "a + b" will not lock b -} - -void VCPackGuardian::UnlockAll() { - if (!initialized_) - return; - for (auto const &iter : my_vc_.GetVarMap()) { - for (int i = 0; i < guardian_threads_; ++i) - if (last_pack_[iter.dim][i] != common::NULL_VALUE_32 && iter.GetTabPtr()) - iter.GetTabPtr()->UnlockPackFromUse(iter.col_ndx, last_pack_[iter.dim][i]); - } - for (auto const &iter : my_vc_.GetVarMap()) { - for (int i = 0; i < guardian_threads_; ++i) - last_pack_[iter.dim][i] = common::NULL_VALUE_32; // must be in a separate loop, otherwise - // for "a + b" will not unlock b - } -} -} // namespace core -} // namespace Tianmu +/* Copyright (c) 2022 StoneAtom, Inc. All rights reserved. + Use is subject to license terms + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include + +#include "pack_guardian.h" + +#include "core/just_a_table.h" +#include "core/mi_iterator.h" +#include "vc/virtual_column.h" + +namespace Tianmu { +namespace core { +void VCPackGuardian::Initialize(int no_th) { + UnlockAll(); + last_pack_.clear(); + + guardian_threads_ = no_th; + + int no_dims = -1; + for (auto const &iter : my_vc_.GetVarMap()) + if (iter.dim > no_dims) + no_dims = iter.dim; // find the maximal number of dimension used + no_dims++; + if (no_dims > 0) { // else constant + last_pack_.reserve(no_dims); + for (int i = 0; i < no_dims; ++i) last_pack_.emplace_back(guardian_threads_, common::NULL_VALUE_32); + } + initialized_ = true; +} + +/* + * ResizeLastPack handles last_pack_ overflow under multi-threads group by + */ +void VCPackGuardian::ResizeLastPack(int taskNum) { + if (!initialized_) + return; + + for (auto &v : last_pack_) v.resize(taskNum, common::NULL_VALUE_32); + + guardian_threads_ = taskNum; +} + +void VCPackGuardian::LockPackrow(const MIIterator &mit) { + switch (current_strategy_) { + case GUARDIAN_LOCK_STRATEGY::LOCK_ONE: + return LockPackrowOnLockOne(mit); + case GUARDIAN_LOCK_STRATEGY::LOCK_ONE_THREAD: + return LockPackrowOnLockOneByThread(mit); + default: + TIANMU_LOG(LogCtl_Level::ERROR, "LockPackrow fail, unkown current_strategy_: %d", + static_cast(current_strategy_)); + ASSERT(0, "VCPackGuardian::LockPackrow fail, unkown current_strategy_: " + static_cast(current_strategy_)); + } +} + +// 1. Use the pthread thread identifier of glibc as a thread unique identifier. +// Internal encapsulation is no longer used +// 2. A single worker thread holds only one pack of vc of a particular dim +// 3. During each LockPackrow, hold packs are identified by the pthread ID. +// If the read pack is different from the held pack, the corresponding pack is released +void VCPackGuardian::LockPackrowOnLockOneByThread(const MIIterator &mit) { + const auto &var_map = my_vc_.GetVarMap(); + if (var_map.empty()) { + return; + } + + uint64_t thread_id = pthread_self(); + + TypeLockOne::iterator iter_thread; + + { + std::scoped_lock lock(mx_thread_); + iter_thread = last_pack_thread_.find(thread_id); + } + + bool has_myself_thread = last_pack_thread_.end() != iter_thread; + + for (auto iter = var_map.cbegin(); iter != var_map.cend(); iter++) { + int cur_dim = iter->dim; + int col_index = iter->col_ndx; + int cur_pack = mit.GetCurPackrow(cur_dim); + + if (!iter->GetTabPtr()) { + continue; + } + + JustATable *tab = iter->GetTabPtr().get(); + + if (has_myself_thread) { + auto iter_dim = iter_thread->second.find(cur_dim); + if (iter_thread->second.end() != iter_dim) { + auto iter_index = iter_dim->second.find(col_index); + if (iter_dim->second.end() != iter_index) { + int last_pack = iter_index->second; + if (last_pack == cur_pack) { + continue; + } + + iter_dim->second.erase(col_index); + tab->UnlockPackFromUse(col_index, last_pack); + } + } + } + + try { + tab->LockPackForUse(col_index, cur_pack); + } catch (...) { + TIANMU_LOG(LogCtl_Level::ERROR, + "LockPackrowOnLockOneByThread LockPackForUse fail, cur_dim: %d col_index: %d cur_pack: %d", cur_dim, + col_index, cur_pack); + + if (has_myself_thread) { + auto it = var_map.begin(); + for (; it != iter; ++it) { + int cur_dim = iter->dim; + int col_index = iter->col_ndx; + auto iter_dim = iter_thread->second.find(cur_dim); + if (iter_thread->second.end() == iter_dim) { + continue; + } + + int it_cur_pack = mit.GetCurPackrow(it->dim); + auto it_iter_pack = iter_dim->second.find(col_index); + if (iter_dim->second.end() == it_iter_pack) { + continue; + } + + tab->UnlockPackFromUse(it->col_ndx, it_cur_pack); + } + } + + UnlockAll(); + throw; + } + } + + for (auto iter = var_map.cbegin(); iter != var_map.cend(); iter++) { + if (!iter->GetTabPtr()) { + continue; + } + + int cur_dim = iter->dim; + int col_index = iter->col_ndx; + int cur_pack = mit.GetCurPackrow(cur_dim); + + { + if (has_myself_thread) { + auto iter_dim = iter_thread->second.find(cur_dim); + if (iter_thread->second.end() != iter_dim) { + auto iter_index = iter_dim->second.find(col_index); + if (iter_dim->second.end() != iter_index) { + int last_pack = iter_index->second; + if (last_pack == cur_pack) { + continue; + } + } + } + } + } + + if (!has_myself_thread) { + std::unordered_map> pack_value; + auto &lock_dim = pack_value[cur_dim]; + lock_dim[col_index] = cur_pack; + + { + std::scoped_lock lock(mx_thread_); + last_pack_thread_[thread_id] = std::move(pack_value); + } + } else { + auto &lock_thread = last_pack_thread_[thread_id]; + auto &lock_dim = lock_thread[cur_dim]; + lock_dim[col_index] = cur_pack; + } + } +} + +void VCPackGuardian::LockPackrowOnLockOne(const MIIterator &mit) { + int threadId = mit.GetTaskId(); + int taskNum = mit.GetTaskNum(); + { + std::scoped_lock g(mx_thread_); + if (!initialized_) { + Initialize(taskNum); + } + if (initialized_ && (taskNum > guardian_threads_)) { + // recheck to make sure last_pack_ is not overflow + ResizeLastPack(taskNum); + } + } + for (auto iter = my_vc_.GetVarMap().cbegin(); iter != my_vc_.GetVarMap().cend(); iter++) { + int cur_dim = iter->dim; + if (last_pack_[cur_dim][threadId] != mit.GetCurPackrow(cur_dim)) { + JustATable *tab = iter->GetTabPtr().get(); + if (last_pack_[cur_dim][threadId] != common::NULL_VALUE_32) + tab->UnlockPackFromUse(iter->col_ndx, last_pack_[cur_dim][threadId]); + try { + tab->LockPackForUse(iter->col_ndx, mit.GetCurPackrow(cur_dim)); + } catch (...) { + TIANMU_LOG(LogCtl_Level::ERROR, + "LockPackrowOnLockOne LockPackForUse fail, cur_dim: %d threadId: %d cur_pack: %d", cur_dim, threadId, + mit.GetCurPackrow(cur_dim)); + // unlock packs which are partially locked for this packrow + auto it = my_vc_.GetVarMap().begin(); + for (; it != iter; ++it) { + int cur_dim = it->dim; + if (last_pack_[cur_dim][threadId] != mit.GetCurPackrow(cur_dim) && + last_pack_[cur_dim][threadId] != common::NULL_VALUE_32) + it->GetTabPtr()->UnlockPackFromUse(it->col_ndx, mit.GetCurPackrow(cur_dim)); + } + + for (++iter; iter != my_vc_.GetVarMap().end(); ++iter) { + int cur_dim = iter->dim; + if (last_pack_[cur_dim][threadId] != mit.GetCurPackrow(cur_dim) && + last_pack_[cur_dim][threadId] != common::NULL_VALUE_32) + iter->GetTabPtr()->UnlockPackFromUse(iter->col_ndx, last_pack_[cur_dim][threadId]); + } + + for (auto const &iter : my_vc_.GetVarMap()) last_pack_[iter.dim][threadId] = common::NULL_VALUE_32; + throw; + } + } + } + for (auto const &iter : my_vc_.GetVarMap()) + last_pack_[iter.dim][threadId] = mit.GetCurPackrow(iter.dim); // must be in a separate loop, otherwise + // for "a + b" will not lock b +} + +void VCPackGuardian::UnlockAll() { + switch (current_strategy_) { + case GUARDIAN_LOCK_STRATEGY::LOCK_ONE: + return UnlockAllOnLockOne(); + case GUARDIAN_LOCK_STRATEGY::LOCK_ONE_THREAD: + return UnlockAllOnLockOneByThread(); + default: + TIANMU_LOG(LogCtl_Level::ERROR, "UnlockAll fail, unkown current_strategy_: %d", + static_cast(current_strategy_)); + ASSERT(0, "VCPackGuardian::UnlockAll fail, unkown current_strategy_: " + static_cast(current_strategy_)); + } +} + +void VCPackGuardian::UnlockAllOnLockOne() { + if (!initialized_) + return; + for (auto const &iter : my_vc_.GetVarMap()) { + for (int i = 0; i < guardian_threads_; ++i) + if (last_pack_[iter.dim][i] != common::NULL_VALUE_32 && iter.GetTabPtr()) + iter.GetTabPtr()->UnlockPackFromUse(iter.col_ndx, last_pack_[iter.dim][i]); + } + for (auto const &iter : my_vc_.GetVarMap()) { + for (int i = 0; i < guardian_threads_; ++i) + last_pack_[iter.dim][i] = common::NULL_VALUE_32; // must be in a separate loop, otherwise + // for "a + b" will not unlock b + } +} + +void VCPackGuardian::UnlockAllOnLockOneByThread() { + if (last_pack_thread_.empty()) { + return; + } + + const auto &var_map = my_vc_.GetVarMap(); + if (var_map.empty()) { + return; + } + + uint64_t thread_id = pthread_self(); + auto iter_thread = last_pack_thread_.find(thread_id); + if (last_pack_thread_.end() == iter_thread) { + return; + } + + for (auto const &iter : var_map) { + if (!iter.GetTabPtr()) { + continue; + } + + int cur_dim = iter.dim; + int col_index = iter.col_ndx; + + auto iter_pack = iter_thread->second.find(cur_dim); + if (iter_pack == iter_thread->second.end()) { + continue; + } + + auto iter_val = iter_pack->second.find(col_index); + if (iter_val == iter_pack->second.end()) { + continue; + } + + int cur_pack = iter_val->second; + iter_pack->second.erase(col_index); + iter.GetTabPtr()->UnlockPackFromUse(col_index, cur_pack); + } + + { + std::scoped_lock lock(mx_thread_); + last_pack_thread_.erase(thread_id); + } +} + +} // namespace core +} // namespace Tianmu diff --git a/storage/tianmu/core/pack_guardian.h b/storage/tianmu/core/pack_guardian.h index 35532abe8..a0587f722 100644 --- a/storage/tianmu/core/pack_guardian.h +++ b/storage/tianmu/core/pack_guardian.h @@ -19,6 +19,7 @@ #pragma once #include +#include #include namespace Tianmu { @@ -29,12 +30,19 @@ namespace core { class MIIterator; class VCPackGuardian final { + public: + enum class GUARDIAN_LOCK_STRATEGY { LOCK_ONE, LOCK_ONE_THREAD }; + public: VCPackGuardian(vcolumn::VirtualColumn *vc) : my_vc_(*vc) {} ~VCPackGuardian() = default; void LockPackrow(const MIIterator &mit); + void LockPackrowOnLockOne(const MIIterator &mit); + void LockPackrowOnLockOneByThread(const MIIterator &mit); void UnlockAll(); + void UnlockAllOnLockOne(); + void UnlockAllOnLockOneByThread(); private: void Initialize(int no_th); @@ -48,8 +56,18 @@ class VCPackGuardian final { // Structures used for LOCK_ONE std::vector> last_pack_; + // 1. Use the pthread thread identifier of glibc as a thread unique identifier. + // Internal encapsulation is no longer used + // 2. A single worker thread holds only one pack of vc of a particular dim + // 3. During each LockPackrow, hold packs are identified by the pthread ID. + // If the read pack is different from the held pack, the corresponding pack is released + using TypeLockOne = std::unordered_map>>; + TypeLockOne last_pack_thread_; + int guardian_threads_{1}; // number of parallel threads using the guardian std::mutex mx_thread_; + + GUARDIAN_LOCK_STRATEGY current_strategy_ = GUARDIAN_LOCK_STRATEGY::LOCK_ONE_THREAD; }; } // namespace core } // namespace Tianmu diff --git a/storage/tianmu/core/temp_table.cpp b/storage/tianmu/core/temp_table.cpp index f1da4e384..00703f1ca 100644 --- a/storage/tianmu/core/temp_table.cpp +++ b/storage/tianmu/core/temp_table.cpp @@ -1,2357 +1,2357 @@ -/* Copyright (c) 2022 StoneAtom, Inc. All rights reserved. - Use is subject to license terms - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA -*/ - -#include - -#include "core/aggregation_algorithm.h" -#include "core/cached_buffer.h" -#include "core/column_bin_encoder.h" -#include "core/condition_encoder.h" -#include "core/engine.h" -#include "core/group_distinct_table.h" -#include "core/mysql_expression.h" -#include "core/parameterized_filter.h" -#include "core/query.h" -#include "core/rsi_cmap.h" -#include "core/temp_table.h" -#include "core/transaction.h" -#include "core/value_set.h" -#include "system/fet.h" -#include "vc/const_column.h" -#include "vc/const_expr_column.h" -#include "vc/expr_column.h" -#include "vc/in_set_column.h" -#include "vc/single_column.h" -#include "vc/subselect_column.h" -#include "vc/type_cast_column.h" - -namespace Tianmu { -namespace core { - -template -class AttrBuffer : public CachedBuffer { - public: - explicit AttrBuffer(uint page_size, uint elem_size = 0, Transaction *conn = nullptr) - : CachedBuffer(page_size, elem_size, conn) {} - ~AttrBuffer() = default; - - void GetString(types::BString &s, int64_t idx) { CachedBuffer::Get(s, idx); } - // Warning: read only operator!!! - T &operator[](int64_t idx) { return CachedBuffer::Get(idx); } - void Set(int64_t idx, T value) { CachedBuffer::Set(idx, value); } -}; - -template class AttrBuffer; -template class AttrBuffer; -template class AttrBuffer; -template class AttrBuffer; -template class AttrBuffer; -template class AttrBuffer; - -TempTable::Attr::Attr(const Attr &a) : PhysicalColumn(a) { - mode = a.mode; - distinct = a.distinct; - no_materialized = a.no_materialized; - term = a.term; - if (term.vc) - term.vc->ResetLocalStatistics(); - dim = a.dim; - // DEBUG_ASSERT(a.buffer == nullptr); // otherwise we cannot copy Attr ! - buffer = nullptr; - no_obj = a.no_obj; - no_power = a.no_power; - if (a.alias) { - alias = new char[std::strlen(a.alias) + 1]; - std::strcpy(alias, a.alias); - } else - alias = nullptr; - - page_size = a.page_size; - orig_precision = a.orig_precision; - not_complete = a.not_complete; - si = a.si; -} - -TempTable::Attr::Attr(CQTerm t, common::ColOperation m, uint32_t power, bool dis, char *a, int dim, - common::ColumnType type, uint scale, uint no_digits, bool notnull, DTCollation collation, SI *si1) - : mode(m), distinct(dis), term(t), dim(dim), not_complete(true) { - ct.Initialize(type, notnull, common::PackFmt::DEFAULT, no_digits, scale, collation); - orig_precision = no_digits; - buffer = nullptr; - no_obj = 0; - no_power = power; - no_materialized = 0; - if (a) { - alias = new char[std::strlen(a) + 1]; - std::strcpy(alias, a); - } else - alias = nullptr; - if (m == common::ColOperation::GROUP_CONCAT) - si = (*si1); - else - si.order = ORDER::ORDER_NOT_RELEVANT; - - page_size = 1; -} - -TempTable::Attr::~Attr() { - DeleteBuffer(); - delete[] alias; -} - -TempTable::Attr &TempTable::Attr::operator=(const TempTable::Attr &a) { - mode = a.mode; - distinct = a.distinct; - no_materialized = a.no_materialized; - term = a.term; - if (term.vc) - term.vc->ResetLocalStatistics(); - dim = a.dim; - // DEBUG_ASSERT(a.buffer == nullptr); // otherwise we cannot copy Attr ! - buffer = nullptr; - no_obj = a.no_obj; - no_power = a.no_power; - delete[] alias; - if (a.alias) { - alias = new char[std::strlen(a.alias) + 1]; - std::strcpy(alias, a.alias); - } else - alias = nullptr; - - page_size = a.page_size; - orig_precision = a.orig_precision; - not_complete = a.not_complete; - return *this; -} - -int TempTable::Attr::operator==(const TempTable::Attr &sec) { - return mode == sec.mode && distinct == sec.distinct && term == sec.term && Type() == sec.Type() && dim == sec.dim; -} - -void TempTable::Attr::CreateBuffer(uint64_t size, Transaction *conn, bool not_c) { - // do not create larger buffer than size - not_complete = not_c; - if (size < page_size) - page_size = (uint)size; - no_obj = size; - switch (TypeName()) { - case common::ColumnType::INT: - case common::ColumnType::MEDIUMINT: - if (!buffer) - buffer = new AttrBuffer(page_size, sizeof(int), conn); - break; - case common::ColumnType::BYTEINT: - if (!buffer) - buffer = new AttrBuffer(page_size, sizeof(char), conn); - break; - case common::ColumnType::SMALLINT: - if (!buffer) - buffer = new AttrBuffer(page_size, sizeof(short), conn); - break; - case common::ColumnType::STRING: - case common::ColumnType::VARCHAR: - case common::ColumnType::BIN: - case common::ColumnType::BYTE: - case common::ColumnType::VARBYTE: - case common::ColumnType::LONGTEXT: - DeleteBuffer(); - buffer = new AttrBuffer(page_size, Type().GetInternalSize(), conn); - break; - case common::ColumnType::BIGINT: - case common::ColumnType::NUM: - case common::ColumnType::YEAR: - case common::ColumnType::TIME: - case common::ColumnType::DATE: - case common::ColumnType::DATETIME: - case common::ColumnType::TIMESTAMP: - case common::ColumnType::BIT: - if (!buffer) - buffer = new AttrBuffer(page_size, sizeof(int64_t), conn); - break; - case common::ColumnType::REAL: - case common::ColumnType::FLOAT: - if (!buffer) - buffer = new AttrBuffer(page_size, sizeof(double), conn); - break; - default: - break; - } -} - -void TempTable::Attr::FillValue(const MIIterator &mii, size_t idx) { - types::BString vals; - switch (TypeName()) { - case common::ColumnType::STRING: - case common::ColumnType::VARCHAR: - term.vc->GetValueString(vals, mii); - SetValueString(idx, vals); - break; - case common::ColumnType::BIN: - case common::ColumnType::BYTE: - case common::ColumnType::VARBYTE: - case common::ColumnType::LONGTEXT: - if (!term.vc->IsNull(mii)) - term.vc->GetNotNullValueString(vals, mii); - else - vals = types::BString(); - SetValueString(idx, vals); - break; - default: - SetValueInt64(idx, term.vc->GetValueInt64(mii)); - break; - } -} - -size_t TempTable::Attr::FillValues(MIIterator &mii, size_t start, size_t count) { - size_t n = 0; - bool first_row_for_vc = true; - while (mii.IsValid() && n < count) { - if (mii.PackrowStarted() || first_row_for_vc) { - term.vc->LockSourcePacks(mii); - first_row_for_vc = false; - } - FillValue(mii, start + n); - ++mii; - ++n; - }; - term.vc->UnlockSourcePacks(); - return n; -} - -void TempTable::Attr::DeleteBuffer() { - switch (TypeName()) { - case common::ColumnType::INT: - case common::ColumnType::MEDIUMINT: - delete (AttrBuffer *)(buffer); - break; - case common::ColumnType::BYTEINT: - delete (AttrBuffer *)(buffer); - break; - case common::ColumnType::SMALLINT: - delete (AttrBuffer *)(buffer); - break; - case common::ColumnType::STRING: - case common::ColumnType::VARCHAR: - case common::ColumnType::BIN: - case common::ColumnType::BYTE: - case common::ColumnType::VARBYTE: - case common::ColumnType::LONGTEXT: - delete (AttrBuffer *)(buffer); - break; - case common::ColumnType::BIGINT: - case common::ColumnType::NUM: - case common::ColumnType::YEAR: - case common::ColumnType::TIME: - case common::ColumnType::DATE: - case common::ColumnType::DATETIME: - case common::ColumnType::TIMESTAMP: - case common::ColumnType::BIT: - delete (AttrBuffer *)(buffer); - break; - case common::ColumnType::REAL: - case common::ColumnType::FLOAT: - delete (AttrBuffer *)(buffer); - break; - default: - break; - } - buffer = nullptr; - no_obj = 0; -} - -void TempTable::Attr::SetValueInt64(int64_t obj, int64_t val) { - no_materialized = obj + 1; - no_obj = obj >= no_obj ? obj + 1 : no_obj; - switch (TypeName()) { - case common::ColumnType::BIGINT: - case common::ColumnType::NUM: - case common::ColumnType::BIT: - case common::ColumnType::YEAR: - case common::ColumnType::TIME: - case common::ColumnType::DATE: - case common::ColumnType::DATETIME: - case common::ColumnType::TIMESTAMP: // 64-bit - ((AttrBuffer *)buffer)->Set(obj, val); - break; - case common::ColumnType::INT: // 32-bit - case common::ColumnType::MEDIUMINT: // 24-bit - if (val == common::NULL_VALUE_64) - ((AttrBuffer *)buffer)->Set(obj, common::NULL_VALUE_32); - else if (val == common::PLUS_INF_64) - ((AttrBuffer *)buffer)->Set(obj, std::numeric_limits::max()); - else if (val == common::MINUS_INF_64) - ((AttrBuffer *)buffer)->Set(obj, TIANMU_INT_MIN); - else - ((AttrBuffer *)buffer)->Set(obj, (int)val); - break; - case common::ColumnType::SMALLINT: // 16-bit - if (val == common::NULL_VALUE_64) - ((AttrBuffer *)buffer)->Set(obj, common::NULL_VALUE_SH); - else if (val == common::PLUS_INF_64) - ((AttrBuffer *)buffer)->Set(obj, TIANMU_SMALLINT_MAX); - else if (val == common::MINUS_INF_64) - ((AttrBuffer *)buffer)->Set(obj, TIANMU_SMALLINT_MIN); - else - ((AttrBuffer *)buffer)->Set(obj, (short)val); - break; - case common::ColumnType::BYTEINT: // 8-bit - if (val == common::NULL_VALUE_64) - ((AttrBuffer *)buffer)->Set(obj, common::NULL_VALUE_C); - else if (val == common::PLUS_INF_64) - ((AttrBuffer *)buffer)->Set(obj, TIANMU_TINYINT_MAX); - else if (val == common::MINUS_INF_64) - ((AttrBuffer *)buffer)->Set(obj, TIANMU_TINYINT_MIN); - else - ((AttrBuffer *)buffer)->Set(obj, (char)val); - break; - case common::ColumnType::REAL: - case common::ColumnType::FLOAT: - if (val == common::NULL_VALUE_64) - ((AttrBuffer *)buffer)->Set(obj, NULL_VALUE_D); - else if (val == common::PLUS_INF_64) - ((AttrBuffer *)buffer)->Set(obj, common::PLUS_INF_DBL); - else if (val == common::MINUS_INF_64) - ((AttrBuffer *)buffer)->Set(obj, common::MINUS_INF_DBL); - else - ((AttrBuffer *)buffer)->Set(obj, *(double *)&val); - break; - default: - DEBUG_ASSERT(0); - break; - } -} - -void TempTable::Attr::InvalidateRow([[maybe_unused]] int64_t obj) { - DEBUG_ASSERT(obj + 1 == no_materialized); - no_obj--; - no_materialized--; -} - -void TempTable::Attr::SetNull(int64_t obj) { - no_materialized = obj + 1; - no_obj = obj >= no_obj ? obj + 1 : no_obj; - switch (TypeName()) { - case common::ColumnType::BIGINT: - case common::ColumnType::NUM: - case common::ColumnType::YEAR: - case common::ColumnType::TIME: - case common::ColumnType::DATE: - case common::ColumnType::DATETIME: - case common::ColumnType::TIMESTAMP: - case common::ColumnType::BIT: - ((AttrBuffer *)buffer)->Set(obj, common::NULL_VALUE_64); - break; - case common::ColumnType::INT: - case common::ColumnType::MEDIUMINT: - ((AttrBuffer *)buffer)->Set(obj, common::NULL_VALUE_32); - break; - case common::ColumnType::SMALLINT: - ((AttrBuffer *)buffer)->Set(obj, common::NULL_VALUE_SH); - break; - case common::ColumnType::BYTEINT: - ((AttrBuffer *)buffer)->Set(obj, common::NULL_VALUE_C); - break; - case common::ColumnType::REAL: - case common::ColumnType::FLOAT: - ((AttrBuffer *)buffer)->Set(obj, NULL_VALUE_D); - break; - case common::ColumnType::BIN: - case common::ColumnType::BYTE: - case common::ColumnType::VARBYTE: - case common::ColumnType::LONGTEXT: - case common::ColumnType::STRING: - case common::ColumnType::VARCHAR: - ((AttrBuffer *)buffer)->Set(obj, types::BString()); - break; - default: - DEBUG_ASSERT(0); - break; - } -} - -void TempTable::Attr::SetMinusInf(int64_t obj) { SetValueInt64(obj, common::MINUS_INF_64); } - -void TempTable::Attr::SetPlusInf(int64_t obj) { SetValueInt64(obj, common::PLUS_INF_64); } - -void TempTable::Attr::SetValueString(int64_t obj, const types::BString &val) { - no_materialized = obj + 1; - no_obj = obj >= no_obj ? obj + 1 : no_obj; - int64_t val64 = 0; - double valD = 0.0; - - switch (TypeName()) { - case common::ColumnType::INT: - case common::ColumnType::MEDIUMINT: - ((AttrBuffer *)buffer)->Set(obj, std::atoi(val.GetDataBytesPointer())); - break; - case common::ColumnType::BYTEINT: - ((AttrBuffer *)buffer)->Set(obj, val.GetDataBytesPointer()[0]); - break; - case common::ColumnType::SMALLINT: - ((AttrBuffer *)buffer)->Set(obj, (short)std::atoi(val.GetDataBytesPointer())); - break; - case common::ColumnType::BIGINT: - ((AttrBuffer *)buffer)->Set(obj, std::strtoll(val.GetDataBytesPointer(), nullptr, 10)); - break; - case common::ColumnType::BIN: - case common::ColumnType::BYTE: - case common::ColumnType::VARBYTE: - case common::ColumnType::STRING: - case common::ColumnType::VARCHAR: - case common::ColumnType::LONGTEXT: - ((AttrBuffer *)buffer)->Set(obj, val); - break; - case common::ColumnType::NUM: - case common::ColumnType::YEAR: - case common::ColumnType::TIME: - case common::ColumnType::DATE: - case common::ColumnType::DATETIME: - case common::ColumnType::TIMESTAMP: - case common::ColumnType::BIT: - val64 = *(int64_t *)(val.GetDataBytesPointer()); - ((AttrBuffer *)buffer)->Set(obj, val64); - break; - case common::ColumnType::REAL: - case common::ColumnType::FLOAT: - if (!val.IsNullOrEmpty()) - valD = *(double *)(val.GetDataBytesPointer()); - else - valD = NULL_VALUE_D; - ((AttrBuffer *)buffer)->Set(obj, valD); - break; - default: - break; - } -} - -types::TianmuValueObject TempTable::Attr::GetValue(int64_t obj, [[maybe_unused]] bool lookup_to_num) { - if (obj == common::NULL_VALUE_64) - return types::TianmuValueObject(); - types::TianmuValueObject ret; - if (ATI::IsStringType(TypeName())) { - types::BString s; - GetValueString(s, obj); - ret = s; - } else if (ATI::IsIntegerType(TypeName())) - ret = types::TianmuNum(GetValueInt64(obj), 0, false, common::ColumnType::NUM); - else if (ATI::IsDateTimeType(TypeName())) - ret = types::TianmuDateTime(this->GetValueInt64(obj), TypeName() /*, precision*/); - else if (ATI::IsRealType(TypeName())) - ret = types::TianmuNum(this->GetValueInt64(obj), 0, true); - else if (TypeName() == common::ColumnType::NUM) - ret = types::TianmuNum((int64_t)GetValueInt64(obj), Type().GetScale()); - else if (TypeName() == common::ColumnType::BIT) - ret = types::TianmuNum((int64_t)GetValueInt64(obj), Type().GetScale(), false, - TypeName()); // TODO(check prec & scale) - return ret; -} - -void TempTable::Attr::GetValueString(types::BString &value, int64_t obj) { - if (obj == common::NULL_VALUE_64) { - value = types::BString(); - return; - } - - switch (TypeName()) { - case common::ColumnType::BIN: - case common::ColumnType::BYTE: - case common::ColumnType::VARBYTE: - case common::ColumnType::STRING: - case common::ColumnType::VARCHAR: - case common::ColumnType::LONGTEXT: - (*(AttrBuffer *)buffer).GetString(value, obj); - break; - case common::ColumnType::BYTEINT: { - types::TianmuNum tianmu_n(static_cast((*(AttrBuffer *)buffer)[obj]), -1, false, TypeName()); - value = tianmu_n.GetValueInt64() == common::NULL_VALUE_64 ? types::BString() : tianmu_n.ToBString(); - break; - } - case common::ColumnType::SMALLINT: { - types::TianmuNum tianmu_n(static_cast((*(AttrBuffer *)buffer)[obj]), -1, false, TypeName()); - value = tianmu_n.GetValueInt64() == common::NULL_VALUE_64 ? types::BString() : tianmu_n.ToBString(); - break; - } - case common::ColumnType::INT: - case common::ColumnType::MEDIUMINT: { - types::TianmuNum tianmu_n(static_cast((*(AttrBuffer *)buffer)[obj]), -1, false, TypeName()); - value = tianmu_n.ValueInt() == common::NULL_VALUE_32 ? types::BString() : tianmu_n.ToBString(); - break; - } - case common::ColumnType::BIGINT: { - types::TianmuNum tianmu_n(static_cast((*(AttrBuffer *)buffer)[obj]), -1, false, TypeName()); - value = tianmu_n.GetValueInt64() == common::NULL_VALUE_64 ? types::BString() : tianmu_n.ToBString(); - break; - } - case common::ColumnType::NUM: { - types::TianmuNum tianmu_n((*(AttrBuffer *)buffer)[obj], Type().GetScale()); - value = tianmu_n.GetValueInt64() == common::NULL_VALUE_64 ? types::BString() : tianmu_n.ToBString(); - break; - } - case common::ColumnType::BIT: { - types::TianmuNum tianmu_n((*(AttrBuffer *)buffer)[obj], Type().GetScale(), false, TypeName()); - value = tianmu_n.GetValueInt64() == common::NULL_VALUE_64 ? types::BString() : tianmu_n.ToBString(); - break; - } - case common::ColumnType::YEAR: - case common::ColumnType::TIME: - case common::ColumnType::DATE: - case common::ColumnType::DATETIME: - case common::ColumnType::TIMESTAMP: { - types::TianmuDateTime tianmu_dt((*(AttrBuffer *)buffer)[obj], TypeName()); - if (TypeName() == common::ColumnType::TIMESTAMP) { - types::TianmuDateTime::AdjustTimezone(tianmu_dt); - } - if (tianmu_dt.GetInt64() == common::NULL_VALUE_64) { - value = types::BString(); - } else { - const types::BString &tianmu_dt_str = tianmu_dt.ToBString(); - size_t len = tianmu_dt_str.len_ > Type().GetPrecision() ? Type().GetPrecision() : tianmu_dt_str.len_; - value = types::BString(tianmu_dt_str.GetDataBytesPointer(), len, tianmu_dt_str.IsPersistent()); - } - break; - } - case common::ColumnType::REAL: - case common::ColumnType::FLOAT: { - double *d_p = &(*(AttrBuffer *)buffer)[obj]; - types::TianmuNum tianmu_n(static_cast(*d_p), 0, true, TypeName()); - value = tianmu_n.GetValueInt64() == common::NULL_VALUE_64 ? types::BString() : tianmu_n.ToBString(); - break; - } - default: - break; - } -} - -int64_t TempTable::Attr::GetSum(int pack, bool &nonnegative) { - DEBUG_ASSERT(ATI::IsNumericType(ct.GetTypeName())); - int64_t start = pack * (1 << no_power); - int64_t stop = (1 << no_power); - stop = stop > no_obj ? no_obj : stop; - if (not_complete || no_materialized < stop) - return common::NULL_VALUE_64; - int64_t sum = 0, val; - double sum_d = 0.0; - bool not_null_exists = false; - nonnegative = true; - for (int64_t i = start; i < stop; i++) { - if (!IsNull(i)) { - not_null_exists = true; - val = GetNotNullValueInt64(i); - nonnegative = nonnegative && (val >= 0); - if (ATI::IsRealType(ct.GetTypeName())) { - sum_d += *(double *)&val; - } else - sum += val; - } - } - if (ATI::IsRealType(ct.GetTypeName())) - sum = *(int64_t *)&sum_d; - return not_null_exists ? sum : common::NULL_VALUE_64; -} - -int64_t TempTable::Attr::GetNumOfNulls(int pack) { - if (not_complete) - return common::NULL_VALUE_64; - int64_t start; - int64_t stop; - if (pack == -1) { - start = 0; - stop = no_obj; - } else { - start = pack * (1 << no_power); - stop = (pack + 1) * (1 << no_power); - stop = stop > no_obj ? no_obj : stop; - } - if (no_materialized < stop) - return common::NULL_VALUE_64; - int64_t no_nulls = 0; - for (int64_t i = start; i < stop; i++) { - if (IsNull(i)) - no_nulls++; - } - return no_nulls; -} - -types::BString TempTable::Attr::GetMinString([[maybe_unused]] int pack) { - return types::BString(); // it should not touch data -} - -types::BString TempTable::Attr::GetMaxString([[maybe_unused]] int pack) { - return types::BString(); // it should not touch data -} - -int64_t TempTable::Attr::GetMaxInt64(int pack) { - if (not_complete) - return common::PLUS_INF_64; - int64_t start = (1 << no_power); - int64_t stop = (pack + 1) * (1 << no_power); - stop = stop > no_obj ? no_obj : stop; - if (no_materialized < stop) - return common::NULL_VALUE_64; - int64_t val, max = common::TIANMU_BIGINT_MIN; - for (int64_t i = start; i < stop; i++) { - if (!IsNull(i)) { - val = GetNotNullValueInt64(i); - if ((ATI::IsRealType(ct.GetTypeName()) && - (max == common::TIANMU_BIGINT_MIN || *(double *)&val > *(double *)&max)) || - (!ATI::IsRealType(ct.GetTypeName()) && val > max)) - max = val; - } - } - return (max == common::TIANMU_BIGINT_MIN ? common::PLUS_INF_64 : max); -} - -int64_t TempTable::Attr::GetMinInt64(int pack) { - if (not_complete) - return common::MINUS_INF_64; - int64_t start = pack * (1 << no_power); - int64_t stop = (pack + 1) * (1 << no_power); - stop = stop > no_obj ? no_obj : stop; - if (no_materialized < stop) - return common::NULL_VALUE_64; - int64_t val, min = common::TIANMU_BIGINT_MAX; - for (int64_t i = start; i < stop; i++) { - if (!IsNull(i)) { - val = GetNotNullValueInt64(i); - if ((ATI::IsRealType(ct.GetTypeName()) && - (min == common::TIANMU_BIGINT_MAX || *(double *)&val < *(double *)&min)) || - (!ATI::IsRealType(ct.GetTypeName()) && val < min)) - min = val; - } - } - return (min == common::TIANMU_BIGINT_MAX ? common::MINUS_INF_64 : min); -} - -int64_t TempTable::Attr::GetValueInt64(int64_t obj) const { - int64_t res = common::NULL_VALUE_64; - if (obj == common::NULL_VALUE_64) - return res; - switch (TypeName()) { - case common::ColumnType::BIGINT: - case common::ColumnType::NUM: - case common::ColumnType::YEAR: - case common::ColumnType::TIME: - case common::ColumnType::DATE: - case common::ColumnType::DATETIME: - case common::ColumnType::TIMESTAMP: - case common::ColumnType::BIT: - if (!IsNull(obj)) - res = (*(AttrBuffer *)buffer)[obj]; - break; - case common::ColumnType::INT: - case common::ColumnType::MEDIUMINT: - if (!IsNull(obj)) - res = (*(AttrBuffer *)buffer)[obj]; - break; - case common::ColumnType::SMALLINT: - if (!IsNull(obj)) - res = (*(AttrBuffer *)buffer)[obj]; - break; - case common::ColumnType::BYTEINT: - if (!IsNull(obj)) - res = (*(AttrBuffer *)buffer)[obj]; - break; - case common::ColumnType::STRING: - case common::ColumnType::VARCHAR: - DEBUG_ASSERT(0); - break; - case common::ColumnType::REAL: - case common::ColumnType::FLOAT: - if (!IsNull(obj)) - res = *(int64_t *)&(*(AttrBuffer *)buffer)[obj]; - else - res = *(int64_t *)&NULL_VALUE_D; - break; - case common::ColumnType::BIN: - case common::ColumnType::BYTE: - case common::ColumnType::VARBYTE: - case common::ColumnType::LONGTEXT: - DEBUG_ASSERT(0); - break; - default: - break; - } - return res; -} - -int64_t TempTable::Attr::GetNotNullValueInt64(int64_t obj) const { - int64_t res = common::NULL_VALUE_64; - switch (TypeName()) { - case common::ColumnType::INT: - case common::ColumnType::MEDIUMINT: - res = (*(AttrBuffer *)buffer)[obj]; - break; - case common::ColumnType::BYTEINT: - res = (*(AttrBuffer *)buffer)[obj]; - break; - case common::ColumnType::SMALLINT: - res = (*(AttrBuffer *)buffer)[obj]; - break; - case common::ColumnType::BIGINT: - case common::ColumnType::NUM: - case common::ColumnType::YEAR: - case common::ColumnType::TIME: - case common::ColumnType::DATE: - case common::ColumnType::DATETIME: - case common::ColumnType::TIMESTAMP: - case common::ColumnType::BIT: - res = (*(AttrBuffer *)buffer)[obj]; - break; - case common::ColumnType::REAL: - case common::ColumnType::FLOAT: - res = *(int64_t *)&(*(AttrBuffer *)buffer)[obj]; - break; - default: - DEBUG_ASSERT(0); - break; - } - return res; -} - -bool TempTable::Attr::IsNull(const int64_t obj) const { - if (obj == common::NULL_VALUE_64) - return true; - bool res = false; - switch (TypeName()) { - case common::ColumnType::INT: - case common::ColumnType::MEDIUMINT: - res = (*(AttrBuffer *)buffer)[obj] == common::NULL_VALUE_32; - break; - case common::ColumnType::BYTEINT: - res = (*(AttrBuffer *)buffer)[obj] == common::NULL_VALUE_C; - break; - case common::ColumnType::SMALLINT: - res = (*(AttrBuffer *)buffer)[obj] == common::NULL_VALUE_SH; - break; - case common::ColumnType::BIN: - case common::ColumnType::BYTE: - case common::ColumnType::VARBYTE: - case common::ColumnType::STRING: - case common::ColumnType::VARCHAR: - case common::ColumnType::LONGTEXT: - res = (*(AttrBuffer *)buffer)[obj].IsNull(); - break; - case common::ColumnType::BIGINT: - case common::ColumnType::NUM: - case common::ColumnType::YEAR: - case common::ColumnType::TIME: - case common::ColumnType::DATE: - case common::ColumnType::DATETIME: - case common::ColumnType::TIMESTAMP: - case common::ColumnType::BIT: - res = (*(AttrBuffer *)buffer)[obj] == common::NULL_VALUE_64; - break; - case common::ColumnType::REAL: - case common::ColumnType::FLOAT: { - common::double_int_t v((*(AttrBuffer *)buffer)[obj]); - res = v.i == common::NULL_VALUE_64; - break; - } - default: - break; - } - return res; -} - -void TempTable::Attr::ApplyFilter(MultiIndex &mind_, int64_t offset, int64_t last_index) { - DEBUG_ASSERT(mind_.NumOfDimensions() == 1); - - if (mind_.NumOfDimensions() != 1) - throw common::NotImplementedException("MultiIndex has too many dimensions."); - if (mind_.ZeroTuples() || no_obj == 0 || offset >= mind_.NumOfTuples()) { - DeleteBuffer(); - return; - } - - if (last_index > mind_.NumOfTuples()) - last_index = mind_.NumOfTuples(); - - void *old_buffer = buffer; - buffer = nullptr; - CreateBuffer(last_index - offset, mind_.m_conn); - - MIIterator mit(&mind_, mind_.ValueOfPower()); - for (int64_t i = 0; i < offset; i++) ++mit; - uint64_t idx = 0; - for (int64_t i = 0; i < last_index - offset; i++, ++mit) { - idx = mit[0]; - DEBUG_ASSERT(idx != static_cast(common::NULL_VALUE_64)); // null object should never appear - // in a materialized temp. table - switch (TypeName()) { - case common::ColumnType::INT: - case common::ColumnType::MEDIUMINT: - ((AttrBuffer *)buffer)->Set(i, (*(AttrBuffer *)old_buffer)[idx]); - break; - case common::ColumnType::BYTEINT: - ((AttrBuffer *)buffer)->Set(i, (*(AttrBuffer *)old_buffer)[idx]); - break; - case common::ColumnType::SMALLINT: - ((AttrBuffer *)buffer)->Set(i, (*(AttrBuffer *)old_buffer)[idx]); - break; - case common::ColumnType::STRING: - case common::ColumnType::VARCHAR: - case common::ColumnType::BIN: - case common::ColumnType::BYTE: - case common::ColumnType::VARBYTE: - case common::ColumnType::LONGTEXT: - ((AttrBuffer *)buffer)->Set(i, (*(AttrBuffer *)old_buffer)[idx]); - break; - case common::ColumnType::BIGINT: - case common::ColumnType::NUM: - case common::ColumnType::YEAR: - case common::ColumnType::TIME: - case common::ColumnType::DATE: - case common::ColumnType::DATETIME: - case common::ColumnType::TIMESTAMP: - case common::ColumnType::BIT: - ((AttrBuffer *)buffer)->Set(i, (*(AttrBuffer *)old_buffer)[idx]); - break; - case common::ColumnType::REAL: - case common::ColumnType::FLOAT: - ((AttrBuffer *)buffer)->Set(i, (*(AttrBuffer *)old_buffer)[idx]); - break; - default: - DEBUG_ASSERT(0); - break; - } - } - - switch (TypeName()) { - case common::ColumnType::INT: - case common::ColumnType::MEDIUMINT: - delete (AttrBuffer *)old_buffer; - break; - case common::ColumnType::BYTEINT: - delete (AttrBuffer *)old_buffer; - break; - case common::ColumnType::SMALLINT: - delete (AttrBuffer *)old_buffer; - break; - case common::ColumnType::STRING: - case common::ColumnType::VARCHAR: - case common::ColumnType::BIN: - case common::ColumnType::BYTE: - case common::ColumnType::VARBYTE: - case common::ColumnType::LONGTEXT: - delete (AttrBuffer *)old_buffer; - break; - case common::ColumnType::BIGINT: - case common::ColumnType::NUM: - case common::ColumnType::YEAR: - case common::ColumnType::TIME: - case common::ColumnType::DATE: - case common::ColumnType::DATETIME: - case common::ColumnType::TIMESTAMP: - case common::ColumnType::BIT: - delete (AttrBuffer *)old_buffer; - break; - case common::ColumnType::REAL: - case common::ColumnType::FLOAT: - delete (AttrBuffer *)old_buffer; - break; - default: - DEBUG_ASSERT(0); - break; - } -} - -// provide the best upper approximation of number of diff. values (incl. null) -uint64_t TempTable::Attr::ApproxDistinctVals([[maybe_unused]] bool incl_nulls, Filter *f, - [[maybe_unused]] common::RoughSetValue *rf, - [[maybe_unused]] bool outer_nulls_possible) { - // TODO: can it be done better? - if (f) - return f->NumOfOnes(); - - return no_obj; -} - -size_t TempTable::Attr::MaxStringSize([[maybe_unused]] Filter *f) // maximal byte std::string length in column -{ - uint res = ct.GetPrecision(); - if (ct.IsFixed()) - res = std::max(res, 21u); // max. numeric size ("-aaa.bbb") - else if (!ct.IsString()) - res = std::max(res, 23u); // max. size of datetime/double etc. - - return res; -} - -void TempTable::Attr::SetNewPageSize(uint new_page_size) { - if (buffer) { - switch (TypeName()) { - case common::ColumnType::INT: - case common::ColumnType::MEDIUMINT: - static_cast *>(buffer)->SetNewPageSize(new_page_size); - break; - case common::ColumnType::BYTEINT: - static_cast *>(buffer)->SetNewPageSize(new_page_size); - break; - case common::ColumnType::SMALLINT: - static_cast *>(buffer)->SetNewPageSize(new_page_size); - break; - case common::ColumnType::STRING: - case common::ColumnType::VARCHAR: - case common::ColumnType::BIN: - case common::ColumnType::BYTE: - case common::ColumnType::VARBYTE: - case common::ColumnType::LONGTEXT: - static_cast *>(buffer)->SetNewPageSize(new_page_size); - break; - case common::ColumnType::BIGINT: - case common::ColumnType::NUM: - case common::ColumnType::YEAR: - case common::ColumnType::TIME: - case common::ColumnType::DATE: - case common::ColumnType::DATETIME: - case common::ColumnType::TIMESTAMP: - static_cast *>(buffer)->SetNewPageSize(new_page_size); - break; - case common::ColumnType::REAL: - case common::ColumnType::FLOAT: - static_cast *>(buffer)->SetNewPageSize(new_page_size); - break; - default: - ASSERT(0, "Attr::SetNewPageSize: unrecognized type"); - break; - } - } - page_size = new_page_size; -} - -TempTable::TempTable(const TempTable &t, bool is_vc_owner) - : filter(t.filter), output_mind(t.output_mind), is_vc_owner(is_vc_owner), m_conn(t.m_conn) { - no_obj = t.no_obj; - materialized = t.materialized; - aliases = t.aliases; - group_by = t.group_by; - no_cols = t.no_cols; - mode = t.mode; - virt_cols = t.virt_cols; - virt_cols_for_having = t.virt_cols_for_having; - having_conds = t.having_conds; - tables = t.tables; - join_types = t.join_types; - order_by = t.order_by; - has_temp_table = t.has_temp_table; - lazy = t.lazy; - force_full_materialize = t.force_full_materialize; - no_materialized = t.no_materialized; - no_global_virt_cols = int(t.virt_cols.size()); - for (uint i = 0; i < t.attrs.size(); i++) { - attrs.push_back(new Attr(*t.attrs[i])); - } - is_sent = t.is_sent; - mem_scale = t.mem_scale; - rough_is_empty = t.rough_is_empty; - p_power = t.p_power; - size_of_one_record = 0; -} - -TempTable::~TempTable() { - MEASURE_FET("TempTable::~TempTable(...)"); - // remove all temporary tables used by *this - // but only if *this should manage those tables - if (is_vc_owner) { - for (uint i = 0; i < virt_cols.size(); i++) delete virt_cols[i]; - } else { - TranslateBackVCs(); - for (uint i = no_global_virt_cols; i < virt_cols.size(); i++) delete virt_cols[i]; - } - - for (uint i = 0; i < attrs.size(); i++) { - delete attrs[i]; - } -} - -void TempTable::TranslateBackVCs() { - for (int i = 0; i < no_global_virt_cols; i++) - if (virt_cols[i] && static_cast(virt_cols[i]->IsSingleColumn())) - static_cast(virt_cols[i])->TranslateSourceColumns(attr_back_translation); -} - -std::shared_ptr TempTable::CreateMaterializedCopy(bool translate_order, - bool in_subq) // move all buffers to a newly created - // TempTable, make this VC-pointing to - // it; the new table must be deleted - // by DeleteMaterializedCopy() -{ - MEASURE_FET("TempTable::CreateMaterializedCopy(...)"); - // Copy buffers in a safe place for a moment - std::vector copy_buf; - std::map attr_translation; // new attr (this), old attr (working_copy) - for (uint i = 0; i < attrs.size(); i++) { - copy_buf.push_back(attrs[i]->buffer); - attrs[i]->buffer = nullptr; - } - if (no_global_virt_cols != -1) { - // this is a TempTable copy - for (uint i = no_global_virt_cols; i < virt_cols.size(); i++) { - delete virt_cols[i]; - virt_cols[i] = nullptr; - } - virt_cols.resize(no_global_virt_cols); - } - std::shared_ptr working_copy = Create(*this, in_subq); // Original VCs of this will be copied to - // working_copy, and then deleted in its - // destructor - for (uint i = 0; i < attrs.size(); i++) { - attrs[i]->mode = common::ColOperation::LISTING; - } - working_copy->mode = TableMode(); // reset all flags (distinct, limit) on copy - // working_copy->for_subq = this->for_subq; - // working_copy->no_global_virt_cols = this->no_global_virt_cols; - for (uint i = 0; i < attrs.size(); i++) { - working_copy->attrs[i]->buffer = copy_buf[i]; // copy the data buffers - attrs[i]->no_obj = 0; - attr_translation[attrs[i]] = working_copy->attrs[i]; - } - // VirtualColumns are copied, and we should replace them by references to the - // temporary source - delete filter.mind_; - filter.mind_ = new MultiIndex(p_power); - filter.mind_->AddDimension_cross(no_obj); - if (virt_cols.size() < attrs.size()) - virt_cols.resize(attrs.size()); - fill(virt_cols.begin(), virt_cols.end(), (vcolumn::VirtualColumn *)nullptr); - for (uint i = 0; i < attrs.size(); i++) { - vcolumn::VirtualColumn *new_vc = - new vcolumn::SingleColumn(working_copy->attrs[i], filter.mind_, 0, 0, working_copy.get(), 0); - virt_cols[i] = new_vc; - attrs[i]->term.vc = new_vc; - attrs[i]->dim = 0; - } - if (translate_order) { - order_by.clear(); // translation needed: virt_cols should point to - // working_copy as a data source - for (uint i = 0; i < working_copy->virt_cols.size(); i++) { - vcolumn::VirtualColumn *orig_vc = working_copy->virt_cols[i]; - // if(in_subq && orig_vc->IsSingleColumn()) - // working_copy->virt_cols[i] = - // CreateVCCopy(working_copy->virt_cols[i]); - for (uint j = 0; j < working_copy->order_by.size(); j++) { - if (working_copy->order_by[j].vc == orig_vc) { - working_copy->order_by[j].vc = working_copy->virt_cols[i]; - } - } - // TODO: redesign it for more universal solution - vcolumn::VirtualColumn *vc = working_copy->virt_cols[i]; - if (vc) { - if (static_cast(vc->IsSingleColumn())) - static_cast(vc)->TranslateSourceColumns(attr_translation); - else { - auto &var_maps = vc->GetVarMap(); - for (uint i = 0; i < var_maps.size(); i++) { - if (var_maps[i].just_a_table.lock().get() == this) - var_maps[i].just_a_table = working_copy; - } - } - } - } - for (uint i = 0; i < working_copy->order_by.size(); i++) { - SortDescriptor sord; - sord.vc = working_copy->order_by[i].vc; - sord.dir = working_copy->order_by[i].dir; - order_by.push_back(sord); - } - } else { // Create() did move vc's used in order_by into working_copy, so we - // should bring them back - for (uint i = 0; i < order_by.size(); i++) { - // find which working_copy->vc is used in ordering - for (uint j = 0; j < working_copy->virt_cols.size(); j++) { - if (/*working_copy->*/ order_by[i].vc == working_copy->virt_cols[j]) { - // order_by[i].vc = working_copy->virt_cols[j]; - MoveVC(j, working_copy->virt_cols, - virt_cols); // moving vc - now it is back in this - break; - } - } - } - } - no_global_virt_cols = (int)virt_cols.size(); - return working_copy; // must be deleted by DeleteMaterializedCopy() -} - -void TempTable::DeleteMaterializedCopy(std::shared_ptr &old_t) // delete the external table and remove - // VC pointers, make this fully - // materialized -{ - MEASURE_FET("TempTable::DeleteMaterializedCopy(...)"); - for (uint i = 0; i < attrs.size(); i++) { // Make sure VCs are deleted before the source table is deleted - attrs[i]->term.vc = nullptr; - delete virt_cols[i]; - virt_cols[i] = nullptr; - } - old_t.reset(); -} - -void TempTable::MoveVC(int colnum, std::vector &from, - std::vector &to) { - vcolumn::VirtualColumn *vc = from[colnum]; - to.push_back(vc); - from[colnum] = nullptr; - std::vector vv = vc->GetChildren(); - for (size_t i = 0; i < vv.size(); i++) MoveVC(vv[i], from, to); -} - -void TempTable::MoveVC(vcolumn::VirtualColumn *vc, std::vector &from, - std::vector &to) { - for (int k = 0; (size_t)k < from.size(); k++) - if (vc == from[k]) { - MoveVC(k, from, to); - break; - } -} - -void TempTable::ReserveVirtColumns(int no) { - DEBUG_ASSERT((no == 0 && virt_cols.size() == 0) || static_cast(no) > virt_cols.size()); - no_global_virt_cols = -1; // usable value only in TempTable copies and in subq - virt_cols.resize(no); - virt_cols_for_having.resize(no); -} - -void TempTable::CreateDisplayableAttrP() { - if (attrs.size() == 0) - return; - displayable_attr.clear(); - displayable_attr.resize(attrs.size()); - int idx = 0; - for (size_t i = 0; i < attrs.size(); i++) { - if (attrs[i]->alias) { - displayable_attr[idx] = attrs[i]; - idx++; - } - } - for (uint i = idx; i < attrs.size(); i++) displayable_attr[i] = nullptr; -} - -uint TempTable::GetDisplayableAttrIndex(uint attr) { - uint idx = -1; - uint i; - for (i = 0; i < attrs.size(); i++) - if (attrs[i]->alias) { - idx++; - if (idx == attr) - break; - } - DEBUG_ASSERT(i < attrs.size()); - return i; -} - -void TempTable::AddConds(Condition *cond, CondType type) { - MEASURE_FET("TempTable::AddConds(...)"); - switch (type) { - case CondType::WHERE_COND: { - // need to add one by one since where_conds can be non-empty - filter.AddConditions(cond, CondType::WHERE_COND); - break; - } - - case CondType::HAVING_COND: { - Descriptor &desc = cond->operator[](0); - DEBUG_ASSERT(desc.tree); - having_conds.AddDescriptor(desc.tree, this, desc.left_dims.Size()); - break; - } - - default: - DEBUG_ASSERT(0); - } -} - -void TempTable::AddInnerConds(Condition *cond, std::vector &dim_aliases) { - for (uint i = 0; i < cond->Size(); i++) - for (uint j = 0; j < dim_aliases.size(); j++) (*cond)[i].left_dims[GetDimension(dim_aliases[j])] = true; - filter.AddConditions(cond, CondType::ON_INNER_FILTER); -} - -void TempTable::AddLeftConds(Condition *cond, std::vector &left_aliases, std::vector &right_aliases) { - for (uint i = 0; i < cond->Size(); i++) { - for (int d = 0; d < (*cond)[i].left_dims.Size(); d++) (*cond)[i].left_dims[d] = (*cond)[i].right_dims[d] = false; - for (uint j = 0; j < left_aliases.size(); j++) (*cond)[i].left_dims[GetDimension(left_aliases[j])] = true; - for (uint j = 0; j < right_aliases.size(); j++) (*cond)[i].right_dims[GetDimension(right_aliases[j])] = true; - } - filter.AddConditions(cond, CondType::ON_LEFT_FILTER); -} - -void TempTable::SetMode(TMParameter mode, int64_t mode_param1, int64_t mode_param2) { - switch (mode) { - case TMParameter::TM_DISTINCT: - this->mode.distinct = true; - break; - case TMParameter::TM_TOP: - this->mode.top = true; - this->mode.param1 = mode_param1; // offset - this->mode.param2 = mode_param2; // limit - break; - case TMParameter::TM_EXISTS: - this->mode.exists = true; - break; - default: - DEBUG_ASSERT(false); - break; - } -} - -int TempTable::AddColumn(CQTerm e, common::ColOperation mode, char *alias, bool distinct, SI si) { - if (alias) - no_cols++; - common::ColumnType type = common::ColumnType::UNK; // type of column - bool notnull = false; // NULLs are allowed - uint scale = 0; // number of decimal places - uint precision = 0; // number of all places - - // new code for vcolumn::VirtualColumn - if (e.vc_id != common::NULL_VALUE_32) { - DEBUG_ASSERT(e.vc); - // enum common::ColOperation {LISTING, COUNT, SUM, MIN, MAX, AVG, GROUP_BY}; - if (mode == common::ColOperation::COUNT) { - type = common::ColumnType::NUM; // 64 bit, Decimal(18,0) - precision = 18; - notnull = true; - } else if (mode == common::ColOperation::BIT_AND || mode == common::ColOperation::BIT_OR || - mode == common::ColOperation::BIT_XOR) { - type = common::ColumnType::BIGINT; - precision = 19; - notnull = true; - } else if (mode == common::ColOperation::AVG || mode == common::ColOperation::VAR_POP || - mode == common::ColOperation::VAR_SAMP || mode == common::ColOperation::STD_POP || - mode == common::ColOperation::STD_SAMP) { - type = common::ColumnType::REAL; // 64 bit - precision = 18; - } else { - scale = e.vc->Type().GetScale(); - precision = e.vc->Type().GetPrecision(); - type = e.vc->TypeName(); - notnull = e.vc->Type().NotNull(); - if (mode == common::ColOperation::SUM) { - switch (e.vc->TypeName()) { - case common::ColumnType::INT: - case common::ColumnType::NUM: - case common::ColumnType::SMALLINT: - case common::ColumnType::BYTEINT: - case common::ColumnType::MEDIUMINT: - type = common::ColumnType::NUM; - precision = 18; - break; - case common::ColumnType::BIGINT: - case common::ColumnType::BIT: - type = common::ColumnType::BIGINT; - precision = 19; - break; - case common::ColumnType::REAL: - case common::ColumnType::FLOAT: - default: // all other types summed up as double (parsed from text) - type = common::ColumnType::REAL; - break; - // default: - // throw - // common::NotImplementedException("SUM - // performed on non-numerical column."); - } - } else if (mode == common::ColOperation::MIN || mode == common::ColOperation::MAX) { - } else if (mode == common::ColOperation::LISTING || mode == common::ColOperation::GROUP_BY) { - if (mode == common::ColOperation::GROUP_BY) - group_by = true; - notnull = e.vc->Type().NotNull(); - } - } - } else if (mode == common::ColOperation::COUNT) { - type = common::ColumnType::NUM; - precision = 18; - notnull = true; - } else { - // illegal execution path: neither VC is set nor mode is - // common::ColOperation::COUNT - DEBUG_ASSERT(!"wrong execution path"); - // throw common::NotImplementedException("Invalid column on SELECT list."); - } - - attrs.push_back(new Attr(e, mode, p_power, distinct, alias, -2, type, scale, precision, notnull, - e.vc ? e.vc->GetCollation() : DTCollation(), &si)); - return -(int)attrs.size(); // attributes are counted from -1, -2, ... -} - -void TempTable::AddOrder(vcolumn::VirtualColumn *vc, int direction) { - // don't sort by const expressions - if (vc->IsConst()) - return; - SortDescriptor d; - d.vc = vc; - d.dir = direction; - bool already_added = false; - for (uint j = 0; j < order_by.size(); j++) { - if (order_by[j] == d) { - already_added = true; - break; - } - } - if (!already_added) - order_by.push_back(d); -} - -void TempTable::Union(TempTable *t, int all) { - MEASURE_FET("TempTable::UnionOld(...)"); - if (!t) { // trivial union with single select and external order by - this->Materialize(); - return; - } - DEBUG_ASSERT(NumOfDisplaybleAttrs() == t->NumOfDisplaybleAttrs()); - if (NumOfDisplaybleAttrs() != t->NumOfDisplaybleAttrs()) - throw common::NotImplementedException("UNION of tables with different number of columns."); - if (this->IsParametrized() || t->IsParametrized()) - throw common::NotImplementedException("Materialize: not implemented union of parameterized queries."); - tianmu_control_.lock(m_conn->GetThreadID()) << "UNION: materializing components." << system::unlock; - this->Materialize(); - t->Materialize(); - if ((!t->NumOfObj() && all) || (!this->NumOfObj() && !t->NumOfObj())) // no objects = no union - return; - - Filter first_f(NumOfObj(), p_power), first_mask(NumOfObj(), - p_power); // mask of objects to be added to the final result set - Filter sec_f(t->NumOfObj(), p_power), sec_mask(t->NumOfObj(), p_power); - first_mask.Set(); - sec_mask.Set(); - if (!all) { - tianmu_control_.lock(m_conn->GetThreadID()) << "UNION: excluding repetitions." << system::unlock; - Filter first_f(NumOfObj(), p_power); - first_f.Set(); - Filter sec_f(t->NumOfObj(), p_power); - sec_f.Set(); - GroupDistinctTable dist_table(p_power); - using vc_ptr_t = std::shared_ptr; - std::vector first_vcs; - std::vector sec_vcs; - uchar *input_buf = nullptr; - { - // block to ensure deleting encoder before deleting first_vcs, sec_vcs - int size = 0; - std::vector encoder; - for (int i = 0; i < (int)NumOfDisplaybleAttrs(); i++) { - first_vcs.push_back( - vc_ptr_t(new vcolumn::SingleColumn(GetDisplayableAttrP(i), &output_mind, 0, -i - 1, this, 0))); - sec_vcs.push_back( - vc_ptr_t(new vcolumn::SingleColumn(t->GetDisplayableAttrP(i), t->GetOutputMultiIndexP(), 1, -i - 1, t, 0))); - encoder.push_back(ColumnBinEncoder()); - bool encoder_created; - if (NumOfObj() == 0) - encoder_created = encoder[i].PrepareEncoder(sec_vcs[i].get()); - else if (t->NumOfObj() == 0) - encoder_created = encoder[i].PrepareEncoder(first_vcs[i].get()); - else - encoder_created = encoder[i].PrepareEncoder(first_vcs[i].get(), sec_vcs[i].get()); - if (!encoder_created) { - std::stringstream ss; - ss << "UNION of non-matching columns (column no " << i << ") ."; - throw common::NotImplementedException(ss.str()); - } - encoder[i].SetPrimaryOffset(size); - size += encoder[i].GetPrimarySize(); - } - input_buf = new uchar[size]; - dist_table.InitializeB(size, NumOfObj() + t->NumOfObj() / 2); // optimization assumption: a - // half of values in the second - // table will be repetitions - MIIterator first_mit(&output_mind, p_power); - MIIterator sec_mit(t->GetOutputMultiIndexP(), p_power); - // check all objects from the first table - do { - first_mit.Rewind(); - dist_table.Clear(); - while (first_mit.IsValid()) { - int64_t pos = **first_mit; - if (first_f.Get(pos)) { - for (uint i = 0; i < encoder.size(); i++) encoder[i].Encode(input_buf, first_mit); - GDTResult res = dist_table.Add(input_buf); - if (res == GDTResult::GDT_EXISTS) - first_mask.ResetDelayed(pos); - if (res != GDTResult::GDT_FULL) // note: if v is omitted here, it will also be - // omitted in sec! - first_f.ResetDelayed(pos); - } - ++first_mit; - if (m_conn->Killed()) - throw common::KilledException(); - } - sec_mit.Rewind(); - while (sec_mit.IsValid()) { - int64_t pos = **sec_mit; - if (sec_f.Get(pos)) { - for (uint i = 0; i < encoder.size(); i++) encoder[i].Encode(input_buf, sec_mit, sec_vcs[i].get()); - GDTResult res = dist_table.Add(input_buf); - if (res == GDTResult::GDT_EXISTS) - sec_mask.ResetDelayed(pos); - if (res != GDTResult::GDT_FULL) - sec_f.ResetDelayed(pos); - } - ++sec_mit; - if (m_conn->Killed()) - throw common::KilledException(); - } - first_f.Commit(); - sec_f.Commit(); - first_mask.Commit(); - sec_mask.Commit(); - } while (!first_f.IsEmpty() || !sec_f.IsEmpty()); - } - delete[] input_buf; - } - int64_t first_no_obj = first_mask.NumOfOnes(); - int64_t sec_no_obj = sec_mask.NumOfOnes(); - int64_t new_no_obj = first_no_obj + sec_no_obj; - tianmu_control_.lock(m_conn->GetThreadID()) - << "UNION: generating result (" << new_no_obj << " rows)." << system::unlock; - uint new_page_size = CalculatePageSize(new_no_obj); - for (uint i = 0; i < NumOfDisplaybleAttrs(); i++) { - Attr *first_attr = GetDisplayableAttrP(i); - Attr *sec_attr = t->GetDisplayableAttrP(i); - ColumnType new_type = GetUnionType(first_attr->Type(), sec_attr->Type()); - if (first_attr->Type() == sec_attr->Type() && first_mask.IsFull() && first_no_obj && sec_no_obj && - first_attr->Type().GetPrecision() >= sec_attr->Type().GetPrecision()) { - // fast path of execution: do not modify first buffer - SetPageSize(new_page_size); - FilterOnesIterator sec_fi(&sec_mask, p_power); - for (int64_t j = 0; j < sec_no_obj; j++) { - types::BString s; - if (ATI::IsStringType(first_attr->TypeName())) { - sec_attr->GetValueString(s, *sec_fi); - first_attr->SetValueString(first_no_obj + j, s); - } else { - first_attr->SetValueInt64(first_no_obj + j, sec_attr->GetValueInt64(*sec_fi)); - } - ++sec_fi; - } - continue; - } - Attr *new_attr = - new Attr(CQTerm(), common::ColOperation::LISTING, p_power, false, first_attr->alias, 0, new_type.GetTypeName(), - new_type.GetScale(), new_type.GetPrecision(), new_type.NotNull(), new_type.GetCollation()); - new_attr->page_size = new_page_size; - new_attr->CreateBuffer(new_no_obj, m_conn); - if (first_attr->TypeName() == common::ColumnType::NUM && sec_attr->TypeName() == common::ColumnType::NUM && - first_attr->Type().GetScale() != sec_attr->Type().GetScale()) { - uint max_scale = new_attr->Type().GetScale(); - // copy attr from first table to new_attr - double multiplier = types::PowOfTen(max_scale - first_attr->Type().GetScale()); - FilterOnesIterator first_fi(&first_mask, p_power); - for (int64_t j = 0; j < first_no_obj; j++) { - int64_t pos = *first_fi; - ++first_fi; - if (!first_attr->IsNull(pos)) - new_attr->SetValueInt64(j, first_attr->GetNotNullValueInt64(pos) * (int64_t)multiplier); - else - new_attr->SetValueInt64(j, common::NULL_VALUE_64); - } - // copy attr from second table to new_attr - multiplier = types::PowOfTen(max_scale - sec_attr->Type().GetScale()); - FilterOnesIterator sec_fi(&sec_mask, p_power); - for (int64_t j = 0; j < sec_no_obj; j++) { - int64_t pos = *sec_fi; - ++sec_fi; - if (!sec_attr->IsNull(pos)) - new_attr->SetValueInt64(first_no_obj + j, sec_attr->GetNotNullValueInt64(pos) * (int64_t)multiplier); - else - new_attr->SetValueInt64(first_no_obj + j, common::NULL_VALUE_64); - } - } else if (ATI::IsStringType(new_attr->TypeName())) { - types::BString s; - FilterOnesIterator first_fi(&first_mask, p_power); - for (int64_t j = 0; j < first_no_obj; j++) { - first_attr->GetValueString(s, *first_fi); - new_attr->SetValueString(j, s); - ++first_fi; - } - FilterOnesIterator sec_fi(&sec_mask, p_power); - for (int64_t j = 0; j < sec_no_obj; j++) { - sec_attr->GetValueString(s, *sec_fi); - new_attr->SetValueString(first_no_obj + j, s); - ++sec_fi; - } - } else if (new_attr->Type().IsFloat()) { - FilterOnesIterator first_fi(&first_mask, p_power); - for (int64_t j = 0; j < first_no_obj; j++) { - int64_t pos = *first_fi; - ++first_fi; - if (first_attr->IsNull(pos)) - new_attr->SetValueInt64(j, common::NULL_VALUE_64); - else if (first_attr->Type().IsFloat()) - new_attr->SetValueInt64(j, first_attr->GetNotNullValueInt64(pos)); - else { - double v = (double)first_attr->GetNotNullValueInt64(pos) / types::PowOfTen(first_attr->Type().GetScale()); - new_attr->SetValueInt64(j, *(int64_t *)&v); - } - } - FilterOnesIterator sec_fi(&sec_mask, p_power); - for (int64_t j = 0; j < sec_no_obj; j++) { - int64_t pos = *sec_fi; - ++sec_fi; - if (sec_attr->IsNull(pos)) - new_attr->SetValueInt64(first_no_obj + j, common::NULL_VALUE_64); - else if (sec_attr->Type().IsFloat()) - new_attr->SetValueInt64(first_no_obj + j, sec_attr->GetNotNullValueInt64(pos)); - else { - double v = (double)sec_attr->GetNotNullValueInt64(pos) / types::PowOfTen(sec_attr->Type().GetScale()); - new_attr->SetValueInt64(first_no_obj + j, *(int64_t *)&v); - } - } - } else { - // copy attr from first table to new_attr - double multiplier = types::PowOfTen(new_attr->Type().GetScale() - first_attr->Type().GetScale()); - FilterOnesIterator first_fi(&first_mask, p_power); - for (int64_t j = 0; j < first_no_obj; j++) { - int64_t pos = *first_fi; - ++first_fi; - if (first_attr->IsNull(pos)) - new_attr->SetValueInt64(j, common::NULL_VALUE_64); - else if (multiplier == 1.0) // do not multiply by 1.0, as it causes - // precision problems on bigint - new_attr->SetValueInt64(j, first_attr->GetNotNullValueInt64(pos)); - else - new_attr->SetValueInt64(j, (int64_t)(first_attr->GetNotNullValueInt64(pos) * multiplier)); - } - multiplier = types::PowOfTen(new_attr->Type().GetScale() - sec_attr->Type().GetScale()); - FilterOnesIterator sec_fi(&sec_mask, p_power); - for (int64_t j = 0; j < sec_no_obj; j++) { - int64_t pos = *sec_fi; - ++sec_fi; - if (sec_attr->IsNull(pos)) - new_attr->SetValueInt64(first_no_obj + j, common::NULL_VALUE_64); - else if (multiplier == 1.0) // do not multiply by 1.0, as it causes - // precision problems on bigint - new_attr->SetValueInt64(first_no_obj + j, sec_attr->GetNotNullValueInt64(pos)); - else - new_attr->SetValueInt64(first_no_obj + j, (int64_t)(sec_attr->GetNotNullValueInt64(pos) * multiplier)); - } - } - attrs[GetDisplayableAttrIndex(i)] = new_attr; - displayable_attr[i] = new_attr; - delete first_attr; - } - SetNumOfMaterialized(new_no_obj); - // this->no_obj = new_no_obj; - // this->Display(); - output_mind.Clear(); - output_mind.AddDimension_cross(no_obj); -} - -void TempTable::Union(TempTable *t, [[maybe_unused]] int all, ResultSender *sender, int64_t &g_offset, - int64_t &g_limit) { - MEASURE_FET("TempTable::UnionSender(...)"); - - DEBUG_ASSERT(NumOfDisplaybleAttrs() == t->NumOfDisplaybleAttrs()); - if (NumOfDisplaybleAttrs() != t->NumOfDisplaybleAttrs()) - throw common::NotImplementedException("UNION of tables with different number of columns."); - if (this->IsParametrized() || t->IsParametrized()) - throw common::NotImplementedException("Materialize: not implemented union of parameterized queries."); - - if (mode.top) { - if (g_offset != 0 || g_limit != -1) { - mode.param2 = std::min(g_offset + g_limit, mode.param2); - } - } else if (g_offset != 0 || g_limit != -1) { - mode.top = true; - mode.param1 = 0; - mode.param2 = g_limit + g_offset; - } - - if (g_offset != 0 || g_limit != -1) - sender->SetLimits(&g_offset, &g_limit); - this->Materialize(false, sender); - if (this->IsMaterialized() && !this->IsSent()) - sender->Send(this); - - if (t->mode.top) { - if (g_offset != 0 || g_limit != -1) { - t->mode.param2 = std::min(g_offset + g_limit, t->mode.param2); - } - } else if (g_offset != 0 || g_limit != -1) { - t->mode.top = true; - t->mode.param1 = 0; - t->mode.param2 = g_limit + g_offset; - } - - // second query might want to switch to mysql but the first is already sent - // we have to prevent switching to mysql otherwise Malformed Packet error may - // occur - try { - t->Materialize(false, sender); - } catch (common::Exception &e) { - std::string msg(e.what()); - msg.append(" Can't switch to MySQL execution path"); - throw common::InternalException(msg); - } - if (t->IsMaterialized() && !t->IsSent()) - sender->Send(t); -} - -void TempTable::Display(std::ostream &out) { - out << "No obj.:" << no_obj << ", No attrs.:" << this->NumOfDisplaybleAttrs() << system::endl - << "-----------" << system::endl; - for (int64_t i = 0; i < no_obj; i++) { - for (uint j = 0; j < this->NumOfDisplaybleAttrs(); j++) { - if (!attrs[j]->alias) - continue; - if (!IsNull(i, j)) { - types::BString s; - GetTable_S(s, i, j); - out << s << " "; - } else - out << "nullptr" - << " "; - } - out << system::endl; - } - out << "-----------" << system::endl; -} - -int TempTable::GetDimension(TabID alias) { - for (uint i = 0; i < aliases.size(); i++) { - if (aliases[i] == alias.n) - return i; - } - return common::NULL_VALUE_32; -} - -int64_t TempTable::GetTable64(int64_t obj, int attr) { - if (no_obj == 0) - return common::NULL_VALUE_64; - DEBUG_ASSERT(obj < no_obj && (uint)attr < attrs.size()); - return attrs[attr]->GetValueInt64(obj); -} - -void TempTable::GetTable_S(types::BString &s, int64_t obj, int _attr) { - if (no_obj == 0) { - s = types::BString(); - return; - } - uint attr = (uint)_attr; - DEBUG_ASSERT(obj < no_obj && attr < attrs.size()); - attrs[attr]->GetValueString(s, obj); -} - -bool TempTable::IsNull(int64_t obj, int attr) { - if (no_obj == 0) - return true; - DEBUG_ASSERT(obj < no_obj && (uint)attr < attrs.size()); - return attrs[attr]->IsNull(obj); -} - -void TempTable::SuspendDisplay() { m_conn->SuspendDisplay(); } - -void TempTable::ResumeDisplay() { m_conn->ResumeDisplay(); } - -uint64_t TempTable::ApproxAnswerSize([[maybe_unused]] int attr, - [[maybe_unused]] Descriptor &d) // provide the most probable - // approximation of number of objects - // matching the condition -{ - // TODO: can it be done better? - return no_obj / 2; -} - -void TempTable::GetTableString(types::BString &s, int64_t obj, uint attr) { - if (no_obj == 0) - s = types::BString(); - DEBUG_ASSERT(obj < no_obj && (uint)attr < attrs.size()); - attrs[attr]->GetValueString(s, obj); -} - -types::TianmuValueObject TempTable::GetValueObject(int64_t obj, uint attr) { - if (no_obj == 0) - return types::TianmuValueObject(); - DEBUG_ASSERT(obj < no_obj && (uint)attr < attrs.size()); - return attrs[attr]->GetValue(obj); -} - -uint TempTable::CalculatePageSize(int64_t _no_obj) { - int64_t new_no_obj = _no_obj == -1 ? no_obj : _no_obj; - uint size_of_one_record = 0; - for (uint i = 0; i < attrs.size(); i++) - if (attrs[i]->TypeName() == common::ColumnType::BIN || attrs[i]->TypeName() == common::ColumnType::BYTE || - attrs[i]->TypeName() == common::ColumnType::VARBYTE || attrs[i]->TypeName() == common::ColumnType::LONGTEXT || - attrs[i]->TypeName() == common::ColumnType::STRING || attrs[i]->TypeName() == common::ColumnType::VARCHAR) - size_of_one_record += attrs[i]->Type().GetInternalSize() + 4; // 4 bytes describing length - else - size_of_one_record += attrs[i]->Type().GetInternalSize(); - uint raw_size = (uint)new_no_obj; - if (size_of_one_record < 1) - size_of_one_record = 1; - - SetOneOutputRecordSize(size_of_one_record); - uint64_t cache_size; - if (mem_scale == -1) - mem_scale = mm::TraceableObject::MemorySettingsScale(); - - switch (mem_scale) { - case 0: - case 1: - cache_size = 1l << 26; - break; // 64MB - case 2: - cache_size = 1l << 27; - break; // 128MB - case 3: - case 4: - cache_size = 1l << 28; - break; // 256MB - case 5: - cache_size = 1l << 29; - break; // 512MB - case 6: - cache_size = 1l << 30; - break; // 1GB - case 7: - case 8: - cache_size = 1l << 31; - break; // 2GB - default: - cache_size = 1l << 31; - break; // heap larger than 40GB-> 2GB Cache size - } - // std::cerr << "cs=" << cache_size << std::endl; - - if (cache_size / size_of_one_record <= (uint64_t)new_no_obj) { - raw_size = uint((cache_size - 1) / size_of_one_record); // minus 1 to avoid overflow - } - if (raw_size < 1) - raw_size = 1; - for (uint i = 0; i < attrs.size(); i++) attrs[i]->page_size = raw_size; - return raw_size; -} - -void TempTable::SetPageSize(int64_t new_page_size) { - for (uint i = 0; i < attrs.size(); i++) attrs[i]->SetNewPageSize((uint)new_page_size); -} - -/*! Filter out rows from the given multiindex according to the tree of - * descriptors - * - */ - -void TempTable::DisplayRSI() { - for (uint i = 0; i < tables.size(); i++) { - if (tables[i]->TableType() == TType::TABLE) - ((TianmuTable *)tables[i])->DisplayRSI(); - } -} - -// Refactoring: extracted methods - -void TempTable::RemoveFromManagedList(const TianmuTable *tab) { - tables.erase(std::remove(tables.begin(), tables.end(), tab), tables.end()); -} - -void TempTable::ApplyOffset(int64_t limit, int64_t offset) { - // filter out all unwanted values from buffers - no_obj = limit; - for (uint i = 0; i < attrs.size(); i++) { - if (attrs[i]->alias) - attrs[i]->ApplyFilter(output_mind, offset, offset + limit); - else - attrs[i]->DeleteBuffer(); - } -} - -void TempTable::ProcessParameters(const MIIterator &mit, const int alias) { - MEASURE_FET("TempTable::ProcessParameters(...)"); - for (uint i = 0; i < virt_cols.size(); i++) virt_cols[i]->RequestEval(mit, alias); - filter.ProcessParameters(); - // filter.Prepare(); - if (mode.top && LimitMayBeAppliedToWhere()) // easy case - apply limits - filter.UpdateMultiIndex(false, (mode.param2 >= 0 ? mode.param2 : 0)); - else - filter.UpdateMultiIndex(false, -1); -} - -void TempTable::RoughProcessParameters(const MIIterator &mit, const int alias) { - MEASURE_FET("TempTable::RoughProcessParameters(...)"); - for (uint i = 0; i < virt_cols.size(); i++) virt_cols[i]->RequestEval(mit, alias); - filter.ProcessParameters(); - filter.RoughUpdateParamFilter(); -} - -bool TempTable::IsParametrized() { - for (uint i = 0; i < virt_cols.size(); i++) - if (virt_cols[i] && virt_cols[i]->IsParameterized()) - return true; - return false; -} - -int TempTable::DimInDistinctContext() { - // return a dimension number if it is used only in contexts where row - // repetitions may be omitted, e.g. distinct - int d = -1; - if (HasHavingConditions() || filter.mind_->NumOfDimensions() == 1) // having or no joins - return -1; - bool group_by_exists = false; - bool aggregation_exists = false; - for (uint i = 0; i < attrs.size(); i++) - if (attrs[i]) { - if (attrs[i]->mode == common::ColOperation::GROUP_BY) - group_by_exists = true; - if (attrs[i]->mode != common::ColOperation::GROUP_BY && attrs[i]->mode != common::ColOperation::LISTING && - attrs[i]->mode != common::ColOperation::DELAYED) - aggregation_exists = true; - if (!attrs[i]->term.vc || attrs[i]->term.vc->IsConst()) - continue; - int local_dim = attrs[i]->term.vc->GetDim(); - if (local_dim == -1 || (d != -1 && d != local_dim)) - return -1; - d = local_dim; - } - // all columns are based on the same dimension - if (group_by_exists && aggregation_exists) // group by with aggregations - not distinct context - return -1; - if (group_by_exists || (mode.distinct && !aggregation_exists)) // select distinct a,b,c...; - // select a,b,c group by a,b,c - return d; - // aggregations exist - check their type - for (uint i = 0; i < attrs.size(); i++) - if (attrs[i] && attrs[i]->mode != common::ColOperation::MIN && attrs[i]->mode != common::ColOperation::MAX && - !attrs[i]->distinct) - return -1; - return d; -} - -bool TempTable::LimitMayBeAppliedToWhere() { - if (order_by.size() > 0) // ORDER BY => false - return false; - if (mode.distinct || HasHavingConditions()) // DISTINCT or HAVING => false - return false; - for (uint i = 0; i < NumOfAttrs(); i++) // GROUP BY or other aggregation => false - if (attrs[i]->mode != common::ColOperation::LISTING) - return false; - return true; -} - -int TempTable::AddVirtColumn(vcolumn::VirtualColumn *vc) { - virt_cols.push_back(vc); - virt_cols_for_having.push_back(vc->GetMultiIndex() == &output_mind); - return (int)virt_cols.size() - 1; -} - -int TempTable::AddVirtColumn(vcolumn::VirtualColumn *vc, int no) { - DEBUG_ASSERT(static_cast(no) < virt_cols.size()); - virt_cols_for_having[no] = (vc->GetMultiIndex() == &output_mind); - virt_cols[no] = vc; - return no; -} - -void TempTable::ResetVCStatistics() { - for (uint i = 0; i < virt_cols.size(); i++) - if (virt_cols[i]) - virt_cols[i]->ResetLocalStatistics(); -} - -void TempTable::SetVCDistinctVals(int dim, int64_t val) { - for (uint i = 0; i < virt_cols.size(); i++) - if (virt_cols[i] && virt_cols[i]->GetDim() == dim) - virt_cols[i]->SetLocalDistVals(val); -} - -std::shared_ptr TempTable::Create(const TempTable &t, bool in_subq) { - MEASURE_FET("TempTable::Create(...)"); - bool _is_vc_owner = !in_subq; - std::shared_ptr tnew = std::shared_ptr(new TempTable(t, _is_vc_owner)); - if (in_subq) { - // map attr_translation; // - // SingleColumns should refer to columns of tnew - for (uint i = 0; i < t.attrs.size(); i++) { - // attr_translation[t.attrs[i]] = tnew->attrs[i]; - tnew->attr_back_translation[tnew->attrs[i]] = t.attrs[i]; - } - // for(uint i = 0; i< tnew->virt_cols.size(); i++) { - // if(tnew->virt_cols[i]->IsSingleColumn()) - // static_cast(tnew->virt_cols[i])->TranslateSourceColumns(attr_translation); - // if(tnew->virt_cols_for_having[i]) { - // tnew->virt_cols[i]->SetMultiIndex(&tnew->output_mind, tnew); - // } else - // tnew->virt_cols[i]->SetMultiIndex(tnew->filter.mind_); - //} - } - return tnew; -} - -std::shared_ptr TempTable::Create(JustATable *const t, int alias, Query *q, bool for_subq) { - if (for_subq) - return std::shared_ptr(new TempTableForSubquery(t, alias, q)); - else - return std::shared_ptr(new TempTable(t, alias, q)); -} - -ColumnType TempTable::GetUnionType(ColumnType type1, ColumnType type2) { - if (type1.IsFloat() || type2.IsFloat()) - return type1.IsFloat() ? type1 : type2; - if (type1.IsString() && type1.GetPrecision() != 0 && !type2.IsString()) { - ColumnType t(type1); - if (t.GetPrecision() < type2.GetPrecision()) - t.SetPrecision(type2.GetPrecision()); - return t; - } - if (type2.IsString() && type2.GetPrecision() != 0 && !type1.IsString()) { - ColumnType t(type2); - if (t.GetPrecision() < type1.GetPrecision()) - t.SetPrecision(type1.GetPrecision()); - return t; - } - if (type1.IsFixed() && type2.IsFixed() && type1.GetScale() != type2.GetScale()) { - uint max_scale = type1.GetScale() > type2.GetScale() ? type1.GetScale() : type2.GetScale(); - uint max_ints = (type1.GetPrecision() - type1.GetScale()) > (type2.GetPrecision() - type2.GetScale()) - ? (type1.GetPrecision() - type1.GetScale()) - : (type2.GetPrecision() - type2.GetScale()); - if (max_ints + max_scale > 18) { - std::stringstream ss; - ss << "UNION of non-matching columns (column no " << 0 << ") ."; - throw common::NotImplementedException(ss.str()); - } - return type1.GetScale() > type2.GetScale() ? type1 : type2; - } - if (type1.GetInternalSize() < type2.GetInternalSize()) - return type2; - else if (type1.GetInternalSize() == type2.GetInternalSize()) - return type1.GetPrecision() > type2.GetPrecision() ? type1 : type2; - else - return type1; -} - -bool TempTable::SubqueryInFrom() { - for (uint i = 0; i < tables.size(); i++) - if (tables[i]->TableType() == TType::TEMP_TABLE) - return true; - return false; -} - -void TempTable::LockPackForUse([[maybe_unused]] unsigned attr, unsigned pack_no) { - while (lazy && no_materialized < std::min(((int64_t)pack_no << p_power) + (1 << p_power), no_obj)) - Materialize(false, nullptr, true); -} - -bool TempTable::CanOrderSources() { - for (uint i = 0; i < order_by.size(); i++) { - if (order_by[i].vc->GetMultiIndex() != filter.mind_) - return false; - } - return true; -} - -void TempTable::Materialize(bool in_subq, ResultSender *sender, bool lazy) { - MEASURE_FET("TempTable::Materialize()"); - if (sender) - sender->SetAffectRows(no_obj); - CreateDisplayableAttrP(); - CalculatePageSize(); - int64_t offset = 0; // controls the first object to be materialized - int64_t limit = -1; // if(limit>=0) -> for(row = offset; row < offset + - // limit; row++) .... - bool limits_present = mode.top; - bool exists_only = mode.exists; - - if (limits_present) { - offset = (mode.param1 >= 0 ? mode.param1 : 0); - limit = (mode.param2 >= 0 ? mode.param2 : 0); - // applied => reset to default values - mode.top = false; - mode.param2 = -1; - mode.param1 = 0; - } - int64_t local_offset = 0; // controls the first object to be materialized in a given algorithm - int64_t local_limit = -1; - if (materialized && (order_by.size() > 0 || limits_present) && no_obj) { - // if TempTable is already materialized but some additional constraints were - // specified, e.g., order by or limit this is typical case for union, where - // constraints are specified for the result of union after materialization - if (limits_present) { - local_offset = offset; - local_limit = std::min(limit, (int64_t)no_obj - offset); - local_limit = local_limit < 0 ? 0 : local_limit; - } else - local_limit = no_obj; - if (exists_only) { - if (local_limit == 0) // else no change needed - no_obj = 0; - return; - } - - if (order_by.size() != 0 && no_obj > 1) { - std::shared_ptr temporary_source_table = - CreateMaterializedCopy(true, in_subq); // true: translate definition of ordering - OrderByAndMaterialize(order_by, local_limit, local_offset); - DeleteMaterializedCopy(temporary_source_table); - } else if (limits_present) - ApplyOffset(local_limit, local_offset); - order_by.clear(); - return; - } - - if ((materialized && !this->lazy) || (this->lazy && no_obj == no_materialized)) { - return; - } - - bool table_distinct = this->mode.distinct; - bool distinct_on_materialized = false; - for (uint i = 0; i < NumOfAttrs(); i++) - if (attrs[i]->mode != common::ColOperation::LISTING) - group_by = true; - if (table_distinct && group_by) { - distinct_on_materialized = true; - table_distinct = false; - } - - if (order_by.size() > 0 || group_by || this->mode.distinct || force_full_materialize) - lazy = false; - this->lazy = lazy; - - bool no_rows_too_large = filter.mind_->TooManyTuples(); - no_obj = -1; // no_obj not calculated yet - wait for better moment - VerifyAttrsSizes(); // resize attr[i] buffers basing on the current - // multiindex state - - // the case when there is no grouping of attributes, check also DISTINCT - // modifier of TT - if (!group_by && !table_distinct) { - DEBUG_ASSERT(!distinct_on_materialized); // should by false here, otherwise must be - // added to conditions below - - if (limits_present) { - if (no_rows_too_large && order_by.size() == 0) - no_obj = offset + limit; // offset + limit in the worst case - else - no_obj = filter.mind_->NumOfTuples(); - if (no_obj <= offset) { - no_obj = 0; - materialized = true; - order_by.clear(); - return; - } - local_offset = offset; - local_limit = std::min(limit, (int64_t)no_obj - offset); - local_limit = local_limit < 0 ? 0 : local_limit; - } else { - no_obj = filter.mind_->NumOfTuples(); - local_limit = no_obj; - } - if (exists_only) { - order_by.clear(); - return; - } - output_mind.Clear(); - output_mind.AddDimension_cross(local_limit); // an artificial dimension for result - - CalculatePageSize(); // recalculate, as no_obj might changed - // perform order by: in this case it can be done on source tables, not on - // the result - bool materialized_by_ordering = false; - if (CanOrderSources()) - // false if no sorting used - materialized_by_ordering = this->OrderByAndMaterialize(order_by, local_limit, local_offset, sender); - if (!materialized_by_ordering) { // not materialized yet? - // materialize without aggregations. If ordering then do not send result - if (order_by.size() == 0) - FillMaterializedBuffers(local_limit, local_offset, sender, lazy); - else // in case of order by we need to materialize all rows to be next - // ordered - FillMaterializedBuffers(no_obj, 0, nullptr, lazy); - } - } else { - // GROUP BY or DISTINCT - compute aggregations - if (limits_present && !distinct_on_materialized && order_by.size() == 0) { - local_offset = offset; - local_limit = limit; - if (exists_only) - local_limit = 1; - } - if (HasHavingConditions() && in_subq) - having_conds[0].tree->Simplify(true); - - ResultSender *local_sender = (distinct_on_materialized || order_by.size() > 0 ? nullptr : sender); - AggregationAlgorithm aggr(this); - aggr.Aggregate(table_distinct, local_limit, local_offset, - local_sender); // this->tree (HAVING) used inside - if (no_obj == 0) { - order_by.clear(); - return; - } - - output_mind.Clear(); - output_mind.AddDimension_cross(no_obj); // an artificial dimension for result - } - - local_offset = 0; - local_limit = -1; - - // DISTINCT after grouping - if (distinct_on_materialized && no_obj > 1) { - if (limits_present && order_by.size() == 0) { - local_offset = std::min((int64_t)no_obj, offset); - local_limit = std::min(limit, (int64_t)no_obj - local_offset); - local_limit = local_limit < 0 ? 0 : local_limit; - if (no_obj <= offset) { - no_obj = 0; - materialized = true; - order_by.clear(); - return; - } - } else - local_limit = no_obj; - if (exists_only) - local_limit = 1; - std::shared_ptr temporary_source_table = CreateMaterializedCopy(false, in_subq); - ResultSender *local_sender = (order_by.size() > 0 ? nullptr : sender); - - AggregationAlgorithm aggr(this); - aggr.Aggregate(true, local_limit, local_offset, - local_sender); // true => select-level distinct - DeleteMaterializedCopy(temporary_source_table); - output_mind.Clear(); - output_mind.AddDimension_cross(no_obj); // an artificial dimension for result - } // end of distinct part - // ORDER BY, if not sorted until now - if (order_by.size() != 0) { - if (limits_present) { - local_offset = std::min((int64_t)no_obj, offset); - local_limit = std::min(limit, (int64_t)no_obj - local_offset); - local_limit = local_limit < 0 ? 0 : local_limit; - if (no_obj <= offset) { - no_obj = 0; - materialized = true; - order_by.clear(); - return; - } - } else - local_limit = no_obj; - if (no_obj > 1 && !exists_only) { - std::shared_ptr temporary_source_table = - CreateMaterializedCopy(true, in_subq); // true: translate definition of ordering - OrderByAndMaterialize(order_by, local_limit, local_offset, sender); - DeleteMaterializedCopy(temporary_source_table); - } - order_by.clear(); - output_mind.Clear(); - output_mind.AddDimension_cross(no_obj); // an artificial dimension for result - } - materialized = true; -} - -void TempTable::RecordIterator::PrepareValues() { - if (_currentRNo < uint64_t(table->NumOfObj())) { - uint no_disp_attr = table->NumOfDisplaybleAttrs(); - for (uint att = 0; att < no_disp_attr; ++att) { - common::ColumnType attrt_tmp = table->GetDisplayableAttrP(att)->TypeName(); - if (attrt_tmp == common::ColumnType::INT || attrt_tmp == common::ColumnType::MEDIUMINT) { - int &v = (*(AttrBuffer *)table->GetDisplayableAttrP(att)->buffer)[_currentRNo]; - if (v == common::NULL_VALUE_32) - dataTypes[att]->SetToNull(); - else - ((types::TianmuNum *)dataTypes[att].get())->Assign(v, 0, false, attrt_tmp); - } else if (attrt_tmp == common::ColumnType::SMALLINT) { - short &v = (*(AttrBuffer *)table->GetDisplayableAttrP(att)->buffer)[_currentRNo]; - if (v == common::NULL_VALUE_SH) - dataTypes[att]->SetToNull(); - else - ((types::TianmuNum *)dataTypes[att].get())->Assign(v, 0, false, attrt_tmp); - } else if (attrt_tmp == common::ColumnType::BYTEINT) { - char &v = (*(AttrBuffer *)table->GetDisplayableAttrP(att)->buffer)[_currentRNo]; - if (v == common::NULL_VALUE_C) - dataTypes[att]->SetToNull(); - else - ((types::TianmuNum *)dataTypes[att].get())->Assign(v, 0, false, attrt_tmp); - } else if (ATI::IsRealType(attrt_tmp)) { - double &v = (*(AttrBuffer *)table->GetDisplayableAttrP(att)->buffer)[_currentRNo]; - if (v == NULL_VALUE_D) - dataTypes[att]->SetToNull(); - else - ((types::TianmuNum *)dataTypes[att].get())->Assign(v); - } else if (attrt_tmp == common::ColumnType::NUM || attrt_tmp == common::ColumnType::BIGINT || - attrt_tmp == common::ColumnType::BIT) { - int64_t &v = (*(AttrBuffer *)table->GetDisplayableAttrP(att)->buffer)[_currentRNo]; - if (v == common::NULL_VALUE_64) - dataTypes[att]->SetToNull(); - else - ((types::TianmuNum *)dataTypes[att].get()) - ->Assign(v, table->GetDisplayableAttrP(att)->Type().GetScale(), false, attrt_tmp); - } else if (ATI::IsDateTimeType(attrt_tmp)) { - int64_t &v = (*(AttrBuffer *)table->GetDisplayableAttrP(att)->buffer)[_currentRNo]; - if (v == common::NULL_VALUE_64) - dataTypes[att]->SetToNull(); - else - ((types::TianmuDateTime *)dataTypes[att].get())->Assign(v, attrt_tmp); - } else { - ASSERT(ATI::IsStringType(attrt_tmp), "not all possible attr_types checked"); - (*(AttrBuffer *)table->GetDisplayableAttrP(att)->buffer) - .GetString(*(types::BString *)dataTypes[att].get(), _currentRNo); - } - } - } -} - -TempTable::RecordIterator &TempTable::RecordIterator::operator++() { - DEBUG_ASSERT(_currentRNo < uint64_t(table->NumOfObj())); - is_prepared = false; - ++_currentRNo; - return (*this); -} - -TempTable::RecordIterator TempTable::begin(Transaction *conn) { return (RecordIterator(this, conn, 0)); } - -TempTable::RecordIterator TempTable::end(Transaction *conn) { return (RecordIterator(this, conn, NumOfObj())); } - -TempTable::RecordIterator::RecordIterator() : table(nullptr), _currentRNo(0), _conn(nullptr), is_prepared(false) {} - -TempTable::RecordIterator::RecordIterator(TempTable *table_, Transaction *conn_, uint64_t rowNo_) - : table(table_), _currentRNo(rowNo_), _conn(conn_), is_prepared(false) { - DEBUG_ASSERT(table != 0); - DEBUG_ASSERT(_currentRNo <= uint64_t(table->NumOfObj())); - for (uint att = 0; att < table->NumOfDisplaybleAttrs(); att++) { - common::ColumnType att_type = table->GetDisplayableAttrP(att)->TypeName(); - if (att_type == common::ColumnType::INT || att_type == common::ColumnType::MEDIUMINT || - att_type == common::ColumnType::SMALLINT || att_type == common::ColumnType::BYTEINT || - ATI::IsRealType(att_type) || att_type == common::ColumnType::NUM || att_type == common::ColumnType::BIGINT || - att_type == common::ColumnType::BIT) - dataTypes.emplace_back(new types::TianmuNum()); - else if (ATI::IsDateTimeType(att_type)) - dataTypes.emplace_back(new types::TianmuDateTime()); - else { - ASSERT(ATI::IsStringType(att_type), "not all possible attr_types checked"); - dataTypes.emplace_back(new types::BString()); - } - } -} - -TempTable::RecordIterator::RecordIterator(RecordIterator const &it) - : table(it.table), _currentRNo(it._currentRNo), _conn(it._conn), is_prepared(false) { - for (uint att = 0; att < it.dataTypes.size(); att++) - if (it.dataTypes[att]) - dataTypes.emplace_back(it.dataTypes[att]->Clone()); - else - dataTypes.emplace_back(nullptr); -} - -bool TempTable::RecordIterator::operator==(RecordIterator const &it) const { - DEBUG_ASSERT((!(table || it.table)) || (table == it.table)); - return (_currentRNo == it._currentRNo); -} - -bool TempTable::RecordIterator::operator!=(RecordIterator const &it) const { - DEBUG_ASSERT((!(table || it.table)) || (table == it.table)); - return (_currentRNo != it._currentRNo); -} - -TempTableForSubquery::~TempTableForSubquery() { - if (no_global_virt_cols != -1) { // otherwise never evaluated - for (uint i = no_global_virt_cols; i < virt_cols.size(); i++) delete virt_cols[i]; - - virt_cols.resize(no_global_virt_cols); - virt_cols = template_virt_cols; - } - delete template_filter; - SetAttrsForExact(); - for (uint i = 0; i < attrs_for_rough.size(); i++) delete attrs_for_rough[i]; - for (uint i = 0; i < template_attrs.size(); i++) delete template_attrs[i]; -} - -void TempTableForSubquery::ResetToTemplate(bool rough, bool use_filter_shallow) { - if (!template_filter) - return; - - for (uint i = no_global_virt_cols; i < virt_cols.size(); i++) delete virt_cols[i]; - - virt_cols.resize(template_virt_cols.size()); - - for (uint i = 0; i < template_virt_cols.size(); i++) virt_cols[i] = template_virt_cols[i]; - - for (uint i = 0; i < attrs.size(); i++) { - void *orig_buf = (*attrs[i]).buffer; - *attrs[i] = *template_attrs[i]; - (*attrs[i]).buffer = orig_buf; - } - - if (use_filter_shallow) { - filter = std::move(*template_filter); // shallow - filter_shallow_memory = true; - } else { - filter = *template_filter; - filter_shallow_memory = false; - } - - for (int i = 0; i < no_global_virt_cols; i++) - if (!virt_cols_for_having[i]) - virt_cols[i]->SetMultiIndex(filter.mind_); - - having_conds = template_having_conds; - order_by = template_order_by; - mode = template_mode; - no_obj = 0; - - (rough) ? rough_materialized = false : materialized = false; - - no_materialized = 0; - rough_is_empty = common::Tribool(); -} - -void TempTableForSubquery::SetAttrsForRough() { - if (!is_attr_for_rough) { - for (uint i = attrs_for_exact.size(); i < attrs.size(); i++) delete attrs[i]; - attrs = attrs_for_rough; - is_attr_for_rough = true; - } -} - -void TempTableForSubquery::SetAttrsForExact() { - if (is_attr_for_rough) { - for (uint i = (int)attrs_for_rough.size(); i < attrs.size(); i++) delete attrs[i]; - attrs = attrs_for_exact; - is_attr_for_rough = false; - } -} - -void TempTableForSubquery::Materialize(bool in_subq, [[maybe_unused]] ResultSender *sender, - [[maybe_unused]] bool lazy) { - CreateTemplateIfNotExists(); - SetAttrsForExact(); - TempTable::Materialize(in_subq); -} - -void TempTableForSubquery::RoughMaterialize(bool in_subq, [[maybe_unused]] ResultSender *sender, - [[maybe_unused]] bool lazy) { - CreateTemplateIfNotExists(); - SetAttrsForRough(); - if (rough_materialized) - return; - TempTable::RoughMaterialize(in_subq); - materialized = false; - rough_materialized = true; -} - -void TempTableForSubquery::CreateTemplateIfNotExists() { - if (attrs_for_rough.size() == 0) { - attrs_for_exact = attrs; - is_attr_for_rough = false; - for (uint i = 0; i < attrs.size(); i++) attrs_for_rough.push_back(new Attr(*attrs[i])); - } - if (!template_filter && IsParametrized()) { - template_filter = new ParameterizedFilter(filter); - for (uint i = 0; i < attrs.size(); i++) template_attrs.push_back(new Attr(*attrs[i])); - no_global_virt_cols = int(virt_cols.size()); - template_having_conds = having_conds; - template_order_by = order_by; - template_mode = mode; - template_virt_cols = virt_cols; - } -} - -} // namespace core -} // namespace Tianmu +/* Copyright (c) 2022 StoneAtom, Inc. All rights reserved. + Use is subject to license terms + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include + +#include "core/aggregation_algorithm.h" +#include "core/cached_buffer.h" +#include "core/column_bin_encoder.h" +#include "core/condition_encoder.h" +#include "core/engine.h" +#include "core/group_distinct_table.h" +#include "core/mysql_expression.h" +#include "core/parameterized_filter.h" +#include "core/query.h" +#include "core/rsi_cmap.h" +#include "core/temp_table.h" +#include "core/transaction.h" +#include "core/value_set.h" +#include "system/fet.h" +#include "vc/const_column.h" +#include "vc/const_expr_column.h" +#include "vc/expr_column.h" +#include "vc/in_set_column.h" +#include "vc/single_column.h" +#include "vc/subselect_column.h" +#include "vc/type_cast_column.h" + +namespace Tianmu { +namespace core { + +template +class AttrBuffer : public CachedBuffer { + public: + explicit AttrBuffer(uint page_size, uint elem_size = 0, Transaction *conn = nullptr) + : CachedBuffer(page_size, elem_size, conn) {} + ~AttrBuffer() = default; + + void GetString(types::BString &s, int64_t idx) { CachedBuffer::Get(s, idx); } + // Warning: read only operator!!! + T &operator[](int64_t idx) { return CachedBuffer::Get(idx); } + void Set(int64_t idx, T value) { CachedBuffer::Set(idx, value); } +}; + +template class AttrBuffer; +template class AttrBuffer; +template class AttrBuffer; +template class AttrBuffer; +template class AttrBuffer; +template class AttrBuffer; + +TempTable::Attr::Attr(const Attr &a) : PhysicalColumn(a) { + mode = a.mode; + distinct = a.distinct; + no_materialized = a.no_materialized; + term = a.term; + if (term.vc) + term.vc->ResetLocalStatistics(); + dim = a.dim; + // DEBUG_ASSERT(a.buffer == nullptr); // otherwise we cannot copy Attr ! + buffer = nullptr; + no_obj = a.no_obj; + no_power = a.no_power; + if (a.alias) { + alias = new char[std::strlen(a.alias) + 1]; + std::strcpy(alias, a.alias); + } else + alias = nullptr; + + page_size = a.page_size; + orig_precision = a.orig_precision; + not_complete = a.not_complete; + si = a.si; +} + +TempTable::Attr::Attr(CQTerm t, common::ColOperation m, uint32_t power, bool dis, char *a, int dim, + common::ColumnType type, uint scale, uint no_digits, bool notnull, DTCollation collation, SI *si1) + : mode(m), distinct(dis), term(t), dim(dim), not_complete(true) { + ct.Initialize(type, notnull, common::PackFmt::DEFAULT, no_digits, scale, collation); + orig_precision = no_digits; + buffer = nullptr; + no_obj = 0; + no_power = power; + no_materialized = 0; + if (a) { + alias = new char[std::strlen(a) + 1]; + std::strcpy(alias, a); + } else + alias = nullptr; + if (m == common::ColOperation::GROUP_CONCAT) + si = (*si1); + else + si.order = ORDER::ORDER_NOT_RELEVANT; + + page_size = 1; +} + +TempTable::Attr::~Attr() { + DeleteBuffer(); + delete[] alias; +} + +TempTable::Attr &TempTable::Attr::operator=(const TempTable::Attr &a) { + mode = a.mode; + distinct = a.distinct; + no_materialized = a.no_materialized; + term = a.term; + if (term.vc) + term.vc->ResetLocalStatistics(); + dim = a.dim; + // DEBUG_ASSERT(a.buffer == nullptr); // otherwise we cannot copy Attr ! + buffer = nullptr; + no_obj = a.no_obj; + no_power = a.no_power; + delete[] alias; + if (a.alias) { + alias = new char[std::strlen(a.alias) + 1]; + std::strcpy(alias, a.alias); + } else + alias = nullptr; + + page_size = a.page_size; + orig_precision = a.orig_precision; + not_complete = a.not_complete; + return *this; +} + +int TempTable::Attr::operator==(const TempTable::Attr &sec) { + return mode == sec.mode && distinct == sec.distinct && term == sec.term && Type() == sec.Type() && dim == sec.dim; +} + +void TempTable::Attr::CreateBuffer(uint64_t size, Transaction *conn, bool not_c) { + // do not create larger buffer than size + not_complete = not_c; + if (size < page_size) + page_size = (uint)size; + no_obj = size; + switch (TypeName()) { + case common::ColumnType::INT: + case common::ColumnType::MEDIUMINT: + if (!buffer) + buffer = new AttrBuffer(page_size, sizeof(int), conn); + break; + case common::ColumnType::BYTEINT: + if (!buffer) + buffer = new AttrBuffer(page_size, sizeof(char), conn); + break; + case common::ColumnType::SMALLINT: + if (!buffer) + buffer = new AttrBuffer(page_size, sizeof(short), conn); + break; + case common::ColumnType::STRING: + case common::ColumnType::VARCHAR: + case common::ColumnType::BIN: + case common::ColumnType::BYTE: + case common::ColumnType::VARBYTE: + case common::ColumnType::LONGTEXT: + DeleteBuffer(); + buffer = new AttrBuffer(page_size, Type().GetInternalSize(), conn); + break; + case common::ColumnType::BIGINT: + case common::ColumnType::NUM: + case common::ColumnType::YEAR: + case common::ColumnType::TIME: + case common::ColumnType::DATE: + case common::ColumnType::DATETIME: + case common::ColumnType::TIMESTAMP: + case common::ColumnType::BIT: + if (!buffer) + buffer = new AttrBuffer(page_size, sizeof(int64_t), conn); + break; + case common::ColumnType::REAL: + case common::ColumnType::FLOAT: + if (!buffer) + buffer = new AttrBuffer(page_size, sizeof(double), conn); + break; + default: + break; + } +} + +void TempTable::Attr::FillValue(const MIIterator &mii, size_t idx) { + types::BString vals; + switch (TypeName()) { + case common::ColumnType::STRING: + case common::ColumnType::VARCHAR: + term.vc->GetValueString(vals, mii); + SetValueString(idx, vals); + break; + case common::ColumnType::BIN: + case common::ColumnType::BYTE: + case common::ColumnType::VARBYTE: + case common::ColumnType::LONGTEXT: + if (!term.vc->IsNull(mii)) + term.vc->GetNotNullValueString(vals, mii); + else + vals = types::BString(); + SetValueString(idx, vals); + break; + default: + SetValueInt64(idx, term.vc->GetValueInt64(mii)); + break; + } +} + +size_t TempTable::Attr::FillValues(MIIterator &mii, size_t start, size_t count) { + size_t n = 0; + bool first_row_for_vc = true; + while (mii.IsValid() && n < count) { + if (mii.PackrowStarted() || first_row_for_vc) { + term.vc->LockSourcePacks(mii); + first_row_for_vc = false; + } + FillValue(mii, start + n); + ++mii; + ++n; + }; + term.vc->UnlockSourcePacks(); + return n; +} + +void TempTable::Attr::DeleteBuffer() { + switch (TypeName()) { + case common::ColumnType::INT: + case common::ColumnType::MEDIUMINT: + delete (AttrBuffer *)(buffer); + break; + case common::ColumnType::BYTEINT: + delete (AttrBuffer *)(buffer); + break; + case common::ColumnType::SMALLINT: + delete (AttrBuffer *)(buffer); + break; + case common::ColumnType::STRING: + case common::ColumnType::VARCHAR: + case common::ColumnType::BIN: + case common::ColumnType::BYTE: + case common::ColumnType::VARBYTE: + case common::ColumnType::LONGTEXT: + delete (AttrBuffer *)(buffer); + break; + case common::ColumnType::BIGINT: + case common::ColumnType::NUM: + case common::ColumnType::YEAR: + case common::ColumnType::TIME: + case common::ColumnType::DATE: + case common::ColumnType::DATETIME: + case common::ColumnType::TIMESTAMP: + case common::ColumnType::BIT: + delete (AttrBuffer *)(buffer); + break; + case common::ColumnType::REAL: + case common::ColumnType::FLOAT: + delete (AttrBuffer *)(buffer); + break; + default: + break; + } + buffer = nullptr; + no_obj = 0; +} + +void TempTable::Attr::SetValueInt64(int64_t obj, int64_t val) { + no_materialized = obj + 1; + no_obj = obj >= no_obj ? obj + 1 : no_obj; + switch (TypeName()) { + case common::ColumnType::BIGINT: + case common::ColumnType::NUM: + case common::ColumnType::BIT: + case common::ColumnType::YEAR: + case common::ColumnType::TIME: + case common::ColumnType::DATE: + case common::ColumnType::DATETIME: + case common::ColumnType::TIMESTAMP: // 64-bit + ((AttrBuffer *)buffer)->Set(obj, val); + break; + case common::ColumnType::INT: // 32-bit + case common::ColumnType::MEDIUMINT: // 24-bit + if (val == common::NULL_VALUE_64) + ((AttrBuffer *)buffer)->Set(obj, common::NULL_VALUE_32); + else if (val == common::PLUS_INF_64) + ((AttrBuffer *)buffer)->Set(obj, std::numeric_limits::max()); + else if (val == common::MINUS_INF_64) + ((AttrBuffer *)buffer)->Set(obj, TIANMU_INT_MIN); + else + ((AttrBuffer *)buffer)->Set(obj, (int)val); + break; + case common::ColumnType::SMALLINT: // 16-bit + if (val == common::NULL_VALUE_64) + ((AttrBuffer *)buffer)->Set(obj, common::NULL_VALUE_SH); + else if (val == common::PLUS_INF_64) + ((AttrBuffer *)buffer)->Set(obj, TIANMU_SMALLINT_MAX); + else if (val == common::MINUS_INF_64) + ((AttrBuffer *)buffer)->Set(obj, TIANMU_SMALLINT_MIN); + else + ((AttrBuffer *)buffer)->Set(obj, (short)val); + break; + case common::ColumnType::BYTEINT: // 8-bit + if (val == common::NULL_VALUE_64) + ((AttrBuffer *)buffer)->Set(obj, common::NULL_VALUE_C); + else if (val == common::PLUS_INF_64) + ((AttrBuffer *)buffer)->Set(obj, TIANMU_TINYINT_MAX); + else if (val == common::MINUS_INF_64) + ((AttrBuffer *)buffer)->Set(obj, TIANMU_TINYINT_MIN); + else + ((AttrBuffer *)buffer)->Set(obj, (char)val); + break; + case common::ColumnType::REAL: + case common::ColumnType::FLOAT: + if (val == common::NULL_VALUE_64) + ((AttrBuffer *)buffer)->Set(obj, NULL_VALUE_D); + else if (val == common::PLUS_INF_64) + ((AttrBuffer *)buffer)->Set(obj, common::PLUS_INF_DBL); + else if (val == common::MINUS_INF_64) + ((AttrBuffer *)buffer)->Set(obj, common::MINUS_INF_DBL); + else + ((AttrBuffer *)buffer)->Set(obj, *(double *)&val); + break; + default: + DEBUG_ASSERT(0); + break; + } +} + +void TempTable::Attr::InvalidateRow([[maybe_unused]] int64_t obj) { + DEBUG_ASSERT(obj + 1 == no_materialized); + no_obj--; + no_materialized--; +} + +void TempTable::Attr::SetNull(int64_t obj) { + no_materialized = obj + 1; + no_obj = obj >= no_obj ? obj + 1 : no_obj; + switch (TypeName()) { + case common::ColumnType::BIGINT: + case common::ColumnType::NUM: + case common::ColumnType::YEAR: + case common::ColumnType::TIME: + case common::ColumnType::DATE: + case common::ColumnType::DATETIME: + case common::ColumnType::TIMESTAMP: + case common::ColumnType::BIT: + ((AttrBuffer *)buffer)->Set(obj, common::NULL_VALUE_64); + break; + case common::ColumnType::INT: + case common::ColumnType::MEDIUMINT: + ((AttrBuffer *)buffer)->Set(obj, common::NULL_VALUE_32); + break; + case common::ColumnType::SMALLINT: + ((AttrBuffer *)buffer)->Set(obj, common::NULL_VALUE_SH); + break; + case common::ColumnType::BYTEINT: + ((AttrBuffer *)buffer)->Set(obj, common::NULL_VALUE_C); + break; + case common::ColumnType::REAL: + case common::ColumnType::FLOAT: + ((AttrBuffer *)buffer)->Set(obj, NULL_VALUE_D); + break; + case common::ColumnType::BIN: + case common::ColumnType::BYTE: + case common::ColumnType::VARBYTE: + case common::ColumnType::LONGTEXT: + case common::ColumnType::STRING: + case common::ColumnType::VARCHAR: + ((AttrBuffer *)buffer)->Set(obj, types::BString()); + break; + default: + DEBUG_ASSERT(0); + break; + } +} + +void TempTable::Attr::SetMinusInf(int64_t obj) { SetValueInt64(obj, common::MINUS_INF_64); } + +void TempTable::Attr::SetPlusInf(int64_t obj) { SetValueInt64(obj, common::PLUS_INF_64); } + +void TempTable::Attr::SetValueString(int64_t obj, const types::BString &val) { + no_materialized = obj + 1; + no_obj = obj >= no_obj ? obj + 1 : no_obj; + int64_t val64 = 0; + double valD = 0.0; + + switch (TypeName()) { + case common::ColumnType::INT: + case common::ColumnType::MEDIUMINT: + ((AttrBuffer *)buffer)->Set(obj, std::atoi(val.GetDataBytesPointer())); + break; + case common::ColumnType::BYTEINT: + ((AttrBuffer *)buffer)->Set(obj, val.GetDataBytesPointer()[0]); + break; + case common::ColumnType::SMALLINT: + ((AttrBuffer *)buffer)->Set(obj, (short)std::atoi(val.GetDataBytesPointer())); + break; + case common::ColumnType::BIGINT: + ((AttrBuffer *)buffer)->Set(obj, std::strtoll(val.GetDataBytesPointer(), nullptr, 10)); + break; + case common::ColumnType::BIN: + case common::ColumnType::BYTE: + case common::ColumnType::VARBYTE: + case common::ColumnType::STRING: + case common::ColumnType::VARCHAR: + case common::ColumnType::LONGTEXT: + ((AttrBuffer *)buffer)->Set(obj, val); + break; + case common::ColumnType::NUM: + case common::ColumnType::YEAR: + case common::ColumnType::TIME: + case common::ColumnType::DATE: + case common::ColumnType::DATETIME: + case common::ColumnType::TIMESTAMP: + case common::ColumnType::BIT: + val64 = *(int64_t *)(val.GetDataBytesPointer()); + ((AttrBuffer *)buffer)->Set(obj, val64); + break; + case common::ColumnType::REAL: + case common::ColumnType::FLOAT: + if (!val.IsNullOrEmpty()) + valD = *(double *)(val.GetDataBytesPointer()); + else + valD = NULL_VALUE_D; + ((AttrBuffer *)buffer)->Set(obj, valD); + break; + default: + break; + } +} + +types::TianmuValueObject TempTable::Attr::GetValue(int64_t obj, [[maybe_unused]] bool lookup_to_num) { + if (obj == common::NULL_VALUE_64) + return types::TianmuValueObject(); + types::TianmuValueObject ret; + if (ATI::IsStringType(TypeName())) { + types::BString s; + GetValueString(s, obj); + ret = s; + } else if (ATI::IsIntegerType(TypeName())) + ret = types::TianmuNum(GetValueInt64(obj), 0, false, common::ColumnType::NUM); + else if (ATI::IsDateTimeType(TypeName())) + ret = types::TianmuDateTime(this->GetValueInt64(obj), TypeName() /*, precision*/); + else if (ATI::IsRealType(TypeName())) + ret = types::TianmuNum(this->GetValueInt64(obj), 0, true); + else if (TypeName() == common::ColumnType::NUM) + ret = types::TianmuNum((int64_t)GetValueInt64(obj), Type().GetScale()); + else if (TypeName() == common::ColumnType::BIT) + ret = types::TianmuNum((int64_t)GetValueInt64(obj), Type().GetScale(), false, + TypeName()); // TODO(check prec & scale) + return ret; +} + +void TempTable::Attr::GetValueString(types::BString &value, int64_t obj) { + if (obj == common::NULL_VALUE_64) { + value = types::BString(); + return; + } + + switch (TypeName()) { + case common::ColumnType::BIN: + case common::ColumnType::BYTE: + case common::ColumnType::VARBYTE: + case common::ColumnType::STRING: + case common::ColumnType::VARCHAR: + case common::ColumnType::LONGTEXT: + (*(AttrBuffer *)buffer).GetString(value, obj); + break; + case common::ColumnType::BYTEINT: { + types::TianmuNum tianmu_n(static_cast((*(AttrBuffer *)buffer)[obj]), -1, false, TypeName()); + value = tianmu_n.GetValueInt64() == common::NULL_VALUE_64 ? types::BString() : tianmu_n.ToBString(); + break; + } + case common::ColumnType::SMALLINT: { + types::TianmuNum tianmu_n(static_cast((*(AttrBuffer *)buffer)[obj]), -1, false, TypeName()); + value = tianmu_n.GetValueInt64() == common::NULL_VALUE_64 ? types::BString() : tianmu_n.ToBString(); + break; + } + case common::ColumnType::INT: + case common::ColumnType::MEDIUMINT: { + types::TianmuNum tianmu_n(static_cast((*(AttrBuffer *)buffer)[obj]), -1, false, TypeName()); + value = tianmu_n.ValueInt() == common::NULL_VALUE_32 ? types::BString() : tianmu_n.ToBString(); + break; + } + case common::ColumnType::BIGINT: { + types::TianmuNum tianmu_n(static_cast((*(AttrBuffer *)buffer)[obj]), -1, false, TypeName()); + value = tianmu_n.GetValueInt64() == common::NULL_VALUE_64 ? types::BString() : tianmu_n.ToBString(); + break; + } + case common::ColumnType::NUM: { + types::TianmuNum tianmu_n((*(AttrBuffer *)buffer)[obj], Type().GetScale()); + value = tianmu_n.GetValueInt64() == common::NULL_VALUE_64 ? types::BString() : tianmu_n.ToBString(); + break; + } + case common::ColumnType::BIT: { + types::TianmuNum tianmu_n((*(AttrBuffer *)buffer)[obj], Type().GetScale(), false, TypeName()); + value = tianmu_n.GetValueInt64() == common::NULL_VALUE_64 ? types::BString() : tianmu_n.ToBString(); + break; + } + case common::ColumnType::YEAR: + case common::ColumnType::TIME: + case common::ColumnType::DATE: + case common::ColumnType::DATETIME: + case common::ColumnType::TIMESTAMP: { + types::TianmuDateTime tianmu_dt((*(AttrBuffer *)buffer)[obj], TypeName()); + if (TypeName() == common::ColumnType::TIMESTAMP) { + types::TianmuDateTime::AdjustTimezone(tianmu_dt); + } + if (tianmu_dt.GetInt64() == common::NULL_VALUE_64) { + value = types::BString(); + } else { + const types::BString &tianmu_dt_str = tianmu_dt.ToBString(); + size_t len = tianmu_dt_str.len_ > Type().GetPrecision() ? Type().GetPrecision() : tianmu_dt_str.len_; + value = types::BString(tianmu_dt_str.GetDataBytesPointer(), len, tianmu_dt_str.IsPersistent()); + } + break; + } + case common::ColumnType::REAL: + case common::ColumnType::FLOAT: { + double *d_p = &(*(AttrBuffer *)buffer)[obj]; + types::TianmuNum tianmu_n(static_cast(*d_p), 0, true, TypeName()); + value = tianmu_n.GetValueInt64() == common::NULL_VALUE_64 ? types::BString() : tianmu_n.ToBString(); + break; + } + default: + break; + } +} + +int64_t TempTable::Attr::GetSum(int pack, bool &nonnegative) { + DEBUG_ASSERT(ATI::IsNumericType(ct.GetTypeName())); + int64_t start = pack * (1 << no_power); + int64_t stop = (1 << no_power); + stop = stop > no_obj ? no_obj : stop; + if (not_complete || no_materialized < stop) + return common::NULL_VALUE_64; + int64_t sum = 0, val; + double sum_d = 0.0; + bool not_null_exists = false; + nonnegative = true; + for (int64_t i = start; i < stop; i++) { + if (!IsNull(i)) { + not_null_exists = true; + val = GetNotNullValueInt64(i); + nonnegative = nonnegative && (val >= 0); + if (ATI::IsRealType(ct.GetTypeName())) { + sum_d += *(double *)&val; + } else + sum += val; + } + } + if (ATI::IsRealType(ct.GetTypeName())) + sum = *(int64_t *)&sum_d; + return not_null_exists ? sum : common::NULL_VALUE_64; +} + +int64_t TempTable::Attr::GetNumOfNulls(int pack) { + if (not_complete) + return common::NULL_VALUE_64; + int64_t start; + int64_t stop; + if (pack == -1) { + start = 0; + stop = no_obj; + } else { + start = pack * (1 << no_power); + stop = (pack + 1) * (1 << no_power); + stop = stop > no_obj ? no_obj : stop; + } + if (no_materialized < stop) + return common::NULL_VALUE_64; + int64_t no_nulls = 0; + for (int64_t i = start; i < stop; i++) { + if (IsNull(i)) + no_nulls++; + } + return no_nulls; +} + +types::BString TempTable::Attr::GetMinString([[maybe_unused]] int pack) { + return types::BString(); // it should not touch data +} + +types::BString TempTable::Attr::GetMaxString([[maybe_unused]] int pack) { + return types::BString(); // it should not touch data +} + +int64_t TempTable::Attr::GetMaxInt64(int pack) { + if (not_complete) + return common::PLUS_INF_64; + int64_t start = (1 << no_power); + int64_t stop = (pack + 1) * (1 << no_power); + stop = stop > no_obj ? no_obj : stop; + if (no_materialized < stop) + return common::NULL_VALUE_64; + int64_t val, max = common::TIANMU_BIGINT_MIN; + for (int64_t i = start; i < stop; i++) { + if (!IsNull(i)) { + val = GetNotNullValueInt64(i); + if ((ATI::IsRealType(ct.GetTypeName()) && + (max == common::TIANMU_BIGINT_MIN || *(double *)&val > *(double *)&max)) || + (!ATI::IsRealType(ct.GetTypeName()) && val > max)) + max = val; + } + } + return (max == common::TIANMU_BIGINT_MIN ? common::PLUS_INF_64 : max); +} + +int64_t TempTable::Attr::GetMinInt64(int pack) { + if (not_complete) + return common::MINUS_INF_64; + int64_t start = pack * (1 << no_power); + int64_t stop = (pack + 1) * (1 << no_power); + stop = stop > no_obj ? no_obj : stop; + if (no_materialized < stop) + return common::NULL_VALUE_64; + int64_t val, min = common::TIANMU_BIGINT_MAX; + for (int64_t i = start; i < stop; i++) { + if (!IsNull(i)) { + val = GetNotNullValueInt64(i); + if ((ATI::IsRealType(ct.GetTypeName()) && + (min == common::TIANMU_BIGINT_MAX || *(double *)&val < *(double *)&min)) || + (!ATI::IsRealType(ct.GetTypeName()) && val < min)) + min = val; + } + } + return (min == common::TIANMU_BIGINT_MAX ? common::MINUS_INF_64 : min); +} + +int64_t TempTable::Attr::GetValueInt64(int64_t obj) const { + int64_t res = common::NULL_VALUE_64; + if (obj == common::NULL_VALUE_64) + return res; + switch (TypeName()) { + case common::ColumnType::BIGINT: + case common::ColumnType::NUM: + case common::ColumnType::YEAR: + case common::ColumnType::TIME: + case common::ColumnType::DATE: + case common::ColumnType::DATETIME: + case common::ColumnType::TIMESTAMP: + case common::ColumnType::BIT: + if (!IsNull(obj)) + res = (*(AttrBuffer *)buffer)[obj]; + break; + case common::ColumnType::INT: + case common::ColumnType::MEDIUMINT: + if (!IsNull(obj)) + res = (*(AttrBuffer *)buffer)[obj]; + break; + case common::ColumnType::SMALLINT: + if (!IsNull(obj)) + res = (*(AttrBuffer *)buffer)[obj]; + break; + case common::ColumnType::BYTEINT: + if (!IsNull(obj)) + res = (*(AttrBuffer *)buffer)[obj]; + break; + case common::ColumnType::STRING: + case common::ColumnType::VARCHAR: + DEBUG_ASSERT(0); + break; + case common::ColumnType::REAL: + case common::ColumnType::FLOAT: + if (!IsNull(obj)) + res = *(int64_t *)&(*(AttrBuffer *)buffer)[obj]; + else + res = *(int64_t *)&NULL_VALUE_D; + break; + case common::ColumnType::BIN: + case common::ColumnType::BYTE: + case common::ColumnType::VARBYTE: + case common::ColumnType::LONGTEXT: + DEBUG_ASSERT(0); + break; + default: + break; + } + return res; +} + +int64_t TempTable::Attr::GetNotNullValueInt64(int64_t obj) const { + int64_t res = common::NULL_VALUE_64; + switch (TypeName()) { + case common::ColumnType::INT: + case common::ColumnType::MEDIUMINT: + res = (*(AttrBuffer *)buffer)[obj]; + break; + case common::ColumnType::BYTEINT: + res = (*(AttrBuffer *)buffer)[obj]; + break; + case common::ColumnType::SMALLINT: + res = (*(AttrBuffer *)buffer)[obj]; + break; + case common::ColumnType::BIGINT: + case common::ColumnType::NUM: + case common::ColumnType::YEAR: + case common::ColumnType::TIME: + case common::ColumnType::DATE: + case common::ColumnType::DATETIME: + case common::ColumnType::TIMESTAMP: + case common::ColumnType::BIT: + res = (*(AttrBuffer *)buffer)[obj]; + break; + case common::ColumnType::REAL: + case common::ColumnType::FLOAT: + res = *(int64_t *)&(*(AttrBuffer *)buffer)[obj]; + break; + default: + DEBUG_ASSERT(0); + break; + } + return res; +} + +bool TempTable::Attr::IsNull(const int64_t obj) const { + if (obj == common::NULL_VALUE_64) + return true; + bool res = false; + switch (TypeName()) { + case common::ColumnType::INT: + case common::ColumnType::MEDIUMINT: + res = (*(AttrBuffer *)buffer)[obj] == common::NULL_VALUE_32; + break; + case common::ColumnType::BYTEINT: + res = (*(AttrBuffer *)buffer)[obj] == common::NULL_VALUE_C; + break; + case common::ColumnType::SMALLINT: + res = (*(AttrBuffer *)buffer)[obj] == common::NULL_VALUE_SH; + break; + case common::ColumnType::BIN: + case common::ColumnType::BYTE: + case common::ColumnType::VARBYTE: + case common::ColumnType::STRING: + case common::ColumnType::VARCHAR: + case common::ColumnType::LONGTEXT: + res = (*(AttrBuffer *)buffer)[obj].IsNull(); + break; + case common::ColumnType::BIGINT: + case common::ColumnType::NUM: + case common::ColumnType::YEAR: + case common::ColumnType::TIME: + case common::ColumnType::DATE: + case common::ColumnType::DATETIME: + case common::ColumnType::TIMESTAMP: + case common::ColumnType::BIT: + res = (*(AttrBuffer *)buffer)[obj] == common::NULL_VALUE_64; + break; + case common::ColumnType::REAL: + case common::ColumnType::FLOAT: { + common::double_int_t v((*(AttrBuffer *)buffer)[obj]); + res = v.i == common::NULL_VALUE_64; + break; + } + default: + break; + } + return res; +} + +void TempTable::Attr::ApplyFilter(MultiIndex &mind_, int64_t offset, int64_t last_index) { + DEBUG_ASSERT(mind_.NumOfDimensions() == 1); + + if (mind_.NumOfDimensions() != 1) + throw common::NotImplementedException("MultiIndex has too many dimensions."); + if (mind_.ZeroTuples() || no_obj == 0 || offset >= mind_.NumOfTuples()) { + DeleteBuffer(); + return; + } + + if (last_index > mind_.NumOfTuples()) + last_index = mind_.NumOfTuples(); + + void *old_buffer = buffer; + buffer = nullptr; + CreateBuffer(last_index - offset, mind_.m_conn); + + MIIterator mit(&mind_, mind_.ValueOfPower()); + for (int64_t i = 0; i < offset; i++) ++mit; + uint64_t idx = 0; + for (int64_t i = 0; i < last_index - offset; i++, ++mit) { + idx = mit[0]; + DEBUG_ASSERT(idx != static_cast(common::NULL_VALUE_64)); // null object should never appear + // in a materialized temp. table + switch (TypeName()) { + case common::ColumnType::INT: + case common::ColumnType::MEDIUMINT: + ((AttrBuffer *)buffer)->Set(i, (*(AttrBuffer *)old_buffer)[idx]); + break; + case common::ColumnType::BYTEINT: + ((AttrBuffer *)buffer)->Set(i, (*(AttrBuffer *)old_buffer)[idx]); + break; + case common::ColumnType::SMALLINT: + ((AttrBuffer *)buffer)->Set(i, (*(AttrBuffer *)old_buffer)[idx]); + break; + case common::ColumnType::STRING: + case common::ColumnType::VARCHAR: + case common::ColumnType::BIN: + case common::ColumnType::BYTE: + case common::ColumnType::VARBYTE: + case common::ColumnType::LONGTEXT: + ((AttrBuffer *)buffer)->Set(i, (*(AttrBuffer *)old_buffer)[idx]); + break; + case common::ColumnType::BIGINT: + case common::ColumnType::NUM: + case common::ColumnType::YEAR: + case common::ColumnType::TIME: + case common::ColumnType::DATE: + case common::ColumnType::DATETIME: + case common::ColumnType::TIMESTAMP: + case common::ColumnType::BIT: + ((AttrBuffer *)buffer)->Set(i, (*(AttrBuffer *)old_buffer)[idx]); + break; + case common::ColumnType::REAL: + case common::ColumnType::FLOAT: + ((AttrBuffer *)buffer)->Set(i, (*(AttrBuffer *)old_buffer)[idx]); + break; + default: + DEBUG_ASSERT(0); + break; + } + } + + switch (TypeName()) { + case common::ColumnType::INT: + case common::ColumnType::MEDIUMINT: + delete (AttrBuffer *)old_buffer; + break; + case common::ColumnType::BYTEINT: + delete (AttrBuffer *)old_buffer; + break; + case common::ColumnType::SMALLINT: + delete (AttrBuffer *)old_buffer; + break; + case common::ColumnType::STRING: + case common::ColumnType::VARCHAR: + case common::ColumnType::BIN: + case common::ColumnType::BYTE: + case common::ColumnType::VARBYTE: + case common::ColumnType::LONGTEXT: + delete (AttrBuffer *)old_buffer; + break; + case common::ColumnType::BIGINT: + case common::ColumnType::NUM: + case common::ColumnType::YEAR: + case common::ColumnType::TIME: + case common::ColumnType::DATE: + case common::ColumnType::DATETIME: + case common::ColumnType::TIMESTAMP: + case common::ColumnType::BIT: + delete (AttrBuffer *)old_buffer; + break; + case common::ColumnType::REAL: + case common::ColumnType::FLOAT: + delete (AttrBuffer *)old_buffer; + break; + default: + DEBUG_ASSERT(0); + break; + } +} + +// provide the best upper approximation of number of diff. values (incl. null) +uint64_t TempTable::Attr::ApproxDistinctVals([[maybe_unused]] bool incl_nulls, Filter *f, + [[maybe_unused]] common::RoughSetValue *rf, + [[maybe_unused]] bool outer_nulls_possible) { + // TODO: can it be done better? + if (f) + return f->NumOfOnes(); + + return no_obj; +} + +size_t TempTable::Attr::MaxStringSize([[maybe_unused]] Filter *f) // maximal byte std::string length in column +{ + uint res = ct.GetPrecision(); + if (ct.IsFixed()) + res = std::max(res, 21u); // max. numeric size ("-aaa.bbb") + else if (!ct.IsString()) + res = std::max(res, 23u); // max. size of datetime/double etc. + + return res; +} + +void TempTable::Attr::SetNewPageSize(uint new_page_size) { + if (buffer) { + switch (TypeName()) { + case common::ColumnType::INT: + case common::ColumnType::MEDIUMINT: + static_cast *>(buffer)->SetNewPageSize(new_page_size); + break; + case common::ColumnType::BYTEINT: + static_cast *>(buffer)->SetNewPageSize(new_page_size); + break; + case common::ColumnType::SMALLINT: + static_cast *>(buffer)->SetNewPageSize(new_page_size); + break; + case common::ColumnType::STRING: + case common::ColumnType::VARCHAR: + case common::ColumnType::BIN: + case common::ColumnType::BYTE: + case common::ColumnType::VARBYTE: + case common::ColumnType::LONGTEXT: + static_cast *>(buffer)->SetNewPageSize(new_page_size); + break; + case common::ColumnType::BIGINT: + case common::ColumnType::NUM: + case common::ColumnType::YEAR: + case common::ColumnType::TIME: + case common::ColumnType::DATE: + case common::ColumnType::DATETIME: + case common::ColumnType::TIMESTAMP: + static_cast *>(buffer)->SetNewPageSize(new_page_size); + break; + case common::ColumnType::REAL: + case common::ColumnType::FLOAT: + static_cast *>(buffer)->SetNewPageSize(new_page_size); + break; + default: + ASSERT(0, "Attr::SetNewPageSize: unrecognized type"); + break; + } + } + page_size = new_page_size; +} + +TempTable::TempTable(const TempTable &t, bool is_vc_owner) + : filter(t.filter), output_mind(t.output_mind), is_vc_owner(is_vc_owner), m_conn(t.m_conn) { + no_obj = t.no_obj; + materialized = t.materialized; + aliases = t.aliases; + group_by = t.group_by; + no_cols = t.no_cols; + mode = t.mode; + virt_cols = t.virt_cols; + virt_cols_for_having = t.virt_cols_for_having; + having_conds = t.having_conds; + tables = t.tables; + join_types = t.join_types; + order_by = t.order_by; + has_temp_table = t.has_temp_table; + lazy = t.lazy; + force_full_materialize = t.force_full_materialize; + no_materialized = t.no_materialized; + no_global_virt_cols = int(t.virt_cols.size()); + for (uint i = 0; i < t.attrs.size(); i++) { + attrs.push_back(new Attr(*t.attrs[i])); + } + is_sent = t.is_sent; + mem_scale = t.mem_scale; + rough_is_empty = t.rough_is_empty; + p_power = t.p_power; + size_of_one_record = 0; +} + +TempTable::~TempTable() { + MEASURE_FET("TempTable::~TempTable(...)"); + // remove all temporary tables used by *this + // but only if *this should manage those tables + if (is_vc_owner) { + for (uint i = 0; i < virt_cols.size(); i++) delete virt_cols[i]; + } else { + TranslateBackVCs(); + for (uint i = no_global_virt_cols; i < virt_cols.size(); i++) delete virt_cols[i]; + } + + for (uint i = 0; i < attrs.size(); i++) { + delete attrs[i]; + } +} + +void TempTable::TranslateBackVCs() { + for (int i = 0; i < no_global_virt_cols; i++) + if (virt_cols[i] && static_cast(virt_cols[i]->IsSingleColumn())) + static_cast(virt_cols[i])->TranslateSourceColumns(attr_back_translation); +} + +std::shared_ptr TempTable::CreateMaterializedCopy(bool translate_order, + bool in_subq) // move all buffers to a newly created + // TempTable, make this VC-pointing to + // it; the new table must be deleted + // by DeleteMaterializedCopy() +{ + MEASURE_FET("TempTable::CreateMaterializedCopy(...)"); + // Copy buffers in a safe place for a moment + std::vector copy_buf; + std::map attr_translation; // new attr (this), old attr (working_copy) + for (uint i = 0; i < attrs.size(); i++) { + copy_buf.push_back(attrs[i]->buffer); + attrs[i]->buffer = nullptr; + } + if (no_global_virt_cols != -1) { + // this is a TempTable copy + for (uint i = no_global_virt_cols; i < virt_cols.size(); i++) { + delete virt_cols[i]; + virt_cols[i] = nullptr; + } + virt_cols.resize(no_global_virt_cols); + } + std::shared_ptr working_copy = Create(*this, in_subq); // Original VCs of this will be copied to + // working_copy, and then deleted in its + // destructor + for (uint i = 0; i < attrs.size(); i++) { + attrs[i]->mode = common::ColOperation::LISTING; + } + working_copy->mode = TableMode(); // reset all flags (distinct, limit) on copy + // working_copy->for_subq = this->for_subq; + // working_copy->no_global_virt_cols = this->no_global_virt_cols; + for (uint i = 0; i < attrs.size(); i++) { + working_copy->attrs[i]->buffer = copy_buf[i]; // copy the data buffers + attrs[i]->no_obj = 0; + attr_translation[attrs[i]] = working_copy->attrs[i]; + } + // VirtualColumns are copied, and we should replace them by references to the + // temporary source + delete filter.mind_; + filter.mind_ = new MultiIndex(p_power); + filter.mind_->AddDimension_cross(no_obj); + if (virt_cols.size() < attrs.size()) + virt_cols.resize(attrs.size()); + fill(virt_cols.begin(), virt_cols.end(), (vcolumn::VirtualColumn *)nullptr); + for (uint i = 0; i < attrs.size(); i++) { + vcolumn::VirtualColumn *new_vc = + new vcolumn::SingleColumn(working_copy->attrs[i], filter.mind_, 0, 0, working_copy.get(), 0); + virt_cols[i] = new_vc; + attrs[i]->term.vc = new_vc; + attrs[i]->dim = 0; + } + if (translate_order) { + order_by.clear(); // translation needed: virt_cols should point to + // working_copy as a data source + for (uint i = 0; i < working_copy->virt_cols.size(); i++) { + vcolumn::VirtualColumn *orig_vc = working_copy->virt_cols[i]; + // if(in_subq && orig_vc->IsSingleColumn()) + // working_copy->virt_cols[i] = + // CreateVCCopy(working_copy->virt_cols[i]); + for (uint j = 0; j < working_copy->order_by.size(); j++) { + if (working_copy->order_by[j].vc == orig_vc) { + working_copy->order_by[j].vc = working_copy->virt_cols[i]; + } + } + // TODO: redesign it for more universal solution + vcolumn::VirtualColumn *vc = working_copy->virt_cols[i]; + if (vc) { + if (static_cast(vc->IsSingleColumn())) + static_cast(vc)->TranslateSourceColumns(attr_translation); + else { + auto &var_maps = vc->GetVarMap(); + for (uint i = 0; i < var_maps.size(); i++) { + if (var_maps[i].just_a_table.lock().get() == this) + var_maps[i].just_a_table = working_copy; + } + } + } + } + for (uint i = 0; i < working_copy->order_by.size(); i++) { + SortDescriptor sord; + sord.vc = working_copy->order_by[i].vc; + sord.dir = working_copy->order_by[i].dir; + order_by.push_back(sord); + } + } else { // Create() did move vc's used in order_by into working_copy, so we + // should bring them back + for (uint i = 0; i < order_by.size(); i++) { + // find which working_copy->vc is used in ordering + for (uint j = 0; j < working_copy->virt_cols.size(); j++) { + if (/*working_copy->*/ order_by[i].vc == working_copy->virt_cols[j]) { + // order_by[i].vc = working_copy->virt_cols[j]; + MoveVC(j, working_copy->virt_cols, + virt_cols); // moving vc - now it is back in this + break; + } + } + } + } + no_global_virt_cols = (int)virt_cols.size(); + return working_copy; // must be deleted by DeleteMaterializedCopy() +} + +void TempTable::DeleteMaterializedCopy(std::shared_ptr &old_t) // delete the external table and remove + // VC pointers, make this fully + // materialized +{ + MEASURE_FET("TempTable::DeleteMaterializedCopy(...)"); + for (uint i = 0; i < attrs.size(); i++) { // Make sure VCs are deleted before the source table is deleted + attrs[i]->term.vc = nullptr; + delete virt_cols[i]; + virt_cols[i] = nullptr; + } + old_t.reset(); +} + +void TempTable::MoveVC(int colnum, std::vector &from, + std::vector &to) { + vcolumn::VirtualColumn *vc = from[colnum]; + to.push_back(vc); + from[colnum] = nullptr; + std::vector vv = vc->GetChildren(); + for (size_t i = 0; i < vv.size(); i++) MoveVC(vv[i], from, to); +} + +void TempTable::MoveVC(vcolumn::VirtualColumn *vc, std::vector &from, + std::vector &to) { + for (int k = 0; (size_t)k < from.size(); k++) + if (vc == from[k]) { + MoveVC(k, from, to); + break; + } +} + +void TempTable::ReserveVirtColumns(int no) { + DEBUG_ASSERT((no == 0 && virt_cols.size() == 0) || static_cast(no) > virt_cols.size()); + no_global_virt_cols = -1; // usable value only in TempTable copies and in subq + virt_cols.resize(no); + virt_cols_for_having.resize(no); +} + +void TempTable::CreateDisplayableAttrP() { + if (attrs.size() == 0) + return; + displayable_attr.clear(); + displayable_attr.resize(attrs.size()); + int idx = 0; + for (size_t i = 0; i < attrs.size(); i++) { + if (attrs[i]->alias) { + displayable_attr[idx] = attrs[i]; + idx++; + } + } + for (uint i = idx; i < attrs.size(); i++) displayable_attr[i] = nullptr; +} + +uint TempTable::GetDisplayableAttrIndex(uint attr) { + uint idx = -1; + uint i; + for (i = 0; i < attrs.size(); i++) + if (attrs[i]->alias) { + idx++; + if (idx == attr) + break; + } + DEBUG_ASSERT(i < attrs.size()); + return i; +} + +void TempTable::AddConds(Condition *cond, CondType type) { + MEASURE_FET("TempTable::AddConds(...)"); + switch (type) { + case CondType::WHERE_COND: { + // need to add one by one since where_conds can be non-empty + filter.AddConditions(cond, CondType::WHERE_COND); + break; + } + + case CondType::HAVING_COND: { + Descriptor &desc = cond->operator[](0); + DEBUG_ASSERT(desc.tree); + having_conds.AddDescriptor(desc.tree, this, desc.left_dims.Size()); + break; + } + + default: + DEBUG_ASSERT(0); + } +} + +void TempTable::AddInnerConds(Condition *cond, std::vector &dim_aliases) { + for (uint i = 0; i < cond->Size(); i++) + for (uint j = 0; j < dim_aliases.size(); j++) (*cond)[i].left_dims[GetDimension(dim_aliases[j])] = true; + filter.AddConditions(cond, CondType::ON_INNER_FILTER); +} + +void TempTable::AddLeftConds(Condition *cond, std::vector &left_aliases, std::vector &right_aliases) { + for (uint i = 0; i < cond->Size(); i++) { + for (int d = 0; d < (*cond)[i].left_dims.Size(); d++) (*cond)[i].left_dims[d] = (*cond)[i].right_dims[d] = false; + for (uint j = 0; j < left_aliases.size(); j++) (*cond)[i].left_dims[GetDimension(left_aliases[j])] = true; + for (uint j = 0; j < right_aliases.size(); j++) (*cond)[i].right_dims[GetDimension(right_aliases[j])] = true; + } + filter.AddConditions(cond, CondType::ON_LEFT_FILTER); +} + +void TempTable::SetMode(TMParameter mode, int64_t mode_param1, int64_t mode_param2) { + switch (mode) { + case TMParameter::TM_DISTINCT: + this->mode.distinct = true; + break; + case TMParameter::TM_TOP: + this->mode.top = true; + this->mode.param1 = mode_param1; // offset + this->mode.param2 = mode_param2; // limit + break; + case TMParameter::TM_EXISTS: + this->mode.exists = true; + break; + default: + DEBUG_ASSERT(false); + break; + } +} + +int TempTable::AddColumn(CQTerm e, common::ColOperation mode, char *alias, bool distinct, SI si) { + if (alias) + no_cols++; + common::ColumnType type = common::ColumnType::UNK; // type of column + bool notnull = false; // NULLs are allowed + uint scale = 0; // number of decimal places + uint precision = 0; // number of all places + + // new code for vcolumn::VirtualColumn + if (e.vc_id != common::NULL_VALUE_32) { + DEBUG_ASSERT(e.vc); + // enum common::ColOperation {LISTING, COUNT, SUM, MIN, MAX, AVG, GROUP_BY}; + if (mode == common::ColOperation::COUNT) { + type = common::ColumnType::NUM; // 64 bit, Decimal(18,0) + precision = 18; + notnull = true; + } else if (mode == common::ColOperation::BIT_AND || mode == common::ColOperation::BIT_OR || + mode == common::ColOperation::BIT_XOR) { + type = common::ColumnType::BIGINT; + precision = 19; + notnull = true; + } else if (mode == common::ColOperation::AVG || mode == common::ColOperation::VAR_POP || + mode == common::ColOperation::VAR_SAMP || mode == common::ColOperation::STD_POP || + mode == common::ColOperation::STD_SAMP) { + type = common::ColumnType::REAL; // 64 bit + precision = 18; + } else { + scale = e.vc->Type().GetScale(); + precision = e.vc->Type().GetPrecision(); + type = e.vc->TypeName(); + notnull = e.vc->Type().NotNull(); + if (mode == common::ColOperation::SUM) { + switch (e.vc->TypeName()) { + case common::ColumnType::INT: + case common::ColumnType::NUM: + case common::ColumnType::SMALLINT: + case common::ColumnType::BYTEINT: + case common::ColumnType::MEDIUMINT: + type = common::ColumnType::NUM; + precision = 18; + break; + case common::ColumnType::BIGINT: + case common::ColumnType::BIT: + type = common::ColumnType::BIGINT; + precision = 19; + break; + case common::ColumnType::REAL: + case common::ColumnType::FLOAT: + default: // all other types summed up as double (parsed from text) + type = common::ColumnType::REAL; + break; + // default: + // throw + // common::NotImplementedException("SUM + // performed on non-numerical column."); + } + } else if (mode == common::ColOperation::MIN || mode == common::ColOperation::MAX) { + } else if (mode == common::ColOperation::LISTING || mode == common::ColOperation::GROUP_BY) { + if (mode == common::ColOperation::GROUP_BY) + group_by = true; + notnull = e.vc->Type().NotNull(); + } + } + } else if (mode == common::ColOperation::COUNT) { + type = common::ColumnType::NUM; + precision = 18; + notnull = true; + } else { + // illegal execution path: neither VC is set nor mode is + // common::ColOperation::COUNT + DEBUG_ASSERT(!"wrong execution path"); + // throw common::NotImplementedException("Invalid column on SELECT list."); + } + + attrs.push_back(new Attr(e, mode, p_power, distinct, alias, -2, type, scale, precision, notnull, + e.vc ? e.vc->GetCollation() : DTCollation(), &si)); + return -(int)attrs.size(); // attributes are counted from -1, -2, ... +} + +void TempTable::AddOrder(vcolumn::VirtualColumn *vc, int direction) { + // don't sort by const expressions + if (vc->IsConst()) + return; + SortDescriptor d; + d.vc = vc; + d.dir = direction; + bool already_added = false; + for (uint j = 0; j < order_by.size(); j++) { + if (order_by[j] == d) { + already_added = true; + break; + } + } + if (!already_added) + order_by.push_back(d); +} + +void TempTable::Union(TempTable *t, int all) { + MEASURE_FET("TempTable::UnionOld(...)"); + if (!t) { // trivial union with single select and external order by + this->Materialize(); + return; + } + DEBUG_ASSERT(NumOfDisplaybleAttrs() == t->NumOfDisplaybleAttrs()); + if (NumOfDisplaybleAttrs() != t->NumOfDisplaybleAttrs()) + throw common::NotImplementedException("UNION of tables with different number of columns."); + if (this->IsParametrized() || t->IsParametrized()) + throw common::NotImplementedException("Materialize: not implemented union of parameterized queries."); + tianmu_control_.lock(m_conn->GetThreadID()) << "UNION: materializing components." << system::unlock; + this->Materialize(); + t->Materialize(); + if ((!t->NumOfObj() && all) || (!this->NumOfObj() && !t->NumOfObj())) // no objects = no union + return; + + Filter first_f(NumOfObj(), p_power), first_mask(NumOfObj(), + p_power); // mask of objects to be added to the final result set + Filter sec_f(t->NumOfObj(), p_power), sec_mask(t->NumOfObj(), p_power); + first_mask.Set(); + sec_mask.Set(); + if (!all) { + tianmu_control_.lock(m_conn->GetThreadID()) << "UNION: excluding repetitions." << system::unlock; + Filter first_f(NumOfObj(), p_power); + first_f.Set(); + Filter sec_f(t->NumOfObj(), p_power); + sec_f.Set(); + GroupDistinctTable dist_table(p_power); + using vc_ptr_t = std::shared_ptr; + std::vector first_vcs; + std::vector sec_vcs; + uchar *input_buf = nullptr; + { + // block to ensure deleting encoder before deleting first_vcs, sec_vcs + int size = 0; + std::vector encoder; + for (int i = 0; i < (int)NumOfDisplaybleAttrs(); i++) { + first_vcs.push_back( + vc_ptr_t(new vcolumn::SingleColumn(GetDisplayableAttrP(i), &output_mind, 0, -i - 1, this, 0))); + sec_vcs.push_back( + vc_ptr_t(new vcolumn::SingleColumn(t->GetDisplayableAttrP(i), t->GetOutputMultiIndexP(), 1, -i - 1, t, 0))); + encoder.push_back(ColumnBinEncoder()); + bool encoder_created; + if (NumOfObj() == 0) + encoder_created = encoder[i].PrepareEncoder(sec_vcs[i].get()); + else if (t->NumOfObj() == 0) + encoder_created = encoder[i].PrepareEncoder(first_vcs[i].get()); + else + encoder_created = encoder[i].PrepareEncoder(first_vcs[i].get(), sec_vcs[i].get()); + if (!encoder_created) { + std::stringstream ss; + ss << "UNION of non-matching columns (column no " << i << ") ."; + throw common::NotImplementedException(ss.str()); + } + encoder[i].SetPrimaryOffset(size); + size += encoder[i].GetPrimarySize(); + } + input_buf = new uchar[size]; + dist_table.InitializeB(size, NumOfObj() + t->NumOfObj() / 2); // optimization assumption: a + // half of values in the second + // table will be repetitions + MIIterator first_mit(&output_mind, p_power); + MIIterator sec_mit(t->GetOutputMultiIndexP(), p_power); + // check all objects from the first table + do { + first_mit.Rewind(); + dist_table.Clear(); + while (first_mit.IsValid()) { + int64_t pos = **first_mit; + if (first_f.Get(pos)) { + for (uint i = 0; i < encoder.size(); i++) encoder[i].Encode(input_buf, first_mit); + GDTResult res = dist_table.Add(input_buf); + if (res == GDTResult::GDT_EXISTS) + first_mask.ResetDelayed(pos); + if (res != GDTResult::GDT_FULL) // note: if v is omitted here, it will also be + // omitted in sec! + first_f.ResetDelayed(pos); + } + ++first_mit; + if (m_conn->Killed()) + throw common::KilledException(); + } + sec_mit.Rewind(); + while (sec_mit.IsValid()) { + int64_t pos = **sec_mit; + if (sec_f.Get(pos)) { + for (uint i = 0; i < encoder.size(); i++) encoder[i].Encode(input_buf, sec_mit, sec_vcs[i].get()); + GDTResult res = dist_table.Add(input_buf); + if (res == GDTResult::GDT_EXISTS) + sec_mask.ResetDelayed(pos); + if (res != GDTResult::GDT_FULL) + sec_f.ResetDelayed(pos); + } + ++sec_mit; + if (m_conn->Killed()) + throw common::KilledException(); + } + first_f.Commit(); + sec_f.Commit(); + first_mask.Commit(); + sec_mask.Commit(); + } while (!first_f.IsEmpty() || !sec_f.IsEmpty()); + } + delete[] input_buf; + } + int64_t first_no_obj = first_mask.NumOfOnes(); + int64_t sec_no_obj = sec_mask.NumOfOnes(); + int64_t new_no_obj = first_no_obj + sec_no_obj; + tianmu_control_.lock(m_conn->GetThreadID()) + << "UNION: generating result (" << new_no_obj << " rows)." << system::unlock; + uint new_page_size = CalculatePageSize(new_no_obj); + for (uint i = 0; i < NumOfDisplaybleAttrs(); i++) { + Attr *first_attr = GetDisplayableAttrP(i); + Attr *sec_attr = t->GetDisplayableAttrP(i); + ColumnType new_type = GetUnionType(first_attr->Type(), sec_attr->Type()); + if (first_attr->Type() == sec_attr->Type() && first_mask.IsFull() && first_no_obj && sec_no_obj && + first_attr->Type().GetPrecision() >= sec_attr->Type().GetPrecision()) { + // fast path of execution: do not modify first buffer + SetPageSize(new_page_size); + FilterOnesIterator sec_fi(&sec_mask, p_power); + for (int64_t j = 0; j < sec_no_obj; j++) { + types::BString s; + if (ATI::IsStringType(first_attr->TypeName())) { + sec_attr->GetValueString(s, *sec_fi); + first_attr->SetValueString(first_no_obj + j, s); + } else { + first_attr->SetValueInt64(first_no_obj + j, sec_attr->GetValueInt64(*sec_fi)); + } + ++sec_fi; + } + continue; + } + Attr *new_attr = + new Attr(CQTerm(), common::ColOperation::LISTING, p_power, false, first_attr->alias, 0, new_type.GetTypeName(), + new_type.GetScale(), new_type.GetPrecision(), new_type.NotNull(), new_type.GetCollation()); + new_attr->page_size = new_page_size; + new_attr->CreateBuffer(new_no_obj, m_conn); + if (first_attr->TypeName() == common::ColumnType::NUM && sec_attr->TypeName() == common::ColumnType::NUM && + first_attr->Type().GetScale() != sec_attr->Type().GetScale()) { + uint max_scale = new_attr->Type().GetScale(); + // copy attr from first table to new_attr + double multiplier = types::PowOfTen(max_scale - first_attr->Type().GetScale()); + FilterOnesIterator first_fi(&first_mask, p_power); + for (int64_t j = 0; j < first_no_obj; j++) { + int64_t pos = *first_fi; + ++first_fi; + if (!first_attr->IsNull(pos)) + new_attr->SetValueInt64(j, first_attr->GetNotNullValueInt64(pos) * (int64_t)multiplier); + else + new_attr->SetValueInt64(j, common::NULL_VALUE_64); + } + // copy attr from second table to new_attr + multiplier = types::PowOfTen(max_scale - sec_attr->Type().GetScale()); + FilterOnesIterator sec_fi(&sec_mask, p_power); + for (int64_t j = 0; j < sec_no_obj; j++) { + int64_t pos = *sec_fi; + ++sec_fi; + if (!sec_attr->IsNull(pos)) + new_attr->SetValueInt64(first_no_obj + j, sec_attr->GetNotNullValueInt64(pos) * (int64_t)multiplier); + else + new_attr->SetValueInt64(first_no_obj + j, common::NULL_VALUE_64); + } + } else if (ATI::IsStringType(new_attr->TypeName())) { + types::BString s; + FilterOnesIterator first_fi(&first_mask, p_power); + for (int64_t j = 0; j < first_no_obj; j++) { + first_attr->GetValueString(s, *first_fi); + new_attr->SetValueString(j, s); + ++first_fi; + } + FilterOnesIterator sec_fi(&sec_mask, p_power); + for (int64_t j = 0; j < sec_no_obj; j++) { + sec_attr->GetValueString(s, *sec_fi); + new_attr->SetValueString(first_no_obj + j, s); + ++sec_fi; + } + } else if (new_attr->Type().IsFloat()) { + FilterOnesIterator first_fi(&first_mask, p_power); + for (int64_t j = 0; j < first_no_obj; j++) { + int64_t pos = *first_fi; + ++first_fi; + if (first_attr->IsNull(pos)) + new_attr->SetValueInt64(j, common::NULL_VALUE_64); + else if (first_attr->Type().IsFloat()) + new_attr->SetValueInt64(j, first_attr->GetNotNullValueInt64(pos)); + else { + double v = (double)first_attr->GetNotNullValueInt64(pos) / types::PowOfTen(first_attr->Type().GetScale()); + new_attr->SetValueInt64(j, *(int64_t *)&v); + } + } + FilterOnesIterator sec_fi(&sec_mask, p_power); + for (int64_t j = 0; j < sec_no_obj; j++) { + int64_t pos = *sec_fi; + ++sec_fi; + if (sec_attr->IsNull(pos)) + new_attr->SetValueInt64(first_no_obj + j, common::NULL_VALUE_64); + else if (sec_attr->Type().IsFloat()) + new_attr->SetValueInt64(first_no_obj + j, sec_attr->GetNotNullValueInt64(pos)); + else { + double v = (double)sec_attr->GetNotNullValueInt64(pos) / types::PowOfTen(sec_attr->Type().GetScale()); + new_attr->SetValueInt64(first_no_obj + j, *(int64_t *)&v); + } + } + } else { + // copy attr from first table to new_attr + double multiplier = types::PowOfTen(new_attr->Type().GetScale() - first_attr->Type().GetScale()); + FilterOnesIterator first_fi(&first_mask, p_power); + for (int64_t j = 0; j < first_no_obj; j++) { + int64_t pos = *first_fi; + ++first_fi; + if (first_attr->IsNull(pos)) + new_attr->SetValueInt64(j, common::NULL_VALUE_64); + else if (multiplier == 1.0) // do not multiply by 1.0, as it causes + // precision problems on bigint + new_attr->SetValueInt64(j, first_attr->GetNotNullValueInt64(pos)); + else + new_attr->SetValueInt64(j, (int64_t)(first_attr->GetNotNullValueInt64(pos) * multiplier)); + } + multiplier = types::PowOfTen(new_attr->Type().GetScale() - sec_attr->Type().GetScale()); + FilterOnesIterator sec_fi(&sec_mask, p_power); + for (int64_t j = 0; j < sec_no_obj; j++) { + int64_t pos = *sec_fi; + ++sec_fi; + if (sec_attr->IsNull(pos)) + new_attr->SetValueInt64(first_no_obj + j, common::NULL_VALUE_64); + else if (multiplier == 1.0) // do not multiply by 1.0, as it causes + // precision problems on bigint + new_attr->SetValueInt64(first_no_obj + j, sec_attr->GetNotNullValueInt64(pos)); + else + new_attr->SetValueInt64(first_no_obj + j, (int64_t)(sec_attr->GetNotNullValueInt64(pos) * multiplier)); + } + } + attrs[GetDisplayableAttrIndex(i)] = new_attr; + displayable_attr[i] = new_attr; + delete first_attr; + } + SetNumOfMaterialized(new_no_obj); + // this->no_obj = new_no_obj; + // this->Display(); + output_mind.Clear(); + output_mind.AddDimension_cross(no_obj); +} + +void TempTable::Union(TempTable *t, [[maybe_unused]] int all, ResultSender *sender, int64_t &g_offset, + int64_t &g_limit) { + MEASURE_FET("TempTable::UnionSender(...)"); + + DEBUG_ASSERT(NumOfDisplaybleAttrs() == t->NumOfDisplaybleAttrs()); + if (NumOfDisplaybleAttrs() != t->NumOfDisplaybleAttrs()) + throw common::NotImplementedException("UNION of tables with different number of columns."); + if (this->IsParametrized() || t->IsParametrized()) + throw common::NotImplementedException("Materialize: not implemented union of parameterized queries."); + + if (mode.top) { + if (g_offset != 0 || g_limit != -1) { + mode.param2 = std::min(g_offset + g_limit, mode.param2); + } + } else if (g_offset != 0 || g_limit != -1) { + mode.top = true; + mode.param1 = 0; + mode.param2 = g_limit + g_offset; + } + + if (g_offset != 0 || g_limit != -1) + sender->SetLimits(&g_offset, &g_limit); + this->Materialize(false, sender); + if (this->IsMaterialized() && !this->IsSent()) + sender->Send(this); + + if (t->mode.top) { + if (g_offset != 0 || g_limit != -1) { + t->mode.param2 = std::min(g_offset + g_limit, t->mode.param2); + } + } else if (g_offset != 0 || g_limit != -1) { + t->mode.top = true; + t->mode.param1 = 0; + t->mode.param2 = g_limit + g_offset; + } + + // second query might want to switch to mysql but the first is already sent + // we have to prevent switching to mysql otherwise Malformed Packet error may + // occur + try { + t->Materialize(false, sender); + } catch (common::Exception &e) { + std::string msg(e.what()); + msg.append(" Can't switch to MySQL execution path"); + throw common::InternalException(msg); + } + if (t->IsMaterialized() && !t->IsSent()) + sender->Send(t); +} + +void TempTable::Display(std::ostream &out) { + out << "No obj.:" << no_obj << ", No attrs.:" << this->NumOfDisplaybleAttrs() << system::endl + << "-----------" << system::endl; + for (int64_t i = 0; i < no_obj; i++) { + for (uint j = 0; j < this->NumOfDisplaybleAttrs(); j++) { + if (!attrs[j]->alias) + continue; + if (!IsNull(i, j)) { + types::BString s; + GetTable_S(s, i, j); + out << s << " "; + } else + out << "nullptr" + << " "; + } + out << system::endl; + } + out << "-----------" << system::endl; +} + +int TempTable::GetDimension(TabID alias) { + for (uint i = 0; i < aliases.size(); i++) { + if (aliases[i] == alias.n) + return i; + } + return common::NULL_VALUE_32; +} + +int64_t TempTable::GetTable64(int64_t obj, int attr) { + if (no_obj == 0) + return common::NULL_VALUE_64; + DEBUG_ASSERT(obj < no_obj && (uint)attr < attrs.size()); + return attrs[attr]->GetValueInt64(obj); +} + +void TempTable::GetTable_S(types::BString &s, int64_t obj, int _attr) { + if (no_obj == 0) { + s = types::BString(); + return; + } + uint attr = (uint)_attr; + DEBUG_ASSERT(obj < no_obj && attr < attrs.size()); + attrs[attr]->GetValueString(s, obj); +} + +bool TempTable::IsNull(int64_t obj, int attr) { + if (no_obj == 0) + return true; + DEBUG_ASSERT(obj < no_obj && (uint)attr < attrs.size()); + return attrs[attr]->IsNull(obj); +} + +void TempTable::SuspendDisplay() { m_conn->SuspendDisplay(); } + +void TempTable::ResumeDisplay() { m_conn->ResumeDisplay(); } + +uint64_t TempTable::ApproxAnswerSize([[maybe_unused]] int attr, + [[maybe_unused]] Descriptor &d) // provide the most probable + // approximation of number of objects + // matching the condition +{ + // TODO: can it be done better? + return no_obj / 2; +} + +void TempTable::GetTableString(types::BString &s, int64_t obj, uint attr) { + if (no_obj == 0) + s = types::BString(); + DEBUG_ASSERT(obj < no_obj && (uint)attr < attrs.size()); + attrs[attr]->GetValueString(s, obj); +} + +types::TianmuValueObject TempTable::GetValueObject(int64_t obj, uint attr) { + if (no_obj == 0) + return types::TianmuValueObject(); + DEBUG_ASSERT(obj < no_obj && (uint)attr < attrs.size()); + return attrs[attr]->GetValue(obj); +} + +uint TempTable::CalculatePageSize(int64_t _no_obj) { + int64_t new_no_obj = _no_obj == -1 ? no_obj : _no_obj; + uint size_of_one_record = 0; + for (uint i = 0; i < attrs.size(); i++) + if (attrs[i]->TypeName() == common::ColumnType::BIN || attrs[i]->TypeName() == common::ColumnType::BYTE || + attrs[i]->TypeName() == common::ColumnType::VARBYTE || attrs[i]->TypeName() == common::ColumnType::LONGTEXT || + attrs[i]->TypeName() == common::ColumnType::STRING || attrs[i]->TypeName() == common::ColumnType::VARCHAR) + size_of_one_record += attrs[i]->Type().GetInternalSize() + 4; // 4 bytes describing length + else + size_of_one_record += attrs[i]->Type().GetInternalSize(); + uint raw_size = (uint)new_no_obj; + if (size_of_one_record < 1) + size_of_one_record = 1; + + SetOneOutputRecordSize(size_of_one_record); + uint64_t cache_size; + if (mem_scale == -1) + mem_scale = mm::TraceableObject::MemorySettingsScale(); + + switch (mem_scale) { + case 0: + case 1: + cache_size = 1l << 26; + break; // 64MB + case 2: + cache_size = 1l << 27; + break; // 128MB + case 3: + case 4: + cache_size = 1l << 28; + break; // 256MB + case 5: + cache_size = 1l << 29; + break; // 512MB + case 6: + cache_size = 1l << 30; + break; // 1GB + case 7: + case 8: + cache_size = 1l << 31; + break; // 2GB + default: + cache_size = 1l << 31; + break; // heap larger than 40GB-> 2GB Cache size + } + // std::cerr << "cs=" << cache_size << std::endl; + + if (cache_size / size_of_one_record <= (uint64_t)new_no_obj) { + raw_size = uint((cache_size - 1) / size_of_one_record); // minus 1 to avoid overflow + } + if (raw_size < 1) + raw_size = 1; + for (uint i = 0; i < attrs.size(); i++) attrs[i]->page_size = raw_size; + return raw_size; +} + +void TempTable::SetPageSize(int64_t new_page_size) { + for (uint i = 0; i < attrs.size(); i++) attrs[i]->SetNewPageSize((uint)new_page_size); +} + +/*! Filter out rows from the given multiindex according to the tree of + * descriptors + * + */ + +void TempTable::DisplayRSI() { + for (uint i = 0; i < tables.size(); i++) { + if (tables[i]->TableType() == TType::TABLE) + ((TianmuTable *)tables[i])->DisplayRSI(); + } +} + +// Refactoring: extracted methods + +void TempTable::RemoveFromManagedList(const TianmuTable *tab) { + tables.erase(std::remove(tables.begin(), tables.end(), tab), tables.end()); +} + +void TempTable::ApplyOffset(int64_t limit, int64_t offset) { + // filter out all unwanted values from buffers + no_obj = limit; + for (uint i = 0; i < attrs.size(); i++) { + if (attrs[i]->alias) + attrs[i]->ApplyFilter(output_mind, offset, offset + limit); + else + attrs[i]->DeleteBuffer(); + } +} + +void TempTable::ProcessParameters(const MIIterator &mit, const int alias) { + MEASURE_FET("TempTable::ProcessParameters(...)"); + for (uint i = 0; i < virt_cols.size(); i++) virt_cols[i]->RequestEval(mit, alias); + filter.ProcessParameters(); + // filter.Prepare(); + if (mode.top && LimitMayBeAppliedToWhere()) // easy case - apply limits + filter.UpdateMultiIndex(false, (mode.param2 >= 0 ? mode.param2 : 0)); + else + filter.UpdateMultiIndex(false, -1); +} + +void TempTable::RoughProcessParameters(const MIIterator &mit, const int alias) { + MEASURE_FET("TempTable::RoughProcessParameters(...)"); + for (uint i = 0; i < virt_cols.size(); i++) virt_cols[i]->RequestEval(mit, alias); + filter.ProcessParameters(); + filter.RoughUpdateParamFilter(); +} + +bool TempTable::IsParametrized() { + for (uint i = 0; i < virt_cols.size(); i++) + if (virt_cols[i] && virt_cols[i]->IsParameterized()) + return true; + return false; +} + +int TempTable::DimInDistinctContext() { + // return a dimension number if it is used only in contexts where row + // repetitions may be omitted, e.g. distinct + int d = -1; + if (HasHavingConditions() || filter.mind_->NumOfDimensions() == 1) // having or no joins + return -1; + bool group_by_exists = false; + bool aggregation_exists = false; + for (uint i = 0; i < attrs.size(); i++) + if (attrs[i]) { + if (attrs[i]->mode == common::ColOperation::GROUP_BY) + group_by_exists = true; + if (attrs[i]->mode != common::ColOperation::GROUP_BY && attrs[i]->mode != common::ColOperation::LISTING && + attrs[i]->mode != common::ColOperation::DELAYED) + aggregation_exists = true; + if (!attrs[i]->term.vc || attrs[i]->term.vc->IsConst()) + continue; + int local_dim = attrs[i]->term.vc->GetDim(); + if (local_dim == -1 || (d != -1 && d != local_dim)) + return -1; + d = local_dim; + } + // all columns are based on the same dimension + if (group_by_exists && aggregation_exists) // group by with aggregations - not distinct context + return -1; + if (group_by_exists || (mode.distinct && !aggregation_exists)) // select distinct a,b,c...; + // select a,b,c group by a,b,c + return d; + // aggregations exist - check their type + for (uint i = 0; i < attrs.size(); i++) + if (attrs[i] && attrs[i]->mode != common::ColOperation::MIN && attrs[i]->mode != common::ColOperation::MAX && + !attrs[i]->distinct) + return -1; + return d; +} + +bool TempTable::LimitMayBeAppliedToWhere() { + if (order_by.size() > 0) // ORDER BY => false + return false; + if (mode.distinct || HasHavingConditions()) // DISTINCT or HAVING => false + return false; + for (uint i = 0; i < NumOfAttrs(); i++) // GROUP BY or other aggregation => false + if (attrs[i]->mode != common::ColOperation::LISTING) + return false; + return true; +} + +int TempTable::AddVirtColumn(vcolumn::VirtualColumn *vc) { + virt_cols.push_back(vc); + virt_cols_for_having.push_back(vc->GetMultiIndex() == &output_mind); + return (int)virt_cols.size() - 1; +} + +int TempTable::AddVirtColumn(vcolumn::VirtualColumn *vc, int no) { + DEBUG_ASSERT(static_cast(no) < virt_cols.size()); + virt_cols_for_having[no] = (vc->GetMultiIndex() == &output_mind); + virt_cols[no] = vc; + return no; +} + +void TempTable::ResetVCStatistics() { + for (uint i = 0; i < virt_cols.size(); i++) + if (virt_cols[i]) + virt_cols[i]->ResetLocalStatistics(); +} + +void TempTable::SetVCDistinctVals(int dim, int64_t val) { + for (uint i = 0; i < virt_cols.size(); i++) + if (virt_cols[i] && virt_cols[i]->GetDim() == dim) + virt_cols[i]->SetLocalDistVals(val); +} + +std::shared_ptr TempTable::Create(const TempTable &t, bool in_subq) { + MEASURE_FET("TempTable::Create(...)"); + bool _is_vc_owner = !in_subq; + std::shared_ptr tnew = std::shared_ptr(new TempTable(t, _is_vc_owner)); + if (in_subq) { + // map attr_translation; // + // SingleColumns should refer to columns of tnew + for (uint i = 0; i < t.attrs.size(); i++) { + // attr_translation[t.attrs[i]] = tnew->attrs[i]; + tnew->attr_back_translation[tnew->attrs[i]] = t.attrs[i]; + } + // for(uint i = 0; i< tnew->virt_cols.size(); i++) { + // if(tnew->virt_cols[i]->IsSingleColumn()) + // static_cast(tnew->virt_cols[i])->TranslateSourceColumns(attr_translation); + // if(tnew->virt_cols_for_having[i]) { + // tnew->virt_cols[i]->SetMultiIndex(&tnew->output_mind, tnew); + // } else + // tnew->virt_cols[i]->SetMultiIndex(tnew->filter.mind_); + //} + } + return tnew; +} + +std::shared_ptr TempTable::Create(JustATable *const t, int alias, Query *q, bool for_subq) { + if (for_subq) + return std::shared_ptr(new TempTableForSubquery(t, alias, q)); + else + return std::shared_ptr(new TempTable(t, alias, q)); +} + +ColumnType TempTable::GetUnionType(ColumnType type1, ColumnType type2) { + if (type1.IsFloat() || type2.IsFloat()) + return type1.IsFloat() ? type1 : type2; + if (type1.IsString() && type1.GetPrecision() != 0 && !type2.IsString()) { + ColumnType t(type1); + if (t.GetPrecision() < type2.GetPrecision()) + t.SetPrecision(type2.GetPrecision()); + return t; + } + if (type2.IsString() && type2.GetPrecision() != 0 && !type1.IsString()) { + ColumnType t(type2); + if (t.GetPrecision() < type1.GetPrecision()) + t.SetPrecision(type1.GetPrecision()); + return t; + } + if (type1.IsFixed() && type2.IsFixed() && type1.GetScale() != type2.GetScale()) { + uint max_scale = type1.GetScale() > type2.GetScale() ? type1.GetScale() : type2.GetScale(); + uint max_ints = (type1.GetPrecision() - type1.GetScale()) > (type2.GetPrecision() - type2.GetScale()) + ? (type1.GetPrecision() - type1.GetScale()) + : (type2.GetPrecision() - type2.GetScale()); + if (max_ints + max_scale > 18) { + std::stringstream ss; + ss << "UNION of non-matching columns (column no " << 0 << ") ."; + throw common::NotImplementedException(ss.str()); + } + return type1.GetScale() > type2.GetScale() ? type1 : type2; + } + if (type1.GetInternalSize() < type2.GetInternalSize()) + return type2; + else if (type1.GetInternalSize() == type2.GetInternalSize()) + return type1.GetPrecision() > type2.GetPrecision() ? type1 : type2; + else + return type1; +} + +bool TempTable::SubqueryInFrom() { + for (uint i = 0; i < tables.size(); i++) + if (tables[i]->TableType() == TType::TEMP_TABLE) + return true; + return false; +} + +void TempTable::LockPackForUse([[maybe_unused]] unsigned attr, unsigned pack_no) { + while (lazy && no_materialized < std::min(((int64_t)pack_no << p_power) + (1 << p_power), no_obj)) + Materialize(false, nullptr, true); +} + +bool TempTable::CanOrderSources() { + for (uint i = 0; i < order_by.size(); i++) { + if (order_by[i].vc->GetMultiIndex() != filter.mind_) + return false; + } + return true; +} + +void TempTable::Materialize(bool in_subq, ResultSender *sender, bool lazy) { + MEASURE_FET("TempTable::Materialize()"); + if (sender) + sender->SetAffectRows(no_obj); + CreateDisplayableAttrP(); + CalculatePageSize(); + int64_t offset = 0; // controls the first object to be materialized + int64_t limit = -1; // if(limit>=0) -> for(row = offset; row < offset + + // limit; row++) .... + bool limits_present = mode.top; + bool exists_only = mode.exists; + + if (limits_present) { + offset = (mode.param1 >= 0 ? mode.param1 : 0); + limit = (mode.param2 >= 0 ? mode.param2 : 0); + // applied => reset to default values + mode.top = false; + mode.param2 = -1; + mode.param1 = 0; + } + int64_t local_offset = 0; // controls the first object to be materialized in a given algorithm + int64_t local_limit = -1; + if (materialized && (order_by.size() > 0 || limits_present) && no_obj) { + // if TempTable is already materialized but some additional constraints were + // specified, e.g., order by or limit this is typical case for union, where + // constraints are specified for the result of union after materialization + if (limits_present) { + local_offset = offset; + local_limit = std::min(limit, (int64_t)no_obj - offset); + local_limit = local_limit < 0 ? 0 : local_limit; + } else + local_limit = no_obj; + if (exists_only) { + if (local_limit == 0) // else no change needed + no_obj = 0; + return; + } + + if (order_by.size() != 0 && no_obj > 1) { + std::shared_ptr temporary_source_table = + CreateMaterializedCopy(true, in_subq); // true: translate definition of ordering + OrderByAndMaterialize(order_by, local_limit, local_offset); + DeleteMaterializedCopy(temporary_source_table); + } else if (limits_present) + ApplyOffset(local_limit, local_offset); + order_by.clear(); + return; + } + + if ((materialized && !this->lazy) || (this->lazy && no_obj == no_materialized)) { + return; + } + + bool table_distinct = this->mode.distinct; + bool distinct_on_materialized = false; + for (uint i = 0; i < NumOfAttrs(); i++) + if (attrs[i]->mode != common::ColOperation::LISTING) + group_by = true; + if (table_distinct && group_by) { + distinct_on_materialized = true; + table_distinct = false; + } + + if (order_by.size() > 0 || group_by || this->mode.distinct || force_full_materialize) + lazy = false; + this->lazy = lazy; + + bool no_rows_too_large = filter.mind_->TooManyTuples(); + no_obj = -1; // no_obj not calculated yet - wait for better moment + VerifyAttrsSizes(); // resize attr[i] buffers basing on the current + // multiindex state + + // the case when there is no grouping of attributes, check also DISTINCT + // modifier of TT + if (!group_by && !table_distinct) { + DEBUG_ASSERT(!distinct_on_materialized); // should by false here, otherwise must be + // added to conditions below + + if (limits_present) { + if (no_rows_too_large && order_by.size() == 0) + no_obj = offset + limit; // offset + limit in the worst case + else + no_obj = filter.mind_->NumOfTuples(); + if (no_obj <= offset) { + no_obj = 0; + materialized = true; + order_by.clear(); + return; + } + local_offset = offset; + local_limit = std::min(limit, (int64_t)no_obj - offset); + local_limit = local_limit < 0 ? 0 : local_limit; + } else { + no_obj = filter.mind_->NumOfTuples(); + local_limit = no_obj; + } + if (exists_only) { + order_by.clear(); + return; + } + output_mind.Clear(); + output_mind.AddDimension_cross(local_limit); // an artificial dimension for result + + CalculatePageSize(); // recalculate, as no_obj might changed + // perform order by: in this case it can be done on source tables, not on + // the result + bool materialized_by_ordering = false; + if (CanOrderSources()) + // false if no sorting used + materialized_by_ordering = this->OrderByAndMaterialize(order_by, local_limit, local_offset, sender); + if (!materialized_by_ordering) { // not materialized yet? + // materialize without aggregations. If ordering then do not send result + if (order_by.size() == 0) + FillMaterializedBuffers(local_limit, local_offset, sender, lazy); + else // in case of order by we need to materialize all rows to be next + // ordered + FillMaterializedBuffers(no_obj, 0, nullptr, lazy); + } + } else { + // GROUP BY or DISTINCT - compute aggregations + if (limits_present && !distinct_on_materialized && order_by.size() == 0) { + local_offset = offset; + local_limit = limit; + if (exists_only) + local_limit = 1; + } + if (HasHavingConditions() && in_subq) + having_conds[0].tree->Simplify(true); + + ResultSender *local_sender = (distinct_on_materialized || order_by.size() > 0 ? nullptr : sender); + AggregationAlgorithm aggr(this); + aggr.Aggregate(table_distinct, local_limit, local_offset, + local_sender); // this->tree (HAVING) used inside + if (no_obj == 0) { + order_by.clear(); + return; + } + + output_mind.Clear(); + output_mind.AddDimension_cross(no_obj); // an artificial dimension for result + } + + local_offset = 0; + local_limit = -1; + + // DISTINCT after grouping + if (distinct_on_materialized && no_obj > 1) { + if (limits_present && order_by.size() == 0) { + local_offset = std::min((int64_t)no_obj, offset); + local_limit = std::min(limit, (int64_t)no_obj - local_offset); + local_limit = local_limit < 0 ? 0 : local_limit; + if (no_obj <= offset) { + no_obj = 0; + materialized = true; + order_by.clear(); + return; + } + } else + local_limit = no_obj; + if (exists_only) + local_limit = 1; + std::shared_ptr temporary_source_table = CreateMaterializedCopy(false, in_subq); + ResultSender *local_sender = (order_by.size() > 0 ? nullptr : sender); + + AggregationAlgorithm aggr(this); + aggr.Aggregate(true, local_limit, local_offset, + local_sender); // true => select-level distinct + DeleteMaterializedCopy(temporary_source_table); + output_mind.Clear(); + output_mind.AddDimension_cross(no_obj); // an artificial dimension for result + } // end of distinct part + // ORDER BY, if not sorted until now + if (order_by.size() != 0) { + if (limits_present) { + local_offset = std::min((int64_t)no_obj, offset); + local_limit = std::min(limit, (int64_t)no_obj - local_offset); + local_limit = local_limit < 0 ? 0 : local_limit; + if (no_obj <= offset) { + no_obj = 0; + materialized = true; + order_by.clear(); + return; + } + } else + local_limit = no_obj; + if (no_obj > 1 && !exists_only) { + std::shared_ptr temporary_source_table = + CreateMaterializedCopy(true, in_subq); // true: translate definition of ordering + OrderByAndMaterialize(order_by, local_limit, local_offset, sender); + DeleteMaterializedCopy(temporary_source_table); + } + order_by.clear(); + output_mind.Clear(); + output_mind.AddDimension_cross(no_obj); // an artificial dimension for result + } + materialized = true; +} + +void TempTable::RecordIterator::PrepareValues() { + if (_currentRNo < uint64_t(table->NumOfObj())) { + uint no_disp_attr = table->NumOfDisplaybleAttrs(); + for (uint att = 0; att < no_disp_attr; ++att) { + common::ColumnType attrt_tmp = table->GetDisplayableAttrP(att)->TypeName(); + if (attrt_tmp == common::ColumnType::INT || attrt_tmp == common::ColumnType::MEDIUMINT) { + int &v = (*(AttrBuffer *)table->GetDisplayableAttrP(att)->buffer)[_currentRNo]; + if (v == common::NULL_VALUE_32) + dataTypes[att]->SetToNull(); + else + ((types::TianmuNum *)dataTypes[att].get())->Assign(v, 0, false, attrt_tmp); + } else if (attrt_tmp == common::ColumnType::SMALLINT) { + short &v = (*(AttrBuffer *)table->GetDisplayableAttrP(att)->buffer)[_currentRNo]; + if (v == common::NULL_VALUE_SH) + dataTypes[att]->SetToNull(); + else + ((types::TianmuNum *)dataTypes[att].get())->Assign(v, 0, false, attrt_tmp); + } else if (attrt_tmp == common::ColumnType::BYTEINT) { + char &v = (*(AttrBuffer *)table->GetDisplayableAttrP(att)->buffer)[_currentRNo]; + if (v == common::NULL_VALUE_C) + dataTypes[att]->SetToNull(); + else + ((types::TianmuNum *)dataTypes[att].get())->Assign(v, 0, false, attrt_tmp); + } else if (ATI::IsRealType(attrt_tmp)) { + double &v = (*(AttrBuffer *)table->GetDisplayableAttrP(att)->buffer)[_currentRNo]; + if (v == NULL_VALUE_D) + dataTypes[att]->SetToNull(); + else + ((types::TianmuNum *)dataTypes[att].get())->Assign(v); + } else if (attrt_tmp == common::ColumnType::NUM || attrt_tmp == common::ColumnType::BIGINT || + attrt_tmp == common::ColumnType::BIT) { + int64_t &v = (*(AttrBuffer *)table->GetDisplayableAttrP(att)->buffer)[_currentRNo]; + if (v == common::NULL_VALUE_64) + dataTypes[att]->SetToNull(); + else + ((types::TianmuNum *)dataTypes[att].get()) + ->Assign(v, table->GetDisplayableAttrP(att)->Type().GetScale(), false, attrt_tmp); + } else if (ATI::IsDateTimeType(attrt_tmp)) { + int64_t &v = (*(AttrBuffer *)table->GetDisplayableAttrP(att)->buffer)[_currentRNo]; + if (v == common::NULL_VALUE_64) + dataTypes[att]->SetToNull(); + else + ((types::TianmuDateTime *)dataTypes[att].get())->Assign(v, attrt_tmp); + } else { + ASSERT(ATI::IsStringType(attrt_tmp), "not all possible attr_types checked"); + (*(AttrBuffer *)table->GetDisplayableAttrP(att)->buffer) + .GetString(*(types::BString *)dataTypes[att].get(), _currentRNo); + } + } + } +} + +TempTable::RecordIterator &TempTable::RecordIterator::operator++() { + DEBUG_ASSERT(_currentRNo < uint64_t(table->NumOfObj())); + is_prepared = false; + ++_currentRNo; + return (*this); +} + +TempTable::RecordIterator TempTable::begin(Transaction *conn) { return (RecordIterator(this, conn, 0)); } + +TempTable::RecordIterator TempTable::end(Transaction *conn) { return (RecordIterator(this, conn, NumOfObj())); } + +TempTable::RecordIterator::RecordIterator() : table(nullptr), _currentRNo(0), _conn(nullptr), is_prepared(false) {} + +TempTable::RecordIterator::RecordIterator(TempTable *table_, Transaction *conn_, uint64_t rowNo_) + : table(table_), _currentRNo(rowNo_), _conn(conn_), is_prepared(false) { + DEBUG_ASSERT(table != 0); + DEBUG_ASSERT(_currentRNo <= uint64_t(table->NumOfObj())); + for (uint att = 0; att < table->NumOfDisplaybleAttrs(); att++) { + common::ColumnType att_type = table->GetDisplayableAttrP(att)->TypeName(); + if (att_type == common::ColumnType::INT || att_type == common::ColumnType::MEDIUMINT || + att_type == common::ColumnType::SMALLINT || att_type == common::ColumnType::BYTEINT || + ATI::IsRealType(att_type) || att_type == common::ColumnType::NUM || att_type == common::ColumnType::BIGINT || + att_type == common::ColumnType::BIT) + dataTypes.emplace_back(new types::TianmuNum()); + else if (ATI::IsDateTimeType(att_type)) + dataTypes.emplace_back(new types::TianmuDateTime()); + else { + ASSERT(ATI::IsStringType(att_type), "not all possible attr_types checked"); + dataTypes.emplace_back(new types::BString()); + } + } +} + +TempTable::RecordIterator::RecordIterator(RecordIterator const &it) + : table(it.table), _currentRNo(it._currentRNo), _conn(it._conn), is_prepared(false) { + for (uint att = 0; att < it.dataTypes.size(); att++) + if (it.dataTypes[att]) + dataTypes.emplace_back(it.dataTypes[att]->Clone()); + else + dataTypes.emplace_back(nullptr); +} + +bool TempTable::RecordIterator::operator==(RecordIterator const &it) const { + DEBUG_ASSERT((!(table || it.table)) || (table == it.table)); + return (_currentRNo == it._currentRNo); +} + +bool TempTable::RecordIterator::operator!=(RecordIterator const &it) const { + DEBUG_ASSERT((!(table || it.table)) || (table == it.table)); + return (_currentRNo != it._currentRNo); +} + +TempTableForSubquery::~TempTableForSubquery() { + if (no_global_virt_cols != -1) { // otherwise never evaluated + for (uint i = no_global_virt_cols; i < virt_cols.size(); i++) delete virt_cols[i]; + + virt_cols.resize(no_global_virt_cols); + virt_cols = template_virt_cols; + } + delete template_filter; + SetAttrsForExact(); + for (uint i = 0; i < attrs_for_rough.size(); i++) delete attrs_for_rough[i]; + for (uint i = 0; i < template_attrs.size(); i++) delete template_attrs[i]; +} + +void TempTableForSubquery::ResetToTemplate(bool rough, bool use_filter_shallow) { + if (!template_filter) + return; + + for (uint i = no_global_virt_cols; i < virt_cols.size(); i++) delete virt_cols[i]; + + virt_cols.resize(template_virt_cols.size()); + + for (uint i = 0; i < template_virt_cols.size(); i++) virt_cols[i] = template_virt_cols[i]; + + for (uint i = 0; i < attrs.size(); i++) { + void *orig_buf = (*attrs[i]).buffer; + *attrs[i] = *template_attrs[i]; + (*attrs[i]).buffer = orig_buf; + } + + if (use_filter_shallow) { + filter = std::move(*template_filter); // shallow + filter_shallow_memory = true; + } else { + filter = *template_filter; + filter_shallow_memory = false; + } + + for (int i = 0; i < no_global_virt_cols; i++) + if (!virt_cols_for_having[i]) + virt_cols[i]->SetMultiIndex(filter.mind_); + + having_conds = template_having_conds; + order_by = template_order_by; + mode = template_mode; + no_obj = 0; + + (rough) ? rough_materialized = false : materialized = false; + + no_materialized = 0; + rough_is_empty = common::Tribool(); +} + +void TempTableForSubquery::SetAttrsForRough() { + if (!is_attr_for_rough) { + for (uint i = attrs_for_exact.size(); i < attrs.size(); i++) delete attrs[i]; + attrs = attrs_for_rough; + is_attr_for_rough = true; + } +} + +void TempTableForSubquery::SetAttrsForExact() { + if (is_attr_for_rough) { + for (uint i = (int)attrs_for_rough.size(); i < attrs.size(); i++) delete attrs[i]; + attrs = attrs_for_exact; + is_attr_for_rough = false; + } +} + +void TempTableForSubquery::Materialize(bool in_subq, [[maybe_unused]] ResultSender *sender, + [[maybe_unused]] bool lazy) { + CreateTemplateIfNotExists(); + SetAttrsForExact(); + TempTable::Materialize(in_subq); +} + +void TempTableForSubquery::RoughMaterialize(bool in_subq, [[maybe_unused]] ResultSender *sender, + [[maybe_unused]] bool lazy) { + CreateTemplateIfNotExists(); + SetAttrsForRough(); + if (rough_materialized) + return; + TempTable::RoughMaterialize(in_subq); + materialized = false; + rough_materialized = true; +} + +void TempTableForSubquery::CreateTemplateIfNotExists() { + if (attrs_for_rough.size() == 0) { + attrs_for_exact = attrs; + is_attr_for_rough = false; + for (uint i = 0; i < attrs.size(); i++) attrs_for_rough.push_back(new Attr(*attrs[i])); + } + if (!template_filter && IsParametrized()) { + template_filter = new ParameterizedFilter(filter); + for (uint i = 0; i < attrs.size(); i++) template_attrs.push_back(new Attr(*attrs[i])); + no_global_virt_cols = int(virt_cols.size()); + template_having_conds = having_conds; + template_order_by = order_by; + template_mode = mode; + template_virt_cols = virt_cols; + } +} + +} // namespace core +} // namespace Tianmu diff --git a/storage/tianmu/core/tianmu_attr.cpp b/storage/tianmu/core/tianmu_attr.cpp index 6de8f5961..d23b63051 100644 --- a/storage/tianmu/core/tianmu_attr.cpp +++ b/storage/tianmu/core/tianmu_attr.cpp @@ -812,6 +812,10 @@ void TianmuAttr::UnlockPackFromUse(common::PACK_INDEX pn) { return; } + if (pn >= m_idx.size()) { + return; + } + auto dpn = &get_dpn(pn); if (dpn->IsLocal()) dpn = m_share->get_dpn_ptr(dpn->base); @@ -823,18 +827,22 @@ void TianmuAttr::UnlockPackFromUse(common::PACK_INDEX pn) { unsigned long newv; do { - ASSERT(v > tag_one, - "Unexpected lock counter!: " + Path().string() + " index:" + std::to_string(pn) + " " + std::to_string(v)); + if (v <= tag_one) { + TIANMU_LOG(LogCtl_Level::ERROR, "UnlockPackFromUse fail, v [%ld] <= tag_one [%ld]", v, tag_one); + ASSERT(0, + "Unexpected lock counter!: " + Path().string() + " index:" + std::to_string(pn) + " " + std::to_string(v)); + } newv = v - tag_one; if ((v & ~tag_mask) == tag_one) newv = 0; } while (!dpn->CAS(v, newv)); - if (newv == 0) { - auto ap = reinterpret_cast(v & tag_mask); - ap->Unlock(); - } else { + if (newv != 0) { + return; } + + auto ap = reinterpret_cast(v & tag_mask); + ap->Unlock(); } void TianmuAttr::Collapse() { diff --git a/storage/tianmu/core/value_or_null.cpp b/storage/tianmu/core/value_or_null.cpp index 24fe160b5..ee3943c6b 100644 --- a/storage/tianmu/core/value_or_null.cpp +++ b/storage/tianmu/core/value_or_null.cpp @@ -19,6 +19,7 @@ #include "common/assert.h" #include "types/tianmu_num.h" +#include "util/log_ctl.h" namespace Tianmu { namespace core { @@ -71,14 +72,13 @@ void ValueOrNull::GetBString(types::BString &tianmu_s) const { } ValueOrNull::ValueOrNull(ValueOrNull const &von) - : x(von.x), - sp(von.string_owner ? new char[von.len + 1] : von.sp), - len(von.len), - string_owner(von.string_owner), - null(von.null) { + : x(von.x), len(von.len), string_owner(von.string_owner), null(von.null) { if (string_owner) { + sp = new char[len + 1]; std::memcpy(sp, von.sp, len); sp[len] = 0; + } else { + sp = von.sp; } } diff --git a/storage/tianmu/handler/ha_tianmu.cpp b/storage/tianmu/handler/ha_tianmu.cpp index 31a09056a..65d129c8f 100644 --- a/storage/tianmu/handler/ha_tianmu.cpp +++ b/storage/tianmu/handler/ha_tianmu.cpp @@ -2409,10 +2409,18 @@ static MYSQL_SYSVAR_UINT(distinct_cache_size, tianmu_sysvar_distcache_size, PLUG static MYSQL_SYSVAR_BOOL(filterevaluation_speedup, tianmu_sysvar_filterevaluation_speedup, PLUGIN_VAR_BOOL, "-", nullptr, nullptr, TRUE); static MYSQL_SYSVAR_BOOL(groupby_speedup, tianmu_sysvar_groupby_speedup, PLUGIN_VAR_BOOL, "-", nullptr, nullptr, TRUE); -static MYSQL_SYSVAR_BOOL(orderby_speedup, tianmu_sysvar_orderby_speedup, PLUGIN_VAR_BOOL, "-", nullptr, nullptr, FALSE); +static MYSQL_SYSVAR_UINT(groupby_parallel_degree, tianmu_sysvar_groupby_parallel_degree, PLUGIN_VAR_INT, + "group by parallel degree, number of worker threads", nullptr, nullptr, 8, 0, INT32_MAX, 0); +static MYSQL_SYSVAR_ULONGLONG(groupby_parallel_rows_minimum, tianmu_sysvar_groupby_parallel_rows_minimum, + PLUGIN_VAR_LONGLONG, "group by parallel minimum rows", nullptr, nullptr, 655360, 655360, + INT64_MAX, 0); +static MYSQL_SYSVAR_UINT(slow_query_record_interval, tianmu_sysvar_slow_query_record_interval, PLUGIN_VAR_INT, + "slow Query Threshold of recording tianmu logs, in seconds", nullptr, nullptr, 0, 0, INT32_MAX, + 0); +static MYSQL_SYSVAR_BOOL(orderby_speedup, tianmu_sysvar_orderby_speedup, PLUGIN_VAR_BOOL, "-", nullptr, nullptr, TRUE); static MYSQL_SYSVAR_UINT(join_parallel, tianmu_sysvar_join_parallel, PLUGIN_VAR_INT, "join matching parallel: 0-Disabled, 1-Auto, N-specify count", nullptr, nullptr, 1, 0, 1000, - 0); + 1); static MYSQL_SYSVAR_UINT(join_splitrows, tianmu_sysvar_join_splitrows, PLUGIN_VAR_INT, "join split rows:0-Disabled, 1-Auto, N-specify count", nullptr, nullptr, 0, 0, 1000, 0); static MYSQL_SYSVAR_BOOL(minmax_speedup, tianmu_sysvar_minmax_speedup, PLUGIN_VAR_BOOL, "-", nullptr, nullptr, TRUE); @@ -2446,7 +2454,7 @@ static MYSQL_SYSVAR_UINT(lookup_max_size, tianmu_sysvar_lookup_max_size, PLUGIN_ static MYSQL_SYSVAR_BOOL(qps_log, tianmu_sysvar_qps_log, PLUGIN_VAR_BOOL, "-", nullptr, nullptr, TRUE); -static MYSQL_SYSVAR_BOOL(force_hashjoin, tianmu_sysvar_force_hashjoin, PLUGIN_VAR_BOOL, "-", nullptr, nullptr, FALSE); +static MYSQL_SYSVAR_BOOL(force_hashjoin, tianmu_sysvar_force_hashjoin, PLUGIN_VAR_BOOL, "-", nullptr, nullptr, TRUE); static MYSQL_SYSVAR_UINT(start_async, tianmu_sysvar_start_async, PLUGIN_VAR_INT, "Enable async, specifies async threads x/100 * cpus", nullptr, start_async_update, 0, 0, 100, 0); @@ -2536,7 +2544,9 @@ static struct st_mysql_sys_var *tianmu_showvars[] = {MYSQL_SYSVAR(bg_load_thread MYSQL_SYSVAR(distinct_cache_size), MYSQL_SYSVAR(filterevaluation_speedup), MYSQL_SYSVAR(global_debug_level), - MYSQL_SYSVAR(groupby_speedup), + MYSQL_SYSVAR(groupby_parallel_degree), + MYSQL_SYSVAR(groupby_parallel_rows_minimum), + MYSQL_SYSVAR(slow_query_record_interval), MYSQL_SYSVAR(hugefiledir), MYSQL_SYSVAR(index_cache_size), MYSQL_SYSVAR(index_search), diff --git a/storage/tianmu/system/configuration.cpp b/storage/tianmu/system/configuration.cpp index 8c5f3cb49..1127beb17 100644 --- a/storage/tianmu/system/configuration.cpp +++ b/storage/tianmu/system/configuration.cpp @@ -57,6 +57,9 @@ unsigned int tianmu_sysvar_delete_or_update_threads; my_bool tianmu_sysvar_compensation_start; my_bool tianmu_sysvar_filterevaluation_speedup; my_bool tianmu_sysvar_groupby_speedup; +unsigned int tianmu_sysvar_groupby_parallel_degree; +unsigned long long tianmu_sysvar_groupby_parallel_rows_minimum; +unsigned int tianmu_sysvar_slow_query_record_interval; unsigned int tianmu_sysvar_index_cache_size; my_bool tianmu_sysvar_index_search; my_bool tianmu_sysvar_enable_rowstore; diff --git a/storage/tianmu/system/configuration.h b/storage/tianmu/system/configuration.h index 0807dcfb2..5bc9e450b 100644 --- a/storage/tianmu/system/configuration.h +++ b/storage/tianmu/system/configuration.h @@ -88,6 +88,14 @@ extern char tianmu_sysvar_enable_histogram_cmap_bloom; extern unsigned int tianmu_sysvar_result_sender_rows; // Number of threads executing (delete_row) and (update_row) in parallel extern unsigned int tianmu_sysvar_delete_or_update_threads; +// The parallelism degree of multithreaded aggregation +// the number of threads executing group by multithreaded aggregation +extern unsigned int tianmu_sysvar_groupby_parallel_degree; +// Threshold for the minimum number of rows +// that can start executing a multithreaded group by thread +extern unsigned long long tianmu_sysvar_groupby_parallel_rows_minimum; +// Slow Query Threshold of recording tianmu logs, in seconds +extern unsigned int tianmu_sysvar_slow_query_record_interval; void ConfigureRCControl();