Commit e829e96d authored by monty@donna.mysql.fi's avatar monty@donna.mysql.fi

Patch from sleepycat to fix problem with BDB and log files

Print full command name to log files
Convert table type to supported onces on ALTER TABLE
parent f1b9242d
...@@ -10794,7 +10794,12 @@ other contexts, however. ...@@ -10794,7 +10794,12 @@ other contexts, however.
@strong{MySQL} doesn't yet support the Oracle SQL extension: @strong{MySQL} doesn't yet support the Oracle SQL extension:
@code{SELECT ... INTO TABLE ...}. @strong{MySQL} supports instead the @code{SELECT ... INTO TABLE ...}. @strong{MySQL} supports instead the
ANSI SQL syntax @code{INSERT INTO ... SELECT ...}, which is basically ANSI SQL syntax @code{INSERT INTO ... SELECT ...}, which is basically
the same thing. the same thing. @xref{INSERT}.
@example
INSERT INTO tblTemp2 (fldID) SELECT tblTemp1.fldOrder_ID FROM tblTemp1 WHERE
tblTemp1.fldOrder_ID > 100;
@end example
Alternatively, you can use @code{SELECT INTO OUTFILE...} or @code{CREATE Alternatively, you can use @code{SELECT INTO OUTFILE...} or @code{CREATE
TABLE ... SELECT} to solve your problem. TABLE ... SELECT} to solve your problem.
...@@ -11041,7 +11046,22 @@ constraints for application that can't easily be coded to avoid them. ...@@ -11041,7 +11046,22 @@ constraints for application that can't easily be coded to avoid them.
@subsection Views @subsection Views
@cindex views @cindex views
@strong{MySQL} doesn't support views, but this is on the TODO. @strong{MySQL} doesn't yet support views, but we plan to implement these
to about 4.1.
Views are mostly useful in letting user access a set of relations as one
table (in read-only mode). Many SQL databases doesn't allow one to update
any rows in a view, but you have to do the updates in the separate tables.
As @strong{MySQL} is mostly used in applications and on web system where
the application write has full control on the database usage, most of
our users haven't regarded views to be very important. (At least no one
has been interested enough of this to be prepared to finance the
implementation of views).
One doesn't need views in @strong{MySQL} to restrict access to columns
as @strong{MySQL} has a very sophisticated privilege
system. @xref{Privilege system}.
@node Missing comments, , Missing Views, Missing functions @node Missing comments, , Missing Views, Missing functions
@subsection @samp{--} as the Start of a Comment @subsection @samp{--} as the Start of a Comment
...@@ -19539,15 +19559,18 @@ or INSERT [LOW_PRIORITY | DELAYED] [IGNORE] ...@@ -19539,15 +19559,18 @@ or INSERT [LOW_PRIORITY | DELAYED] [IGNORE]
or INSERT [LOW_PRIORITY | DELAYED] [IGNORE] or INSERT [LOW_PRIORITY | DELAYED] [IGNORE]
[INTO] tbl_name [INTO] tbl_name
SET col_name=expression, col_name=expression, ... SET col_name=expression, col_name=expression, ...
or INSERT [LOW_PRIORITY] [IGNORE] [INTO] tbl_name
SELECT ...
@end example @end example
@code{INSERT} inserts new rows into an existing table. The @code{INSERT ... @code{INSERT} inserts new rows into an existing table. The @code{INSERT
VALUES} form of the statement inserts rows based on explicitly specified ... VALUES} form of the statement inserts rows based on explicitly
values. The @code{INSERT ... SELECT} form inserts rows selected from another specified values. The @code{INSERT ... SELECT} form inserts rows
table or tables. The @code{INSERT ... VALUES} form with multiple value lists selected from another table or tables. The @code{INSERT ... VALUES}
is supported in @strong{MySQL} Version 3.22.5 or later. The form with multiple value lists is supported in @strong{MySQL} Version
@code{col_name=expression} syntax is supported in @strong{MySQL} Version 3.22.10 or 3.22.5 or later. The @code{col_name=expression} syntax is supported in
later. @strong{MySQL} Version 3.22.10 or later.
@code{tbl_name} is the table into which rows should be inserted. The column @code{tbl_name} is the table into which rows should be inserted. The column
name list or the @code{SET} clause indicates which columns the statement name list or the @code{SET} clause indicates which columns the statement
...@@ -19607,9 +19630,17 @@ specify values for all columns that require a non-@code{NULL} value. ...@@ -19607,9 +19630,17 @@ specify values for all columns that require a non-@code{NULL} value.
You can find the value used for an @code{AUTO_INCREMENT} column You can find the value used for an @code{AUTO_INCREMENT} column
with the @code{mysql_insert_id} function. with the @code{mysql_insert_id} function.
@xref{mysql_insert_id, , @code{mysql_insert_id()}}. @xref{mysql_insert_id, , @code{mysql_insert_id()}}.
@end itemize
@item With @code{INSERT ... SELECT} statement you can quickly insert many rows
The following conditions hold for an @code{INSERT INTO ... SELECT} statement: into a table from one or many tables.
@example
INSERT INTO tblTemp2 (fldID) SELECT tblTemp1.fldOrder_ID FROM tblTemp1 WHERE
tblTemp1.fldOrder_ID > 100;
@end example
The following conditions hold for an @code{INSERT ... SELECT} statement:
@itemize @minus @itemize @minus
@item @item
...@@ -19626,7 +19657,6 @@ sub-select clauses, the situation could easily be very confusing!) ...@@ -19626,7 +19657,6 @@ sub-select clauses, the situation could easily be very confusing!)
@item @item
@code{AUTO_INCREMENT} columns work as usual. @code{AUTO_INCREMENT} columns work as usual.
@end itemize @end itemize
@end itemize
@findex mysql_info() @findex mysql_info()
If you use @code{INSERT ... SELECT} or an @code{INSERT ... VALUES} If you use @code{INSERT ... SELECT} or an @code{INSERT ... VALUES}
...@@ -29385,16 +29415,16 @@ going. Hopefully this will be better handled in future Linux Kernels. ...@@ -29385,16 +29415,16 @@ going. Hopefully this will be better handled in future Linux Kernels.
This should contain a technical description of the @strong{MySQL} This should contain a technical description of the @strong{MySQL}
benchmark suite (and @code{crash-me}), but that description is not benchmark suite (and @code{crash-me}), but that description is not
written yet. Currently, you should look at the code and results in the written yet. Currently, you can get a good idea of the benchmark by
@file{sql-bench} directory in the distribution (and of course on the Web page looking at the code and results in the @file{sql-bench} directory in any
at @uref{http://www.mysql.com/information/crash-me.php} and (normally found in @strong{MySQL} source distributions.
the @file{sql-bench} directory in the @strong{MySQL} distribution)).
It is meant to be a benchmark that will tell any user what things a This benchmark suite is meant to be a benchmark that will tell any user
given SQL implementation performs well or poorly at. what things a given SQL implementation performs well or poorly at.
Note that this benchmark is single threaded, so it measures the minimum Note that this benchmark is single threaded, so it measures the minimum
time for the operations. time for the operations. We plan to in the future add a lot of
multi-threaded tests to the benchmark suite.
For example, (run on the same NT 4.0 machine): For example, (run on the same NT 4.0 machine):
...@@ -29424,12 +29454,28 @@ For example, (run on the same NT 4.0 machine): ...@@ -29424,12 +29454,28 @@ For example, (run on the same NT 4.0 machine):
In the above test @strong{MySQL} was run with a 8M index cache. In the above test @strong{MySQL} was run with a 8M index cache.
We have gather some more benchmark results at
@uref{http://www.mysql.com/information/benchmarks.html}.
Note that Oracle is not included because they asked to be removed. All Note that Oracle is not included because they asked to be removed. All
Oracle benchmarks have to be passed by Oracle! We believe that makes Oracle benchmarks have to be passed by Oracle! We believe that makes
Oracle benchmarks @strong{VERY} biased because the above benchmarks are Oracle benchmarks @strong{VERY} biased because the above benchmarks are
supposed to show what a standard installation can do for a single supposed to show what a standard installation can do for a single
client. client.
To run the benchmark suite, you have to download a MySQL source distribution
install the perl DBI driver, the perl DBD driver for the database you want to
test and then do:
@example
cd sql-bench
perl run-all-tests --server=#
@end example
where # is one of supported servers. You can get a list of all options
and supported servers by doing @code{run-all-tests --help}.
@cindex crash-me
@code{crash-me} tries to determine what features a database supports and @code{crash-me} tries to determine what features a database supports and
what it's capabilities and limitations are by actually running what it's capabilities and limitations are by actually running
queries. For example, it determines: queries. For example, it determines:
...@@ -29447,6 +29493,9 @@ How big a query can be ...@@ -29447,6 +29493,9 @@ How big a query can be
How big a @code{VARCHAR} column can be How big a @code{VARCHAR} column can be
@end itemize @end itemize
We can find the result from crash-me on a lot of different databases at
@uref{http://www.mysql.com/information/crash-me.php}.
@cindex utilities @cindex utilities
@node Tools, Maintenance, MySQL Benchmarks, Top @node Tools, Maintenance, MySQL Benchmarks, Top
@chapter MySQL Utilites @chapter MySQL Utilites
...@@ -39011,6 +39060,7 @@ You can also find this at: ...@@ -39011,6 +39060,7 @@ You can also find this at:
There are 2 supported JDBC drivers for @strong{MySQL} (the mm driver and There are 2 supported JDBC drivers for @strong{MySQL} (the mm driver and
the Reisin JDBC driver). You can find a copy of the mm driver at the Reisin JDBC driver). You can find a copy of the mm driver at
@uref{http://mmmysql.sourceforge.net/} or
@uref{http://www.mysql.com/Downloads/Contrib/} and the Reisin driver at @uref{http://www.mysql.com/Downloads/Contrib/} and the Reisin driver at
@uref{http://www.caucho.com/projects/jdbc-mysql/index.xtp} For @uref{http://www.caucho.com/projects/jdbc-mysql/index.xtp} For
documentation consult any JDBC documentation and the driver's own documentation consult any JDBC documentation and the driver's own
...@@ -50,6 +50,7 @@ static const char revid[] = "$Id: log_rec.c,v 11.48 2001/01/11 18:19:53 bostic E ...@@ -50,6 +50,7 @@ static const char revid[] = "$Id: log_rec.c,v 11.48 2001/01/11 18:19:53 bostic E
#include "db_am.h" #include "db_am.h"
#include "log.h" #include "log.h"
static int __log_check_master __P((DB_ENV *, u_int8_t *, char *));
static int __log_do_open __P((DB_ENV *, DB_LOG *, static int __log_do_open __P((DB_ENV *, DB_LOG *,
u_int8_t *, char *, DBTYPE, int32_t, db_pgno_t)); u_int8_t *, char *, DBTYPE, int32_t, db_pgno_t));
static int __log_open_file __P((DB_ENV *, DB_LOG *, __log_register_args *)); static int __log_open_file __P((DB_ENV *, DB_LOG *, __log_register_args *));
...@@ -341,6 +342,9 @@ __log_do_open(dbenv, lp, uid, name, ftype, ndx, meta_pgno) ...@@ -341,6 +342,9 @@ __log_do_open(dbenv, lp, uid, name, ftype, ndx, meta_pgno)
* Verify that we are opening the same file that we were * Verify that we are opening the same file that we were
* referring to when we wrote this log record. * referring to when we wrote this log record.
*/ */
if (meta_pgno != PGNO_BASE_MD &&
__log_check_master(dbenv, uid, name) != 0)
goto not_right;
if (memcmp(uid, dbp->fileid, DB_FILE_ID_LEN) != 0) { if (memcmp(uid, dbp->fileid, DB_FILE_ID_LEN) != 0) {
memset(zeroid, 0, DB_FILE_ID_LEN); memset(zeroid, 0, DB_FILE_ID_LEN);
if (memcmp(dbp->fileid, zeroid, DB_FILE_ID_LEN) != 0) if (memcmp(dbp->fileid, zeroid, DB_FILE_ID_LEN) != 0)
...@@ -361,6 +365,28 @@ not_right: ...@@ -361,6 +365,28 @@ not_right:
return (ENOENT); return (ENOENT);
} }
static int
__log_check_master(dbenv, uid, name)
DB_ENV *dbenv;
u_int8_t *uid;
char *name;
{
DB *dbp;
int ret;
ret = 0;
if ((ret = db_create(&dbp, dbenv, 0)) != 0)
return (ret);
dbp->type = DB_BTREE;
ret = __db_dbopen(dbp, name, 0, __db_omode("rw----"), PGNO_BASE_MD);
if (ret == 0 && memcmp(uid, dbp->fileid, DB_FILE_ID_LEN) != 0)
ret = EINVAL;
(void) dbp->close(dbp, 0);
return (ret);
}
/* /*
* __log_add_logid -- * __log_add_logid --
* Adds a DB entry to the log's DB entry table. * Adds a DB entry to the log's DB entry table.
......
# This patch fixes a bug caused mysqld to get a core dump while
# bdb tries to resolve the log file after mysqld was killed with kill -9.
#
# Author: Michael Ubell, Sleepycat Software
# Mon, 26 Feb 2001 12:56:23 -0500 (EST)
#
*** log/log_rec.c 2001/02/08 03:05:01 11.50
--- log/log_rec.c 2001/02/24 00:42:46 11.51
***************
*** 50,55 ****
--- 50,56 ----
#include "db_am.h"
#include "log.h"
+ static int __log_check_master __P((DB_ENV *, u_int8_t *, char *));
static int __log_do_open __P((DB_ENV *, DB_LOG *,
u_int8_t *, char *, DBTYPE, int32_t, db_pgno_t));
static int __log_open_file __P((DB_ENV *, DB_LOG *, __log_register_args *));
***************
*** 341,346 ****
--- 342,350 ----
* Verify that we are opening the same file that we were
* referring to when we wrote this log record.
*/
+ if (meta_pgno != PGNO_BASE_MD &&
+ __log_check_master(dbenv, uid, name) != 0)
+ goto not_right;
if (memcmp(uid, dbp->fileid, DB_FILE_ID_LEN) != 0) {
memset(zeroid, 0, DB_FILE_ID_LEN);
if (memcmp(dbp->fileid, zeroid, DB_FILE_ID_LEN) != 0)
***************
*** 359,364 ****
--- 363,390 ----
(void)__log_add_logid(dbenv, lp, NULL, ndx);
return (ENOENT);
+ }
+
+ static int
+ __log_check_master(dbenv, uid, name)
+ DB_ENV *dbenv;
+ u_int8_t *uid;
+ char *name;
+ {
+ DB *dbp;
+ int ret;
+
+ ret = 0;
+ if ((ret = db_create(&dbp, dbenv, 0)) != 0)
+ return (ret);
+ dbp->type = DB_BTREE;
+ ret = __db_dbopen(dbp, name, 0, __db_omode("rw----"), PGNO_BASE_MD);
+
+ if (ret == 0 && memcmp(uid, dbp->fileid, DB_FILE_ID_LEN) != 0)
+ ret = EINVAL;
+
+ (void) dbp->close(dbp, 0);
+ return (ret);
}
/*
...@@ -22,3 +22,6 @@ libs_LIBRARIES = libibuf.a ...@@ -22,3 +22,6 @@ libs_LIBRARIES = libibuf.a
libibuf_a_SOURCES = ibuf0ibuf.c libibuf_a_SOURCES = ibuf0ibuf.c
EXTRA_PROGRAMS = EXTRA_PROGRAMS =
# Don't update the files from bitkeeper
%::SCCS/s.%
...@@ -54,3 +54,6 @@ noinst_HEADERS = btr0btr.h btr0btr.ic btr0cur.h btr0cur.ic \ ...@@ -54,3 +54,6 @@ noinst_HEADERS = btr0btr.h btr0btr.ic btr0cur.h btr0cur.ic \
usr0sess.h usr0sess.ic usr0types.h ut0byte.h ut0byte.ic \ usr0sess.h usr0sess.ic usr0types.h ut0byte.h ut0byte.ic \
ut0dbg.h ut0lst.h ut0mem.h ut0mem.ic ut0rnd.h ut0rnd.ic \ ut0dbg.h ut0lst.h ut0mem.h ut0mem.ic ut0rnd.h ut0rnd.ic \
ut0sort.h ut0ut.h ut0ut.ic ut0sort.h ut0ut.h ut0ut.ic
# Don't update the files from bitkeeper
%::SCCS/s.%
...@@ -22,3 +22,6 @@ man_MANS = mysql.1 isamchk.1 isamlog.1 mysql_zap.1 mysqlaccess.1 \ ...@@ -22,3 +22,6 @@ man_MANS = mysql.1 isamchk.1 isamlog.1 mysql_zap.1 mysqlaccess.1 \
perror.1 replace.1 safe_mysqld.1 perror.1 replace.1 safe_mysqld.1
EXTRA_DIST = $(man_MANS) EXTRA_DIST = $(man_MANS)
# Don't update the files from bitkeeper
%::SCCS/s.%
...@@ -155,6 +155,7 @@ my_bool check_table_is_closed(const char *name, const char *where) ...@@ -155,6 +155,7 @@ my_bool check_table_is_closed(const char *name, const char *where)
{ {
char filename[FN_REFLEN]; char filename[FN_REFLEN];
LIST *pos; LIST *pos;
DBUG_ENTER("check_table_is_closed");
(void) fn_format(filename,name,"",MI_NAME_IEXT,4+16+32); (void) fn_format(filename,name,"",MI_NAME_IEXT,4+16+32);
for (pos=myisam_open_list ; pos ; pos=pos->next) for (pos=myisam_open_list ; pos ; pos=pos->next)
...@@ -163,10 +164,14 @@ my_bool check_table_is_closed(const char *name, const char *where) ...@@ -163,10 +164,14 @@ my_bool check_table_is_closed(const char *name, const char *where)
MYISAM_SHARE *share=info->s; MYISAM_SHARE *share=info->s;
if (!strcmp(share->filename,filename)) if (!strcmp(share->filename,filename))
{ {
fprintf(stderr,"Warning: Table: %s is open on %s\n", name,where); if (share->last_version)
return 1; {
fprintf(stderr,"Warning: Table: %s is open on %s\n", name,where);
DBUG_PRINT("warning",("Table: %s is open on %s", name,where));
DBUG_RETURN(1);
}
} }
} }
return 0; DBUG_RETURN(0);
} }
#endif /* EXTRA_DEBUG */ #endif /* EXTRA_DEBUG */
...@@ -413,6 +413,7 @@ start_slave() ...@@ -413,6 +413,7 @@ start_slave()
--core \ --core \
--tmpdir=$MYSQL_TMP_DIR \ --tmpdir=$MYSQL_TMP_DIR \
--language=english \ --language=english \
--skip-innobase \
$SMALL_SERVER \ $SMALL_SERVER \
$EXTRA_SLAVE_OPT $EXTRA_SLAVE_MYSQLD_OPT" $EXTRA_SLAVE_OPT $EXTRA_SLAVE_MYSQLD_OPT"
if [ x$DO_DDD = x1 ] if [ x$DO_DDD = x1 ]
......
...@@ -7,7 +7,7 @@ t1 ref a,b a 9 const,const 1 where used; Using index ...@@ -7,7 +7,7 @@ t1 ref a,b a 9 const,const 1 where used; Using index
table type possible_keys key key_len ref rows Extra table type possible_keys key key_len ref rows Extra
t1 const a,b a 9 const,const 1 t1 const a,b a 9 const,const 1
table type possible_keys key key_len ref rows Extra table type possible_keys key key_len ref rows Extra
t1 index NULL a 8 NULL 12 where used; Using index t1 index NULL a 9 NULL 12 where used; Using index
table type possible_keys key key_len ref rows Extra table type possible_keys key key_len ref rows Extra
t1 range a,b a 9 NULL 3 where used; Using index t1 range a,b a 9 NULL 3 where used; Using index
table type possible_keys key key_len ref rows Extra table type possible_keys key key_len ref rows Extra
......
...@@ -499,6 +499,7 @@ innobase_end(void) ...@@ -499,6 +499,7 @@ innobase_end(void)
DBUG_ENTER("innobase_end"); DBUG_ENTER("innobase_end");
err = innobase_shutdown_for_mysql(); err = innobase_shutdown_for_mysql();
hash_free(&innobase_open_tables);
if (err != DB_SUCCESS) { if (err != DB_SUCCESS) {
...@@ -1214,7 +1215,7 @@ ha_innobase::write_row( ...@@ -1214,7 +1215,7 @@ ha_innobase::write_row(
row_prebuilt_t* prebuilt = (row_prebuilt_t*)innobase_prebuilt; row_prebuilt_t* prebuilt = (row_prebuilt_t*)innobase_prebuilt;
int error; int error;
DBUG_ENTER("write_row"); DBUG_ENTER("ha_innobase::write_row");
statistic_increment(ha_write_count, &LOCK_status); statistic_increment(ha_write_count, &LOCK_status);
...@@ -1432,7 +1433,7 @@ ha_innobase::update_row( ...@@ -1432,7 +1433,7 @@ ha_innobase::update_row(
upd_t* uvect; upd_t* uvect;
int error = 0; int error = 0;
DBUG_ENTER("update_row"); DBUG_ENTER("ha_innobase::update_row");
if (prebuilt->upd_node) { if (prebuilt->upd_node) {
uvect = prebuilt->upd_node->update; uvect = prebuilt->upd_node->update;
...@@ -1476,7 +1477,7 @@ ha_innobase::delete_row( ...@@ -1476,7 +1477,7 @@ ha_innobase::delete_row(
row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt; row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
int error = 0; int error = 0;
DBUG_ENTER("update_row"); DBUG_ENTER("ha_innobase::delete_row");
if (!prebuilt->upd_node) { if (!prebuilt->upd_node) {
row_get_prebuilt_update_vector(prebuilt); row_get_prebuilt_update_vector(prebuilt);
......
...@@ -583,7 +583,7 @@ bool MYSQL_LOG::write(THD *thd,enum enum_server_command command, ...@@ -583,7 +583,7 @@ bool MYSQL_LOG::write(THD *thd,enum enum_server_command command,
} }
else if (my_b_write(&log_file, (byte*) "\t\t",2) < 0) else if (my_b_write(&log_file, (byte*) "\t\t",2) < 0)
error=errno; error=errno;
sprintf(buff,"%7ld %-10.10s", id,command_name[(uint) command]); sprintf(buff,"%7ld %-11.11s", id,command_name[(uint) command]);
if (my_b_write(&log_file, (byte*) buff,strlen(buff))) if (my_b_write(&log_file, (byte*) buff,strlen(buff)))
error=errno; error=errno;
if (format) if (format)
......
...@@ -747,6 +747,7 @@ bool close_cached_table(THD *thd,TABLE *table) ...@@ -747,6 +747,7 @@ bool close_cached_table(THD *thd,TABLE *table)
DBUG_ENTER("close_cached_table"); DBUG_ENTER("close_cached_table");
if (table) if (table)
{ {
DBUG_PRINT("enter",("table: %s", table->table_name));
VOID(table->file->extra(HA_EXTRA_FORCE_REOPEN)); // Close all data files VOID(table->file->extra(HA_EXTRA_FORCE_REOPEN)); // Close all data files
/* Mark all tables that are in use as 'old' */ /* Mark all tables that are in use as 'old' */
mysql_lock_abort(thd,table); // end threads waiting on lock mysql_lock_abort(thd,table); // end threads waiting on lock
...@@ -1139,9 +1140,9 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -1139,9 +1140,9 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
old_db_type=table->db_type; old_db_type=table->db_type;
if (create_info->db_type == DB_TYPE_DEFAULT) if (create_info->db_type == DB_TYPE_DEFAULT)
create_info->db_type=old_db_type; create_info->db_type=old_db_type;
new_db_type=create_info->db_type= ha_checktype(create_info->db_type);
if (create_info->row_type == ROW_TYPE_DEFAULT) if (create_info->row_type == ROW_TYPE_DEFAULT)
create_info->row_type=table->row_type; create_info->row_type=table->row_type;
new_db_type=create_info->db_type;
/* Check if the user only wants to do a simple RENAME */ /* Check if the user only wants to do a simple RENAME */
...@@ -1518,6 +1519,8 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -1518,6 +1519,8 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
goto err; goto err;
} }
table=0; // Marker for win32 version table=0; // Marker for win32 version
#else
table->file->extra(HA_EXTRA_FORCE_REOPEN); // Don't use this file anymore
#endif #endif
error=0; error=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