summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/mysql_com.h2
-rw-r--r--libmysqld/emb_qcache.cc1
-rw-r--r--libmysqld/lib_sql.cc8
-rw-r--r--myisam/mi_locking.c15
-rw-r--r--myisam/mi_rnext.c64
-rw-r--r--myisam/mi_rprev.c23
-rw-r--r--mysql-test/r/func_gconcat.result84
-rw-r--r--mysql-test/t/func_gconcat.test70
-rw-r--r--mysql-test/t/func_group.test1
-rw-r--r--sql-common/client.c2
-rw-r--r--sql/derror.cc4
-rw-r--r--sql/field.cc11
-rw-r--r--sql/field.h1
-rw-r--r--sql/ha_innodb.cc13
-rw-r--r--sql/item.cc1
-rw-r--r--sql/item_cmpfunc.cc4
-rw-r--r--sql/item_func.cc3
-rw-r--r--sql/item_geofunc.cc16
-rw-r--r--sql/item_sum.cc277
-rw-r--r--sql/item_sum.h85
-rw-r--r--sql/log.cc1
-rw-r--r--sql/log_event.cc2
-rw-r--r--sql/mysqld.cc3
-rw-r--r--sql/protocol.cc2
-rw-r--r--sql/set_var.cc3
-rw-r--r--sql/slave.cc31
-rw-r--r--sql/sql_cache.cc4
-rw-r--r--sql/sql_derived.cc1
-rw-r--r--sql/sql_insert.cc6
-rw-r--r--sql/sql_lex.cc2
-rw-r--r--sql/sql_lex.h2
-rw-r--r--sql/sql_parse.cc17
-rw-r--r--sql/sql_prepare.cc3
-rw-r--r--sql/sql_select.cc35
-rw-r--r--sql/sql_show.cc7
-rw-r--r--sql/sql_yacc.yy13
36 files changed, 493 insertions, 324 deletions
diff --git a/include/mysql_com.h b/include/mysql_com.h
index 4b94fc71c0c..578ef964d8d 100644
--- a/include/mysql_com.h
+++ b/include/mysql_com.h
@@ -119,7 +119,7 @@ enum enum_server_command
#define CLIENT_SECURE_CONNECTION 32768 /* New 4.1 authentication */
#define CLIENT_MULTI_STATEMENTS 65536 /* Enable/disable multi-stmt support */
#define CLIENT_MULTI_RESULTS 131072 /* Enable/disable multi-results */
-#define CLIENT_REMEMBER_OPTIONS ((ulong) (1L << 31))
+#define CLIENT_REMEMBER_OPTIONS (((ulong) 1) << 31)
#define SERVER_STATUS_IN_TRANS 1 /* Transaction has started */
#define SERVER_STATUS_AUTOCOMMIT 2 /* Server in auto_commit mode */
diff --git a/libmysqld/emb_qcache.cc b/libmysqld/emb_qcache.cc
index 4dac154ab80..0b6416632b7 100644
--- a/libmysqld/emb_qcache.cc
+++ b/libmysqld/emb_qcache.cc
@@ -428,7 +428,6 @@ int emb_load_querycache_result(THD *thd, Querycache_stream *src)
*prev_row= row;
row->data= columns;
MYSQL_ROW col_end= columns + mysql->field_count;
- uint len;
for (; columns < col_end; columns++)
src->load_column(&data->alloc, columns);
diff --git a/libmysqld/lib_sql.cc b/libmysqld/lib_sql.cc
index 6fb23f8f00d..cfb50d3907a 100644
--- a/libmysqld/lib_sql.cc
+++ b/libmysqld/lib_sql.cc
@@ -332,10 +332,10 @@ char ** copy_arguments_ptr= 0;
int init_embedded_server(int argc, char **argv, char **groups)
{
- char glob_hostname[FN_REFLEN];
-
- /* This mess is to allow people to call the init function without
- * having to mess with a fake argv */
+ /*
+ This mess is to allow people to call the init function without
+ having to mess with a fake argv
+ */
int *argcp;
char ***argvp;
int fake_argc = 1;
diff --git a/myisam/mi_locking.c b/myisam/mi_locking.c
index 816748d459a..b13ebfb4cad 100644
--- a/myisam/mi_locking.c
+++ b/myisam/mi_locking.c
@@ -286,6 +286,21 @@ void mi_copy_status(void* to,void *from)
((MI_INFO*) to)->state= &((MI_INFO*) from)->save_state;
}
+
+/*
+ Check if should allow concurrent inserts
+
+ IMPLEMENTATION
+ Don't allow concurrent inserts if we have a hole in the table.
+
+ NOTES
+ Rtree indexes are disabled in mi_open()
+
+ RETURN
+ 0 ok to use concurrent inserts
+ 1 not ok
+*/
+
my_bool mi_check_status(void* param)
{
MI_INFO *info=(MI_INFO*) param;
diff --git a/myisam/mi_rnext.c b/myisam/mi_rnext.c
index e1cf916d6d9..6e6056f98d9 100644
--- a/myisam/mi_rnext.c
+++ b/myisam/mi_rnext.c
@@ -57,47 +57,45 @@ int mi_rnext(MI_INFO *info, byte *buf, int inx)
}
else
{
- switch(info->s->keyinfo[inx].key_alg)
- {
- case HA_KEY_ALG_RTREE:
+ switch (info->s->keyinfo[inx].key_alg) {
+ case HA_KEY_ALG_RTREE:
/*
- Note that rtree doesn't support that the table
- may be changed since last call, so we do need
- to skip rows inserted by other threads like in btree
+ Note that rtree doesn't support that the table
+ may be changed since last call, so we do need
+ to skip rows inserted by other threads like in btree
*/
- error=rtree_get_next(info,inx,info->lastkey_length);
- break;
+ error= rtree_get_next(info,inx,info->lastkey_length);
+ break;
- case HA_KEY_ALG_BTREE:
- default:
- if (!changed)
- {
- error=_mi_search_next(info,info->s->keyinfo+inx,info->lastkey,
- info->lastkey_length,flag,
- info->s->state.key_root[inx]);
- }
- else
- {
- error=_mi_search(info,info->s->keyinfo+inx,info->lastkey,
- USE_WHOLE_KEY,flag, info->s->state.key_root[inx]);
- }
- if (!error && info->s->concurrent_insert)
- {
- while (info->lastpos >= info->state->data_file_length)
- {
- /* Skip rows that are inserted by other threads since we got a lock */
- if ((error=_mi_search_next(info,info->s->keyinfo+inx,info->lastkey,
- info->lastkey_length,
- SEARCH_BIGGER,
- info->s->state.key_root[inx])))
- break;
- }
- }
+ case HA_KEY_ALG_BTREE:
+ default:
+ if (!changed)
+ error= _mi_search_next(info,info->s->keyinfo+inx,info->lastkey,
+ info->lastkey_length,flag,
+ info->s->state.key_root[inx]);
+ else
+ error= _mi_search(info,info->s->keyinfo+inx,info->lastkey,
+ USE_WHOLE_KEY,flag, info->s->state.key_root[inx]);
}
}
if (info->s->concurrent_insert)
+ {
+ if (!error)
+ {
+ while (info->lastpos >= info->state->data_file_length)
+ {
+ /* Skip rows inserted by other threads since we got a lock */
+ if ((error=_mi_search_next(info,info->s->keyinfo+inx,
+ info->lastkey,
+ info->lastkey_length,
+ SEARCH_BIGGER,
+ info->s->state.key_root[inx])))
+ break;
+ }
+ }
rw_unlock(&info->s->key_root_lock[inx]);
+ }
/* Don't clear if database-changed */
info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
info->update|= HA_STATE_NEXT_FOUND;
diff --git a/myisam/mi_rprev.c b/myisam/mi_rprev.c
index 4807e636252..b787210e037 100644
--- a/myisam/mi_rprev.c
+++ b/myisam/mi_rprev.c
@@ -52,21 +52,22 @@ int mi_rprev(MI_INFO *info, byte *buf, int inx)
error=_mi_search(info,share->keyinfo+inx,info->lastkey,
USE_WHOLE_KEY, flag, share->state.key_root[inx]);
- if (!error)
+ if (share->concurrent_insert)
{
- while (info->lastpos >= info->state->data_file_length)
+ if (!error)
{
- /* Skip rows that are inserted by other threads since we got a lock */
- if ((error=_mi_search_next(info,share->keyinfo+inx,info->lastkey,
- info->lastkey_length,
- SEARCH_SMALLER,
- share->state.key_root[inx])))
- break;
+ while (info->lastpos >= info->state->data_file_length)
+ {
+ /* Skip rows that are inserted by other threads since we got a lock */
+ if ((error=_mi_search_next(info,share->keyinfo+inx,info->lastkey,
+ info->lastkey_length,
+ SEARCH_SMALLER,
+ share->state.key_root[inx])))
+ break;
+ }
}
- }
-
- if (share->concurrent_insert)
rw_unlock(&share->key_root_lock[inx]);
+ }
info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
info->update|= HA_STATE_PREV_FOUND;
if (error)
diff --git a/mysql-test/r/func_gconcat.result b/mysql-test/r/func_gconcat.result
index 5807bae6a06..3ab43ce11d5 100644
--- a/mysql-test/r/func_gconcat.result
+++ b/mysql-test/r/func_gconcat.result
@@ -136,17 +136,7 @@ grp ROUND(group_concat(a separator ""))
3 456789
drop table t1;
create table t1 (grp int, c char(10));
-insert into t1 values (1,NULL);
-insert into t1 values (2,"b");
-insert into t1 values (2,NULL);
-insert into t1 values (3,"E");
-insert into t1 values (3,NULL);
-insert into t1 values (3,"D");
-insert into t1 values (3,NULL);
-insert into t1 values (3,NULL);
-insert into t1 values (3,"D");
-insert into t1 values (4,"");
-insert into t1 values (5,NULL);
+insert into t1 values (1,NULL),(2,"b"),(2,NULL),(3,"E"),(3,NULL),(3,"D"),(3,NULL),(3,NULL),(3,"D"),(4,""),(5,NULL);
select grp,group_concat(c order by c) from t1 group by grp;
grp group_concat(c order by c)
1 NULL
@@ -222,3 +212,75 @@ select group_concat(a1 order by (t1.a)) from t1;
group_concat(a1 order by (t1.a))
b,a,c
drop table t1, t2;
+CREATE TABLE t1 (id1 tinyint(4) NOT NULL, id2 tinyint(4) NOT NULL);
+INSERT INTO t1 VALUES (1, 1),(1, 2),(1, 3),(1, 4),(1, 5),(2, 1),(2, 2),(2, 3);
+CREATE TABLE t2 (id1 tinyint(4) NOT NULL);
+INSERT INTO t2 VALUES (1),(2),(3),(4),(5);
+SELECT t1.id1, GROUP_CONCAT(t1.id2 ORDER BY t1.id2 ASC) AS concat_id FROM t1, t2 WHERE t1.id1 = t2.id1 AND t1.id1=1 GROUP BY t1.id1;
+id1 concat_id
+1 1,2,3,4,5
+SELECT t1.id1, GROUP_CONCAT(t1.id2 ORDER BY t1.id2 ASC) AS concat_id FROM t1, t2 WHERE t1.id1 = t2.id1 GROUP BY t1.id1;
+id1 concat_id
+1 1,2,3,4,5
+2 1,2,3
+SELECT t1.id1, GROUP_CONCAT(t1.id2 ORDER BY t1.id2 DESC) AS concat_id FROM t1, t2 WHERE t1.id1 = t2.id1 GROUP BY t1.id1;
+id1 concat_id
+1 5,4,3,2,1
+2 3,2,1
+SELECT t1.id1, GROUP_CONCAT(t1.id2 ORDER BY 6-t1.id2 ASC) AS concat_id FROM t1, t2 WHERE t1.id1 = t2.id1 GROUP BY t1.id1;
+id1 concat_id
+1 5,4,3,2,1
+2 3,2,1
+SELECT t1.id1, GROUP_CONCAT(t1.id2,6-t1.id2 ORDER BY 6-t1.id2 ASC) AS concat_id FROM t1, t2 WHERE t1.id1 = t2.id1 GROUP BY t1.id1;
+id1 concat_id
+1 51,42,33,24,15
+2 33,24,15
+SELECT t1.id1, GROUP_CONCAT(t1.id2,6-t1.id2 ORDER BY 6-t1.id2 ASC) AS concat_id FROM t1, t2 WHERE t1.id1 = t2.id1 GROUP BY t1.id1;
+id1 concat_id
+1 51,42,33,24,15
+2 33,24,15
+SELECT t1.id1, GROUP_CONCAT(t1.id2,"/",6-t1.id2 ORDER BY 1+0,6-t1.id2,t1.id2 ASC) AS concat_id FROM t1, t2 WHERE t1.id1 = t2.id1 GROUP BY t1.id1;
+id1 concat_id
+1 5/1,4/2,3/3,2/4,1/5
+2 3/3,2/4,1/5
+drop table t1,t2;
+create table t1 (s1 char(10), s2 int not null);
+insert into t1 values ('a',2),('b',2),('c',1),('a',3),('b',4),('c',4);
+select distinct s1 from t1 order by s2;
+s1
+c
+a
+b
+select group_concat(distinct s1) from t1;
+group_concat(distinct s1)
+a,b,c
+select group_concat(distinct s1 order by s2) from t1 where s2 < 4;
+group_concat(distinct s1 order by s2)
+c,b,a
+select group_concat(distinct s1 order by s2) from t1;
+group_concat(distinct s1 order by s2)
+c,b,a,c
+drop table t1;
+create table t1 (a int, c int);
+insert into t1 values (1, 2), (2, 3), (2, 4), (3, 5);
+create table t2 (a int, c int);
+insert into t2 values (1, 5), (2, 4), (3, 3), (3,3);
+select group_concat(c) from t1;
+group_concat(c)
+2,3,4,5
+select group_concat(c order by (select c from t2 where t2.a=t1.a limit 1)) as grp from t1;
+grp
+5,4,3,2
+select group_concat(c order by (select mid(group_concat(c order by a),1,5) from t2 where t2.a=t1.a)) as grp from t1;
+grp
+5,4,3,2
+select group_concat(c order by (select mid(group_concat(c order by a),1,5) from t2 where t2.a=t1.a) desc) as grp from t1;
+grp
+2,4,3,5
+select a,c,(select group_concat(c order by a) from t2 where a=t1.a) as grp from t1 order by grp;
+a c grp
+3 5 3,3
+2 3 4
+2 4 4
+1 2 5
+drop table t1,t2;
diff --git a/mysql-test/t/func_gconcat.test b/mysql-test/t/func_gconcat.test
index d004c81f14e..87df427616a 100644
--- a/mysql-test/t/func_gconcat.test
+++ b/mysql-test/t/func_gconcat.test
@@ -50,22 +50,12 @@ select grp,group_concat(c order by grp desc) from t1 group by grp order by grp;
select grp, group_concat(a separator "")+0 from t1 group by grp;
select grp, group_concat(a separator "")+0.0 from t1 group by grp;
select grp, ROUND(group_concat(a separator "")) from t1 group by grp;
+drop table t1;
# Test NULL values
-drop table t1;
create table t1 (grp int, c char(10));
-insert into t1 values (1,NULL);
-insert into t1 values (2,"b");
-insert into t1 values (2,NULL);
-insert into t1 values (3,"E");
-insert into t1 values (3,NULL);
-insert into t1 values (3,"D");
-insert into t1 values (3,NULL);
-insert into t1 values (3,NULL);
-insert into t1 values (3,"D");
-insert into t1 values (4,"");
-insert into t1 values (5,NULL);
+insert into t1 values (1,NULL),(2,"b"),(2,NULL),(3,"E"),(3,NULL),(3,"D"),(3,NULL),(3,NULL),(3,"D"),(4,""),(5,NULL);
select grp,group_concat(c order by c) from t1 group by grp;
# Test warnings
@@ -129,4 +119,58 @@ insert into t1 values (0,"a"),(0,"b"),(1,"c");
insert into t2 values (1),(2),(3);
select group_concat(a1 order by (t1.a IN (select a0 from t2))) from t1;
select group_concat(a1 order by (t1.a)) from t1;
-drop table t1, t2; \ No newline at end of file
+drop table t1, t2;
+
+#
+# Problem with GROUP BY (Bug #2695)
+#
+
+CREATE TABLE t1 (id1 tinyint(4) NOT NULL, id2 tinyint(4) NOT NULL);
+INSERT INTO t1 VALUES (1, 1),(1, 2),(1, 3),(1, 4),(1, 5),(2, 1),(2, 2),(2, 3);
+CREATE TABLE t2 (id1 tinyint(4) NOT NULL);
+INSERT INTO t2 VALUES (1),(2),(3),(4),(5);
+SELECT t1.id1, GROUP_CONCAT(t1.id2 ORDER BY t1.id2 ASC) AS concat_id FROM t1, t2 WHERE t1.id1 = t2.id1 AND t1.id1=1 GROUP BY t1.id1;
+SELECT t1.id1, GROUP_CONCAT(t1.id2 ORDER BY t1.id2 ASC) AS concat_id FROM t1, t2 WHERE t1.id1 = t2.id1 GROUP BY t1.id1;
+SELECT t1.id1, GROUP_CONCAT(t1.id2 ORDER BY t1.id2 DESC) AS concat_id FROM t1, t2 WHERE t1.id1 = t2.id1 GROUP BY t1.id1;
+SELECT t1.id1, GROUP_CONCAT(t1.id2 ORDER BY 6-t1.id2 ASC) AS concat_id FROM t1, t2 WHERE t1.id1 = t2.id1 GROUP BY t1.id1;
+
+# The following failed when it was run twice:
+SELECT t1.id1, GROUP_CONCAT(t1.id2,6-t1.id2 ORDER BY 6-t1.id2 ASC) AS concat_id FROM t1, t2 WHERE t1.id1 = t2.id1 GROUP BY t1.id1;
+SELECT t1.id1, GROUP_CONCAT(t1.id2,6-t1.id2 ORDER BY 6-t1.id2 ASC) AS concat_id FROM t1, t2 WHERE t1.id1 = t2.id1 GROUP BY t1.id1;
+
+SELECT t1.id1, GROUP_CONCAT(t1.id2,"/",6-t1.id2 ORDER BY 1+0,6-t1.id2,t1.id2 ASC) AS concat_id FROM t1, t2 WHERE t1.id1 = t2.id1 GROUP BY t1.id1;
+drop table t1,t2;
+
+#
+# Problem with distinct (Bug #3381)
+#
+
+create table t1 (s1 char(10), s2 int not null);
+insert into t1 values ('a',2),('b',2),('c',1),('a',3),('b',4),('c',4);
+select distinct s1 from t1 order by s2;
+select group_concat(distinct s1) from t1;
+select group_concat(distinct s1 order by s2) from t1 where s2 < 4;
+# The following is wrong and needs to be fixed ASAP
+select group_concat(distinct s1 order by s2) from t1;
+drop table t1;
+
+#
+# Test with subqueries (Bug #3319)
+#
+
+create table t1 (a int, c int);
+insert into t1 values (1, 2), (2, 3), (2, 4), (3, 5);
+create table t2 (a int, c int);
+insert into t2 values (1, 5), (2, 4), (3, 3), (3,3);
+select group_concat(c) from t1;
+select group_concat(c order by (select c from t2 where t2.a=t1.a limit 1)) as grp from t1;
+
+select group_concat(c order by (select mid(group_concat(c order by a),1,5) from t2 where t2.a=t1.a)) as grp from t1;
+select group_concat(c order by (select mid(group_concat(c order by a),1,5) from t2 where t2.a=t1.a) desc) as grp from t1;
+
+# The following returns random results as we are sorting on blob addresses
+# select group_concat(c order by (select group_concat(c order by a) from t2 where t2.a=t1.a)) as grp from t1;
+# select group_concat(c order by (select group_concat(c) from t2 where a=t1.a)) as grp from t1;
+
+select a,c,(select group_concat(c order by a) from t2 where a=t1.a) as grp from t1 order by grp;
+drop table t1,t2;
diff --git a/mysql-test/t/func_group.test b/mysql-test/t/func_group.test
index ce89cbe1b22..2bd4838f934 100644
--- a/mysql-test/t/func_group.test
+++ b/mysql-test/t/func_group.test
@@ -134,7 +134,6 @@ select max(t2.a1) from t1 left outer join t2 on t1.a2=t2.a1 and 1=0 where t2.a1=
select max(t1.a2),max(t2.a1) from t1 left outer join t2 on t1.a1=10;
drop table t1,t2;
-
#
# Tests to check MIN/MAX query optimization
#
diff --git a/sql-common/client.c b/sql-common/client.c
index b94f3e1de38..4a4de33269b 100644
--- a/sql-common/client.c
+++ b/sql-common/client.c
@@ -2044,7 +2044,7 @@ error:
/* Free alloced memory */
end_server(mysql);
mysql_close_free(mysql);
- if (!(client_flag & CLIENT_REMEMBER_OPTIONS))
+ if (!(((ulong) client_flag) & CLIENT_REMEMBER_OPTIONS))
mysql_close_free_options(mysql);
}
DBUG_RETURN(0);
diff --git a/sql/derror.cc b/sql/derror.cc
index 53d0dc5b7e5..09f43d20044 100644
--- a/sql/derror.cc
+++ b/sql/derror.cc
@@ -50,7 +50,7 @@ static bool read_texts(const char *file_name,const char ***point,
char name[FN_REFLEN];
const char *buff;
uchar head[32],*pos;
- CHARSET_INFO *cset;
+ CHARSET_INFO *cset; // For future
DBUG_ENTER("read_texts");
*point=0; // If something goes wrong
@@ -137,7 +137,7 @@ err1:
if (file != FERR)
VOID(my_close(file,MYF(MY_WME)));
unireg_abort(1);
- DBUG_RETURN(1); // Impossible
+ DBUG_RETURN(1); // keep compiler happy
} /* read_texts */
diff --git a/sql/field.cc b/sql/field.cc
index 89c6464c5f0..89c955ed45a 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -161,13 +161,6 @@ static bool test_if_real(const char *str,int length, CHARSET_INFO *cs)
}
#endif
-static inline uint field_length_without_space(const char *ptr, uint length)
-{
- const char *end= ptr+length;
- while (end > ptr && end[-1] == ' ')
- end--;
- return (uint) (end-ptr);
-}
/*
Tables of filed type compatibility.
@@ -306,7 +299,7 @@ Field::Field(char *ptr_arg,uint32 length_arg,uchar *null_ptr_arg,
field_name(field_name_arg),
query_id(0), key_start(0), part_of_key(0), part_of_sortkey(0),
unireg_check(unireg_check_arg),
- field_length(length_arg),null_bit(null_bit_arg),abs_offset(0)
+ field_length(length_arg),null_bit(null_bit_arg)
{
flags=null_ptr ? 0: NOT_NULL_FLAG;
comment.str= (char*) "";
@@ -5536,7 +5529,7 @@ uint32 calc_pack_length(enum_field_types type,uint32 length)
case FIELD_TYPE_ENUM: abort(); return 0; // This shouldn't happen
default: return 0;
}
- return 0; // This shouldn't happen
+ return 0; // Keep compiler happy
}
diff --git a/sql/field.h b/sql/field.h
index 27fe3858fe6..0752dbae2fc 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -78,7 +78,6 @@ public:
uint32 field_length; // Length of field
uint16 flags;
uchar null_bit; // Bit used to test null bit
- uint abs_offset; // use only in group_concat
Field(char *ptr_arg,uint32 length_arg,uchar *null_ptr_arg,uchar null_bit_arg,
utype unireg_check_arg, const char *field_name_arg,
diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc
index 5d3d2a2fb4f..e0abe5a22e0 100644
--- a/sql/ha_innodb.cc
+++ b/sql/ha_innodb.cc
@@ -134,7 +134,6 @@ static mysql_byte* innobase_get_key(INNOBASE_SHARE *share,uint *length,
my_bool not_used __attribute__((unused)));
static INNOBASE_SHARE *get_share(const char *table_name);
static void free_share(INNOBASE_SHARE *share);
-static void innobase_print_error(const char* db_errpfx, char* buffer);
/* General functions */
@@ -1292,18 +1291,6 @@ innobase_close_connection(
return(0);
}
-/**********************************************************************
-Prints an error message. */
-static
-void
-innobase_print_error(
-/*=================*/
- const char* db_errpfx, /* in: error prefix text */
- char* buffer) /* in: error text */
-{
- sql_print_error("%s: %s", db_errpfx, buffer);
-}
-
/*****************************************************************************
** InnoDB database tables
diff --git a/sql/item.cc b/sql/item.cc
index 48e35f06ec3..80086c3afd7 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -746,7 +746,6 @@ String *Item_param::query_val_str(String* str)
case INT_RESULT:
case REAL_RESULT:
return val_str(str);
- break;
default:
str->set("'", 1, default_charset());
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 24d60b51eab..ae6658c8e35 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -1472,16 +1472,12 @@ cmp_item* cmp_item::get_comparator(Item *item)
switch (item->result_type()) {
case STRING_RESULT:
return new cmp_item_sort_string(item->collation.collation);
- break;
case INT_RESULT:
return new cmp_item_int;
- break;
case REAL_RESULT:
return new cmp_item_real;
- break;
case ROW_RESULT:
return new cmp_item_row;
- break;
default:
DBUG_ASSERT(0);
break;
diff --git a/sql/item_func.cc b/sql/item_func.cc
index fdc0ee9d6a0..d7e778171a0 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -1143,7 +1143,6 @@ String *Item_func_min_max::val_str(String *str)
// This case should never be choosen
DBUG_ASSERT(0);
return 0;
-
}
return 0; // Keep compiler happy
}
@@ -2442,7 +2441,6 @@ Item_func_set_user_var::check()
save_result.vint= args[0]->val_int();
break;
}
- break;
case STRING_RESULT:
{
save_result.vstr= args[0]->val_str(&value);
@@ -2494,7 +2492,6 @@ Item_func_set_user_var::update()
INT_RESULT, &my_charset_bin, DERIVATION_NONE);
break;
}
- break;
case STRING_RESULT:
{
if (!save_result.vstr) // Null value
diff --git a/sql/item_geofunc.cc b/sql/item_geofunc.cc
index a1305e0b1d9..555c1a74eaf 100644
--- a/sql/item_geofunc.cc
+++ b/sql/item_geofunc.cc
@@ -66,7 +66,6 @@ String *Item_func_geometry_from_wkb::val_str(String *str)
String arg_val;
String *wkb= args[0]->val_str(&arg_val);
Geometry_buffer buffer;
- Geometry *geom;
uint32 srid= 0;
if ((arg_count == 2) && !args[1]->null_value)
@@ -78,7 +77,7 @@ String *Item_func_geometry_from_wkb::val_str(String *str)
str->q_append(srid);
if ((null_value=
(args[0]->null_value ||
- !(geom= Geometry::create_from_wkb(&buffer, wkb->ptr(), wkb->length())) ||
+ !Geometry::create_from_wkb(&buffer, wkb->ptr(), wkb->length()) ||
str->append(*wkb))))
return 0;
return str;
@@ -126,12 +125,11 @@ String *Item_func_as_wkb::val_str(String *str)
String arg_val;
String *swkb= args[0]->val_str(&arg_val);
Geometry_buffer buffer;
- Geometry *geom;
if ((null_value=
(args[0]->null_value ||
- !(geom= Geometry::create_from_wkb(&buffer, swkb->ptr() + SRID_SIZE,
- swkb->length() - SRID_SIZE)))))
+ !(Geometry::create_from_wkb(&buffer, swkb->ptr() + SRID_SIZE,
+ swkb->length() - SRID_SIZE)))))
return 0;
str->copy(swkb->ptr() + SRID_SIZE, swkb->length() - SRID_SIZE,
@@ -701,10 +699,10 @@ longlong Item_func_srid::val_int()
Geometry_buffer buffer;
Geometry *geom;
- null_value= !swkb ||
- !(geom= Geometry::create_from_wkb(&buffer,
- swkb->ptr() + SRID_SIZE,
- swkb->length() - SRID_SIZE));
+ null_value= (!swkb ||
+ !Geometry::create_from_wkb(&buffer,
+ swkb->ptr() + SRID_SIZE,
+ swkb->length() - SRID_SIZE));
if (null_value)
return 0;
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index 113ef0e1922..7df2299239f 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -41,7 +41,11 @@ Item_sum::Item_sum(List<Item> &list)
list.empty(); // Fields are used
}
-// Constructor used in processing select with temporary tebles
+
+/*
+ Constructor used in processing select with temporary tebles
+*/
+
Item_sum::Item_sum(THD *thd, Item_sum *item):
Item_result_field(thd, item), quick_group(item->quick_group)
{
@@ -55,6 +59,7 @@ Item_sum::Item_sum(THD *thd, Item_sum *item):
args[i]= item->args[i];
}
+
void Item_sum::mark_as_sum_func()
{
current_thd->lex->current_select->with_sum_func= 1;
@@ -1495,10 +1500,17 @@ String *Item_sum_udf_str::val_str(String *str)
/*****************************************************************************
GROUP_CONCAT function
- Syntax:
- GROUP_CONCAT([DISTINCT] expr,... [ORDER BY col [ASC|DESC],...]
- [SEPARATOR str_const])
+
+ SQL SYNTAX:
+ GROUP_CONCAT([DISTINCT] expr,... [ORDER BY col [ASC|DESC],...]
+ [SEPARATOR str_const])
+
concat of values from "group by" operation
+
+ BUGS
+ DISTINCT and ORDER BY only works if ORDER BY uses all fields and only fields
+ in expression list
+ Blobs doesn't work with DISTINCT or ORDER BY
*****************************************************************************/
/*
@@ -1510,24 +1522,22 @@ int group_concat_key_cmp_with_distinct(void* arg, byte* key1,
byte* key2)
{
Item_func_group_concat* item= (Item_func_group_concat*)arg;
+ uint *offset= item->field_offsets+ item->field_list_offset;
+ Item **field_item, **end;
- for (uint i= 0; i < item->arg_count_field; i++)
+ for (field_item= item->args, end= field_item+item->arg_count_field;
+ field_item < end;
+ field_item++)
{
- Item *field_item= item->args[i];
- Field *field= field_item->real_item()->get_tmp_table_field();
+ Field *field= (*field_item)->real_item()->get_tmp_table_field();
if (field)
{
- uint offset= field->abs_offset;
-
- int res= field->key_cmp(key1 + offset, key2 + offset);
- /*
- if key1 and key2 is not equal than field->key_cmp return offset. This
- function must return value 1 for this case.
- */
- if (res)
- return 1;
+ int res;
+ if ((res= field->key_cmp(key1 + *offset, key2 + *offset)))
+ return res;
+ offset++;
}
- }
+ }
return 0;
}
@@ -1540,22 +1550,23 @@ int group_concat_key_cmp_with_distinct(void* arg, byte* key1,
int group_concat_key_cmp_with_order(void* arg, byte* key1, byte* key2)
{
Item_func_group_concat* item= (Item_func_group_concat*)arg;
+ uint *offset= item->field_offsets;
+ ORDER **order_item, **end;
- for (uint i=0; i < item->arg_count_order; i++)
+ for (order_item= item->order, end=order_item+ item->arg_count_order;
+ order_item < end;
+ order_item++)
{
- ORDER *order_item= item->order[i];
- Item *item= *order_item->item;
+ Item *item= *(*order_item)->item;
Field *field= item->real_item()->get_tmp_table_field();
if (field)
{
- uint offset= field->abs_offset;
-
- bool dir= order_item->asc;
- int res= field->key_cmp(key1 + offset, key2 + offset);
+ int res= field->key_cmp(key1 + *offset, key2 + *offset);
if (res)
- return dir ? res : -res;
+ return (*order_item)->asc ? res : -res;
+ offset++;
}
- }
+ }
/*
We can't return 0 because tree class remove this item as double value.
*/
@@ -1566,6 +1577,11 @@ int group_concat_key_cmp_with_order(void* arg, byte* key1, byte* key2)
/*
function of sort for syntax:
GROUP_CONCAT(DISTINCT expr,... ORDER BY col,... )
+
+ BUG:
+ This doesn't work in the case when the order by contains data that
+ is not part of the field list because tree-insert will not notice
+ the duplicated values when inserting things sorted by ORDER BY
*/
int group_concat_key_cmp_with_distinct_and_order(void* arg,byte* key1,
@@ -1578,58 +1594,53 @@ int group_concat_key_cmp_with_distinct_and_order(void* arg,byte* key1,
/*
- create result
- item is pointer to Item_func_group_concat
+ Append data from current leaf to item->result
*/
int dump_leaf_key(byte* key, uint32 count __attribute__((unused)),
- Item_func_group_concat *group_concat_item)
+ Item_func_group_concat *item)
{
char buff[MAX_FIELD_WIDTH];
String tmp((char *)&buff,sizeof(buff),default_charset_info);
String tmp2((char *)&buff,sizeof(buff),default_charset_info);
-
+ uint *field_offsets= (item->field_offsets +
+ item->field_list_offset);
tmp.length(0);
- for (uint i= 0; i < group_concat_item->arg_show_fields; i++)
+ for (uint i= 0; i < item->arg_count_field; i++)
{
- Item *show_item= group_concat_item->args[i];
+ Item *show_item= item->args[i];
if (!show_item->const_item())
{
Field *f= show_item->real_item()->get_tmp_table_field();
char *sv= f->ptr;
- f->ptr= (char *)key + f->abs_offset;
+ f->ptr= (char *) key + *(field_offsets++);
String *res= f->val_str(&tmp,&tmp2);
- group_concat_item->result.append(*res);
+ item->result.append(*res);
f->ptr= sv;
}
else
{
String *res= show_item->val_str(&tmp);
if (res)
- group_concat_item->result.append(*res);
+ item->result.append(*res);
}
}
- if (group_concat_item->tree_mode) // Last item of tree
+ if (item->tree_mode) // Last item of tree
{
- group_concat_item->show_elements++;
- if (group_concat_item->show_elements <
- group_concat_item->tree->elements_in_tree)
- group_concat_item->result.append(*group_concat_item->separator);
+ item->show_elements++;
+ if (item->show_elements < item->tree->elements_in_tree)
+ item->result.append(*item->separator);
}
else
+ item->result.append(*item->separator);
+
+ /* stop if length of result more than group_concat_max_len */
+ if (item->result.length() > item->group_concat_max_len)
{
- group_concat_item->result.append(*group_concat_item->separator);
- }
- /*
- if length of result more than group_concat_max_len - stop !
- */
- if (group_concat_item->result.length() >
- group_concat_item->group_concat_max_len)
- {
- group_concat_item->count_cut_values++;
- group_concat_item->result.length(group_concat_item->group_concat_max_len);
- group_concat_item->warning_for_row= TRUE;
+ item->count_cut_values++;
+ item->result.length(item->group_concat_max_len);
+ item->warning_for_row= TRUE;
return 1;
}
return 0;
@@ -1654,51 +1665,85 @@ Item_func_group_concat::Item_func_group_concat(bool is_distinct,
separator(is_separator), tree(&tree_base), table(0),
order(0), tables_list(0),
show_elements(0), arg_count_order(0), arg_count_field(0),
- arg_show_fields(0), count_cut_values(0)
-
+ count_cut_values(0)
{
+ Item *item_select;
+ Item **arg_ptr;
+
original= 0;
quick_group= 0;
mark_as_sum_func();
order= 0;
group_concat_max_len= current_thd->variables.group_concat_max_len;
-
- arg_show_fields= arg_count_field= is_select->elements;
+ arg_count_field= is_select->elements;
arg_count_order= is_order ? is_order->elements : 0;
- arg_count= arg_count_field;
+ arg_count= arg_count_field + arg_count_order;
/*
We need to allocate:
- args - arg_count+arg_count_order (for possible order items in temporare
- tables)
+ args - arg_count_field+arg_count_order
+ (for possible order items in temporare tables)
order - arg_count_order
+ field_offset For offset withing the key
*/
- args= (Item**) sql_alloc(sizeof(Item*)*(arg_count+arg_count_order)+
- sizeof(ORDER*)*arg_count_order);
- if (!args)
+ if (!(args= (Item**) sql_alloc((sizeof(Item*) + sizeof(uint)) * arg_count +
+ sizeof(ORDER*)*arg_count_order)))
return;
+ order= (ORDER**)(args + arg_count);
+ field_offsets= (uint*) (order+ arg_count_order);
+
/* fill args items of show and sort */
- int i= 0;
List_iterator_fast<Item> li(*is_select);
- Item *item_select;
- for ( ; (item_select= li++) ; i++)
- args[i]= item_select;
+ for (arg_ptr=args ; (item_select= li++) ; arg_ptr++)
+ *arg_ptr= item_select;
if (arg_count_order)
{
- i= 0;
- order= (ORDER**)(args + arg_count + arg_count_order);
+ ORDER **order_ptr= order;
for (ORDER *order_item= (ORDER*) is_order->first;
- order_item != NULL;
- order_item= order_item->next)
+ order_item != NULL;
+ order_item= order_item->next)
{
- order[i++]= order_item;
+ (*order_ptr++)= order_item;
+ *arg_ptr= *order_item->item;
+ order_item->item= arg_ptr++;
}
}
}
+
+
+Item_func_group_concat::Item_func_group_concat(THD *thd,
+ Item_func_group_concat *item)
+ :Item_sum(thd, item),item_thd(thd),
+ tmp_table_param(item->tmp_table_param),
+ max_elements_in_tree(item->max_elements_in_tree),
+ warning(item->warning),
+ warning_available(item->warning_available),
+ key_length(item->key_length),
+ rec_offset(item->rec_offset),
+ tree_mode(item->tree_mode),
+ distinct(item->distinct),
+ warning_for_row(item->warning_for_row),
+ separator(item->separator),
+ tree(item->tree),
+ table(item->table),
+ order(item->order),
+ field_offsets(item->field_offsets),
+ tables_list(item->tables_list),
+ group_concat_max_len(item->group_concat_max_len),
+ show_elements(item->show_elements),
+ arg_count_order(item->arg_count_order),
+ arg_count_field(item->arg_count_field),
+ field_list_offset(item->field_list_offset),
+ count_cut_values(item->count_cut_values),
+ original(item)
+{
+ quick_group= item->quick_group;
+}
+
void Item_func_group_concat::cleanup()
@@ -1737,12 +1782,11 @@ Item_func_group_concat::~Item_func_group_concat()
*/
if (!original)
{
- THD *thd= current_thd;
if (warning_available)
{
char warn_buff[MYSQL_ERRMSG_SIZE];
sprintf(warn_buff, ER(ER_CUT_VALUE_GROUP_CONCAT), count_cut_values);
- warning->set_msg(thd, warn_buff);
+ warning->set_msg(current_thd, warn_buff);
}
}
}
@@ -1773,13 +1817,15 @@ void Item_func_group_concat::clear()
bool Item_func_group_concat::add()
{
+ bool record_is_null;
+
if (always_null)
return 0;
copy_fields(tmp_table_param);
copy_funcs(tmp_table_param->items_to_copy);
- bool record_is_null= TRUE;
- for (uint i= 0; i < arg_show_fields; i++)
+ record_is_null= TRUE;
+ for (uint i= 0; i < arg_count_field; i++)
{
Item *show_item= args[i];
if (!show_item->const_item())
@@ -1803,8 +1849,7 @@ bool Item_func_group_concat::add()
else
{
if (result.length() <= group_concat_max_len && !warning_for_row)
- dump_leaf_key(table->record[0] + rec_offset, 1,
- (Item_func_group_concat*)this);
+ dump_leaf_key(table->record[0] + rec_offset, 1, this);
}
return 0;
}
@@ -1832,24 +1877,19 @@ Item_func_group_concat::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
thd->allow_sum_func= 0;
maybe_null= 0;
item_thd= thd;
- for (i= 0 ; i < arg_count ; i++)
- {
- if (args[i]->fix_fields(thd, tables, args + i) || args[i]->check_cols(1))
- return 1;
- maybe_null |= args[i]->maybe_null;
- }
+
/*
- Fix fields for order clause in function:
- GROUP_CONCAT(expr,... ORDER BY col,... )
+ Fix fields for select list and ORDER clause
*/
- for (i= 0 ; i < arg_count_order ; i++)
+
+ for (i= 0 ; i < arg_count ; i++)
{
- // order_item->item can be changed by fix_fields() call
- ORDER *order_item= order[i];
- if ((*order_item->item)->fix_fields(thd, tables, order_item->item) ||
- (*order_item->item)->check_cols(1))
+ if (args[i]->fix_fields(thd, tables, args + i) || args[i]->check_cols(1))
return 1;
+ if (i < arg_count_field && args[i]->maybe_null)
+ maybe_null= 0;
}
+
result_field= 0;
null_value= 1;
max_length= group_concat_max_len;
@@ -1864,23 +1904,29 @@ Item_func_group_concat::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
bool Item_func_group_concat::setup(THD *thd)
{
- DBUG_ENTER("Item_func_group_concat::setup");
List<Item> list;
SELECT_LEX *select_lex= thd->lex->current_select;
+ Field **field, **field_end;
+ uint offset, *offsets, const_fields;
+ qsort_cmp2 compare_key;
+ DBUG_ENTER("Item_func_group_concat::setup");
if (select_lex->linkage == GLOBAL_OPTIONS_TYPE)
DBUG_RETURN(1);
+
/*
push all not constant fields to list and create temp table
*/
+ const_fields= 0;
always_null= 0;
- for (uint i= 0; i < arg_count; i++)
+ for (uint i= 0; i < arg_count_field; i++)
{
Item *item= args[i];
if (list.push_back(item))
DBUG_RETURN(1);
if (item->const_item())
{
+ const_fields++;
(void) item->val_int();
if (item->null_value)
always_null= 1;
@@ -1900,12 +1946,19 @@ bool Item_func_group_concat::setup(THD *thd)
count_field_types(tmp_table_param,all_fields,0);
if (table)
{
+ /*
+ We come here when we are getting the result from a temporary table,
+ not the original tables used in the query
+ */
free_tmp_table(thd, table);
tmp_table_param->cleanup();
}
/*
- We have to create a temporary table for that we get descriptions of fields
+ We have to create a temporary table to get descriptions of fields
(types, sizes and so on).
+
+ Note that in the table, we first have the ORDER BY fields, then the
+ field list.
*/
if (!(table=create_tmp_table(thd, tmp_table_param, all_fields, 0,
0, 0, 0,select_lex->options | thd->options,
@@ -1914,27 +1967,27 @@ bool Item_func_group_concat::setup(THD *thd)
table->file->extra(HA_EXTRA_NO_ROWS);
table->no_rows= 1;
-
- Field** field, **field_end;
- field_end = (field = table->field) + table->fields;
- uint offset = 0;
- for (key_length = 0; field < field_end; ++field)
+ field_end= (field= table->field) + table->fields;
+ offsets= field_offsets;
+ offset= 0;
+ for (key_length= 0; field < field_end; field++)
{
uint32 length= (*field)->pack_length();
- (*field)->abs_offset= offset;
+ (*offsets++)= offset;
offset+= length;
key_length += length;
- }
- rec_offset = table->reclength - key_length;
+ }
+ /* Offset to first result field in table */
+ field_list_offset= table->fields - (list.elements - const_fields);
+ /* Offset to first field */
+ rec_offset= (uint) (table->field[0]->ptr - table->record[0]);
if (tree_mode)
delete_tree(tree);
- /*
- choise function of sort
- */
+
+ /* choose function of sort */
tree_mode= distinct || arg_count_order;
- qsort_cmp2 compare_key;
if (tree_mode)
{
if (arg_count_order)
@@ -1946,21 +1999,20 @@ bool Item_func_group_concat::setup(THD *thd)
}
else
{
+ compare_key= NULL;
if (distinct)
compare_key= (qsort_cmp2) group_concat_key_cmp_with_distinct;
- else
- compare_key= NULL;
}
/*
- Create a tree of sort. Tree is used for a sort and a remove dubl
- values (according with syntax of the function). If function does't
+ Create a tree of sort. Tree is used for a sort and a remove double
+ values (according with syntax of the function). If function doesn't
contain DISTINCT and ORDER BY clauses, we don't create this tree.
*/
init_tree(tree, min(thd->variables.max_heap_table_size,
- thd->variables.sortbuff_size/16), 0,
+ thd->variables.sortbuff_size/16), 0,
key_length, compare_key, 0, NULL, (void*) this);
- max_elements_in_tree= ((key_length) ?
- thd->variables.max_heap_table_size/key_length : 1);
+ max_elements_in_tree= (key_length ?
+ thd->variables.max_heap_table_size/key_length : 1);
};
/*
@@ -1975,6 +2027,7 @@ bool Item_func_group_concat::setup(THD *thd)
DBUG_RETURN(0);
}
+
/* This is used by rollup to create a separate usable copy of the function */
void Item_func_group_concat::make_unique()
@@ -2017,7 +2070,7 @@ void Item_func_group_concat::print(String *str)
str->append("group_concat(", 13);
if (distinct)
str->append("distinct ", 9);
- for (uint i= 0; i < arg_count; i++)
+ for (uint i= 0; i < arg_count_field; i++)
{
if (i)
str->append(',');
diff --git a/sql/item_sum.h b/sql/item_sum.h
index 1c31f1a9b70..cac080c5807 100644
--- a/sql/item_sum.h
+++ b/sql/item_sum.h
@@ -204,18 +204,24 @@ class Item_sum_count_distinct :public Item_sum_int
uint key_length;
CHARSET_INFO *key_charset;
- // calculated based on max_heap_table_size. If reached,
- // walk the tree and dump it into MyISAM table
+ /*
+ Calculated based on max_heap_table_size. If reached,
+ walk the tree and dump it into MyISAM table
+ */
uint max_elements_in_tree;
- // the first few bytes of record ( at least one)
- // are just markers for deleted and NULLs. We want to skip them since
- // they will just bloat the tree without providing any valuable info
+ /*
+ The first few bytes of record ( at least one)
+ are just markers for deleted and NULLs. We want to skip them since
+ they will just bloat the tree without providing any valuable info
+ */
int rec_offset;
- // If there are no blobs, we can use a tree, which
- // is faster than heap table. In that case, we still use the table
- // to help get things set up, but we insert nothing in it
+ /*
+ If there are no blobs, we can use a tree, which
+ is faster than heap table. In that case, we still use the table
+ to help get things set up, but we insert nothing in it
+ */
bool use_tree;
bool always_null; // Set to 1 if the result is always NULL
@@ -236,7 +242,8 @@ class Item_sum_count_distinct :public Item_sum_int
Item_sum_count_distinct(THD *thd, Item_sum_count_distinct *item)
:Item_sum_int(thd, item), table(item->table),
used_table_cache(item->used_table_cache),
- field_lengths(item->field_lengths), tmp_table_param(item->tmp_table_param),
+ field_lengths(item->field_lengths),
+ tmp_table_param(item->tmp_table_param),
tree(item->tree), original(item), key_length(item->key_length),
max_elements_in_tree(item->max_elements_in_tree),
rec_offset(item->rec_offset), use_tree(item->use_tree),
@@ -318,18 +325,17 @@ public:
void fix_length_and_dec() {}
};
-/*
-
-variance(a) =
-
-= sum (ai - avg(a))^2 / count(a) )
-= sum (ai^2 - 2*ai*avg(a) + avg(a)^2) / count(a)
-= (sum(ai^2) - sum(2*ai*avg(a)) + sum(avg(a)^2))/count(a) =
-= (sum(ai^2) - 2*avg(a)*sum(a) + count(a)*avg(a)^2)/count(a) =
-= (sum(ai^2) - 2*sum(a)*sum(a)/count(a) + count(a)*sum(a)^2/count(a)^2 )/count(a) =
-= (sum(ai^2) - 2*sum(a)^2/count(a) + sum(a)^2/count(a) )/count(a) =
-= (sum(ai^2) - sum(a)^2/count(a))/count(a)
+/*
+ variance(a) =
+
+ = sum (ai - avg(a))^2 / count(a) )
+ = sum (ai^2 - 2*ai*avg(a) + avg(a)^2) / count(a)
+ = (sum(ai^2) - sum(2*ai*avg(a)) + sum(avg(a)^2))/count(a) =
+ = (sum(ai^2) - 2*avg(a)*sum(a) + count(a)*avg(a)^2)/count(a) =
+ = (sum(ai^2) - 2*sum(a)*sum(a)/count(a) + count(a)*sum(a)^2/count(a)^2 )/count(a) =
+ = (sum(ai^2) - 2*sum(a)^2/count(a) + sum(a)^2/count(a) )/count(a) =
+ = (sum(ai^2) - sum(a)^2/count(a))/count(a)
*/
class Item_sum_variance : public Item_sum_num
@@ -515,8 +521,9 @@ class Item_sum_xor :public Item_sum_bit
/*
-** user defined aggregates
+ User defined aggregates
*/
+
#ifdef HAVE_DLOPEN
class Item_udf_sum : public Item_sum
@@ -682,12 +689,13 @@ class Item_func_group_concat : public Item_sum
friend int group_concat_key_cmp_with_distinct(void* arg, byte* key1,
byte* key2);
- friend int group_concat_key_cmp_with_order(void* arg, byte* key1, byte* key2);
+ friend int group_concat_key_cmp_with_order(void* arg, byte* key1,
+ byte* key2);
friend int group_concat_key_cmp_with_distinct_and_order(void* arg,
byte* key1,
byte* key2);
friend int dump_leaf_key(byte* key, uint32 count __attribute__((unused)),
- Item_func_group_concat *group_concat_item);
+ Item_func_group_concat *group_concat_item);
public:
String result;
@@ -696,12 +704,13 @@ class Item_func_group_concat : public Item_sum
TREE *tree;
TABLE *table;
ORDER **order;
+ uint *field_offsets;
TABLE_LIST *tables_list;
ulong group_concat_max_len;
uint show_elements;
uint arg_count_order;
uint arg_count_field;
- uint arg_show_fields;
+ uint field_list_offset;
uint count_cut_values;
/*
Following is 0 normal object and pointer to original one for copy
@@ -712,38 +721,12 @@ class Item_func_group_concat : public Item_sum
Item_func_group_concat(bool is_distinct,List<Item> *is_select,
SQL_LIST *is_order,String *is_separator);
- Item_func_group_concat(THD *thd, Item_func_group_concat *item)
- :Item_sum(thd, item),item_thd(thd),
- tmp_table_param(item->tmp_table_param),
- max_elements_in_tree(item->max_elements_in_tree),
- warning(item->warning),
- warning_available(item->warning_available),
- key_length(item->key_length),
- rec_offset(item->rec_offset),
- tree_mode(item->tree_mode),
- distinct(item->distinct),
- warning_for_row(item->warning_for_row),
- separator(item->separator),
- tree(item->tree),
- table(item->table),
- order(item->order),
- tables_list(item->tables_list),
- group_concat_max_len(item->group_concat_max_len),
- show_elements(item->show_elements),
- arg_count_order(item->arg_count_order),
- arg_count_field(item->arg_count_field),
- arg_show_fields(item->arg_show_fields),
- count_cut_values(item->count_cut_values),
- original(item)
- {
- quick_group= item->quick_group;
- };
+ Item_func_group_concat(THD *thd, Item_func_group_concat *item);
~Item_func_group_concat();
void cleanup();
enum Sumfunctype sum_func () const {return GROUP_CONCAT_FUNC;}
const char *func_name() const { return "group_concat"; }
- enum Type type() const { return SUM_FUNC_ITEM; }
virtual Item_result result_type () const { return STRING_RESULT; }
void clear();
bool add();
diff --git a/sql/log.cc b/sql/log.cc
index 6b091484a82..0cd9e7172c3 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -507,7 +507,6 @@ int MYSQL_LOG::find_log_pos(LOG_INFO *linfo, const char *log_name,
RETURN VALUES
0 ok
LOG_INFO_EOF End of log-index-file found
- LOG_INFO_SEEK Could not allocate IO cache
LOG_INFO_IO Got IO error while reading file
*/
diff --git a/sql/log_event.cc b/sql/log_event.cc
index 742cf6a1a82..84bbc496c9d 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -83,7 +83,7 @@ inline int ignored_error_code(int err_code)
pretty_print_str()
*/
-#ifndef MYSQL_CLIENT
+#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
static char *pretty_print_str(char *packet, char *str, int len)
{
char *end= str + len;
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index d602c44c8f9..4f58ff33f04 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -2361,9 +2361,8 @@ Now disabling --log-slave-updates.");
{
if (global_system_variables.log_warnings)
sql_print_error("Warning: Failed to lock memory. Errno: %d\n",errno);
+ locked_in_memory= 0;
}
- else
- locked_in_memory=1;
}
#else
locked_in_memory=0;
diff --git a/sql/protocol.cc b/sql/protocol.cc
index 40adc9e8961..61af6ffceaf 100644
--- a/sql/protocol.cc
+++ b/sql/protocol.cc
@@ -166,10 +166,10 @@ net_printf(THD *thd, uint errcode, ...)
const char *format;
#ifndef EMBEDDED_LIBRARY
const char *text_pos;
+ int head_length= NET_HEADER_SIZE;
#else
char text_pos[1024];
#endif
- int head_length= NET_HEADER_SIZE;
NET *net= &thd->net;
DBUG_ENTER("net_printf");
diff --git a/sql/set_var.cc b/sql/set_var.cc
index 5d2a6c1d39e..b99816eaccd 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -838,7 +838,8 @@ bool update_sys_var_str(sys_var_str *var_str, rw_lock_t *var_mutex,
{
char *res= 0, *old_value=(char *)(var ? var->value->str_value.ptr() : 0);
uint new_length= (var ? var->value->str_value.length() : 0);
- if (!old_value) old_value="";
+ if (!old_value)
+ old_value= (char*) "";
if (!(res= my_strdup_with_length(old_value, new_length, MYF(0))))
return 1;
/*
diff --git a/sql/slave.cc b/sql/slave.cc
index be9a5795233..fedf9e3dd69 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -285,8 +285,9 @@ int init_relay_log_pos(RELAY_LOG_INFO* rli,const char* log,
In this case, we will use the same IO_CACHE pointer to
read data as the IO thread is using to write data.
*/
- if (my_b_tell((rli->cur_log=rli->relay_log.get_log_file())) == 0 &&
- check_binlog_magic(rli->cur_log,errmsg))
+ rli->cur_log= rli->relay_log.get_log_file();
+ if (my_b_tell(rli->cur_log) == 0 &&
+ check_binlog_magic(rli->cur_log, errmsg))
goto err;
rli->cur_log_old_open_count=rli->relay_log.get_open_count();
}
@@ -1672,7 +1673,18 @@ int init_master_info(MASTER_INFO* mi, const char* master_info_fname,
DBUG_ENTER("init_master_info");
if (mi->inited)
+ {
+ /*
+ We have to reset read position of relay-log-bin as we may have
+ already been reading from 'hotlog' when the slave was stopped
+ last time. If this case pos_in_file would be set and we would
+ get a crash when trying to read the signature for the binary
+ relay log.
+ */
+ my_b_seek(mi->rli.cur_log, (my_off_t) 0);
DBUG_RETURN(0);
+ }
+
mi->mysql=0;
mi->file_id=1;
fn_format(fname, master_info_fname, mysql_data_home, "", 4+32);
@@ -3616,13 +3628,16 @@ int queue_event(MASTER_INFO* mi,const char* buf, ulong event_len)
mi->master_log_pos+= inc_pos;
DBUG_PRINT("info", ("master_log_pos: %d, event originating from the same server, ignored", (ulong) mi->master_log_pos));
}
- else /* write the event to the relay log */
+ else
+ {
+ /* write the event to the relay log */
if (likely(!(error= rli->relay_log.appendv(buf,event_len,0))))
{
mi->master_log_pos+= inc_pos;
DBUG_PRINT("info", ("master_log_pos: %d", (ulong) mi->master_log_pos));
rli->relay_log.harvest_bytes_written(&rli->log_space_total);
}
+ }
err:
pthread_mutex_unlock(&mi->data_lock);
@@ -4090,8 +4105,9 @@ Before assert, my_b_tell(cur_log)=%s rli->event_relay_log_pos=%s",
if (rli->relay_log.is_active(rli->linfo.log_file_name))
{
#ifdef EXTRA_DEBUG
- sql_print_error("next log '%s' is currently active",
- rli->linfo.log_file_name);
+ if (global_system_variables.log_warnings)
+ sql_print_error("next log '%s' is currently active",
+ rli->linfo.log_file_name);
#endif
rli->cur_log= cur_log= rli->relay_log.get_log_file();
rli->cur_log_old_open_count= rli->relay_log.get_open_count();
@@ -4119,8 +4135,9 @@ Before assert, my_b_tell(cur_log)=%s rli->event_relay_log_pos=%s",
from hot to cold, but not from cold to hot). No need for LOCK_log.
*/
#ifdef EXTRA_DEBUG
- sql_print_error("next log '%s' is not active",
- rli->linfo.log_file_name);
+ if (global_system_variables.log_warnings)
+ sql_print_error("next log '%s' is not active",
+ rli->linfo.log_file_name);
#endif
// open_binlog() will check the magic header
if ((rli->cur_log_fd=open_binlog(cur_log,rli->linfo.log_file_name,
diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc
index 39061a6501b..e1a15eff475 100644
--- a/sql/sql_cache.cc
+++ b/sql/sql_cache.cc
@@ -1860,11 +1860,11 @@ my_bool Query_cache::write_result_data(Query_cache_block **result_block,
{
// It is success (nobody can prevent us write data)
STRUCT_UNLOCK(&structure_guard_mutex);
- byte *rest = (byte*) data;
- Query_cache_block *block = *result_block;
uint headers_len = (ALIGN_SIZE(sizeof(Query_cache_block)) +
ALIGN_SIZE(sizeof(Query_cache_result)));
#ifndef EMBEDDED_LIBRARY
+ Query_cache_block *block= *result_block;
+ byte *rest= (byte*) data;
// Now fill list of blocks that created by allocate_data_chain
do
{
diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc
index ea47ca9f71d..81269a8cbcf 100644
--- a/sql/sql_derived.cc
+++ b/sql/sql_derived.cc
@@ -115,7 +115,6 @@ static int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit,
TABLE *table;
int res;
select_union *derived_result;
- TABLE_LIST *tables= (TABLE_LIST *)first_select->table_list.first;
bool is_union= first_select->next_select() &&
first_select->next_select()->linkage == UNION_TYPE;
bool is_subsel= first_select->first_inner_unit() ? 1: 0;
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index a0117a079a5..fff52ce40bd 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -21,12 +21,14 @@
#include "sql_acl.h"
static int check_null_fields(THD *thd,TABLE *entry);
+#ifndef EMBEDDED_LIBRARY
static TABLE *delayed_get_table(THD *thd,TABLE_LIST *table_list);
static int write_delayed(THD *thd,TABLE *table, enum_duplicates dup,
char *query, uint query_length, int log_on);
static void end_delayed_insert(THD *thd);
extern "C" pthread_handler_decl(handle_delayed_insert,arg);
static void unlink_blobs(register TABLE *table);
+#endif
/* Define to force use of my_malloc() if the allocated memory block is big */
@@ -127,7 +129,9 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
TABLE *table;
List_iterator_fast<List_item> its(values_list);
List_item *values;
- char *query=thd->query;
+#ifndef EMBEDDED_LIBRARY
+ char *query= thd->query;
+#endif
thr_lock_type lock_type = table_list->lock_type;
TABLE_LIST *insert_table_list= (TABLE_LIST*)
thd->lex->select_lex.table_list.first;
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index df7d487194a..4c63a8b7c7f 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -1389,7 +1389,7 @@ create_total_list_n_last_return(THD *thd_arg,
}
}
}
-end:
+
if (slave_list_first)
{
*new_table_list= slave_list_first;
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index b9d85a23011..15aef1a9acc 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -396,6 +396,7 @@ public:
SQL_LIST order_list; /* ORDER clause */
List<List_item> expr_list;
List<List_item> when_list; /* WHEN clause (expression) */
+ SQL_LIST *gorder_list;
ha_rows select_limit, offset_limit; /* LIMIT clause parameters */
// Arrays of pointers to top elements of all_fields list
Item **ref_pointer_array;
@@ -538,7 +539,6 @@ typedef struct st_lex
gptr yacc_yyss,yacc_yyvs;
THD *thd;
CHARSET_INFO *charset;
- SQL_LIST *gorder_list;
List<key_part_spec> col_list;
List<key_part_spec> ref_list;
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 68ef195cdc4..6d989ecf154 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -48,7 +48,9 @@
extern "C" int gethostname(char *name, int namelen);
#endif
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
static int check_for_max_user_connections(THD *thd, USER_CONN *uc);
+#endif
static void decrease_user_connections(USER_CONN *uc);
static bool check_db_used(THD *thd,TABLE_LIST *tables);
static bool check_merge_table_access(THD *thd, char *db, TABLE_LIST *tables);
@@ -426,6 +428,8 @@ void init_max_user_conn(void)
1 error
*/
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+
static int check_for_max_user_connections(THD *thd, USER_CONN *uc)
{
int error=0;
@@ -456,7 +460,7 @@ static int check_for_max_user_connections(THD *thd, USER_CONN *uc)
(void) pthread_mutex_unlock(&LOCK_user_conn);
DBUG_RETURN(error);
}
-
+#endif /* NO_EMBEDDED_ACCESS_CHECKS */
/*
Decrease user connection count
@@ -545,15 +549,15 @@ bool is_update_query(enum enum_sql_command command)
static bool check_mqh(THD *thd, uint check_command)
{
+#ifdef NO_EMBEDDED_ACCESS_CHECKS
+ return(0);
+#else
bool error=0;
time_t check_time = thd->start_time ? thd->start_time : time(NULL);
USER_CONN *uc=thd->user_connect;
DBUG_ENTER("check_mqh");
DBUG_ASSERT(uc != 0);
-#ifdef NO_EMBEDDED_ACCESS_CHECKS
- DBUG_RETURN(0);
-#else
/* If more than a hour since last check, reset resource checking */
if (check_time - uc->intime >= 3600)
{
@@ -3518,7 +3522,10 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv,
DBUG_ENTER("check_access");
DBUG_PRINT("enter",("want_access: %lu master_access: %lu", want_access,
thd->master_access));
- ulong db_access,dummy;
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+ ulong db_access;
+#endif
+ ulong dummy;
if (save_priv)
*save_priv=0;
else
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index 94fef4cafdc..66ea32c9af4 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -1121,9 +1121,10 @@ static void reset_stmt_for_execute(Prepared_statement *stmt)
void mysql_stmt_execute(THD *thd, char *packet, uint packet_length)
{
ulong stmt_id= uint4korr(packet);
+#ifndef EMBEDDED_LIBRARY
uchar *packet_end= (uchar *) packet + packet_length - 1;
+#endif
Prepared_statement *stmt;
-
DBUG_ENTER("mysql_stmt_execute");
packet+= 9; /* stmt_id + 5 bytes of flags */
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 63fe8d77f1a..45857a89ca9 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -3608,7 +3608,6 @@ static void
make_join_readinfo(JOIN *join, uint options)
{
uint i;
- SELECT_LEX *select_lex= &join->thd->lex->select_lex;
bool statistics= test(!(join->select_options & SELECT_DESCRIBE));
DBUG_ENTER("make_join_readinfo");
@@ -3878,9 +3877,7 @@ JOIN::join_free(bool full)
else
{
for (tab= join_tab, end= tab+tables; tab != end; tab++)
- {
tab->cleanup();
- }
table= 0;
}
}
@@ -4787,7 +4784,7 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
else
return new Field_double(item_sum->max_length,maybe_null,
item->name, table, item_sum->decimals);
- case Item_sum::VARIANCE_FUNC: /* Place for sum & count */
+ case Item_sum::VARIANCE_FUNC: /* Place for sum & count */
case Item_sum::STD_FUNC:
if (group)
return new Field_string(sizeof(double)*2+sizeof(longlong),
@@ -4815,17 +4812,19 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
default:
// This case should never be choosen
DBUG_ASSERT(0);
+ thd->fatal_error();
return 0;
}
}
- thd->fatal_error();
- return 0; // Error
+ /* We never come here */
}
case Item::FIELD_ITEM:
case Item::DEFAULT_VALUE_ITEM:
- return create_tmp_field_from_field(thd, (*from_field=
- ((Item_field*) item)->field),
+ {
+ Item_field *field= (Item_field*) item;
+ return create_tmp_field_from_field(thd, (*from_field= field->field),
item, table, modify_item);
+ }
case Item::FUNC_ITEM:
case Item::COND_ITEM:
case Item::FIELD_AVG_ITEM:
@@ -8543,6 +8542,23 @@ bool JOIN::alloc_func_list()
}
+/*
+ Initialize 'sum_funcs' array with all Item_sum objects
+
+ SYNOPSIS
+ make_sum_func_list()
+ field_list All items
+ send_fields Items in select list
+ before_group_by Set to 1 if this is called before GROUP BY handling
+
+ NOTES
+ Calls ::setup() for all item_sum objects in field_list
+
+ RETURN
+ 0 ok
+ 1 error
+*/
+
bool JOIN::make_sum_func_list(List<Item> &field_list, List<Item> &send_fields,
bool before_group_by)
{
@@ -8579,7 +8595,7 @@ bool JOIN::make_sum_func_list(List<Item> &field_list, List<Item> &send_fields,
/*
- Change all funcs and sum_funcs to fields in tmp table, and create
+ Change all funcs and sum_funcs to fields in tmp table, and create
new list of all items.
change_to_use_tmp_fields()
@@ -9079,7 +9095,6 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
List<Item> field_list;
List<Item> item_list;
THD *thd=join->thd;
- SELECT_LEX *select_lex= &join->thd->lex->select_lex;
select_result *result=join->result;
Item *item_null= new Item_null();
CHARSET_INFO *cs= &my_charset_latin1;
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 30adc06fbd0..51b5b2e6077 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -31,9 +31,11 @@ static const char *grant_names[]={
"select","insert","update","delete","create","drop","reload","shutdown",
"process","file","grant","references","index","alter"};
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
static TYPELIB grant_types = { sizeof(grant_names)/sizeof(char **),
"grant_types",
grant_names};
+#endif
static int mysql_find_files(THD *thd,List<char> *files, const char *db,
const char *path, const char *wild, bool dir);
@@ -367,7 +369,9 @@ mysql_find_files(THD *thd,List<char> *files, const char *db,const char *path,
char *ext;
MY_DIR *dirp;
FILEINFO *file;
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
uint col_access=thd->col_access;
+#endif
TABLE_LIST table_list;
DBUG_ENTER("mysql_find_files");
@@ -826,7 +830,9 @@ int mysqld_show_create_db(THD *thd, char *dbname,
char path[FN_REFLEN];
char buff[2048];
String buffer(buff, sizeof(buff), system_charset_info);
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
uint db_access;
+#endif
bool found_libchar;
HA_CREATE_INFO create;
uint create_options = create_info ? create_info->options : 0;
@@ -1135,7 +1141,6 @@ append_identifier(THD *thd, String *packet, const char *name, uint length)
{
const char *name_end;
char quote_char;
- uint part_len;
if (thd->variables.sql_mode & MODE_ANSI_QUOTES)
quote_char= '\"';
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 845f0d42f26..404da12db9d 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -3054,7 +3054,7 @@ sum_expr:
| GROUP_CONCAT_SYM '(' opt_distinct expr_list opt_gorder_clause
opt_gconcat_separator ')'
{
- $$=new Item_func_group_concat($3,$4,Lex->gorder_list,$6);
+ $$=new Item_func_group_concat($3,$4,Select->gorder_list,$6);
$4->empty();
};
@@ -3070,16 +3070,15 @@ opt_gconcat_separator:
opt_gorder_clause:
/* empty */
{
- LEX *lex=Lex;
- lex->gorder_list = NULL;
+ Select->gorder_list = NULL;
}
| order_clause
{
- LEX *lex=Lex;
- lex->gorder_list=
- (SQL_LIST*) sql_memdup((char*) &lex->current_select->order_list,
+ SELECT_LEX *select= Select;
+ select->gorder_list=
+ (SQL_LIST*) sql_memdup((char*) &select->order_list,
sizeof(st_sql_list));
- lex->current_select->order_list.empty();
+ select->order_list.empty();
};