Commit 78292e17 authored by Olivier Bertrand's avatar Olivier Bertrand

- Commit merged files

modified:
  storage/connect/colblk.h
  storage/connect/ha_connect.cc
  storage/connect/mysql-test/connect/r/csv.result
  storage/connect/mysql-test/connect/r/dbf.result
  storage/connect/mysql-test/connect/r/fix.result
  storage/connect/mysql-test/connect/r/ini.result
  storage/connect/mysql-test/connect/r/vec.result
  storage/connect/mysql-test/connect/t/csv.test
  storage/connect/mysql-test/connect/t/dbf.test
  storage/connect/mysql-test/connect/t/fix.test
  storage/connect/mysql-test/connect/t/ini.test
  storage/connect/mysql-test/connect/t/vec.test
  storage/connect/reldef.h
  storage/connect/tabdos.cpp
  storage/connect/tabdos.h
  storage/connect/tabfmt.cpp
  storage/connect/tabmysql.cpp
parents 128136cb c1973c80
This diff is collapsed.
...@@ -1103,6 +1103,7 @@ void *ha_connect::GetColumnOption(PGLOBAL g, void *field, PCOLINFO pcf) ...@@ -1103,6 +1103,7 @@ void *ha_connect::GetColumnOption(PGLOBAL g, void *field, PCOLINFO pcf)
break; break;
case TYPE_DECIM: case TYPE_DECIM:
pcf->Precision= ((Field_new_decimal*)fp)->precision; pcf->Precision= ((Field_new_decimal*)fp)->precision;
pcf->Length= pcf->Precision;
pcf->Scale= fp->decimals(); pcf->Scale= fp->decimals();
break; break;
case TYPE_DATE: case TYPE_DATE:
...@@ -4752,7 +4753,6 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd, ...@@ -4752,7 +4753,6 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
strncpy(dsn, create_info->connect_string.str, len); strncpy(dsn, create_info->connect_string.str, len);
dsn[len]= 0; dsn[len]= 0;
mydef->SetName(create_info->alias); mydef->SetName(create_info->alias);
mydef->SetCat(cat);
if (!mydef->ParseURL(g, dsn, false)) { if (!mydef->ParseURL(g, dsn, false)) {
if (mydef->GetHostname()) if (mydef->GetHostname())
...@@ -5231,21 +5231,18 @@ int ha_connect::create(const char *name, TABLE *table_arg, ...@@ -5231,21 +5231,18 @@ int ha_connect::create(const char *name, TABLE *table_arg,
int port; int port;
host= GetListOption(g, "host", options->oplist, NULL); host= GetListOption(g, "host", options->oplist, NULL);
db= GetListOption(g, "database", options->oplist, NULL); db= GetStringOption("database", NULL);
port= atoi(GetListOption(g, "port", options->oplist, "0")); port= atoi(GetListOption(g, "port", options->oplist, "0"));
if (create_info->connect_string.str) { if (create_info->connect_string.str) {
char *dsn; char *dsn;
int len= create_info->connect_string.length; int len= create_info->connect_string.length;
PMYDEF mydef= new(g) MYSQLDEF(); PMYDEF mydef= new(g) MYSQLDEF();
PDBUSER dup= PlgGetUser(g);
PCATLG cat= (dup) ? dup->Catalog : NULL;
dsn= (char*)PlugSubAlloc(g, NULL, len + 1); dsn= (char*)PlugSubAlloc(g, NULL, len + 1);
strncpy(dsn, create_info->connect_string.str, len); strncpy(dsn, create_info->connect_string.str, len);
dsn[len]= 0; dsn[len]= 0;
mydef->SetName(create_info->alias); mydef->SetName(create_info->alias);
mydef->SetCat(cat);
if (!mydef->ParseURL(g, dsn, false)) { if (!mydef->ParseURL(g, dsn, false)) {
if (mydef->GetHostname()) if (mydef->GetHostname())
......
...@@ -52,9 +52,9 @@ children SMALLINT(2) NOT NULL ...@@ -52,9 +52,9 @@ children SMALLINT(2) NOT NULL
INSERT INTO t1 VALUES ('BILL','1973-06-30',5); INSERT INTO t1 VALUES ('BILL','1973-06-30',5);
ERROR HY000: Table 't1' is read only ERROR HY000: Table 't1' is read only
UPDATE t1 SET children=6 WHERE name='BILL'; UPDATE t1 SET children=6 WHERE name='BILL';
ERROR HY000: Table 't1' is read only ERROR HY000: Got error 174 'Cannot modify this read/only protected table' from CONNECT
DELETE FROM t1 WHERE name='BILL'; DELETE FROM t1 WHERE name='BILL';
ERROR HY000: Table 't1' is read only ERROR HY000: Got error 174 'Cannot modify this read/only protected table' from CONNECT
TRUNCATE TABLE t1; TRUNCATE TABLE t1;
ERROR HY000: Table 't1' is read only ERROR HY000: Table 't1' is read only
SELECT * FROM t1; SELECT * FROM t1;
......
...@@ -77,9 +77,9 @@ t1 CREATE TABLE `t1` ( ...@@ -77,9 +77,9 @@ t1 CREATE TABLE `t1` (
INSERT INTO t1 VALUES (30); INSERT INTO t1 VALUES (30);
ERROR HY000: Table 't1' is read only ERROR HY000: Table 't1' is read only
UPDATE t1 SET a=30 WHERE a=10; UPDATE t1 SET a=30 WHERE a=10;
ERROR HY000: Table 't1' is read only ERROR HY000: Got error 174 'Cannot modify this read/only protected table' from CONNECT
DELETE FROM t1 WHERE a=10; DELETE FROM t1 WHERE a=10;
ERROR HY000: Table 't1' is read only ERROR HY000: Got error 174 'Cannot modify this read/only protected table' from CONNECT
TRUNCATE TABLE t1; TRUNCATE TABLE t1;
ERROR HY000: Table 't1' is read only ERROR HY000: Table 't1' is read only
ALTER TABLE t1 READONLY=NO; ALTER TABLE t1 READONLY=NO;
......
...@@ -30,9 +30,9 @@ t1 CREATE TABLE `t1` ( ...@@ -30,9 +30,9 @@ t1 CREATE TABLE `t1` (
INSERT INTO t1 VALUES (20); INSERT INTO t1 VALUES (20);
ERROR HY000: Table 't1' is read only ERROR HY000: Table 't1' is read only
UPDATE t1 SET id=20 WHERE id=10; UPDATE t1 SET id=20 WHERE id=10;
ERROR HY000: Table 't1' is read only ERROR HY000: Got error 174 'Cannot modify this read/only protected table' from CONNECT
DELETE FROM t1 WHERE id=10; DELETE FROM t1 WHERE id=10;
ERROR HY000: Table 't1' is read only ERROR HY000: Got error 174 'Cannot modify this read/only protected table' from CONNECT
TRUNCATE TABLE t1; TRUNCATE TABLE t1;
ERROR HY000: Table 't1' is read only ERROR HY000: Table 't1' is read only
ALTER TABLE t1 READONLY=0; ALTER TABLE t1 READONLY=0;
......
...@@ -194,9 +194,9 @@ t1 CREATE TABLE `t1` ( ...@@ -194,9 +194,9 @@ t1 CREATE TABLE `t1` (
INSERT INTO t1 VALUES ('US',40); INSERT INTO t1 VALUES ('US',40);
ERROR HY000: Table 't1' is read only ERROR HY000: Table 't1' is read only
UPDATE t1 SET c2=20 WHERE c2=10; UPDATE t1 SET c2=20 WHERE c2=10;
ERROR HY000: Table 't1' is read only ERROR HY000: Got error 174 'Cannot modify this read/only protected table' from CONNECT
DELETE FROM t1 WHERE c2=10; DELETE FROM t1 WHERE c2=10;
ERROR HY000: Table 't1' is read only ERROR HY000: Got error 174 'Cannot modify this read/only protected table' from CONNECT
TRUNCATE TABLE t1; TRUNCATE TABLE t1;
ERROR HY000: Table 't1' is read only ERROR HY000: Table 't1' is read only
ALTER TABLE t1 READONLY=0; ALTER TABLE t1 READONLY=0;
......
...@@ -103,9 +103,9 @@ t1 CREATE TABLE `t1` ( ...@@ -103,9 +103,9 @@ t1 CREATE TABLE `t1` (
INSERT INTO t1 VALUES (4,'test04'); INSERT INTO t1 VALUES (4,'test04');
ERROR HY000: Table 't1' is read only ERROR HY000: Table 't1' is read only
UPDATE t1 SET b='test04' WHERE a=3; UPDATE t1 SET b='test04' WHERE a=3;
ERROR HY000: Table 't1' is read only ERROR HY000: Got error 174 'Cannot modify this read/only protected table' from CONNECT
DELETE FROM t1 WHERE a=3; DELETE FROM t1 WHERE a=3;
ERROR HY000: Table 't1' is read only ERROR HY000: Got error 174 'Cannot modify this read/only protected table' from CONNECT
TRUNCATE TABLE t1; TRUNCATE TABLE t1;
ERROR HY000: Table 't1' is read only ERROR HY000: Table 't1' is read only
ALTER TABLE t1 READONLY=no; ALTER TABLE t1 READONLY=no;
......
...@@ -68,9 +68,9 @@ ALTER TABLE t1 READONLY=Yes; ...@@ -68,9 +68,9 @@ ALTER TABLE t1 READONLY=Yes;
SHOW CREATE TABLE t1; SHOW CREATE TABLE t1;
--error ER_OPEN_AS_READONLY --error ER_OPEN_AS_READONLY
INSERT INTO t1 VALUES (30); INSERT INTO t1 VALUES (30);
--error ER_OPEN_AS_READONLY --error ER_GET_ERRMSG
UPDATE t1 SET a=30 WHERE a=10; UPDATE t1 SET a=30 WHERE a=10;
--error ER_OPEN_AS_READONLY --error ER_GET_ERRMSG
DELETE FROM t1 WHERE a=10; DELETE FROM t1 WHERE a=10;
--error ER_OPEN_AS_READONLY --error ER_OPEN_AS_READONLY
TRUNCATE TABLE t1; TRUNCATE TABLE t1;
......
...@@ -30,9 +30,9 @@ ALTER TABLE t1 READONLY=1; ...@@ -30,9 +30,9 @@ ALTER TABLE t1 READONLY=1;
SHOW CREATE TABLE t1; SHOW CREATE TABLE t1;
--error ER_OPEN_AS_READONLY --error ER_OPEN_AS_READONLY
INSERT INTO t1 VALUES (20); INSERT INTO t1 VALUES (20);
--error ER_OPEN_AS_READONLY --error ER_GET_ERRMSG
UPDATE t1 SET id=20 WHERE id=10; UPDATE t1 SET id=20 WHERE id=10;
--error ER_OPEN_AS_READONLY --error ER_GET_ERRMSG
DELETE FROM t1 WHERE id=10; DELETE FROM t1 WHERE id=10;
--error ER_OPEN_AS_READONLY --error ER_OPEN_AS_READONLY
TRUNCATE TABLE t1; TRUNCATE TABLE t1;
......
let $MYSQLD_DATADIR= `select @@datadir`; let $MYSQLD_DATADIR= `select @@datadir`;
--copy_file $MTR_SUITE_DIR/std_data/contact.ini $MYSQLD_DATADIR/test/contact.ini --copy_file $MTR_SUITE_DIR/std_data/contact.ini $MYSQLD_DATADIR/test/contact.ini
--echo # --echo #
--echo # Testing errors --echo # Testing errors
--echo # --echo #
CREATE TABLE t1 CREATE TABLE t1
( (
ID INT ID INT
) Engine=CONNECT TABLE_TYPE=INI FILE_NAME='nonexistent.txt'; ) Engine=CONNECT TABLE_TYPE=INI FILE_NAME='nonexistent.txt';
--replace_regex /on .*test.nonexistent.txt/on DATADIR\/test\/nonexistent.txt/ --replace_regex /on .*test.nonexistent.txt/on DATADIR\/test\/nonexistent.txt/
# TODO: check why this is needed for Windows # TODO: check why this is needed for Windows
--replace_result Open(rt) Open(rb) --replace_result Open(rt) Open(rb)
SELECT * FROM t1; SELECT * FROM t1;
DROP TABLE t1; DROP TABLE t1;
--echo # --echo #
--echo # Testing examples from the manual --echo # Testing examples from the manual
--echo # --echo #
CREATE TABLE t1 CREATE TABLE t1
( (
contact CHAR(16) flag=1, contact CHAR(16) flag=1,
name CHAR(20), name CHAR(20),
forename CHAR(32), forename CHAR(32),
hired date date_format='DD/MM/YYYY', hired date date_format='DD/MM/YYYY',
address CHAR(64), address CHAR(64),
city CHAR(20), city CHAR(20),
zipcode CHAR(8), zipcode CHAR(8),
tel CHAR(16) tel CHAR(16)
) ENGINE=CONNECT TABLE_TYPE=INI FILE_NAME='contact.ini'; ) ENGINE=CONNECT TABLE_TYPE=INI FILE_NAME='contact.ini';
SELECT contact, name, hired, city, tel FROM t1; SELECT contact, name, hired, city, tel FROM t1;
UPDATE t1 SET forename= 'Harry' where contact='UK1'; UPDATE t1 SET forename= 'Harry' where contact='UK1';
SELECT * FROM t1 WHERE contact='UK1'; SELECT * FROM t1 WHERE contact='UK1';
INSERT INTO t1 (contact,forename) VALUES ('UK1','Harrison'); INSERT INTO t1 (contact,forename) VALUES ('UK1','Harrison');
SELECT * FROM t1 WHERE contact='UK1'; SELECT * FROM t1 WHERE contact='UK1';
INSERT INTO t1 (contact,forename) VALUES ('UK2','John'); INSERT INTO t1 (contact,forename) VALUES ('UK2','John');
SELECT * FROM t1 WHERE contact='UK2'; SELECT * FROM t1 WHERE contact='UK2';
DROP TABLE t1; DROP TABLE t1;
--chmod 0777 $MYSQLD_DATADIR/test/contact.ini --chmod 0777 $MYSQLD_DATADIR/test/contact.ini
--replace_result $MYSQLD_DATADIR DATADIR --replace_result $MYSQLD_DATADIR DATADIR
--eval SELECT REPLACE(REPLACE(LOAD_FILE('$MYSQLD_DATADIR/test/contact.ini'),'\r\n','\n'),'\n\n','\n'); --eval SELECT REPLACE(REPLACE(LOAD_FILE('$MYSQLD_DATADIR/test/contact.ini'),'\r\n','\n'),'\n\n','\n');
CREATE TABLE t1 CREATE TABLE t1
( (
section CHAR(16) flag=1, section CHAR(16) flag=1,
keyname CHAR(16) flag=2, keyname CHAR(16) flag=2,
value CHAR(32) value CHAR(32)
) ENGINE=CONNECT TABLE_TYPE=INI FILE_NAME='contact.ini' ) ENGINE=CONNECT TABLE_TYPE=INI FILE_NAME='contact.ini'
OPTION_LIST='Layout=Row'; OPTION_LIST='Layout=Row';
UPDATE t1 SET value='Paul' WHERE section='UK2' AND keyname='forename'; UPDATE t1 SET value='Paul' WHERE section='UK2' AND keyname='forename';
SELECT * FROM t1; SELECT * FROM t1;
DROP TABLE t1; DROP TABLE t1;
--chmod 0777 $MYSQLD_DATADIR/test/contact.ini --chmod 0777 $MYSQLD_DATADIR/test/contact.ini
--replace_result $MYSQLD_DATADIR DATADIR --replace_result $MYSQLD_DATADIR DATADIR
--eval SELECT REPLACE(REPLACE(LOAD_FILE('$MYSQLD_DATADIR/test/contact.ini'),'\r\n','\n'),'\n\n','\n'); --eval SELECT REPLACE(REPLACE(LOAD_FILE('$MYSQLD_DATADIR/test/contact.ini'),'\r\n','\n'),'\n\n','\n');
--echo # --echo #
--echo # Testing that the underlying file is created --echo # Testing that the underlying file is created
--echo # --echo #
CREATE TABLE t1 CREATE TABLE t1
( (
contact CHAR(12) NOT NULL flag=1, contact CHAR(12) NOT NULL flag=1,
c2 CHAR(12) NOT NULL c2 CHAR(12) NOT NULL
) ENGINE=CONNECT TABLE_TYPE=INI FILE_NAME='tmp.ini'; ) ENGINE=CONNECT TABLE_TYPE=INI FILE_NAME='tmp.ini';
INSERT INTO t1 VALUES (10,10),(20,20),(300,300),(4000,4000), ('a b','c d'); INSERT INTO t1 VALUES (10,10),(20,20),(300,300),(4000,4000), ('a b','c d');
SELECT * FROM t1; SELECT * FROM t1;
DROP TABLE t1; DROP TABLE t1;
--chmod 0777 $MYSQLD_DATADIR/test/tmp.ini --chmod 0777 $MYSQLD_DATADIR/test/tmp.ini
--replace_result $MYSQLD_DATADIR DATADIR --replace_result $MYSQLD_DATADIR DATADIR
--eval SELECT REPLACE(REPLACE(LOAD_FILE('$MYSQLD_DATADIR/test/tmp.ini'),'\r\n','\n'),'\n\n','\n'); --eval SELECT REPLACE(REPLACE(LOAD_FILE('$MYSQLD_DATADIR/test/tmp.ini'),'\r\n','\n'),'\n\n','\n');
--echo # --echo #
--echo # Testing bad table --echo # Testing bad table
--echo # --echo #
CREATE TABLE t1 CREATE TABLE t1
( (
id INT id INT
) ENGINE=CONNECT TABLE_TYPE=INI FILE_NAME='t1.ini'; ) ENGINE=CONNECT TABLE_TYPE=INI FILE_NAME='t1.ini';
--error ER_GET_ERRMSG --error ER_GET_ERRMSG
INSERT INTO t1 VALUES (10); INSERT INTO t1 VALUES (10);
SELECT * FROM t1; SELECT * FROM t1;
DROP TABLE t1; DROP TABLE t1;
--echo # --echo #
--echo # Testing READONLY tables --echo # Testing READONLY tables
--echo # --echo #
CREATE TABLE t1 CREATE TABLE t1
( (
contact CHAR(10) flag=1, contact CHAR(10) flag=1,
c2 CHAR(60) c2 CHAR(60)
) ENGINE=CONNECT TABLE_TYPE=INI FILE_NAME='t1.ini'; ) ENGINE=CONNECT TABLE_TYPE=INI FILE_NAME='t1.ini';
INSERT INTO t1 VALUES ('UK',10),('FR',20),('RU',30); INSERT INTO t1 VALUES ('UK',10),('FR',20),('RU',30);
SELECT * FROM t1; SELECT * FROM t1;
ALTER TABLE t1 READONLY=1; ALTER TABLE t1 READONLY=1;
SHOW CREATE TABLE t1; SHOW CREATE TABLE t1;
--error ER_OPEN_AS_READONLY --error ER_OPEN_AS_READONLY
INSERT INTO t1 VALUES ('US',40); INSERT INTO t1 VALUES ('US',40);
--error ER_OPEN_AS_READONLY --error ER_GET_ERRMSG
UPDATE t1 SET c2=20 WHERE c2=10; UPDATE t1 SET c2=20 WHERE c2=10;
--error ER_OPEN_AS_READONLY --error ER_GET_ERRMSG
DELETE FROM t1 WHERE c2=10; DELETE FROM t1 WHERE c2=10;
--error ER_OPEN_AS_READONLY --error ER_OPEN_AS_READONLY
TRUNCATE TABLE t1; TRUNCATE TABLE t1;
ALTER TABLE t1 READONLY=0; ALTER TABLE t1 READONLY=0;
SHOW CREATE TABLE t1; SHOW CREATE TABLE t1;
INSERT INTO t1 VALUES ('US',40); INSERT INTO t1 VALUES ('US',40);
SELECT * FROM t1; SELECT * FROM t1;
DROP TABLE t1; DROP TABLE t1;
--remove_file $MYSQLD_DATADIR/test/t1.ini --remove_file $MYSQLD_DATADIR/test/t1.ini
# #
# Clean up # Clean up
# #
--remove_file $MYSQLD_DATADIR/test/contact.ini --remove_file $MYSQLD_DATADIR/test/contact.ini
--remove_file $MYSQLD_DATADIR/test/tmp.ini --remove_file $MYSQLD_DATADIR/test/tmp.ini
--echo # --echo #
--echo # Bug: TABLE_TYPE=ini does not clear memory between CREATE TABLEs --echo # Bug: TABLE_TYPE=ini does not clear memory between CREATE TABLEs
--echo # --echo #
CREATE TABLE t1 (sec CHAR(10) NOT NULL FLAG=1, val CHAR(10) NOT NULL) CREATE TABLE t1 (sec CHAR(10) NOT NULL FLAG=1, val CHAR(10) NOT NULL)
ENGINE=CONNECT TABLE_TYPE=INI; ENGINE=CONNECT TABLE_TYPE=INI;
INSERT INTO t1 VALUES ('sec1','val1'),('sec2','val2'); INSERT INTO t1 VALUES ('sec1','val1'),('sec2','val2');
SELECT sec AS s, val AS v FROM t1; SELECT sec AS s, val AS v FROM t1;
DROP TABLE t1; DROP TABLE t1;
CREATE TABLE t1 (sec2 CHAR(10) NOT NULL FLAG=1, val2 CHAR(10) NOT NULL) CREATE TABLE t1 (sec2 CHAR(10) NOT NULL FLAG=1, val2 CHAR(10) NOT NULL)
ENGINE=CONNECT TABLE_TYPE=INI; ENGINE=CONNECT TABLE_TYPE=INI;
INSERT INTO t1 VALUES ('sec1','val11'),('sec2','val22'); INSERT INTO t1 VALUES ('sec1','val11'),('sec2','val22');
SELECT sec2 AS s, val2 AS v FROM t1; SELECT sec2 AS s, val2 AS v FROM t1;
--chmod 0777 $MYSQLD_DATADIR/test/t1.ini --chmod 0777 $MYSQLD_DATADIR/test/t1.ini
--replace_result $MYSQLD_DATADIR DATADIR --replace_result $MYSQLD_DATADIR DATADIR
--eval SELECT REPLACE(REPLACE(LOAD_FILE('$MYSQLD_DATADIR/test/t1.ini'),'\r\n','\n'),'\n\n','\n'); --eval SELECT REPLACE(REPLACE(LOAD_FILE('$MYSQLD_DATADIR/test/t1.ini'),'\r\n','\n'),'\n\n','\n');
DROP TABLE t1; DROP TABLE t1;
CREATE TABLE t1 (sec CHAR(10) NOT NULL FLAG=1, val CHAR(10) NOT NULL) CREATE TABLE t1 (sec CHAR(10) NOT NULL FLAG=1, val CHAR(10) NOT NULL)
ENGINE=CONNECT TABLE_TYPE=INI; ENGINE=CONNECT TABLE_TYPE=INI;
CREATE TABLE t2 (sec CHAR(10) NOT NULL FLAG=1, val CHAR(10) NOT NULL) CREATE TABLE t2 (sec CHAR(10) NOT NULL FLAG=1, val CHAR(10) NOT NULL)
ENGINE=CONNECT TABLE_TYPE=INI; ENGINE=CONNECT TABLE_TYPE=INI;
INSERT INTO t1 VALUES('1sec1','1val1'),('1sec2','1val2'); INSERT INTO t1 VALUES('1sec1','1val1'),('1sec2','1val2');
INSERT INTO t2 VALUES('2sec1','2val1'),('2sec2','2val2'); INSERT INTO t2 VALUES('2sec1','2val1'),('2sec2','2val2');
SELECT sec AS s, val AS v FROM t1; SELECT sec AS s, val AS v FROM t1;
--chmod 0777 $MYSQLD_DATADIR/test/t1.ini --chmod 0777 $MYSQLD_DATADIR/test/t1.ini
--replace_result $MYSQLD_DATADIR DATADIR --replace_result $MYSQLD_DATADIR DATADIR
--eval SELECT REPLACE(REPLACE(LOAD_FILE('$MYSQLD_DATADIR/test/t1.ini'),'\r\n','\n'),'\n\n','\n'); --eval SELECT REPLACE(REPLACE(LOAD_FILE('$MYSQLD_DATADIR/test/t1.ini'),'\r\n','\n'),'\n\n','\n');
SELECT sec AS s, val AS v FROM t2; SELECT sec AS s, val AS v FROM t2;
--chmod 0777 $MYSQLD_DATADIR/test/t2.ini --chmod 0777 $MYSQLD_DATADIR/test/t2.ini
--replace_result $MYSQLD_DATADIR DATADIR --replace_result $MYSQLD_DATADIR DATADIR
--eval SELECT REPLACE(REPLACE(LOAD_FILE('$MYSQLD_DATADIR/test/t2.ini'),'\r\n','\n'),'\n\n','\n'); --eval SELECT REPLACE(REPLACE(LOAD_FILE('$MYSQLD_DATADIR/test/t2.ini'),'\r\n','\n'),'\n\n','\n');
DROP TABLE t1, t2; DROP TABLE t1, t2;
let $MYSQLD_DATADIR= `select @@datadir`; let $MYSQLD_DATADIR= `select @@datadir`;
CREATE TABLE dir1 ( CREATE TABLE dir1 (
spath VARCHAR(256) NOT NULL flag=1, spath VARCHAR(256) NOT NULL flag=1,
fname VARCHAR(256) NOT NULL, fname VARCHAR(256) NOT NULL,
ftype CHAR(4) NOT NULL, ftype CHAR(4) NOT NULL,
size DOUBLE(12,0) NOT NULL flag=5 size DOUBLE(12,0) NOT NULL flag=5
) ENGINE=CONNECT TABLE_TYPE=DIR FILE_NAME='*vec*'; ) ENGINE=CONNECT TABLE_TYPE=DIR FILE_NAME='*vec*';
CREATE TABLE t1 CREATE TABLE t1
( (
a INT NOT NULL, a INT NOT NULL,
b CHAR(10) NOT NULL b CHAR(10) NOT NULL
) ENGINE=CONNECT TABLE_TYPE=VEC FILE_NAME='t1vec'; ) ENGINE=CONNECT TABLE_TYPE=VEC FILE_NAME='t1vec';
SHOW CREATE TABLE t1; SHOW CREATE TABLE t1;
# Testing SELECT on empty file # Testing SELECT on empty file
--replace_regex /Open.rb. error 2 on .*\/test\/t1vec/Open(rb) error 2 on DATADIR\/test\/t1vec/ --replace_regex /Open.rb. error 2 on .*\/test\/t1vec/Open(rb) error 2 on DATADIR\/test\/t1vec/
SELECT * FROM t1; SELECT * FROM t1;
INSERT INTO t1 VALUES (0,'test01'), (1,'test01'), (2,'test02'), (3,'test03'); INSERT INTO t1 VALUES (0,'test01'), (1,'test01'), (2,'test02'), (3,'test03');
SELECT * FROM t1; SELECT * FROM t1;
SELECT a FROM t1; SELECT a FROM t1;
SELECT b FROM t1; SELECT b FROM t1;
--replace_result $MYSQLD_DATADIR DATADIR/ --replace_result $MYSQLD_DATADIR DATADIR/
SELECT fname, ftype, size FROM dir1 ORDER BY fname, ftype; SELECT fname, ftype, size FROM dir1 ORDER BY fname, ftype;
DROP TABLE t1; DROP TABLE t1;
--remove_file $MYSQLD_DATADIR/test/t1vec1 --remove_file $MYSQLD_DATADIR/test/t1vec1
--remove_file $MYSQLD_DATADIR/test/t1vec2 --remove_file $MYSQLD_DATADIR/test/t1vec2
CREATE TABLE t1 CREATE TABLE t1
( (
a INT NOT NULL, a INT NOT NULL,
b CHAR(10) NOT NULL b CHAR(10) NOT NULL
) ENGINE=CONNECT TABLE_TYPE=VEC FILE_NAME='t1vec' MAX_ROWS=10; ) ENGINE=CONNECT TABLE_TYPE=VEC FILE_NAME='t1vec' MAX_ROWS=10;
SHOW CREATE TABLE t1; SHOW CREATE TABLE t1;
# Testing SELECTs on empty file # Testing SELECTs on empty file
--replace_regex /Open.rb. error 2 on .*\/test\/t1vec/Open(rb) error 2 on DATADIR\/test\/t1vec/ --replace_regex /Open.rb. error 2 on .*\/test\/t1vec/Open(rb) error 2 on DATADIR\/test\/t1vec/
SELECT * FROM t1; SELECT * FROM t1;
--replace_regex /Open.rb. error 2 on .*\/test\/t1vec/Open(rb) error 2 on DATADIR\/test\/t1vec/ --replace_regex /Open.rb. error 2 on .*\/test\/t1vec/Open(rb) error 2 on DATADIR\/test\/t1vec/
SELECT a FROM t1; SELECT a FROM t1;
--replace_regex /Open.rb. error 2 on .*\/test\/t1vec/Open(rb) error 2 on DATADIR\/test\/t1vec/ --replace_regex /Open.rb. error 2 on .*\/test\/t1vec/Open(rb) error 2 on DATADIR\/test\/t1vec/
SELECT b FROM t1; SELECT b FROM t1;
INSERT INTO t1 VALUES (0,'test01'), (1,'test01'), (2,'test02'), (3,'test03'); INSERT INTO t1 VALUES (0,'test01'), (1,'test01'), (2,'test02'), (3,'test03');
SELECT * FROM t1; SELECT * FROM t1;
SELECT a FROM t1; SELECT a FROM t1;
SELECT b FROM t1; SELECT b FROM t1;
--replace_result $MYSQLD_DATADIR DATADIR/ --replace_result $MYSQLD_DATADIR DATADIR/
SELECT fname, ftype, size FROM dir1 ORDER BY fname, ftype; SELECT fname, ftype, size FROM dir1 ORDER BY fname, ftype;
--echo # --echo #
--echo # Testing READONLY --echo # Testing READONLY
--echo # --echo #
ALTER TABLE t1 READONLY=yes; ALTER TABLE t1 READONLY=yes;
SHOW CREATE TABLE t1; SHOW CREATE TABLE t1;
--error ER_OPEN_AS_READONLY --error ER_OPEN_AS_READONLY
INSERT INTO t1 VALUES (4,'test04'); INSERT INTO t1 VALUES (4,'test04');
--error ER_OPEN_AS_READONLY --error ER_GET_ERRMSG
UPDATE t1 SET b='test04' WHERE a=3; UPDATE t1 SET b='test04' WHERE a=3;
--error ER_OPEN_AS_READONLY --error ER_GET_ERRMSG
DELETE FROM t1 WHERE a=3; DELETE FROM t1 WHERE a=3;
--error ER_OPEN_AS_READONLY --error ER_OPEN_AS_READONLY
TRUNCATE TABLE t1; TRUNCATE TABLE t1;
ALTER TABLE t1 READONLY=no; ALTER TABLE t1 READONLY=no;
SHOW CREATE TABLE t1; SHOW CREATE TABLE t1;
INSERT INTO t1 VALUES (4,'test04'); INSERT INTO t1 VALUES (4,'test04');
UPDATE t1 SET b='test04a' WHERE a=4; UPDATE t1 SET b='test04a' WHERE a=4;
DELETE FROM t1 WHERE a=0; DELETE FROM t1 WHERE a=0;
SELECT * FROM t1; SELECT * FROM t1;
TRUNCATE TABLE t1; TRUNCATE TABLE t1;
SELECT fname, ftype, size FROM dir1 ORDER BY fname, ftype; SELECT fname, ftype, size FROM dir1 ORDER BY fname, ftype;
SELECT * FROM t1; SELECT * FROM t1;
DROP TABLE t1; DROP TABLE t1;
--remove_file $MYSQLD_DATADIR/test/t1vec --remove_file $MYSQLD_DATADIR/test/t1vec
--remove_file $MYSQLD_DATADIR/test/t1vec.blk --remove_file $MYSQLD_DATADIR/test/t1vec.blk
--echo # --echo #
--echo # Clean up --echo # Clean up
--echo # --echo #
DROP TABLE dir1; DROP TABLE dir1;
...@@ -214,6 +214,7 @@ class DllExport COLDEF : public COLCRT { /* Column description block ...@@ -214,6 +214,7 @@ class DllExport COLDEF : public COLCRT { /* Column description block
int Define(PGLOBAL g, void *memp, PCOLINFO cfp, int poff); int Define(PGLOBAL g, void *memp, PCOLINFO cfp, int poff);
void Define(PGLOBAL g, PCOL colp); void Define(PGLOBAL g, PCOL colp);
bool IsSpecial(void) {return (Flags & U_SPECIAL) ? true : false;} bool IsSpecial(void) {return (Flags & U_SPECIAL) ? true : false;}
bool IsVirtual(void) {return (Flags & U_VIRTUAL) ? true : false;}
protected: protected:
void *To_Min; /* Point to array of block min values */ void *To_Min; /* Point to array of block min values */
......
...@@ -2168,10 +2168,12 @@ DOSCOL::DOSCOL(PGLOBAL g, PCOLDEF cdp, PTDB tp, PCOL cp, int i, PSZ am) ...@@ -2168,10 +2168,12 @@ DOSCOL::DOSCOL(PGLOBAL g, PCOLDEF cdp, PTDB tp, PCOL cp, int i, PSZ am)
} // endif Opt } // endif Opt
OldVal = NULL; // Currently used only in MinMax OldVal = NULL; // Currently used only in MinMax
Dsp = 0;
Ldz = false; Ldz = false;
Nod = false; Nod = false;
Dcm = -1; Dcm = -1;
p = cdp->GetFmt(); p = cdp->GetFmt();
Buf = NULL;
if (p && IsTypeNum(Buf_Type)) { if (p && IsTypeNum(Buf_Type)) {
// Formatted numeric value // Formatted numeric value
...@@ -2183,6 +2185,9 @@ DOSCOL::DOSCOL(PGLOBAL g, PCOLDEF cdp, PTDB tp, PCOL cp, int i, PSZ am) ...@@ -2183,6 +2185,9 @@ DOSCOL::DOSCOL(PGLOBAL g, PCOLDEF cdp, PTDB tp, PCOL cp, int i, PSZ am)
case 'N': // Have no decimal point case 'N': // Have no decimal point
Nod = true; Nod = true;
break; break;
case 'D': // Decimal separator
Dsp = *(++p);
break;
} // endswitch p } // endswitch p
// Set number of decimal digits // Set number of decimal digits
...@@ -2204,6 +2209,7 @@ DOSCOL::DOSCOL(DOSCOL *col1, PTDB tdbp) : COLBLK(col1, tdbp) ...@@ -2204,6 +2209,7 @@ DOSCOL::DOSCOL(DOSCOL *col1, PTDB tdbp) : COLBLK(col1, tdbp)
Long = col1->Long; Long = col1->Long;
To_Val = col1->To_Val; To_Val = col1->To_Val;
Ldz = col1->Ldz; Ldz = col1->Ldz;
Dsp = col1->Dsp;
Nod = col1->Nod; Nod = col1->Nod;
Dcm = col1->Dcm; Dcm = col1->Dcm;
OldVal = col1->OldVal; OldVal = col1->OldVal;
...@@ -2277,7 +2283,7 @@ bool DOSCOL::SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check) ...@@ -2277,7 +2283,7 @@ bool DOSCOL::SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check)
} // endif's Value, Buf_Type } // endif's Value, Buf_Type
// Allocate the buffer used in WriteColumn for numeric columns // Allocate the buffer used in WriteColumn for numeric columns
if (IsTypeNum(Buf_Type)) if (!Buf && IsTypeNum(Buf_Type))
Buf = (char*)PlugSubAlloc(g, NULL, MY_MAX(32, Long + Dcm + 1)); Buf = (char*)PlugSubAlloc(g, NULL, MY_MAX(32, Long + Dcm + 1));
// Because Colblk's have been made from a copy of the original TDB in // Because Colblk's have been made from a copy of the original TDB in
...@@ -2322,14 +2328,18 @@ void DOSCOL::ReadColumn(PGLOBAL g) ...@@ -2322,14 +2328,18 @@ void DOSCOL::ReadColumn(PGLOBAL g)
p = tdbp->To_Line + Deplac; p = tdbp->To_Line + Deplac;
field = Long; field = Long;
/*********************************************************************/
/* For a variable length file, check if the field exists. */
/*********************************************************************/
if (tdbp->Ftype == RECFM_VAR && strlen(tdbp->To_Line) < (unsigned)Deplac)
field = 0;
else if (Dsp)
for(i = 0; i < field; i++)
if (p[i] == Dsp)
p[i] = '.';
switch (tdbp->Ftype) { switch (tdbp->Ftype) {
case RECFM_VAR: case RECFM_VAR:
/*****************************************************************/
/* For a variable length file, check if the field exists. */
/*****************************************************************/
if (strlen(tdbp->To_Line) < (unsigned)Deplac)
field = 0;
case RECFM_FIX: // Fixed length text file case RECFM_FIX: // Fixed length text file
case RECFM_DBF: // Fixed length DBase file case RECFM_DBF: // Fixed length DBase file
if (Nod) switch (Buf_Type) { if (Nod) switch (Buf_Type) {
...@@ -2458,6 +2468,7 @@ void DOSCOL::WriteColumn(PGLOBAL g) ...@@ -2458,6 +2468,7 @@ void DOSCOL::WriteColumn(PGLOBAL g)
len = sprintf(Buf, fmt, field - i, Value->GetTinyValue()); len = sprintf(Buf, fmt, field - i, Value->GetTinyValue());
break; break;
case TYPE_DOUBLE: case TYPE_DOUBLE:
case TYPE_DECIM:
strcpy(fmt, (Ldz) ? "%0*.*lf" : "%*.*lf"); strcpy(fmt, (Ldz) ? "%0*.*lf" : "%*.*lf");
sprintf(Buf, fmt, field + ((Nod && Dcm) ? 1 : 0), sprintf(Buf, fmt, field + ((Nod && Dcm) ? 1 : 0),
Dcm, Value->GetFloatValue()); Dcm, Value->GetFloatValue());
...@@ -2466,7 +2477,7 @@ void DOSCOL::WriteColumn(PGLOBAL g) ...@@ -2466,7 +2477,7 @@ void DOSCOL::WriteColumn(PGLOBAL g)
if (Nod && Dcm) if (Nod && Dcm)
for (i = k = 0; i < len; i++, k++) for (i = k = 0; i < len; i++, k++)
if (Buf[i] != ' ') { if (Buf[i] != ' ') {
if (Buf[i] == '.' || Buf[i] == ',') if (Buf[i] == '.')
k++; k++;
Buf[i] = Buf[k]; Buf[i] = Buf[k];
...@@ -2474,10 +2485,13 @@ void DOSCOL::WriteColumn(PGLOBAL g) ...@@ -2474,10 +2485,13 @@ void DOSCOL::WriteColumn(PGLOBAL g)
len = strlen(Buf); len = strlen(Buf);
break; break;
default:
sprintf(g->Message, "Invalid field format for column %s", Name);
longjmp(g->jumper[g->jump_level], 31);
} // endswitch BufType } // endswitch BufType
p2 = Buf; p2 = Buf;
} else // Standard PlugDB format } else // Standard CONNECT format
p2 = Value->ShowValue(Buf, field); p2 = Value->ShowValue(Buf, field);
if (trace) if (trace)
...@@ -2486,7 +2500,10 @@ void DOSCOL::WriteColumn(PGLOBAL g) ...@@ -2486,7 +2500,10 @@ void DOSCOL::WriteColumn(PGLOBAL g)
if ((len = strlen(p2)) > field) { if ((len = strlen(p2)) > field) {
sprintf(g->Message, MSG(VALUE_TOO_LONG), p2, Name, field); sprintf(g->Message, MSG(VALUE_TOO_LONG), p2, Name, field);
longjmp(g->jumper[g->jump_level], 31); longjmp(g->jumper[g->jump_level], 31);
} // endif } else if (Dsp)
for (i = 0; i < len; i++)
if (p2[i] == '.')
p2[i] = Dsp;
if (trace > 1) if (trace > 1)
htrc("buffer=%s\n", p2); htrc("buffer=%s\n", p2);
......
...@@ -241,7 +241,8 @@ class DllExport DOSCOL : public COLBLK { ...@@ -241,7 +241,8 @@ class DllExport DOSCOL : public COLBLK {
PVBLK Dval; // Array of column distinct values PVBLK Dval; // Array of column distinct values
PVAL To_Val; // To value used for Update/Insert PVAL To_Val; // To value used for Update/Insert
PVAL OldVal; // The previous value of the object. PVAL OldVal; // The previous value of the object.
char *Buf; // Buffer used in write operations char *Buf; // Buffer used in read/write operations
char Dsp; // The decimal separator
bool Ldz; // True if field contains leading zeros bool Ldz; // True if field contains leading zeros
bool Nod; // True if no decimal point bool Nod; // True if no decimal point
int Dcm; // Last Dcm digits are decimals int Dcm; // Last Dcm digits are decimals
......
...@@ -597,7 +597,7 @@ int TDBCSV::EstimatedLength(PGLOBAL g) ...@@ -597,7 +597,7 @@ int TDBCSV::EstimatedLength(PGLOBAL g)
PCSVCOL colp; PCSVCOL colp;
for (colp = (PCSVCOL)Columns; colp; colp = (PCSVCOL)colp->Next) for (colp = (PCSVCOL)Columns; colp; colp = (PCSVCOL)colp->Next)
if (!colp->IsSpecial()) // Not a pseudo column if (!colp->IsSpecial() && !colp->IsVirtual()) // A true column
Fields = MY_MAX(Fields, (int)colp->Fldnum); Fields = MY_MAX(Fields, (int)colp->Fldnum);
if (Columns) if (Columns)
...@@ -640,7 +640,7 @@ bool TDBCSV::OpenDB(PGLOBAL g) ...@@ -640,7 +640,7 @@ bool TDBCSV::OpenDB(PGLOBAL g)
if (!Fields) // May have been set in TABFMT::OpenDB if (!Fields) // May have been set in TABFMT::OpenDB
if (Mode != MODE_UPDATE && Mode != MODE_INSERT) { if (Mode != MODE_UPDATE && Mode != MODE_INSERT) {
for (colp = (PCSVCOL)Columns; colp; colp = (PCSVCOL)colp->Next) for (colp = (PCSVCOL)Columns; colp; colp = (PCSVCOL)colp->Next)
if (!colp->IsSpecial()) // Not a pseudo column if (!colp->IsSpecial() && !colp->IsVirtual())
Fields = MY_MAX(Fields, (int)colp->Fldnum); Fields = MY_MAX(Fields, (int)colp->Fldnum);
if (Columns) if (Columns)
...@@ -648,7 +648,8 @@ bool TDBCSV::OpenDB(PGLOBAL g) ...@@ -648,7 +648,8 @@ bool TDBCSV::OpenDB(PGLOBAL g)
} else } else
for (cdp = tdp->GetCols(); cdp; cdp = cdp->GetNext()) for (cdp = tdp->GetCols(); cdp; cdp = cdp->GetNext())
Fields++; if (!cdp->IsVirtual())
Fields++;
Offset = (int*)PlugSubAlloc(g, NULL, sizeof(int) * Fields); Offset = (int*)PlugSubAlloc(g, NULL, sizeof(int) * Fields);
Fldlen = (int*)PlugSubAlloc(g, NULL, sizeof(int) * Fields); Fldlen = (int*)PlugSubAlloc(g, NULL, sizeof(int) * Fields);
...@@ -671,25 +672,27 @@ bool TDBCSV::OpenDB(PGLOBAL g) ...@@ -671,25 +672,27 @@ bool TDBCSV::OpenDB(PGLOBAL g)
if (Field) if (Field)
// Prepare writing fields // Prepare writing fields
if (Mode != MODE_UPDATE) if (Mode != MODE_UPDATE) {
for (colp = (PCSVCOL)Columns; colp; colp = (PCSVCOL)colp->Next) { for (colp = (PCSVCOL)Columns; colp; colp = (PCSVCOL)colp->Next)
i = colp->Fldnum; if (!colp->IsSpecial() && !colp->IsVirtual()) {
len = colp->GetLength(); i = colp->Fldnum;
Field[i] = (PSZ)PlugSubAlloc(g, NULL, len + 1); len = colp->GetLength();
Field[i][len] = '\0'; Field[i] = (PSZ)PlugSubAlloc(g, NULL, len + 1);
Fldlen[i] = len; Field[i][len] = '\0';
Fldtyp[i] = IsTypeNum(colp->GetResultType()); Fldlen[i] = len;
} // endfor colp Fldtyp[i] = IsTypeNum(colp->GetResultType());
} // endif colp
else // MODE_UPDATE
for (cdp = tdp->GetCols(); cdp; cdp = cdp->GetNext()) { } else // MODE_UPDATE
i = cdp->GetOffset() - 1; for (cdp = tdp->GetCols(); cdp; cdp = cdp->GetNext())
len = cdp->GetLength(); if (!cdp->IsVirtual()) {
Field[i] = (PSZ)PlugSubAlloc(g, NULL, len + 1); i = cdp->GetOffset() - 1;
Field[i][len] = '\0'; len = cdp->GetLength();
Fldlen[i] = len; Field[i] = (PSZ)PlugSubAlloc(g, NULL, len + 1);
Fldtyp[i] = IsTypeNum(cdp->GetType()); Field[i][len] = '\0';
} // endfor colp Fldlen[i] = len;
Fldtyp[i] = IsTypeNum(cdp->GetType());
} // endif cdp
} // endif Use } // endif Use
...@@ -1100,7 +1103,7 @@ bool TDBFMT::OpenDB(PGLOBAL g) ...@@ -1100,7 +1103,7 @@ bool TDBFMT::OpenDB(PGLOBAL g)
PDOSDEF tdp = (PDOSDEF)To_Def; PDOSDEF tdp = (PDOSDEF)To_Def;
for (colp = (PCSVCOL)Columns; colp; colp = (PCSVCOL)colp->Next) for (colp = (PCSVCOL)Columns; colp; colp = (PCSVCOL)colp->Next)
if (!colp->IsSpecial()) // Not a pseudo column if (!colp->IsSpecial() && !colp->IsVirtual()) // a true column
Fields = MY_MAX(Fields, (int)colp->Fldnum); Fields = MY_MAX(Fields, (int)colp->Fldnum);
if (Columns) if (Columns)
...@@ -1114,7 +1117,7 @@ bool TDBFMT::OpenDB(PGLOBAL g) ...@@ -1114,7 +1117,7 @@ bool TDBFMT::OpenDB(PGLOBAL g)
// Get the column formats // Get the column formats
for (cdp = tdp->GetCols(); cdp; cdp = cdp->GetNext()) for (cdp = tdp->GetCols(); cdp; cdp = cdp->GetNext())
if ((i = cdp->GetOffset() - 1) < Fields) { if (!cdp->IsVirtual() && (i = cdp->GetOffset() - 1) < Fields) {
if (!(pfm = cdp->GetFmt())) { if (!(pfm = cdp->GetFmt())) {
sprintf(g->Message, MSG(NO_FLD_FORMAT), i + 1, Name); sprintf(g->Message, MSG(NO_FLD_FORMAT), i + 1, Name);
return true; return true;
...@@ -1336,6 +1339,11 @@ void CSVCOL::ReadColumn(PGLOBAL g) ...@@ -1336,6 +1339,11 @@ void CSVCOL::ReadColumn(PGLOBAL g)
// Field have been copied in TDB Field array // Field have been copied in TDB Field array
PSZ fp = tdbp->Field[Fldnum]; PSZ fp = tdbp->Field[Fldnum];
if (Dsp)
for (int i = 0; fp[i]; i++)
if (fp[i] == Dsp)
fp[i] = '.';
Value->SetValue_psz(fp); Value->SetValue_psz(fp);
// Set null when applicable // Set null when applicable
...@@ -1383,7 +1391,10 @@ void CSVCOL::WriteColumn(PGLOBAL g) ...@@ -1383,7 +1391,10 @@ void CSVCOL::WriteColumn(PGLOBAL g)
sprintf(g->Message, MSG(BAD_FLD_LENGTH), Name, p, flen, sprintf(g->Message, MSG(BAD_FLD_LENGTH), Name, p, flen,
tdbp->RowNumber(g), tdbp->GetFile(g)); tdbp->RowNumber(g), tdbp->GetFile(g));
longjmp(g->jumper[g->jump_level], 34); longjmp(g->jumper[g->jump_level], 34);
} // endif } else if (Dsp)
for (int i = 0; p[i]; i++)
if (p[i] == '.')
p[i] = Dsp;
if (trace > 1) if (trace > 1)
htrc("buffer=%s\n", p); htrc("buffer=%s\n", p);
......
...@@ -190,9 +190,8 @@ bool MYSQLDEF::ParseURL(PGLOBAL g, char *url, bool b) ...@@ -190,9 +190,8 @@ bool MYSQLDEF::ParseURL(PGLOBAL g, char *url, bool b)
return true; return true;
} else } else
// Otherwise, straight server name, // Otherwise, straight server name,
// use tablename of federatedx table as remote table name Tabname = (b) ? GetStringCatInfo(g, "Tabname", Name) : NULL;
Tabname= Name;
if (trace) if (trace)
htrc("server: %s Tabname: %s", url, Tabname); htrc("server: %s Tabname: %s", url, Tabname);
......
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