Commit f993a29e authored by unknown's avatar unknown

Merge work:/home/bk/mysql-4.1 into mashka.mysql.fi:/home/my/mysql-4.1


sql/sql_parse.cc:
  Auto merged
tests/client_test.c:
  Auto merged
parents e2c7d5d7 44641c78
...@@ -37,13 +37,6 @@ ...@@ -37,13 +37,6 @@
*/ */
#include "compat.h" #include "compat.h"
#if !defined(lint) && !defined(SCCSID)
#if 0
static char sccsid[] = "@(#)chared.c 8.1 (Berkeley) 6/4/93";
#else
__RCSID("$NetBSD: chared.c,v 1.14 2001/05/17 01:02:17 christos Exp $");
#endif
#endif /* not lint && not SCCSID */
/* /*
* chared.c: Character editor utilities * chared.c: Character editor utilities
......
...@@ -37,13 +37,6 @@ ...@@ -37,13 +37,6 @@
*/ */
#include "compat.h" #include "compat.h"
#if !defined(lint) && !defined(SCCSID)
#if 0
static char sccsid[] = "@(#)common.c 8.1 (Berkeley) 6/4/93";
#else
__RCSID("$NetBSD: common.c,v 1.10 2001/01/10 07:45:41 jdolecek Exp $");
#endif
#endif /* not lint && not SCCSID */
/* /*
* common.c: Common Editor functions * common.c: Common Editor functions
......
...@@ -37,13 +37,6 @@ ...@@ -37,13 +37,6 @@
*/ */
#include "compat.h" #include "compat.h"
#if !defined(lint) && !defined(SCCSID)
#if 0
static char sccsid[] = "@(#)el.c 8.2 (Berkeley) 1/3/94";
#else
__RCSID("$NetBSD: el.c,v 1.21 2001/01/05 22:45:30 christos Exp $");
#endif
#endif /* not lint && not SCCSID */
/* /*
* el.c: EditLine interface functions * el.c: EditLine interface functions
......
...@@ -37,13 +37,6 @@ ...@@ -37,13 +37,6 @@
*/ */
#include "compat.h" #include "compat.h"
#if !defined(lint) && !defined(SCCSID)
#if 0
static char sccsid[] = "@(#)emacs.c 8.1 (Berkeley) 6/4/93";
#else
__RCSID("$NetBSD: emacs.c,v 1.9 2001/01/10 07:45:41 jdolecek Exp $");
#endif
#endif /* not lint && not SCCSID */
/* /*
* emacs.c: Emacs functions * emacs.c: Emacs functions
......
...@@ -95,9 +95,10 @@ getline (char **lineptr, size_t *n, FILE *stream) ...@@ -95,9 +95,10 @@ getline (char **lineptr, size_t *n, FILE *stream)
char *fgetln(FILE *stream, size_t *len) char *fgetln(FILE *stream, size_t *len)
{ {
char *ptr = NULL; char *ptr = NULL;
int sz = 0; int sz;
size_t length= 0;
sz = getline(&ptr, &sz, stream); sz = getline(&ptr, &length, stream);
if(len) { if(len) {
*len = sz; *len = sz;
} }
......
...@@ -37,13 +37,6 @@ ...@@ -37,13 +37,6 @@
*/ */
#include "compat.h" #include "compat.h"
#if !defined(lint) && !defined(SCCSID)
#if 0
static char sccsid[] = "@(#)hist.c 8.1 (Berkeley) 6/4/93";
#else
__RCSID("$NetBSD: hist.c,v 1.9 2001/05/17 01:02:17 christos Exp $");
#endif
#endif /* not lint && not SCCSID */
/* /*
* hist.c: History access functions * hist.c: History access functions
......
...@@ -37,13 +37,6 @@ ...@@ -37,13 +37,6 @@
*/ */
#include "compat.h" #include "compat.h"
#if !defined(lint) && !defined(SCCSID)
#if 0
static char sccsid[] = "@(#)history.c 8.1 (Berkeley) 6/4/93";
#else
__RCSID("$NetBSD: history.c,v 1.17 2001/03/20 00:08:31 christos Exp $");
#endif
#endif /* not lint && not SCCSID */
/* /*
* hist.c: History access functions * hist.c: History access functions
......
...@@ -37,13 +37,6 @@ ...@@ -37,13 +37,6 @@
*/ */
#include "compat.h" #include "compat.h"
#if !defined(lint) && !defined(SCCSID)
#if 0
static char sccsid[] = "@(#)key.c 8.1 (Berkeley) 6/4/93";
#else
__RCSID("$NetBSD: key.c,v 1.12 2001/05/17 01:02:17 christos Exp $");
#endif
#endif /* not lint && not SCCSID */
/* /*
* key.c: This module contains the procedures for maintaining * key.c: This module contains the procedures for maintaining
......
...@@ -37,13 +37,6 @@ ...@@ -37,13 +37,6 @@
*/ */
#include "compat.h" #include "compat.h"
#if !defined(lint) && !defined(SCCSID)
#if 0
static char sccsid[] = "@(#)map.c 8.1 (Berkeley) 6/4/93";
#else
__RCSID("$NetBSD: map.c,v 1.14 2001/01/09 17:22:09 jdolecek Exp $");
#endif
#endif /* not lint && not SCCSID */
/* /*
* map.c: Editor function definitions * map.c: Editor function definitions
......
...@@ -37,13 +37,6 @@ ...@@ -37,13 +37,6 @@
*/ */
#include "compat.h" #include "compat.h"
#if !defined(lint) && !defined(SCCSID)
#if 0
static char sccsid[] = "@(#)parse.c 8.1 (Berkeley) 6/4/93";
#else
__RCSID("$NetBSD: parse.c,v 1.14 2001/01/23 15:55:30 jdolecek Exp $");
#endif
#endif /* not lint && not SCCSID */
/* /*
* parse.c: parse an editline extended command * parse.c: parse an editline extended command
......
...@@ -37,13 +37,6 @@ ...@@ -37,13 +37,6 @@
*/ */
#include "compat.h" #include "compat.h"
#if !defined(lint) && !defined(SCCSID)
#if 0
static char sccsid[] = "@(#)prompt.c 8.1 (Berkeley) 6/4/93";
#else
__RCSID("$NetBSD: prompt.c,v 1.8 2001/01/10 07:45:41 jdolecek Exp $");
#endif
#endif /* not lint && not SCCSID */
/* /*
* prompt.c: Prompt printing functions * prompt.c: Prompt printing functions
......
...@@ -37,13 +37,6 @@ ...@@ -37,13 +37,6 @@
*/ */
#include "compat.h" #include "compat.h"
#if !defined(lint) && !defined(SCCSID)
#if 0
static char sccsid[] = "@(#)read.c 8.1 (Berkeley) 6/4/93";
#else
__RCSID("$NetBSD: read.c,v 1.19 2001/01/10 07:45:41 jdolecek Exp $");
#endif
#endif /* not lint && not SCCSID */
/* /*
* read.c: Clean this junk up! This is horrible code. * read.c: Clean this junk up! This is horrible code.
......
...@@ -37,10 +37,6 @@ ...@@ -37,10 +37,6 @@
*/ */
#include "compat.h" #include "compat.h"
#if !defined(lint) && !defined(SCCSID)
__RCSID("$NetBSD: readline.c,v 1.19 2001/01/10 08:10:45 jdolecek Exp $");
#endif /* not lint && not SCCSID */
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <stdio.h> #include <stdio.h>
......
...@@ -37,13 +37,6 @@ ...@@ -37,13 +37,6 @@
*/ */
#include "compat.h" #include "compat.h"
#if !defined(lint) && !defined(SCCSID)
#if 0
static char sccsid[] = "@(#)refresh.c 8.1 (Berkeley) 6/4/93";
#else
__RCSID("$NetBSD: refresh.c,v 1.17 2001/04/13 00:53:11 lukem Exp $");
#endif
#endif /* not lint && not SCCSID */
/* /*
* refresh.c: Lower level screen refreshing functions * refresh.c: Lower level screen refreshing functions
......
...@@ -37,13 +37,6 @@ ...@@ -37,13 +37,6 @@
*/ */
#include "compat.h" #include "compat.h"
#if !defined(lint) && !defined(SCCSID)
#if 0
static char sccsid[] = "@(#)search.c 8.1 (Berkeley) 6/4/93";
#else
__RCSID("$NetBSD: search.c,v 1.11 2001/01/23 15:55:31 jdolecek Exp $");
#endif
#endif /* not lint && not SCCSID */
/* /*
* search.c: History and character search functions * search.c: History and character search functions
......
...@@ -37,13 +37,6 @@ ...@@ -37,13 +37,6 @@
*/ */
#include "compat.h" #include "compat.h"
#if !defined(lint) && !defined(SCCSID)
#if 0
static char sccsid[] = "@(#)sig.c 8.1 (Berkeley) 6/4/93";
#else
__RCSID("$NetBSD: sig.c,v 1.8 2001/01/09 17:31:04 jdolecek Exp $");
#endif
#endif /* not lint && not SCCSID */
/* /*
* sig.c: Signal handling stuff. * sig.c: Signal handling stuff.
......
...@@ -37,13 +37,6 @@ ...@@ -37,13 +37,6 @@
*/ */
#include "compat.h" #include "compat.h"
#if !defined(lint) && !defined(SCCSID)
#if 0
static char sccsid[] = "@(#)term.c 8.2 (Berkeley) 4/30/95";
#else
__RCSID("$NetBSD: term.c,v 1.32 2001/01/23 15:55:31 jdolecek Exp $");
#endif
#endif /* not lint && not SCCSID */
/* /*
* term.c: Editor/termcap-curses interface * term.c: Editor/termcap-curses interface
......
...@@ -37,13 +37,6 @@ ...@@ -37,13 +37,6 @@
*/ */
#include "compat.h" #include "compat.h"
#if !defined(lint) && !defined(SCCSID)
#if 0
static char sccsid[] = "@(#)tokenizer.c 8.1 (Berkeley) 6/4/93";
#else
__RCSID("$NetBSD: tokenizer.c,v 1.7 2001/01/04 15:56:32 christos Exp $");
#endif
#endif /* not lint && not SCCSID */
/* /*
* tokenize.c: Bourne shell like tokenizer * tokenize.c: Bourne shell like tokenizer
......
...@@ -37,13 +37,6 @@ ...@@ -37,13 +37,6 @@
*/ */
#include "compat.h" #include "compat.h"
#if !defined(lint) && !defined(SCCSID)
#if 0
static char sccsid[] = "@(#)tty.c 8.1 (Berkeley) 6/4/93";
#else
__RCSID("$NetBSD: tty.c,v 1.15 2001/05/17 01:02:17 christos Exp $");
#endif
#endif /* not lint && not SCCSID */
/* /*
* tty.c: tty interface stuff * tty.c: tty interface stuff
......
...@@ -37,13 +37,6 @@ ...@@ -37,13 +37,6 @@
*/ */
#include "compat.h" #include "compat.h"
#if !defined(lint) && !defined(SCCSID)
#if 0
static char sccsid[] = "@(#)vi.c 8.1 (Berkeley) 6/4/93";
#else
__RCSID("$NetBSD: vi.c,v 1.8 2000/09/04 22:06:33 lukem Exp $");
#endif
#endif /* not lint && not SCCSID */
/* /*
* vi.c: Vi mode commands. * vi.c: Vi mode commands.
......
...@@ -508,6 +508,14 @@ btr_search_check_guess( ...@@ -508,6 +508,14 @@ btr_search_check_guess(
/*===================*/ /*===================*/
/* out: TRUE if success */ /* out: TRUE if success */
btr_cur_t* cursor, /* in: guessed cursor position */ btr_cur_t* cursor, /* in: guessed cursor position */
ibool can_only_compare_to_cursor_rec,
/* in: if we do not have a latch on the page
of cursor, but only a latch on
btr_search_latch, then ONLY the columns
of the record UNDER the cursor are
protected, not the next or previous record
in the chain: we cannot look at the next or
previous record to check our guess! */
dtuple_t* tuple, /* in: data tuple */ dtuple_t* tuple, /* in: data tuple */
ulint mode, /* in: PAGE_CUR_L, PAGE_CUR_LE, PAGE_CUR_G, ulint mode, /* in: PAGE_CUR_L, PAGE_CUR_LE, PAGE_CUR_G,
or PAGE_CUR_GE */ or PAGE_CUR_GE */
...@@ -566,6 +574,13 @@ btr_search_check_guess( ...@@ -566,6 +574,13 @@ btr_search_check_guess(
} }
} }
if (can_only_compare_to_cursor_rec) {
/* Since we could not determine if our guess is right just by
looking at the record under the cursor, return FALSE */
return(FALSE);
}
match = 0; match = 0;
bytes = 0; bytes = 0;
...@@ -670,6 +685,7 @@ btr_search_guess_on_hash( ...@@ -670,6 +685,7 @@ btr_search_guess_on_hash(
ulint fold; ulint fold;
ulint tuple_n_fields; ulint tuple_n_fields;
dulint tree_id; dulint tree_id;
ibool can_only_compare_to_cursor_rec = TRUE;
#ifdef notdefined #ifdef notdefined
btr_cur_t cursor2; btr_cur_t cursor2;
btr_pcur_t pcur; btr_pcur_t pcur;
...@@ -744,6 +760,8 @@ btr_search_guess_on_hash( ...@@ -744,6 +760,8 @@ btr_search_guess_on_hash(
goto failure; goto failure;
} }
can_only_compare_to_cursor_rec = FALSE;
buf_page_dbg_add_level(page, SYNC_TREE_NODE_FROM_HASH); buf_page_dbg_add_level(page, SYNC_TREE_NODE_FROM_HASH);
} }
...@@ -775,7 +793,15 @@ btr_search_guess_on_hash( ...@@ -775,7 +793,15 @@ btr_search_guess_on_hash(
fold); fold);
*/ */
} else { } else {
success = btr_search_check_guess(cursor, tuple, mode, mtr); /* If we only have the latch on btr_search_latch, not on the
page, it only protects the columns of the record the cursor
is positioned on. We cannot look at the next of the previous
record to determine if our guess for the cursor position is
right. */
success = btr_search_check_guess(cursor,
can_only_compare_to_cursor_rec,
tuple, mode, mtr);
} }
if (!success) { if (!success) {
......
...@@ -234,10 +234,16 @@ struct btr_search_sys_struct{ ...@@ -234,10 +234,16 @@ struct btr_search_sys_struct{
extern btr_search_sys_t* btr_search_sys; extern btr_search_sys_t* btr_search_sys;
/* The latch protecting the adaptive search system: this latch protects the /* The latch protecting the adaptive search system: this latch protects the
(1) positions of records on those pages where a hash index has been built. (1) hash index;
NOTE: It does not protect values of non-ordering fields within a record from (2) columns of a record to which we have a pointer in the hash index;
being updated in-place! We can use fact (1) to perform unique searches to
indexes. */ but does NOT protect:
(3) next record offset field in a record;
(4) next or previous records on the same page.
Bear in mind (3) and (4) when using the hash index.
*/
extern rw_lock_t* btr_search_latch_temp; extern rw_lock_t* btr_search_latch_temp;
......
...@@ -60,7 +60,7 @@ noinst_PROGRAMS = charset2html @THREAD_LPROGRAMS@ ...@@ -60,7 +60,7 @@ noinst_PROGRAMS = charset2html @THREAD_LPROGRAMS@
# test_dir_DEPENDENCIES= $(LIBRARIES) # test_dir_DEPENDENCIES= $(LIBRARIES)
# testhash_DEPENDENCIES= $(LIBRARIES) # testhash_DEPENDENCIES= $(LIBRARIES)
# test_charset_DEPENDENCIES= $(LIBRARIES) # test_charset_DEPENDENCIES= $(LIBRARIES)
charset2html_DEPENDENCIES= $(LIBRARIES) # charset2html_DEPENDENCIES= $(LIBRARIES)
EXTRA_PROGRAMS = EXTRA_PROGRAMS =
DEFS = -DDEFAULT_BASEDIR=\"$(prefix)\" \ DEFS = -DDEFAULT_BASEDIR=\"$(prefix)\" \
-DDATADIR="\"$(MYSQLDATAdir)\"" \ -DDATADIR="\"$(MYSQLDATAdir)\"" \
......
...@@ -867,10 +867,11 @@ int Query_log_event::exec_event(struct st_relay_log_info* rli) ...@@ -867,10 +867,11 @@ int Query_log_event::exec_event(struct st_relay_log_info* rli)
if (db_ok(thd->db, replicate_do_db, replicate_ignore_db)) if (db_ok(thd->db, replicate_do_db, replicate_ignore_db))
{ {
thd->query = (char*)query;
thd->set_time((time_t)when); thd->set_time((time_t)when);
thd->current_tablenr = 0; thd->current_tablenr = 0;
thd->query_length= q_len;
VOID(pthread_mutex_lock(&LOCK_thread_count)); VOID(pthread_mutex_lock(&LOCK_thread_count));
thd->query = (char*)query;
thd->query_id = query_id++; thd->query_id = query_id++;
VOID(pthread_mutex_unlock(&LOCK_thread_count)); VOID(pthread_mutex_unlock(&LOCK_thread_count));
thd->query_error= 0; // clear error thd->query_error= 0; // clear error
...@@ -928,7 +929,9 @@ int Query_log_event::exec_event(struct st_relay_log_info* rli) ...@@ -928,7 +929,9 @@ int Query_log_event::exec_event(struct st_relay_log_info* rli)
else else
{ {
// master could be inconsistent, abort and tell DBA to check/fix it // master could be inconsistent, abort and tell DBA to check/fix it
VOID(pthread_mutex_lock(&LOCK_thread_count));
thd->db = thd->query = 0; thd->db = thd->query = 0;
VOID(pthread_mutex_unlock(&LOCK_thread_count));
thd->variables.convert_set = 0; thd->variables.convert_set = 0;
close_thread_tables(thd); close_thread_tables(thd);
free_root(&thd->mem_root,0); free_root(&thd->mem_root,0);
...@@ -936,7 +939,9 @@ int Query_log_event::exec_event(struct st_relay_log_info* rli) ...@@ -936,7 +939,9 @@ int Query_log_event::exec_event(struct st_relay_log_info* rli)
} }
} }
thd->db= 0; // prevent db from being freed thd->db= 0; // prevent db from being freed
VOID(pthread_mutex_lock(&LOCK_thread_count));
thd->query= 0; // just to be sure thd->query= 0; // just to be sure
VOID(pthread_mutex_unlock(&LOCK_thread_count));
// assume no convert for next query unless set explictly // assume no convert for next query unless set explictly
thd->variables.convert_set = 0; thd->variables.convert_set = 0;
close_thread_tables(thd); close_thread_tables(thd);
...@@ -1513,7 +1518,8 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli, ...@@ -1513,7 +1518,8 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli,
{ {
init_sql_alloc(&thd->mem_root, 8192,0); init_sql_alloc(&thd->mem_root, 8192,0);
thd->db = rewrite_db((char*)db); thd->db = rewrite_db((char*)db);
thd->query = 0; DBUG_ASSERT(thd->query == 0);
thd->query = 0; // Should not be needed
thd->query_error = 0; thd->query_error = 0;
if (db_ok(thd->db, replicate_do_db, replicate_ignore_db)) if (db_ok(thd->db, replicate_do_db, replicate_ignore_db))
......
...@@ -1011,6 +1011,7 @@ static int create_table_from_dump(THD* thd, NET* net, const char* db, ...@@ -1011,6 +1011,7 @@ static int create_table_from_dump(THD* thd, NET* net, const char* db,
const char* table_name) const char* table_name)
{ {
ulong packet_len = my_net_read(net); // read create table statement ulong packet_len = my_net_read(net); // read create table statement
char *query;
Vio* save_vio; Vio* save_vio;
HA_CHECK_OPT check_opt; HA_CHECK_OPT check_opt;
TABLE_LIST tables; TABLE_LIST tables;
...@@ -1030,15 +1031,23 @@ static int create_table_from_dump(THD* thd, NET* net, const char* db, ...@@ -1030,15 +1031,23 @@ static int create_table_from_dump(THD* thd, NET* net, const char* db,
return 1; return 1;
} }
thd->command = COM_TABLE_DUMP; thd->command = COM_TABLE_DUMP;
thd->query = sql_alloc(packet_len + 1); /* Note that we should not set thd->query until the area is initalized */
if (!thd->query) if (!(query = sql_alloc(packet_len + 1)))
{ {
sql_print_error("create_table_from_dump: out of memory"); sql_print_error("create_table_from_dump: out of memory");
net_printf(thd, ER_GET_ERRNO, "Out of memory"); net_printf(thd, ER_GET_ERRNO, "Out of memory");
return 1; return 1;
} }
memcpy(thd->query, net->read_pos, packet_len); memcpy(query, net->read_pos, packet_len);
thd->query[packet_len] = 0; query[packet_len]= 0;
thd->query_length= packet_len;
/*
We make the following lock in an attempt to ensure that the compiler will
not rearrange the code so that thd->query is set too soon
*/
VOID(pthread_mutex_lock(&LOCK_thread_count));
thd->query= query;
VOID(pthread_mutex_unlock(&LOCK_thread_count));
thd->current_tablenr = 0; thd->current_tablenr = 0;
thd->query_error = 0; thd->query_error = 0;
thd->net.no_send_ok = 1; thd->net.no_send_ok = 1;
...@@ -2272,7 +2281,9 @@ err: ...@@ -2272,7 +2281,9 @@ err:
// print the current replication position // print the current replication position
sql_print_error("Slave I/O thread exiting, read up to log '%s', position %s", sql_print_error("Slave I/O thread exiting, read up to log '%s', position %s",
IO_RPL_LOG_NAME, llstr(mi->master_log_pos,llbuff)); IO_RPL_LOG_NAME, llstr(mi->master_log_pos,llbuff));
VOID(pthread_mutex_lock(&LOCK_thread_count));
thd->query = thd->db = 0; // extra safety thd->query = thd->db = 0; // extra safety
VOID(pthread_mutex_unlock(&LOCK_thread_count));
if (mysql) if (mysql)
{ {
mc_mysql_close(mysql); mc_mysql_close(mysql);
...@@ -2407,7 +2418,9 @@ the slave SQL thread with \"SLAVE START\". We stopped at log \ ...@@ -2407,7 +2418,9 @@ the slave SQL thread with \"SLAVE START\". We stopped at log \
RPL_LOG_NAME, llstr(rli->master_log_pos,llbuff)); RPL_LOG_NAME, llstr(rli->master_log_pos,llbuff));
err: err:
VOID(pthread_mutex_lock(&LOCK_thread_count));
thd->query = thd->db = 0; // extra safety thd->query = thd->db = 0; // extra safety
VOID(pthread_mutex_unlock(&LOCK_thread_count));
thd->proc_info = "Waiting for slave mutex on exit"; thd->proc_info = "Waiting for slave mutex on exit";
pthread_mutex_lock(&rli->run_lock); pthread_mutex_lock(&rli->run_lock);
DBUG_ASSERT(rli->slave_running == 1); // tracking buffer overrun DBUG_ASSERT(rli->slave_running == 1); // tracking buffer overrun
......
...@@ -949,7 +949,7 @@ int mysql_table_dump(THD* thd, char* db, char* tbl_name, int fd) ...@@ -949,7 +949,7 @@ int mysql_table_dump(THD* thd, char* db, char* tbl_name, int fd)
goto err; goto err;
} }
net_flush(&thd->net); net_flush(&thd->net);
if ((error = table->file->dump(thd,fd))) if ((error= table->file->dump(thd,fd)))
my_error(ER_GET_ERRNO, MYF(0)); my_error(ER_GET_ERRNO, MYF(0));
err: err:
...@@ -1054,7 +1054,6 @@ bool dispatch_command(enum enum_server_command command, THD *thd, ...@@ -1054,7 +1054,6 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
tbl_name[tbl_len] = 0; tbl_name[tbl_len] = 0;
if (mysql_table_dump(thd, db, tbl_name, -1)) if (mysql_table_dump(thd, db, tbl_name, -1))
send_error(thd); // dump to NET send_error(thd); // dump to NET
break; break;
} }
case COM_CHANGE_USER: case COM_CHANGE_USER:
......
...@@ -164,7 +164,7 @@ static void client_connect() ...@@ -164,7 +164,7 @@ static void client_connect()
char buff[255]; char buff[255];
myheader("client_connect"); myheader("client_connect");
if(!(mysql = mysql_init(NULL))) if (!(mysql = mysql_init(NULL)))
{ {
myerror("mysql_init() failed"); myerror("mysql_init() failed");
exit(0); exit(0);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment