diff --git a/Docs/Makefile.am b/Docs/Makefile.am index 156d26a9a02..80832719893 100644 --- a/Docs/Makefile.am +++ b/Docs/Makefile.am @@ -27,7 +27,7 @@ EXTRA_DIST = $(noinst_SCRIPTS) $(BUILT_SOURCES) mysqld_error.txt \ all: $(targets) txt_files txt_files: ../INSTALL-SOURCE ../COPYING ../COPYING.LIB \ - ../MIRRORS INSTALL-BINARY + INSTALL-BINARY # ../MIRRORS CLEAN_FILES: $(BUILD_SOURCES) touch $(BUILD_SOURCES) @@ -254,8 +254,8 @@ INSTALL-BINARY: mysql.info $(GT) ../COPYING.LIB: mysql.info $(GT) perl -w $(GT) mysql.info "LGPL license" "Function Index" > $@ -../MIRRORS: manual.texi $(srcdir)/Support/generate-mirror-listing.pl - perl -w $(srcdir)/Support/generate-mirror-listing.pl manual.texi > $@ +#../MIRRORS: manual.texi $(srcdir)/Support/generate-mirror-listing.pl +# perl -w $(srcdir)/Support/generate-mirror-listing.pl manual.texi > $@ # Don't update the files from bitkeeper %::SCCS/s.% diff --git a/Docs/manual.texi b/Docs/manual.texi index eed8d811a90..6a2f550f9d0 100644 --- a/Docs/manual.texi +++ b/Docs/manual.texi @@ -33450,7 +33450,7 @@ mysql> SELECT COUNT(DISTINCT results) FROM student; In MySQL you can get the number of distinct expression combinations that don't contain NULL by giving a list of expressions. In ANSI SQL you would have to do a concatenation of all expressions -inside @code{CODE(DISTINCT ...)}. +inside @code{COUNT(DISTINCT ...)}. @findex AVG() @item AVG(expr) @@ -33592,7 +33592,8 @@ SELECT [STRAIGHT_JOIN] [INTO @{OUTFILE | DUMPFILE@} 'file_name' export_options] [FROM table_references [WHERE where_definition] - [GROUP BY @{unsigned_integer | col_name | formula@} [ASC | DESC], ...] + [GROUP BY @{unsigned_integer | col_name | formula@} [ASC | DESC], ... + [WITH @{CUBE | ROLLUP@}] ] [HAVING where_definition] [ORDER BY @{unsigned_integer | col_name | formula@} [ASC | DESC] ,...] [LIMIT [offset,] rows] @@ -33801,6 +33802,10 @@ If you are not getting the results you expect from your query, please read the @code{GROUP BY} description. @xref{Group by functions}. +@item +Since Version 3.23.12 MySQL supports @code{CUBE} and @code{ROLLUP} +clauses. @xref{CUBE and ROLLUP}. + @item @cindex hints @code{STRAIGHT_JOIN} forces the optimiser to join the tables in the order in @@ -33910,6 +33915,7 @@ the examined rows will be write locked. @menu * JOIN:: @code{JOIN} Syntax * UNION:: @code{UNION} Syntax +* CUBE and ROLLUP @code{CUBE} and @code{ROLLUP} Syntax @end menu @node JOIN, UNION, SELECT, SELECT @@ -34074,7 +34080,7 @@ mysql> SELECT * FROM table1 IGNORE INDEX (key3) @xref{LEFT JOIN optimisation, , @code{LEFT JOIN} optimisation}. -@node UNION, , JOIN, SELECT +@node UNION, CUBE and ROLLUP, JOIN, SELECT @subsubsection @code{UNION} Syntax @findex UNION @@ -34119,6 +34125,141 @@ UNION ORDER BY a; @end example +@node CUBE and ROLLUP, , UNION, SELECT +@subsubsection @code{CUBE} and @code{ROLLUP} Syntax + +Documentation for OLAP extension + +Introduction +------------ + +MySQL will first support CUBE and ROLLUP operators from entire OLAP +functionality. + +The CUBE and ROLLUP extensions to SQL make querying and reporting +easier in data warehousing environments. ROLLUP creates subtotals at +increasing levels of aggregation, from the most detailed up to a grand +total. CUBE is an extension similar to ROLLUP, enabling a single +statement to calculate all possible combinations of subtotals. + + +Syntax: +------ + +The syntax supported by the enhanced mysql for CUBE and ROLLUP +operators. + +CUBE +---- + +SELECT field1, field2, ... AGGR(fieldn) FROM +table GROUP BY field1, field2 field(n-1) WITH CUBE + +This would generate the aggregates with group bys of all the +combinations of dimensions. + +ROLLUP: +----- + + SELECT field1, field2, ... AGGR(fieldn) FROM table + GROUP BY field1, field2 field(n-1) WITH ROLLUP + +Example: +------- + +mysql> select * from sales; ++------------+---------------+------+--------+ +| product | country | year | profit | ++------------+---------------+------+--------+ +| Computer | India | 2000 | 1200 | +| TV | United States | 1999 | 150 | +| Calculator | United States | 1999 | 50 | +| Computer | United States | 1999 | 1500 | +| Computer | United States | 2000 | 1500 | +| TV | United States | 2000 | 150 | +| TV | India | 2000 | 100 | +| TV | India | 2000 | 100 | +| Calculator | United States | 2000 | 75 | +| Calculator | India | 2000 | 75 | +| TV | India | 1999 | 100 | +| Computer | India | 1999 | 1200 | +| Computer | United States | 2000 | 1500 | +| Calculator | United States | 2000 | 75 | ++------------+---------------+------+--------+ +14 rows in set (0.00 sec) + + + +mysql> Select sales.product, sales.country , sales.year, sum(profit) from +sales group by product, country, year with cube; + ++------------+---------------+------+-------------+ +| product | country | year | sum(profit) | ++------------+---------------+------+-------------+ +| Calculator | India | 2000 | 75 | +| Calculator | United States | 1999 | 50 | +| Calculator | United States | 2000 | 150 | +| Computer | India | 1999 | 1200 | +| Computer | India | 2000 | 1200 | +| Computer | United States | 1999 | 1500 | +| Computer | United States | 2000 | 3000 | +| TV | India | 1999 | 100 | +| TV | India | 2000 | 200 | +| TV | United States | 1999 | 150 | +| TV | United States | 2000 | 150 | +| ALL | India | 1999 | 1300 | +| ALL | India | 2000 | 1475 | +| ALL | United States | 1999 | 1700 | +| ALL | United States | 2000 | 3300 | +| Calculator | ALL | 1999 | 50 | +| Calculator | ALL | 2000 | 225 | +| Computer | ALL | 1999 | 2700 | +| Computer | ALL | 2000 | 4200 | +| TV | ALL | 1999 | 250 | +| TV | ALL | 2000 | 350 | +| Calculator | India | 0 | 75 | +| Calculator | United States | 0 | 200 | +| Computer | India | 0 | 2400 | +| Computer | United States | 0 | 4500 | +| TV | India | 0 | 300 | +| TV | United States | 0 | 300 | +| ALL | ALL | 1999 | 3000 | +| ALL | ALL | 2000 | 4775 | +| ALL | India | 0 | 2775 | +| ALL | United States | 0 | 5000 | +| Calculator | ALL | 0 | 275 | +| Computer | ALL | 0 | 6900 | +| TV | ALL | 0 | 600 | +| ALL | ALL | 0 | 7775 | ++------------+---------------+------+-------------+ +35 rows in set (0.00 sec) + + +MySQL supports now CUBE and ROLLUP extensions, with all functions +that one wishes to use with them. + +Those extensions already work in all tested combinations. They work +with UNION's, should work with sub-selects in 4.1 and derived tables. + +TODO +---- + +For the moment, ORDER and LIMIT are disabled for CUBE and ROLLUP. This +however remains to be added later. + +Another feature that has to be added later is grouping of select list +itmes in order to alleviate user errors. For the moment, missing +(hidden) columns are not used at all. + +Third feature to be done is to make SQL SET OPTION to set values for +all values of the column optionally to: + +* ALL (as it is now) +* NULL +* blank + +------------------------------------------------------------------------- + @findex HANDLER @node HANDLER, INSERT, SELECT, Data Manipulation @subsection @code{HANDLER} Syntax @@ -37823,8 +37964,8 @@ The disadvantages with @code{MERGE} tables are: @itemize @bullet @item You can only use identical @code{MyISAM} tables for a @code{MERGE} table. -@item -@code{AUTO_INCREMENT} columns are not automatically updated on @code{INSERT}. +@c @item +@c @code{AUTO_INCREMENT} columns are not automatically updated on @code{INSERT}. @item @code{REPLACE} doesn't work. @item @@ -37864,13 +38005,13 @@ CREATE TABLE t1 (a INT AUTO_INCREMENT PRIMARY KEY, message CHAR(20)); CREATE TABLE t2 (a INT AUTO_INCREMENT PRIMARY KEY, message CHAR(20)); INSERT INTO t1 (message) VALUES ("Testing"),("table"),("t1"); INSERT INTO t2 (message) VALUES ("Testing"),("table"),("t2"); -CREATE TABLE total (a INT NOT NULL, message CHAR(20), KEY(a)) +CREATE TABLE total (a INT AUTO_INCREMENT PRIMARY KEY, message CHAR(20)) TYPE=MERGE UNION=(t1,t2) INSERT_METHOD=LAST; @end example -Note that we didn't create a @code{UNIQUE} or @code{PRIMARY KEY} in the -@code{total} table as the key isn't going to be unique in the @code{total} -table. +@c Note that we didn't create a @code{UNIQUE} or @code{PRIMARY KEY} in the +@c @code{total} table as the key isn't going to be unique in the @code{total} +@c table. Note that you can also manipulate the @file{.MRG} file directly from the outside of the MySQL server: @@ -37897,6 +38038,10 @@ mysql> SELECT * FROM total; +---+---------+ @end example +Note that the @code{a} column, though declared as @code{PRIMARY KEY}, +is not really unique, as @code{MERGE} table cannot enforce uniqueness +over a set of underlying @code{MyISAM} tables. + To remap a @code{MERGE} table you can do one of the following: @itemize @bullet @@ -37924,8 +38069,8 @@ The following are the known problems with @code{MERGE} tables: A @code{MERGE} table cannot maintain @code{UNIQUE} constraints over the whole table. When you do @code{INSERT}, the data goes into the first or last table (according to @code{INSERT_METHOD=xxx}) and this @code{MyISAM} -table ensures that the data are unique, but it knows nothing about the -first @code{MyISAM} table. +table ensures that the data are unique, but it knows nothing about +others @code{MyISAM} tables. @item @code{DELETE FROM merge_table} used without a @code{WHERE} will only clear the mapping for the table, not delete everything in the @@ -49735,13 +49880,9 @@ Our TODO section contains what we plan to have in 4.0. @xref{TODO MySQL 4.0}. @itemize @bullet @item Fixed a bug that made the pager option in the mysql client non-functional. -Extended @code{LOG()} function to accept an optional arbitrary base parameter. -@xref{Mathematical functions}. -@item -Added @code{LOG2()} function (useful for finding out how many bits a number would require for storage). -@item -Added @code{LN()} natural logarithm function for compatibility with other databases. It is synonymous with @code{LOG(X)}. @end itemize +@item +Added full @code{AUTO_INCREMENT} support to @code{MERGE} tables. Added OLAP functionality. @c Arjen , please add the following text somewhere appropriate in the @@ -49750,6 +49891,7 @@ text above: ------------------------------------------------------------------------- Documentation for OLAP extension + Introduction ------------ @@ -49880,6 +50022,7 @@ all values of the column optionally to: ------------------------------------------------------------------------- + @node News-4.0.2, News-4.0.1, News-4.0.3, News-4.0.x @appendixsubsec Changes in release 4.0.2 (01 July 2002) diff --git a/Makefile.am b/Makefile.am index f56e67f1e83..87d1c7b5b71 100644 --- a/Makefile.am +++ b/Makefile.am @@ -20,7 +20,7 @@ AUTOMAKE_OPTIONS = foreign # These are built from source in the Docs directory EXTRA_DIST = INSTALL-SOURCE README \ - COPYING COPYING.LIB MIRRORS + COPYING COPYING.LIB SUBDIRS = include @docs_dirs@ @readline_dir@ \ @thread_dirs@ pstack @sql_client_dirs@ \ @sql_server_dirs@ @libmysqld_dirs@ scripts man \ diff --git a/include/my_sys.h b/include/my_sys.h index 664131e8187..b8c861288af 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -323,8 +323,7 @@ typedef struct st_io_cache_share int count; /* actual IO_CACHE that filled the buffer */ struct st_io_cache *active; - /* the following will be implemented whenever the need arises */ -#ifdef NOT_IMPLEMENTED +#ifdef NOT_YET_IMPLEMENTED /* whether the structure should be free'd */ my_bool alloced; #endif diff --git a/include/myisam.h b/include/myisam.h index cd70292d283..8e1be66331a 100644 --- a/include/myisam.h +++ b/include/myisam.h @@ -358,7 +358,7 @@ typedef struct st_sort_info MI_CHECK *param; enum data_file_type new_data_file_type; SORT_KEY_BLOCKS *key_block,*key_block_end; - uint kei, total_keys; + uint current_key, total_keys; my_off_t filelength,dupp,buff_length; ha_rows max_records; char *buff; diff --git a/libmysqld/Makefile.am b/libmysqld/Makefile.am index edee13c98bb..a196adc7314 100644 --- a/libmysqld/Makefile.am +++ b/libmysqld/Makefile.am @@ -49,7 +49,7 @@ sqlsources = convert.cc derror.cc field.cc field_conv.cc filesort.cc \ repl_failsafe.cc slave.cc \ sql_analyse.cc sql_base.cc sql_cache.cc sql_class.cc \ sql_crypt.cc sql_db.cc sql_delete.cc sql_insert.cc sql_lex.cc \ - sql_list.cc sql_manager.cc sql_map.cc sql_parse.cc \ + sql_list.cc sql_manager.cc sql_map.cc sql_olap.cc sql_parse.cc \ sql_rename.cc sql_repl.cc sql_select.cc sql_do.cc sql_show.cc \ sql_string.cc sql_table.cc sql_test.cc sql_udf.cc \ sql_update.cc sql_yacc.cc table.cc thr_malloc.cc time.cc \ diff --git a/myisam/mi_check.c b/myisam/mi_check.c index daecbb7ef2c..52ad02a3c1a 100644 --- a/myisam/mi_check.c +++ b/myisam/mi_check.c @@ -3223,7 +3223,7 @@ static int sort_delete_record(MI_SORT_PARAM *sort_param) old_file=info->dfile; info->dfile=info->rec_cache.file; - if (sort_info->kei) + if (sort_info->current_key) { key=info->lastkey+info->s->base.max_key_length; if ((error=(*info->s->read_rnd)(info,sort_param->record,info->lastpos,0)) && @@ -3234,7 +3234,7 @@ static int sort_delete_record(MI_SORT_PARAM *sort_param) DBUG_RETURN(1); } - for (i=0 ; i < sort_info->kei ; i++) + for (i=0 ; i < sort_info->current_key ; i++) { uint key_length=_mi_make_key(info,i,key,sort_param->record,info->lastpos); if (_mi_ck_delete(info,i,key,key_length)) diff --git a/mysql-test/r/merge.result b/mysql-test/r/merge.result index f6ca2acc91c..b95352a9eaa 100644 --- a/mysql-test/r/merge.result +++ b/mysql-test/r/merge.result @@ -275,12 +275,12 @@ a b 1 2 drop table t3,t1,t2; drop table if exists t6, t5, t4, t3, t2, t1; -create table t1 (a int not null, b int not null, key(a,b)); -create table t2 (a int not null, b int not null, key(a,b)); +create table t1 (a int not null, b int not null auto_increment, primary key(a,b)); +create table t2 (a int not null, b int not null auto_increment, primary key(a,b)); create table t3 (a int not null, b int not null, key(a,b)) UNION=(t1,t2) INSERT_METHOD=NO; create table t4 (a int not null, b int not null, key(a,b)) TYPE=MERGE UNION=(t1,t2) INSERT_METHOD=NO; -create table t5 (a int not null, b int not null, key(a,b)) TYPE=MERGE UNION=(t1,t2) INSERT_METHOD=FIRST; -create table t6 (a int not null, b int not null, key(a,b)) TYPE=MERGE UNION=(t1,t2) INSERT_METHOD=LAST; +create table t5 (a int not null, b int not null auto_increment, primary key(a,b)) TYPE=MERGE UNION=(t1,t2) INSERT_METHOD=FIRST; +create table t6 (a int not null, b int not null auto_increment, primary key(a,b)) TYPE=MERGE UNION=(t1,t2) INSERT_METHOD=LAST; show create table t3; Table Create Table t3 CREATE TABLE `t3` ( @@ -299,18 +299,18 @@ show create table t5; Table Create Table t5 CREATE TABLE `t5` ( `a` int(11) NOT NULL default '0', - `b` int(11) NOT NULL default '0', - KEY `a` (`a`,`b`) + `b` int(11) NOT NULL auto_increment, + PRIMARY KEY (`a`,`b`) ) TYPE=MRG_MyISAM INSERT_METHOD=FIRST UNION=(t1,t2) show create table t6; Table Create Table t6 CREATE TABLE `t6` ( `a` int(11) NOT NULL default '0', - `b` int(11) NOT NULL default '0', - KEY `a` (`a`,`b`) + `b` int(11) NOT NULL auto_increment, + PRIMARY KEY (`a`,`b`) ) TYPE=MRG_MyISAM INSERT_METHOD=LAST UNION=(t1,t2) -insert into t1 values (1,1),(1,2),(1,3),(1,4); -insert into t2 values (2,1),(2,2),(2,3),(2,4); +insert into t1 values (1,NULL),(1,NULL),(1,NULL),(1,NULL); +insert into t2 values (2,NULL),(2,NULL),(2,NULL),(2,NULL); select * from t3 order by b,a limit 3; a b select * from t4 order by b,a limit 3; @@ -461,6 +461,73 @@ a b 5 2 6 1 6 2 +select 1; +1 +1 +insert into t5 values (1,NULL),(5,NULL); +insert into t6 values (2,NULL),(6,NULL); +select * from t1 order by a,b; +a b +1 1 +1 2 +1 3 +1 4 +1 5 +4 1 +4 2 +5 1 +5 2 +5 3 +select * from t2 order by a,b; +a b +2 1 +2 2 +2 3 +2 4 +2 5 +6 1 +6 2 +6 3 +select * from t5 order by a,b; +a b +1 1 +1 2 +1 3 +1 4 +1 5 +2 1 +2 2 +2 3 +2 4 +2 5 +4 1 +4 2 +5 1 +5 2 +5 3 +6 1 +6 2 +6 3 +select * from t6 order by a,b; +a b +1 1 +1 2 +1 3 +1 4 +1 5 +2 1 +2 2 +2 3 +2 4 +2 5 +4 1 +4 2 +5 1 +5 2 +5 3 +6 1 +6 2 +6 3 drop table if exists t6, t5, t4, t3, t2, t1; CREATE TABLE t1 ( a int(11) NOT NULL default '0', b int(11) NOT NULL default '0', PRIMARY KEY (a,b)) TYPE=MyISAM; INSERT INTO t1 VALUES (1,1), (2,1); diff --git a/mysql-test/t/merge.test b/mysql-test/t/merge.test index 483ff316740..86e787db0a3 100644 --- a/mysql-test/t/merge.test +++ b/mysql-test/t/merge.test @@ -129,18 +129,18 @@ drop table t3,t1,t2; drop table if exists t6, t5, t4, t3, t2, t1; # first testing of common stuff with new parameters -create table t1 (a int not null, b int not null, key(a,b)); -create table t2 (a int not null, b int not null, key(a,b)); +create table t1 (a int not null, b int not null auto_increment, primary key(a,b)); +create table t2 (a int not null, b int not null auto_increment, primary key(a,b)); create table t3 (a int not null, b int not null, key(a,b)) UNION=(t1,t2) INSERT_METHOD=NO; create table t4 (a int not null, b int not null, key(a,b)) TYPE=MERGE UNION=(t1,t2) INSERT_METHOD=NO; -create table t5 (a int not null, b int not null, key(a,b)) TYPE=MERGE UNION=(t1,t2) INSERT_METHOD=FIRST; -create table t6 (a int not null, b int not null, key(a,b)) TYPE=MERGE UNION=(t1,t2) INSERT_METHOD=LAST; +create table t5 (a int not null, b int not null auto_increment, primary key(a,b)) TYPE=MERGE UNION=(t1,t2) INSERT_METHOD=FIRST; +create table t6 (a int not null, b int not null auto_increment, primary key(a,b)) TYPE=MERGE UNION=(t1,t2) INSERT_METHOD=LAST; show create table t3; show create table t4; show create table t5; show create table t6; -insert into t1 values (1,1),(1,2),(1,3),(1,4); -insert into t2 values (2,1),(2,2),(2,3),(2,4); +insert into t1 values (1,NULL),(1,NULL),(1,NULL),(1,NULL); +insert into t2 values (2,NULL),(2,NULL),(2,NULL),(2,NULL); select * from t3 order by b,a limit 3; select * from t4 order by b,a limit 3; select * from t5 order by b,a limit 3,3; @@ -167,7 +167,16 @@ select * from t2 order by a,b; select * from t3 order by a,b; select * from t4 order by a,b; select * from t5 order by a,b; +# auto_increment +select 1; +insert into t5 values (1,NULL),(5,NULL); +insert into t6 values (2,NULL),(6,NULL); +select * from t1 order by a,b; +select * from t2 order by a,b; +select * from t5 order by a,b; +select * from t6 order by a,b; drop table if exists t6, t5, t4, t3, t2, t1; + CREATE TABLE t1 ( a int(11) NOT NULL default '0', b int(11) NOT NULL default '0', PRIMARY KEY (a,b)) TYPE=MyISAM; INSERT INTO t1 VALUES (1,1), (2,1); CREATE TABLE t2 ( a int(11) NOT NULL default '0', b int(11) NOT NULL default '0', PRIMARY KEY (a,b)) TYPE=MyISAM; diff --git a/sql/ha_myisammrg.cc b/sql/ha_myisammrg.cc index 4e09c87f341..a04aafec130 100644 --- a/sql/ha_myisammrg.cc +++ b/sql/ha_myisammrg.cc @@ -75,8 +75,7 @@ int ha_myisammrg::write_row(byte * buf) if (table->time_stamp) update_timestamp(buf+table->time_stamp-1); if (table->next_number_field && buf == table->record[0]) - return (my_errno=HA_ERR_WRONG_COMMAND); - // update_auto_increment(); - [phi] have to check this before allowing it + update_auto_increment(); return myrg_write(file,buf); } diff --git a/sql/ha_myisammrg.h b/sql/ha_myisammrg.h index 2b9d7433d2f..47d3e022eb5 100644 --- a/sql/ha_myisammrg.h +++ b/sql/ha_myisammrg.h @@ -34,7 +34,7 @@ class ha_myisammrg: public handler const char **bas_ext() const; ulong table_flags() const { - return (HA_REC_NOT_IN_SEQ | HA_READ_RND_SAME | + return (HA_REC_NOT_IN_SEQ | HA_READ_RND_SAME | HA_AUTO_PART_KEY | HA_KEYPOS_TO_RNDPOS | HA_LASTKEY_ORDER | HA_NULL_KEY | HA_BLOB_KEY); } diff --git a/sql/handler.cc b/sql/handler.cc index 25617d95075..f1308a0de6e 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -628,16 +628,29 @@ longlong handler::get_auto_increment() { longlong nr; int error; + (void) extra(HA_EXTRA_KEYREAD); index_init(table->next_number_index); - error=index_last(table->record[1]); + if (!table->next_number_key_offset) + { // Autoincrement at key-start + error=index_last(table->record[1]); + } + else + { + byte key[MAX_KEY_LENGTH]; + key_copy(key,table,table->next_number_index, + table->next_number_key_offset); + error=index_read(table->record[1], key, table->next_number_key_offset, + HA_READ_PREFIX_LAST); + } + if (error) nr=1; else nr=(longlong) table->next_number_field-> val_int_offset(table->rec_buff_length)+1; - (void) extra(HA_EXTRA_NO_KEYREAD); index_end(); + (void) extra(HA_EXTRA_NO_KEYREAD); return nr; }