Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
M
mariadb
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
mariadb
Commits
68a159b1
Commit
68a159b1
authored
May 26, 2003
by
monty@mashka.mysql.fi
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
New 4.1 protocol; SQLSTATE, CLIENT_MULTI_RESULTS, client character set
parent
b1adadd5
Changes
12
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
279 additions
and
164 deletions
+279
-164
Docs/internals.texi
Docs/internals.texi
+12
-6
include/mysql.h
include/mysql.h
+5
-0
include/mysql_com.h
include/mysql_com.h
+10
-7
libmysql/libmysql.c
libmysql/libmysql.c
+165
-81
sql/field.cc
sql/field.cc
+1
-1
sql/field.h
sql/field.h
+1
-2
sql/mysql_priv.h
sql/mysql_priv.h
+1
-1
sql/mysqld.cc
sql/mysqld.cc
+18
-14
sql/protocol.cc
sql/protocol.cc
+42
-42
sql/protocol.h
sql/protocol.h
+0
-1
sql/repl_failsafe.cc
sql/repl_failsafe.cc
+1
-1
sql/sql_parse.cc
sql/sql_parse.cc
+23
-8
No files found.
Docs/internals.texi
View file @
68a159b1
...
@@ -1766,7 +1766,10 @@ following connection establishment sequence is followed:
...
@@ -1766,7 +1766,10 @@ following connection establishment sequence is followed:
+--------------------------------------------------------------------+
+--------------------------------------------------------------------+
| Header | CLIENT
_
xxx options supported | max
_
allowed
_
packet |
| Header | CLIENT
_
xxx options supported | max
_
allowed
_
packet |
| | by client | for client |
| | by client | for client |
| | 2 Bytes | 3 bytes |
| | 4 Bytes | 4 bytes |
|--------------------------------------------------------------------|
| Character set | Reserved for the future |
| 1 Bytes | 23 bytes |
|--------------------------------------------------------------------|
|--------------------------------------------------------------------|
| User Name | 0x00 | Crypted Password | 0x00 | Database Name |
| User Name | 0x00 | Crypted Password | 0x00 | Database Name |
| n Bytes | 1 Byte | 8 Bytes | 1 Byte | n Bytes |
| n Bytes | 1 Byte | 8 Bytes | 1 Byte | n Bytes |
...
@@ -2326,7 +2329,7 @@ Warnings
...
@@ -2326,7 +2329,7 @@ Warnings
@item
@item
Prepared statements
Prepared statements
@item
@item
Binary protocol (
will
be faster than the current protocol that
Binary protocol (
is
be faster than the current protocol that
converts everything to strings)
converts everything to strings)
@end itemize
@end itemize
...
@@ -2335,7 +2338,7 @@ What has changed in 4.1 are:
...
@@ -2335,7 +2338,7 @@ What has changed in 4.1 are:
@itemize @bullet
@itemize @bullet
@item
@item
A lot of new field information (database, real table name etc)
A lot of new field information (
catalog,
database, real table name etc)
@item
@item
The 'ok' packet has more status fields
The 'ok' packet has more status fields
@item
@item
...
@@ -2374,15 +2377,16 @@ The field description result set contains the meta info for a result set.
...
@@ -2374,15 +2377,16 @@ The field description result set contains the meta info for a result set.
@multitable @columnfractions .20 .80
@multitable @columnfractions .20 .80
@item Type @tab Comment
@item Type @tab Comment
@item string @tab Catalog name (for 5.x)
@item string @tab Database name
@item string @tab Database name
@item string @tab Table name alias (or table name if no alias)
@item string @tab Table name alias (or table name if no alias)
@item string @tab Real table name
@item string @tab Real table name
@item string @tab Alias for column name (or column name if not used)
@item string @tab Alias for column name (or column name if not used)
@item 1
1
byte @tab Fixed length fields in one field part:
@item 1
2
byte @tab Fixed length fields in one field part:
@itemize
@itemize
@item 2 byte int @tab Character set number
@item 2 byte int @tab Character set number
@item
3
byte int @tab Length of column definition
@item
4
byte int @tab Length of column definition
@item 1 byte int @tab Enum value for field type
@item 1 byte int @tab Enum value for field type
@item 3 byte int @tab 2 byte column flags (NOT
_
NULL
_
FLAG etc..) + 1 byte number of decimals.
@item 3 byte int @tab 2 byte column flags (NOT
_
NULL
_
FLAG etc..) + 1 byte number of decimals.
@item 2 byte int @tab zero (reserved for future use)
@item 2 byte int @tab zero (reserved for future use)
...
@@ -2457,7 +2461,9 @@ The error packet has the following structure:
...
@@ -2457,7 +2461,9 @@ The error packet has the following structure:
@item Size @tab Comment
@item Size @tab Comment
@item 1 @tab 255 Error packet marker
@item 1 @tab 255 Error packet marker
@item 2 @tab Error code
@item 2 @tab Error code
@item 1-255 @tab Null terminated error message
@item 1 @tab '#' marker that SQLSTATE follows
@item 6 @tab SQLSTATE code (000000 for many messages)
@item 1-512 @tab Null terminated error message
@end multitable
@end multitable
The client/server protocol is designed in such a way that a packet
The client/server protocol is designed in such a way that a packet
...
...
include/mysql.h
View file @
68a159b1
...
@@ -83,6 +83,7 @@ typedef struct st_mysql_field {
...
@@ -83,6 +83,7 @@ typedef struct st_mysql_field {
char
*
table
;
/* Table of column if column was a field */
char
*
table
;
/* Table of column if column was a field */
char
*
org_table
;
/* Org table name, if table was an alias */
char
*
org_table
;
/* Org table name, if table was an alias */
char
*
db
;
/* Database for table */
char
*
db
;
/* Database for table */
char
*
catalog
;
/* Catalog for table */
char
*
def
;
/* Default value (set by mysql_list_fields) */
char
*
def
;
/* Default value (set by mysql_list_fields) */
unsigned
long
length
;
/* Width of column */
unsigned
long
length
;
/* Width of column */
unsigned
long
max_length
;
/* Max width of selected set */
unsigned
long
max_length
;
/* Max width of selected set */
...
@@ -91,6 +92,7 @@ typedef struct st_mysql_field {
...
@@ -91,6 +92,7 @@ typedef struct st_mysql_field {
unsigned
int
table_length
;
unsigned
int
table_length
;
unsigned
int
org_table_length
;
unsigned
int
org_table_length
;
unsigned
int
db_length
;
unsigned
int
db_length
;
unsigned
int
catalog_length
;
unsigned
int
def_length
;
unsigned
int
def_length
;
unsigned
int
flags
;
/* Div flags */
unsigned
int
flags
;
/* Div flags */
unsigned
int
decimals
;
/* Number of decimals in field */
unsigned
int
decimals
;
/* Number of decimals in field */
...
@@ -346,6 +348,7 @@ my_ulonglong STDCALL mysql_affected_rows(MYSQL *mysql);
...
@@ -346,6 +348,7 @@ my_ulonglong STDCALL mysql_affected_rows(MYSQL *mysql);
my_ulonglong
STDCALL
mysql_insert_id
(
MYSQL
*
mysql
);
my_ulonglong
STDCALL
mysql_insert_id
(
MYSQL
*
mysql
);
unsigned
int
STDCALL
mysql_errno
(
MYSQL
*
mysql
);
unsigned
int
STDCALL
mysql_errno
(
MYSQL
*
mysql
);
const
char
*
STDCALL
mysql_error
(
MYSQL
*
mysql
);
const
char
*
STDCALL
mysql_error
(
MYSQL
*
mysql
);
const
char
*
STDCALL
mysql_sqlstate
(
MYSQL
*
mysql
);
unsigned
int
STDCALL
mysql_warning_count
(
MYSQL
*
mysql
);
unsigned
int
STDCALL
mysql_warning_count
(
MYSQL
*
mysql
);
const
char
*
STDCALL
mysql_info
(
MYSQL
*
mysql
);
const
char
*
STDCALL
mysql_info
(
MYSQL
*
mysql
);
unsigned
long
STDCALL
mysql_thread_id
(
MYSQL
*
mysql
);
unsigned
long
STDCALL
mysql_thread_id
(
MYSQL
*
mysql
);
...
@@ -543,6 +546,7 @@ typedef struct st_mysql_stmt
...
@@ -543,6 +546,7 @@ typedef struct st_mysql_stmt
unsigned
int
last_errno
;
/* error code */
unsigned
int
last_errno
;
/* error code */
enum
PREP_STMT_STATE
state
;
/* statement state */
enum
PREP_STMT_STATE
state
;
/* statement state */
char
last_error
[
MYSQL_ERRMSG_SIZE
];
/* error message */
char
last_error
[
MYSQL_ERRMSG_SIZE
];
/* error message */
char
sqlstate
[
SQLSTATE_LENGTH
+
1
];
my_bool
long_alloced
;
/* flag to indicate long alloced */
my_bool
long_alloced
;
/* flag to indicate long alloced */
my_bool
send_types_to_server
;
/* Types sent to server */
my_bool
send_types_to_server
;
/* Types sent to server */
my_bool
param_buffers
;
/* param bound buffers */
my_bool
param_buffers
;
/* param bound buffers */
...
@@ -560,6 +564,7 @@ my_bool STDCALL mysql_bind_result(MYSQL_STMT * stmt, MYSQL_BIND * bnd);
...
@@ -560,6 +564,7 @@ my_bool STDCALL mysql_bind_result(MYSQL_STMT * stmt, MYSQL_BIND * bnd);
my_bool
STDCALL
mysql_stmt_close
(
MYSQL_STMT
*
stmt
);
my_bool
STDCALL
mysql_stmt_close
(
MYSQL_STMT
*
stmt
);
unsigned
int
STDCALL
mysql_stmt_errno
(
MYSQL_STMT
*
stmt
);
unsigned
int
STDCALL
mysql_stmt_errno
(
MYSQL_STMT
*
stmt
);
const
char
*
STDCALL
mysql_stmt_error
(
MYSQL_STMT
*
stmt
);
const
char
*
STDCALL
mysql_stmt_error
(
MYSQL_STMT
*
stmt
);
const
char
*
STDCALL
mysql_stmt_sqlstate
(
MYSQL_STMT
*
stmt
);
my_bool
STDCALL
mysql_commit
(
MYSQL
*
mysql
);
my_bool
STDCALL
mysql_commit
(
MYSQL
*
mysql
);
my_bool
STDCALL
mysql_rollback
(
MYSQL
*
mysql
);
my_bool
STDCALL
mysql_rollback
(
MYSQL
*
mysql
);
my_bool
STDCALL
mysql_autocommit
(
MYSQL
*
mysql
,
my_bool
auto_mode
);
my_bool
STDCALL
mysql_autocommit
(
MYSQL
*
mysql
,
my_bool
auto_mode
);
...
...
include/mysql_com.h
View file @
68a159b1
...
@@ -25,6 +25,7 @@
...
@@ -25,6 +25,7 @@
#define HOSTNAME_LENGTH 60
#define HOSTNAME_LENGTH 60
#define USERNAME_LENGTH 16
#define USERNAME_LENGTH 16
#define SERVER_VERSION_LENGTH 60
#define SERVER_VERSION_LENGTH 60
#define SQLSTATE_LENGTH 6
#define LOCAL_HOST "localhost"
#define LOCAL_HOST "localhost"
#define LOCAL_HOST_NAMEDPIPE "."
#define LOCAL_HOST_NAMEDPIPE "."
...
@@ -100,20 +101,22 @@ enum enum_server_command
...
@@ -100,20 +101,22 @@ enum enum_server_command
#define CLIENT_ODBC 64
/* Odbc client */
#define CLIENT_ODBC 64
/* Odbc client */
#define CLIENT_LOCAL_FILES 128
/* Can use LOAD DATA LOCAL */
#define CLIENT_LOCAL_FILES 128
/* Can use LOAD DATA LOCAL */
#define CLIENT_IGNORE_SPACE 256
/* Ignore spaces before '(' */
#define CLIENT_IGNORE_SPACE 256
/* Ignore spaces before '(' */
#define CLIENT_PROTOCOL_41 512
/* New 4.1 protocol */
#define CLIENT_INTERACTIVE 1024
/* This is an interactive client */
#define CLIENT_INTERACTIVE 1024
/* This is an interactive client */
#define CLIENT_SSL 2048
/* Switch to SSL after handshake */
#define CLIENT_SSL 2048
/* Switch to SSL after handshake */
#define CLIENT_IGNORE_SIGPIPE 4096
/* IGNORE sigpipes */
#define CLIENT_IGNORE_SIGPIPE 4096
/* IGNORE sigpipes */
#define CLIENT_TRANSACTIONS 8192
/* Client knows about transactions */
#define CLIENT_TRANSACTIONS 8192
/* Client knows about transactions */
#define CLIENT_
PROTOCOL_41 16384
/* New
4.1 protocol */
#define CLIENT_
RESERVED 16384
/* Old flag for
4.1 protocol */
#define CLIENT_SECURE_CONNECTION 32768
/* New 4.1 authentication */
#define CLIENT_SECURE_CONNECTION 32768
/* New 4.1 authentication */
#define CLIENT_MULTI_QUERIES 65536
/* Enable/disable multi query support */
#define CLIENT_MULTI_QUERIES 65536
/* Enable/disable multiquery support */
#define CLIENT_MULTI_RESULTS 131072
/* Enable/disable multi-results */
#define SERVER_STATUS_IN_TRANS 1
/* Transaction has started */
#define SERVER_STATUS_IN_TRANS 1
/* Transaction has started */
#define SERVER_STATUS_AUTOCOMMIT 2
/* Server in auto_commit mode */
#define SERVER_STATUS_AUTOCOMMIT 2
/* Server in auto_commit mode */
#define SERVER_STATUS_MORE_RESULTS 4
/* More results on server */
#define SERVER_STATUS_MORE_RESULTS 4
/* More results on server */
#define SERVER_MORE_RESULTS_EXISTS 8
/* Multi query - next query exists */
#define SERVER_MORE_RESULTS_EXISTS 8
/* Multi query - next query exists */
#define MYSQL_ERRMSG_SIZE
200
#define MYSQL_ERRMSG_SIZE
512
#define NET_READ_TIMEOUT 30
/* Timeout on read */
#define NET_READ_TIMEOUT 30
/* Timeout on read */
#define NET_WRITE_TIMEOUT 60
/* Timeout on write */
#define NET_WRITE_TIMEOUT 60
/* Timeout on write */
#define NET_WAIT_TIMEOUT 8*60*60
/* Wait for new query */
#define NET_WAIT_TIMEOUT 8*60*60
/* Wait for new query */
...
@@ -149,7 +152,7 @@ typedef struct st_net {
...
@@ -149,7 +152,7 @@ typedef struct st_net {
queries in cache that have not stored its results yet
queries in cache that have not stored its results yet
*/
*/
#endif
#endif
char
last_error
[
MYSQL_ERRMSG_SIZE
];
char
last_error
[
MYSQL_ERRMSG_SIZE
]
,
sqlstate
[
SQLSTATE_LENGTH
+
1
]
;
unsigned
int
last_errno
;
unsigned
int
last_errno
;
unsigned
char
error
;
unsigned
char
error
;
gptr
query_cache_query
;
gptr
query_cache_query
;
...
...
libmysql/libmysql.c
View file @
68a159b1
This diff is collapsed.
Click to expand it.
sql/field.cc
View file @
68a159b1
...
@@ -5519,6 +5519,6 @@ void Field::set_warning(const uint level, const uint code)
...
@@ -5519,6 +5519,6 @@ void Field::set_warning(const uint level, const uint code)
{
{
THD
*
thd
=
current_thd
;
THD
*
thd
=
current_thd
;
thd
->
cuted_fields
++
;
thd
->
cuted_fields
++
;
push_warning_printf
(
thd
,
(
MYSQL_ERROR
::
enum_warning_level
)
level
,
push_warning_printf
(
thd
,
(
MYSQL_ERROR
::
enum_warning_level
)
level
,
code
,
ER
(
code
),
field_name
,
thd
->
row_count
);
code
,
ER
(
code
),
field_name
,
thd
->
row_count
);
}
}
sql/field.h
View file @
68a159b1
...
@@ -212,8 +212,7 @@ public:
...
@@ -212,8 +212,7 @@ public:
virtual
bool
get_time
(
TIME
*
ltime
);
virtual
bool
get_time
(
TIME
*
ltime
);
virtual
CHARSET_INFO
*
charset
(
void
)
const
{
return
&
my_charset_bin
;
}
virtual
CHARSET_INFO
*
charset
(
void
)
const
{
return
&
my_charset_bin
;
}
virtual
void
set_charset
(
CHARSET_INFO
*
charset
)
{
}
virtual
void
set_charset
(
CHARSET_INFO
*
charset
)
{
}
virtual
void
set_warning
(
const
unsigned
int
level
,
void
set_warning
(
const
unsigned
int
level
,
const
unsigned
int
code
);
const
unsigned
int
code
);
friend
bool
reopen_table
(
THD
*
,
struct
st_table
*
,
bool
);
friend
bool
reopen_table
(
THD
*
,
struct
st_table
*
,
bool
);
friend
int
cre_myisam
(
my_string
name
,
register
TABLE
*
form
,
uint
options
,
friend
int
cre_myisam
(
my_string
name
,
register
TABLE
*
form
,
uint
options
,
ulonglong
auto_increment_value
);
ulonglong
auto_increment_value
);
...
...
sql/mysql_priv.h
View file @
68a159b1
...
@@ -384,7 +384,7 @@ void table_cache_init(void);
...
@@ -384,7 +384,7 @@ void table_cache_init(void);
void
table_cache_free
(
void
);
void
table_cache_free
(
void
);
uint
cached_tables
(
void
);
uint
cached_tables
(
void
);
void
kill_mysql
(
void
);
void
kill_mysql
(
void
);
void
close_connection
(
NET
*
net
,
uint
errcode
=
0
,
bool
lock
=
1
);
void
close_connection
(
THD
*
thd
,
uint
errcode
,
bool
lock
);
bool
check_access
(
THD
*
thd
,
ulong
access
,
const
char
*
db
=
0
,
ulong
*
save_priv
=
0
,
bool
check_access
(
THD
*
thd
,
ulong
access
,
const
char
*
db
=
0
,
ulong
*
save_priv
=
0
,
bool
no_grant
=
0
,
bool
no_errors
=
0
);
bool
no_grant
=
0
,
bool
no_errors
=
0
);
bool
check_table_access
(
THD
*
thd
,
ulong
want_access
,
TABLE_LIST
*
tables
,
bool
check_table_access
(
THD
*
thd
,
ulong
want_access
,
TABLE_LIST
*
tables
,
...
...
sql/mysqld.cc
View file @
68a159b1
...
@@ -597,7 +597,6 @@ static void close_connections(void)
...
@@ -597,7 +597,6 @@ static void close_connections(void)
/* Force remaining threads to die by closing the connection to the client */
/* Force remaining threads to die by closing the connection to the client */
(
void
)
my_net_init
(
&
net
,
(
st_vio
*
)
0
);
for
(;;)
for
(;;)
{
{
DBUG_PRINT
(
"quit"
,(
"Locking LOCK_thread_count"
));
DBUG_PRINT
(
"quit"
,(
"Locking LOCK_thread_count"
));
...
@@ -609,17 +608,16 @@ static void close_connections(void)
...
@@ -609,17 +608,16 @@ static void close_connections(void)
break
;
break
;
}
}
#ifndef __bsdi__ // Bug in BSDI kernel
#ifndef __bsdi__ // Bug in BSDI kernel
if
(
(
net
.
vio
=
tmp
->
net
.
vio
)
!=
0
)
if
(
tmp
->
net
.
vio
)
{
{
sql_print_error
(
ER
(
ER_FORCING_CLOSE
),
my_progname
,
sql_print_error
(
ER
(
ER_FORCING_CLOSE
),
my_progname
,
tmp
->
thread_id
,
tmp
->
user
?
tmp
->
user
:
""
);
tmp
->
thread_id
,
tmp
->
user
?
tmp
->
user
:
""
);
close_connection
(
&
net
,
0
,
0
);
close_connection
(
tmp
,
0
,
0
);
}
}
#endif
#endif
DBUG_PRINT
(
"quit"
,(
"Unlocking LOCK_thread_count"
));
DBUG_PRINT
(
"quit"
,(
"Unlocking LOCK_thread_count"
));
(
void
)
pthread_mutex_unlock
(
&
LOCK_thread_count
);
(
void
)
pthread_mutex_unlock
(
&
LOCK_thread_count
);
}
}
net_end
(
&
net
);
/* All threads has now been aborted */
/* All threads has now been aborted */
DBUG_PRINT
(
"quit"
,(
"Waiting for threads to die (count=%u)"
,
thread_count
));
DBUG_PRINT
(
"quit"
,(
"Waiting for threads to die (count=%u)"
,
thread_count
));
(
void
)
pthread_mutex_lock
(
&
LOCK_thread_count
);
(
void
)
pthread_mutex_lock
(
&
LOCK_thread_count
);
...
@@ -1215,19 +1213,20 @@ void yyerror(const char *s)
...
@@ -1215,19 +1213,20 @@ void yyerror(const char *s)
#ifndef EMBEDDED_LIBRARY
#ifndef EMBEDDED_LIBRARY
void
close_connection
(
NET
*
net
,
uint
errcode
,
bool
lock
)
void
close_connection
(
THD
*
thd
,
uint
errcode
,
bool
lock
)
{
{
st_vio
*
vio
;
st_vio
*
vio
;
DBUG_ENTER
(
"close_connection"
);
DBUG_ENTER
(
"close_connection"
);
DBUG_PRINT
(
"enter"
,(
"fd: %s error: '%s'"
,
DBUG_PRINT
(
"enter"
,(
"fd: %s error: '%s'"
,
net
->
vio
?
vio_description
(
net
->
vio
)
:
"(not connected)"
,
thd
->
net
.
vio
?
vio_description
(
thd
->
net
.
vio
)
:
"(not connected)"
,
errcode
?
ER
(
errcode
)
:
""
));
errcode
?
ER
(
errcode
)
:
""
));
if
(
lock
)
if
(
lock
)
(
void
)
pthread_mutex_lock
(
&
LOCK_thread_count
);
(
void
)
pthread_mutex_lock
(
&
LOCK_thread_count
);
if
((
vio
=
net
->
vio
)
!=
0
)
if
((
vio
=
thd
->
net
.
vio
)
!=
0
)
{
{
if
(
errcode
)
if
(
errcode
)
net_send_error
(
net
,
errcode
,
ER
(
errcode
));
/* purecov: inspected */
send_error
(
thd
,
errcode
,
ER
(
errcode
));
/* purecov: inspected */
vio_close
(
vio
);
/* vio is freed in delete thd */
vio_close
(
vio
);
/* vio is freed in delete thd */
}
}
if
(
lock
)
if
(
lock
)
...
@@ -2717,7 +2716,7 @@ static void create_new_thread(THD *thd)
...
@@ -2717,7 +2716,7 @@ static void create_new_thread(THD *thd)
if
(
thread_count
-
delayed_insert_threads
>=
max_connections
+
1
||
abort_loop
)
if
(
thread_count
-
delayed_insert_threads
>=
max_connections
+
1
||
abort_loop
)
{
{
DBUG_PRINT
(
"error"
,(
"Too many connections"
));
DBUG_PRINT
(
"error"
,(
"Too many connections"
));
close_connection
(
net
,
ER_CON_COUNT_ERROR
);
close_connection
(
thd
,
ER_CON_COUNT_ERROR
,
1
);
delete
thd
;
delete
thd
;
DBUG_VOID_RETURN
;
DBUG_VOID_RETURN
;
}
}
...
@@ -2772,7 +2771,7 @@ static void create_new_thread(THD *thd)
...
@@ -2772,7 +2771,7 @@ static void create_new_thread(THD *thd)
(
void
)
pthread_mutex_unlock
(
&
LOCK_thread_count
);
(
void
)
pthread_mutex_unlock
(
&
LOCK_thread_count
);
net_printf
(
thd
,
ER_CANT_CREATE_THREAD
,
error
);
net_printf
(
thd
,
ER_CANT_CREATE_THREAD
,
error
);
(
void
)
pthread_mutex_lock
(
&
LOCK_thread_count
);
(
void
)
pthread_mutex_lock
(
&
LOCK_thread_count
);
close_connection
(
net
,
0
,
0
);
close_connection
(
thd
,
0
,
0
);
delete
thd
;
delete
thd
;
(
void
)
pthread_mutex_unlock
(
&
LOCK_thread_count
);
(
void
)
pthread_mutex_unlock
(
&
LOCK_thread_count
);
DBUG_VOID_RETURN
;
DBUG_VOID_RETURN
;
...
@@ -3093,7 +3092,7 @@ extern "C" pthread_handler_decl(handle_connections_namedpipes,arg)
...
@@ -3093,7 +3092,7 @@ extern "C" pthread_handler_decl(handle_connections_namedpipes,arg)
if
(
!
(
thd
->
net
.
vio
=
vio_new_win32pipe
(
hConnectedPipe
))
||
if
(
!
(
thd
->
net
.
vio
=
vio_new_win32pipe
(
hConnectedPipe
))
||
my_net_init
(
&
thd
->
net
,
thd
->
net
.
vio
))
my_net_init
(
&
thd
->
net
,
thd
->
net
.
vio
))
{
{
close_connection
(
&
thd
->
net
,
ER_OUT_OF_RESOURCES
);
close_connection
(
thd
,
ER_OUT_OF_RESOURCES
,
1
);
delete
thd
;
delete
thd
;
continue
;
continue
;
}
}
...
@@ -3294,7 +3293,7 @@ Send number of connection to client
...
@@ -3294,7 +3293,7 @@ Send number of connection to client
event_client_read
,
event_server_wrote
,
event_server_read
))
||
event_client_read
,
event_server_wrote
,
event_server_read
))
||
my_net_init
(
&
thd
->
net
,
thd
->
net
.
vio
))
my_net_init
(
&
thd
->
net
,
thd
->
net
.
vio
))
{
{
close_connection
(
&
thd
->
net
,
ER_OUT_OF_RESOURCES
);
close_connection
(
thd
,
ER_OUT_OF_RESOURCES
,
1
);
delete
thd
;
delete
thd
;
error_allow
=
TRUE
;
error_allow
=
TRUE
;
}
}
...
@@ -5284,6 +5283,11 @@ static void get_options(int argc,char **argv)
...
@@ -5284,6 +5283,11 @@ static void get_options(int argc,char **argv)
if
((
ho_error
=
handle_options
(
&
argc
,
&
argv
,
my_long_options
,
get_one_option
)))
if
((
ho_error
=
handle_options
(
&
argc
,
&
argv
,
my_long_options
,
get_one_option
)))
exit
(
ho_error
);
exit
(
ho_error
);
if
(
argc
>
0
)
{
fprintf
(
stderr
,
"%s: Too many arguments.
\n
Use --help to get a list of available options
\n
"
,
my_progname
);
exit
(
ho_error
);
}
#if defined(HAVE_BROKEN_REALPATH)
#if defined(HAVE_BROKEN_REALPATH)
my_use_symdir
=
0
;
my_use_symdir
=
0
;
...
...
sql/protocol.cc
View file @
68a159b1
...
@@ -52,7 +52,7 @@ void send_error(THD *thd, uint sql_errno, const char *err)
...
@@ -52,7 +52,7 @@ void send_error(THD *thd, uint sql_errno, const char *err)
{
{
#ifndef EMBEDDED_LIBRARY
#ifndef EMBEDDED_LIBRARY
uint
length
;
uint
length
;
char
buff
[
MYSQL_ERRMSG_SIZE
+
2
];
char
buff
[
MYSQL_ERRMSG_SIZE
+
2
]
,
*
pos
;
#endif
#endif
NET
*
net
=
&
thd
->
net
;
NET
*
net
=
&
thd
->
net
;
DBUG_ENTER
(
"send_error"
);
DBUG_ENTER
(
"send_error"
);
...
@@ -98,7 +98,14 @@ void send_error(THD *thd, uint sql_errno, const char *err)
...
@@ -98,7 +98,14 @@ void send_error(THD *thd, uint sql_errno, const char *err)
if
(
net
->
return_errno
)
if
(
net
->
return_errno
)
{
// new client code; Add errno before message
{
// new client code; Add errno before message
int2store
(
buff
,
sql_errno
);
int2store
(
buff
,
sql_errno
);
length
=
(
uint
)
(
strmake
(
buff
+
2
,
err
,
MYSQL_ERRMSG_SIZE
-
1
)
-
buff
);
pos
=
buff
+
2
;
if
(
thd
->
client_capabilities
&
CLIENT_PROTOCOL_41
)
{
/* The first # is to make the protocol backward compatible */
strmov
(
buff
+
2
,
"#000000"
);
pos
=
buff
+
2
+
SQLSTATE_LENGTH
+
1
;
}
length
=
(
uint
)
(
strmake
(
pos
,
err
,
MYSQL_ERRMSG_SIZE
-
1
)
-
buff
);
err
=
buff
;
err
=
buff
;
}
}
else
else
...
@@ -113,26 +120,6 @@ void send_error(THD *thd, uint sql_errno, const char *err)
...
@@ -113,26 +120,6 @@ void send_error(THD *thd, uint sql_errno, const char *err)
DBUG_VOID_RETURN
;
DBUG_VOID_RETURN
;
}
}
/*
Send an error to the client when a connection is forced close
This is used by mysqld.cc, which doesn't have a THD
*/
#ifndef EMBEDDED_LIBRARY
void
net_send_error
(
NET
*
net
,
uint
sql_errno
,
const
char
*
err
)
{
char
buff
[
2
];
uint
length
;
DBUG_ENTER
(
"send_net_error"
);
int2store
(
buff
,
sql_errno
);
length
=
(
uint
)
strlen
(
err
);
set_if_smaller
(
length
,
MYSQL_ERRMSG_SIZE
-
1
);
net_write_command
(
net
,(
uchar
)
255
,
buff
,
2
,
err
,
length
);
DBUG_VOID_RETURN
;
}
#endif
/*
/*
Send a warning to the end user
Send a warning to the end user
...
@@ -173,7 +160,7 @@ net_printf(THD *thd, uint errcode, ...)
...
@@ -173,7 +160,7 @@ net_printf(THD *thd, uint errcode, ...)
#ifndef EMBEDDED_LIBRARY
#ifndef EMBEDDED_LIBRARY
const
char
*
text_pos
;
const
char
*
text_pos
;
#else
#else
char
text_pos
[
500
];
char
text_pos
[
1024
];
#endif
#endif
int
head_length
=
NET_HEADER_SIZE
;
int
head_length
=
NET_HEADER_SIZE
;
NET
*
net
=
&
thd
->
net
;
NET
*
net
=
&
thd
->
net
;
...
@@ -199,9 +186,11 @@ net_printf(THD *thd, uint errcode, ...)
...
@@ -199,9 +186,11 @@ net_printf(THD *thd, uint errcode, ...)
format
=
va_arg
(
args
,
char
*
);
format
=
va_arg
(
args
,
char
*
);
errcode
=
ER_UNKNOWN_ERROR
;
errcode
=
ER_UNKNOWN_ERROR
;
}
}
offset
=
net
->
return_errno
?
2
:
0
;
offset
=
(
net
->
return_errno
?
((
thd
->
client_capabilities
&
CLIENT_PROTOCOL_41
)
?
2
+
SQLSTATE_LENGTH
+
1
:
2
)
:
0
);
#ifndef EMBEDDED_LIBRARY
#ifndef EMBEDDED_LIBRARY
text_pos
=
(
char
*
)
net
->
buff
+
head_length
+
offset
+
1
;
text_pos
=
(
char
*
)
net
->
buff
+
head_length
+
offset
+
1
;
#endif
#endif
(
void
)
vsprintf
(
my_const_cast
(
char
*
)
(
text_pos
),
format
,
args
);
(
void
)
vsprintf
(
my_const_cast
(
char
*
)
(
text_pos
),
format
,
args
);
length
=
(
uint
)
strlen
((
char
*
)
text_pos
);
length
=
(
uint
)
strlen
((
char
*
)
text_pos
);
...
@@ -228,7 +217,15 @@ net_printf(THD *thd, uint errcode, ...)
...
@@ -228,7 +217,15 @@ net_printf(THD *thd, uint errcode, ...)
net
->
buff
[
3
]
=
(
net
->
compress
)
?
0
:
(
uchar
)
(
net
->
pkt_nr
++
);
net
->
buff
[
3
]
=
(
net
->
compress
)
?
0
:
(
uchar
)
(
net
->
pkt_nr
++
);
net
->
buff
[
head_length
]
=
(
uchar
)
255
;
// Error package
net
->
buff
[
head_length
]
=
(
uchar
)
255
;
// Error package
if
(
offset
)
if
(
offset
)
int2store
(
text_pos
-
2
,
errcode
);
{
uchar
*
pos
=
net
->
buff
+
head_length
+
1
;
int2store
(
pos
,
errcode
);
if
(
thd
->
client_capabilities
&
CLIENT_PROTOCOL_41
)
{
/* The first # is to make the protocol backward compatible */
memcpy
(
pos
+
2
,
"#000000"
,
SQLSTATE_LENGTH
+
1
);
}
}
VOID
(
net_real_write
(
net
,(
char
*
)
net
->
buff
,
length
+
head_length
+
1
+
offset
));
VOID
(
net_real_write
(
net
,(
char
*
)
net
->
buff
,
length
+
head_length
+
1
+
offset
));
#else
#else
net
->
last_errno
=
errcode
;
net
->
last_errno
=
errcode
;
...
@@ -502,6 +499,7 @@ bool Protocol::send_fields(List<Item> *list, uint flag)
...
@@ -502,6 +499,7 @@ bool Protocol::send_fields(List<Item> *list, uint flag)
String
tmp
((
char
*
)
buff
,
sizeof
(
buff
),
&
my_charset_bin
);
String
tmp
((
char
*
)
buff
,
sizeof
(
buff
),
&
my_charset_bin
);
Protocol_simple
prot
(
thd
);
Protocol_simple
prot
(
thd
);
String
*
packet
=
prot
.
storage_packet
();
String
*
packet
=
prot
.
storage_packet
();
CHARSET_INFO
*
thd_charset
=
thd
->
charset
();
DBUG_ENTER
(
"send_fields"
);
DBUG_ENTER
(
"send_fields"
);
if
(
flag
&
1
)
if
(
flag
&
1
)
...
@@ -526,36 +524,37 @@ bool Protocol::send_fields(List<Item> *list, uint flag)
...
@@ -526,36 +524,37 @@ bool Protocol::send_fields(List<Item> *list, uint flag)
if
(
thd
->
client_capabilities
&
CLIENT_PROTOCOL_41
)
if
(
thd
->
client_capabilities
&
CLIENT_PROTOCOL_41
)
{
{
if
(
prot
.
store
(
field
.
db_name
,
(
uint
)
strlen
(
field
.
db_name
),
if
(
prot
.
store
(
"std"
,
3
,
cs
,
thd_charset
)
||
cs
,
thd
->
charset
())
||
prot
.
store
(
field
.
db_name
,
(
uint
)
strlen
(
field
.
db_name
),
cs
,
thd_charset
)
||
prot
.
store
(
field
.
table_name
,
(
uint
)
strlen
(
field
.
table_name
),
prot
.
store
(
field
.
table_name
,
(
uint
)
strlen
(
field
.
table_name
),
cs
,
thd
->
charset
()
)
||
cs
,
thd
_charset
)
||
prot
.
store
(
field
.
org_table_name
,
(
uint
)
strlen
(
field
.
org_table_name
),
prot
.
store
(
field
.
org_table_name
,
(
uint
)
strlen
(
field
.
org_table_name
),
cs
,
thd
->
charset
()
)
||
cs
,
thd
_charset
)
||
prot
.
store
(
field
.
col_name
,
(
uint
)
strlen
(
field
.
col_name
),
prot
.
store
(
field
.
col_name
,
(
uint
)
strlen
(
field
.
col_name
),
cs
,
thd
->
charset
()
)
||
cs
,
thd
_charset
)
||
prot
.
store
(
field
.
org_col_name
,
(
uint
)
strlen
(
field
.
org_col_name
),
prot
.
store
(
field
.
org_col_name
,
(
uint
)
strlen
(
field
.
org_col_name
),
cs
,
thd
->
charset
()
)
||
cs
,
thd
_charset
)
||
packet
->
realloc
(
packet
->
length
()
+
12
))
packet
->
realloc
(
packet
->
length
()
+
12
))
goto
err
;
goto
err
;
/* Store fixed length fields */
/* Store fixed length fields */
pos
=
(
char
*
)
packet
->
ptr
()
+
packet
->
length
();
pos
=
(
char
*
)
packet
->
ptr
()
+
packet
->
length
();
*
pos
++=
1
1
;
// Length of packed fields
*
pos
++=
1
2
;
// Length of packed fields
int2store
(
pos
,
field
.
charsetnr
);
int2store
(
pos
,
field
.
charsetnr
);
int3store
(
pos
+
2
,
field
.
length
);
int4store
(
pos
+
2
,
field
.
length
);
pos
[
5
]
=
field
.
type
;
pos
[
6
]
=
field
.
type
;
int2store
(
pos
+
6
,
field
.
flags
);
int2store
(
pos
+
7
,
field
.
flags
);
pos
[
8
]
=
(
char
)
field
.
decimals
;
pos
[
9
]
=
(
char
)
field
.
decimals
;
pos
[
9
]
=
0
;
// For the future
pos
[
10
]
=
0
;
// For the future
pos
[
10
]
=
0
;
// For the future
pos
+=
11
;
pos
[
11
]
=
0
;
// For the future
pos
+=
12
;
}
}
else
else
{
{
if
(
prot
.
store
(
field
.
table_name
,
(
uint
)
strlen
(
field
.
table_name
),
if
(
prot
.
store
(
field
.
table_name
,
(
uint
)
strlen
(
field
.
table_name
),
cs
,
thd
->
charset
()
)
||
cs
,
thd
_charset
)
||
prot
.
store
(
field
.
col_name
,
(
uint
)
strlen
(
field
.
col_name
),
prot
.
store
(
field
.
col_name
,
(
uint
)
strlen
(
field
.
col_name
),
cs
,
thd
->
charset
()
)
||
cs
,
thd
_charset
)
||
packet
->
realloc
(
packet
->
length
()
+
10
))
packet
->
realloc
(
packet
->
length
()
+
10
))
goto
err
;
goto
err
;
pos
=
(
char
*
)
packet
->
ptr
()
+
packet
->
length
();
pos
=
(
char
*
)
packet
->
ptr
()
+
packet
->
length
();
...
@@ -893,9 +892,10 @@ bool Protocol_simple::store_time(TIME *tm)
...
@@ -893,9 +892,10 @@ bool Protocol_simple::store_time(TIME *tm)
#endif
#endif
char
buff
[
40
];
char
buff
[
40
];
uint
length
;
uint
length
;
uint
day
=
(
tm
->
year
||
tm
->
month
)
?
0
:
tm
->
day
;
length
=
my_sprintf
(
buff
,(
buff
,
"%s%02ld:%02d:%02d"
,
length
=
my_sprintf
(
buff
,(
buff
,
"%s%02ld:%02d:%02d"
,
tm
->
neg
?
"-"
:
""
,
tm
->
neg
?
"-"
:
""
,
(
long
)
tm
->
day
*
3600
L
+
(
long
)
tm
->
hour
,
(
long
)
day
*
24
L
+
(
long
)
tm
->
hour
,
(
int
)
tm
->
minute
,
(
int
)
tm
->
minute
,
(
int
)
tm
->
second
));
(
int
)
tm
->
second
));
return
net_store_data
((
char
*
)
buff
,
length
);
return
net_store_data
((
char
*
)
buff
,
length
);
...
...
sql/protocol.h
View file @
68a159b1
...
@@ -162,7 +162,6 @@ void net_printf(THD *thd,uint sql_errno, ...);
...
@@ -162,7 +162,6 @@ void net_printf(THD *thd,uint sql_errno, ...);
void
send_ok
(
THD
*
thd
,
ha_rows
affected_rows
=
0L
,
ulonglong
id
=
0L
,
void
send_ok
(
THD
*
thd
,
ha_rows
affected_rows
=
0L
,
ulonglong
id
=
0L
,
const
char
*
info
=
0
);
const
char
*
info
=
0
);
void
send_eof
(
THD
*
thd
,
bool
no_flush
=
0
);
void
send_eof
(
THD
*
thd
,
bool
no_flush
=
0
);
void
net_send_error
(
NET
*
net
,
uint
sql_errno
,
const
char
*
err
);
char
*
net_store_length
(
char
*
packet
,
ulonglong
length
);
char
*
net_store_length
(
char
*
packet
,
ulonglong
length
);
char
*
net_store_length
(
char
*
packet
,
uint
length
);
char
*
net_store_length
(
char
*
packet
,
uint
length
);
char
*
net_store_data
(
char
*
to
,
const
char
*
from
,
uint
length
);
char
*
net_store_data
(
char
*
to
,
const
char
*
from
,
uint
length
);
...
...
sql/repl_failsafe.cc
View file @
68a159b1
...
@@ -72,7 +72,7 @@ static int init_failsafe_rpl_thread(THD* thd)
...
@@ -72,7 +72,7 @@ static int init_failsafe_rpl_thread(THD* thd)
if
(
init_thr_lock
()
||
thd
->
store_globals
())
if
(
init_thr_lock
()
||
thd
->
store_globals
())
{
{
close_connection
(
&
thd
->
net
,
ER_OUT_OF_RESOURCES
);
// is this needed?
close_connection
(
thd
,
ER_OUT_OF_RESOURCES
,
1
);
// is this needed?
end_thread
(
thd
,
0
);
end_thread
(
thd
,
0
);
DBUG_RETURN
(
-
1
);
DBUG_RETURN
(
-
1
);
}
}
...
...
sql/sql_parse.cc
View file @
68a159b1
...
@@ -601,7 +601,7 @@ check_connections(THD *thd)
...
@@ -601,7 +601,7 @@ check_connections(THD *thd)
{
{
/* buff[] needs to big enough to hold the server_version variable */
/* buff[] needs to big enough to hold the server_version variable */
char
buff
[
SERVER_VERSION_LENGTH
+
SCRAMBLE_LENGTH
+
64
];
char
buff
[
SERVER_VERSION_LENGTH
+
SCRAMBLE_LENGTH
+
64
];
int
client_flags
=
(
CLIENT_LONG_FLAG
|
CLIENT_CONNECT_WITH_DB
|
ulong
client_flags
=
(
CLIENT_LONG_FLAG
|
CLIENT_CONNECT_WITH_DB
|
CLIENT_PROTOCOL_41
|
CLIENT_SECURE_CONNECTION
);
CLIENT_PROTOCOL_41
|
CLIENT_SECURE_CONNECTION
);
if
(
opt_using_transactions
)
if
(
opt_using_transactions
)
...
@@ -644,11 +644,26 @@ check_connections(THD *thd)
...
@@ -644,11 +644,26 @@ check_connections(THD *thd)
return
(
ER_OUT_OF_RESOURCES
);
return
(
ER_OUT_OF_RESOURCES
);
thd
->
client_capabilities
=
uint2korr
(
net
->
read_pos
);
thd
->
client_capabilities
=
uint2korr
(
net
->
read_pos
);
#ifdef TO_BE_REMOVED_IN_4_1_RELEASE
/*
This is just a safety check against any client that would use the old
CLIENT_CHANGE_USER flag
*/
if
((
thd
->
client_capabilities
&
CLIENT_PROTOCOL_41
)
&&
!
(
thd
->
client_capabilities
&
(
CLIENT_RESERVED
|
CLIENT_SECURE_CONNECTION
|
CLIENT_MULTI_RESULTS
)))
thd
->
client_capabilities
&=
~
CLIENT_PROTOCOL_41
;
#endif
if
(
thd
->
client_capabilities
&
CLIENT_PROTOCOL_41
)
if
(
thd
->
client_capabilities
&
CLIENT_PROTOCOL_41
)
{
{
thd
->
client_capabilities
|=
((
ulong
)
uint2korr
(
net
->
read_pos
+
2
))
<<
16
;
thd
->
client_capabilities
|=
((
ulong
)
uint2korr
(
net
->
read_pos
+
2
))
<<
16
;
thd
->
max_client_packet_length
=
uint4korr
(
net
->
read_pos
+
4
);
thd
->
max_client_packet_length
=
uint4korr
(
net
->
read_pos
+
4
);
end
=
(
char
*
)
net
->
read_pos
+
8
;
if
(
!
(
thd
->
variables
.
character_set_client
=
get_charset
((
uint
)
net
->
read_pos
[
8
],
MYF
(
0
))))
thd
->
variables
.
character_set_client
=
global_system_variables
.
character_set_client
;
end
=
(
char
*
)
net
->
read_pos
+
32
;
}
}
else
else
{
{
...
@@ -778,7 +793,7 @@ pthread_handler_decl(handle_one_connection,arg)
...
@@ -778,7 +793,7 @@ pthread_handler_decl(handle_one_connection,arg)
// The following calls needs to be done before we call DBUG_ macros
// The following calls needs to be done before we call DBUG_ macros
if
(
!
(
test_flags
&
TEST_NO_THREADS
)
&
my_thread_init
())
if
(
!
(
test_flags
&
TEST_NO_THREADS
)
&
my_thread_init
())
{
{
close_connection
(
&
thd
->
net
,
ER_OUT_OF_RESOURCES
);
close_connection
(
thd
,
ER_OUT_OF_RESOURCES
,
1
);
statistic_increment
(
aborted_connects
,
&
LOCK_status
);
statistic_increment
(
aborted_connects
,
&
LOCK_status
);
end_thread
(
thd
,
0
);
end_thread
(
thd
,
0
);
return
0
;
return
0
;
...
@@ -805,7 +820,7 @@ pthread_handler_decl(handle_one_connection,arg)
...
@@ -805,7 +820,7 @@ pthread_handler_decl(handle_one_connection,arg)
#endif
#endif
if
(
thd
->
store_globals
())
if
(
thd
->
store_globals
())
{
{
close_connection
(
&
thd
->
net
,
ER_OUT_OF_RESOURCES
);
close_connection
(
thd
,
ER_OUT_OF_RESOURCES
,
1
);
statistic_increment
(
aborted_connects
,
&
LOCK_status
);
statistic_increment
(
aborted_connects
,
&
LOCK_status
);
end_thread
(
thd
,
0
);
end_thread
(
thd
,
0
);
return
0
;
return
0
;
...
@@ -863,7 +878,7 @@ pthread_handler_decl(handle_one_connection,arg)
...
@@ -863,7 +878,7 @@ pthread_handler_decl(handle_one_connection,arg)
}
}
end_thread:
end_thread:
close_connection
(
net
);
close_connection
(
thd
,
0
,
1
);
end_thread
(
thd
,
1
);
end_thread
(
thd
,
1
);
/*
/*
If end_thread returns, we are either running with --one-thread
If end_thread returns, we are either running with --one-thread
...
@@ -889,7 +904,7 @@ extern "C" pthread_handler_decl(handle_bootstrap,arg)
...
@@ -889,7 +904,7 @@ extern "C" pthread_handler_decl(handle_bootstrap,arg)
/* The following must be called before DBUG_ENTER */
/* The following must be called before DBUG_ENTER */
if
(
my_thread_init
()
||
thd
->
store_globals
())
if
(
my_thread_init
()
||
thd
->
store_globals
())
{
{
close_connection
(
&
thd
->
net
,
ER_OUT_OF_RESOURCES
);
close_connection
(
thd
,
ER_OUT_OF_RESOURCES
,
1
);
thd
->
fatal_error
();
thd
->
fatal_error
();
goto
end
;
goto
end
;
}
}
...
@@ -1419,7 +1434,7 @@ restore_user:
...
@@ -1419,7 +1434,7 @@ restore_user:
#ifndef OS2
#ifndef OS2
send_eof
(
thd
);
// This is for 'quit request'
send_eof
(
thd
);
// This is for 'quit request'
#endif
#endif
close_connection
(
net
);
close_connection
(
thd
,
0
,
1
);
close_thread_tables
(
thd
);
// Free before kill
close_thread_tables
(
thd
);
// Free before kill
free_root
(
&
thd
->
mem_root
,
MYF
(
0
));
free_root
(
&
thd
->
mem_root
,
MYF
(
0
));
free_root
(
&
thd
->
transaction
.
mem_root
,
MYF
(
0
));
free_root
(
&
thd
->
transaction
.
mem_root
,
MYF
(
0
));
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment