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
7dc48ae3
Commit
7dc48ae3
authored
Oct 29, 2013
by
Alexander Barkov
Browse files
Options
Browse Files
Download
Plain Diff
Merge 10.0-connect -> 10.0
parents
9290a580
727c1f62
Changes
35
Hide whitespace changes
Inline
Side-by-side
Showing
35 changed files
with
1703 additions
and
303 deletions
+1703
-303
client/mysqldump.c
client/mysqldump.c
+1
-0
mysql-test/mysql-test-run.pl
mysql-test/mysql-test-run.pl
+1
-0
mysql-test/valgrind.supp
mysql-test/valgrind.supp
+92
-0
storage/connect/colblk.cpp
storage/connect/colblk.cpp
+1
-1
storage/connect/domdoc.cpp
storage/connect/domdoc.cpp
+14
-2
storage/connect/domdoc.h
storage/connect/domdoc.h
+2
-1
storage/connect/ha_connect.cc
storage/connect/ha_connect.cc
+146
-41
storage/connect/ha_connect.h
storage/connect/ha_connect.h
+2
-1
storage/connect/libdoc.cpp
storage/connect/libdoc.cpp
+146
-27
storage/connect/myconn.cpp
storage/connect/myconn.cpp
+2
-2
storage/connect/myconn.h
storage/connect/myconn.h
+1
-0
storage/connect/mysql-test/connect/r/mysql.result
storage/connect/mysql-test/connect/r/mysql.result
+21
-0
storage/connect/mysql-test/connect/r/xml.result
storage/connect/mysql-test/connect/r/xml.result
+1
-1
storage/connect/mysql-test/connect/t/mysql.test
storage/connect/mysql-test/connect/t/mysql.test
+15
-1
storage/connect/mysql-test/connect/t/mysql_grant.test
storage/connect/mysql-test/connect/t/mysql_grant.test
+78
-78
storage/connect/odbccat.h
storage/connect/odbccat.h
+2
-0
storage/connect/odbconn.cpp
storage/connect/odbconn.cpp
+294
-33
storage/connect/odbconn.h
storage/connect/odbconn.h
+5
-3
storage/connect/os.h
storage/connect/os.h
+1
-1
storage/connect/plgdbsem.h
storage/connect/plgdbsem.h
+2
-0
storage/connect/plgdbutl.cpp
storage/connect/plgdbutl.cpp
+28
-0
storage/connect/plgxml.h
storage/connect/plgxml.h
+1
-0
storage/connect/tabfmt.cpp
storage/connect/tabfmt.cpp
+1
-1
storage/connect/tabmul.cpp
storage/connect/tabmul.cpp
+5
-3
storage/connect/tabmysql.cpp
storage/connect/tabmysql.cpp
+245
-23
storage/connect/tabmysql.h
storage/connect/tabmysql.h
+86
-2
storage/connect/tabodbc.cpp
storage/connect/tabodbc.cpp
+374
-50
storage/connect/tabodbc.h
storage/connect/tabodbc.h
+85
-8
storage/connect/tabutil.cpp
storage/connect/tabutil.cpp
+12
-1
storage/connect/tabutil.h
storage/connect/tabutil.h
+2
-1
storage/connect/tabxcl.cpp
storage/connect/tabxcl.cpp
+4
-2
storage/connect/tabxcl.h
storage/connect/tabxcl.h
+1
-1
storage/connect/tabxml.cpp
storage/connect/tabxml.cpp
+27
-11
storage/connect/tabxml.h
storage/connect/tabxml.h
+1
-3
storage/connect/valblk.cpp
storage/connect/valblk.cpp
+4
-5
No files found.
client/mysqldump.c
View file @
7dc48ae3
...
...
@@ -5147,6 +5147,7 @@ char check_if_ignore_table(const char *table_name, char *table_type)
if
(
!
opt_no_data
&&
(
!
my_strcasecmp
(
&
my_charset_latin1
,
table_type
,
"MRG_MyISAM"
)
||
!
strcmp
(
table_type
,
"MRG_ISAM"
)
||
!
strcmp
(
table_type
,
"CONNECT"
)
||
!
strcmp
(
table_type
,
"FEDERATED"
)))
result
=
IGNORE_DATA
;
}
...
...
mysql-test/mysql-test-run.pl
View file @
7dc48ae3
...
...
@@ -379,6 +379,7 @@ sub main {
mtr_report
("
Logging: $0
",
join
("
",
@ARGV
));
$DEFAULT_SUITES
.=
'
,
'
.
join
('
,
',
qw(
connect
query_response_time
sequence
spider
...
...
mysql-test/valgrind.supp
View file @
7dc48ae3
...
...
@@ -1117,3 +1117,95 @@
fun:_nss_dns_gethostbyaddr_r
fun:gethostbyaddr_r
}
{
ConnectSE: unixODBC SQLAllocEnv leaves some "still reachable" pointers
Memcheck:Leak
fun:malloc
fun:strdup
...
obj:*/libodbc.so*
fun:_ZN7ODBConn10GetDriversEP7_qryres
}
{
ConnectSE: unixODBC SQLAllocEnv leaves some "still reachable" pointers
Memcheck:Leak
fun:calloc
...
obj:*/libodbc.so*
fun:_ZN7ODBConn10GetDriversEP7_qryres
}
{
ConnectSE: unixODBC SQLAllocEnv leavs some "still reachable" pointers
Memcheck:Leak
fun:malloc
fun:strdup
...
obj:*/libodbc.so*
fun:_ZN7ODBConn14GetDataSourcesEP7_qryres
}
{
ConnectSE: unixODBC SQLAllocEnv leavs some "still reachable" pointers
Memcheck:Leak
fun:calloc
...
obj:*/libodbc.so*
fun:_ZN7ODBConn14GetDataSourcesEP7_qryres
}
{
ConnectSE: unixODBC SQLDriverConnect leaves some "still reachable" pointers
Memcheck:Leak
fun:malloc
fun:strdup
...
obj:*/libodbc.so*
fun:SQLDriverConnect
fun:_ZN7ODBConn7ConnectEj
fun:_ZN7ODBConn4OpenEPcj
fun:_Z11ODBCColumnsP7_globalPcS1_S1_b
fun:_ZL26connect_assisted_discoveryP10handlertonP3THDP11TABLE_SHAREP14HA_CREATE_INFO
}
{
ConnectSE: unixODBC SQLDriverConnect leaves some "still reachable" pointers
Memcheck:Leak
fun:calloc
...
obj:*/libodbc.so*
fun:SQLDriverConnect
fun:_ZN7ODBConn7ConnectEj
fun:_ZN7ODBConn4OpenEPcj
fun:_Z11ODBCColumnsP7_globalPcS1_S1_b
fun:_ZL26connect_assisted_discoveryP10handlertonP3THDP11TABLE_SHAREP14HA_CREATE_INFO
}
{
ConnectSE: unixODBC SQLDriverConnect leaves some "still reachable" pointers
Memcheck:Leak
fun:malloc
...
obj:*/libodbc.so*
fun:SQLDriverConnect
fun:_ZN7ODBConn7ConnectEj
fun:_ZN7ODBConn4OpenEPcj
fun:_Z11ODBCColumnsP7_globalPcS1_S1_b
fun:_ZL26connect_assisted_discoveryP10handlertonP3THDP11TABLE_SHAREP14HA_CREATE_INFO
}
{
ConnectSE: unixODBC dlopen leaves some "still reachable"
Memcheck:Leak
fun:malloc
fun:expand_dynamic_string_token
...
obj:*/libltdl.so*
...
obj:*/libodbc.so*
}
storage/connect/colblk.cpp
View file @
7dc48ae3
...
...
@@ -178,7 +178,7 @@ bool COLBLK::InitValue(PGLOBAL g)
(
To_Tdb
)
?
To_Tdb
->
GetCat
()
:
NULL
)))
return
true
;
Status
=
BUF_READY
;
AddStatus
(
BUF_READY
)
;
Value
->
SetNullable
(
Nullable
);
#ifdef DEBTRACE
...
...
storage/connect/domdoc.cpp
View file @
7dc48ae3
...
...
@@ -592,6 +592,18 @@ PXNODE DOMNODELIST::GetItem(PGLOBAL g, int n, PXNODE np)
}
// end of GetItem
/******************************************************************/
/* Reset the pointer on the deleted item. */
/******************************************************************/
bool
DOMNODELIST
::
DropItem
(
PGLOBAL
g
,
int
n
)
{
if
(
Listp
==
NULL
||
Listp
->
length
<=
n
)
return
true
;
//Listp->item[n] = NULL; La proprit n'a pas de mthode 'set'
return
false
;
}
// end of DeleteItem
/* ----------------------- class DOMATTR ------------------------ */
/******************************************************************/
...
...
@@ -618,8 +630,8 @@ bool DOMATTR::SetText(PGLOBAL g, char *txtp, int len)
Len
=
len
;
}
// endif len
if
(
!
MultiByteToWideChar
(
CP_
ACP
,
0
,
txtp
,
strlen
(
txtp
)
+
1
,
Ws
,
Len
+
1
))
{
if
(
!
MultiByteToWideChar
(
CP_
UTF8
,
0
,
txtp
,
strlen
(
txtp
)
+
1
,
Ws
,
Len
+
1
))
{
sprintf
(
g
->
Message
,
MSG
(
WS_CONV_ERR
),
txtp
);
return
true
;
}
// endif
...
...
storage/connect/domdoc.h
View file @
7dc48ae3
...
...
@@ -104,8 +104,9 @@ class DOMNODELIST : public XMLNODELIST {
friend
class
DOMNODE
;
public:
// Methods
virtual
int
GetLength
(
void
)
{
return
Listp
->
length
;}
virtual
int
GetLength
(
void
)
{
return
Listp
->
length
;}
virtual
PXNODE
GetItem
(
PGLOBAL
g
,
int
n
,
PXNODE
np
);
virtual
bool
DropItem
(
PGLOBAL
g
,
int
n
);
protected:
// Constructor
...
...
storage/connect/ha_connect.cc
View file @
7dc48ae3
...
...
@@ -165,7 +165,7 @@ extern "C" char nmfile[];
extern
"C"
char
pdebug
[];
extern
"C"
{
char
version
[]
=
"Version 1.01.000
7 July 26
, 2013"
;
char
version
[]
=
"Version 1.01.000
8 August 18
, 2013"
;
#if defined(XMSG)
char
msglang
[];
// Default message language
...
...
@@ -1093,7 +1093,8 @@ PTDB ha_connect::GetTDB(PGLOBAL g)
if
(
!
xp
->
CheckQuery
(
valid_query_id
)
&&
tdbp
&&
!
stricmp
(
tdbp
->
GetName
(),
table_name
)
&&
tdbp
->
GetMode
()
==
xmod
)
{
&&
(
tdbp
->
GetMode
()
==
xmod
||
tdbp
->
GetAmType
()
==
TYPE_AM_XML
))
{
tp
=
tdbp
;
tp
->
SetMode
(
xmod
);
}
else
if
((
tp
=
CntGetTDB
(
g
,
table_name
,
xmod
,
this
)))
...
...
@@ -1132,13 +1133,14 @@ bool ha_connect::OpenTable(PGLOBAL g, bool del)
break
;
}
// endswitch xmode
if
(
xmod
!=
MODE_INSERT
)
{
if
(
xmod
!=
MODE_INSERT
||
tdbp
->
GetAmType
()
==
TYPE_AM_ODBC
||
tdbp
->
GetAmType
()
==
TYPE_AM_MYSQL
)
{
// Get the list of used fields (columns)
char
*
p
;
unsigned
int
k1
,
k2
,
n1
,
n2
;
Field
*
*
field
;
Field
*
fp
;
MY_BITMAP
*
map
=
table
->
read_set
;
MY_BITMAP
*
map
=
(
xmod
==
MODE_INSERT
)
?
table
->
write_set
:
table
->
read_set
;
MY_BITMAP
*
ump
=
(
xmod
==
MODE_UPDATE
)
?
table
->
write_set
:
NULL
;
k1
=
k2
=
0
;
...
...
@@ -1373,7 +1375,8 @@ int ha_connect::ScanRecord(PGLOBAL g, uchar *buf)
fp
->
option_struct
->
special
)
continue
;
// Is a virtual column possible here ???
if
(
xmod
==
MODE_INSERT
||
if
((
xmod
==
MODE_INSERT
&&
tdbp
->
GetAmType
()
!=
TYPE_AM_MYSQL
&&
tdbp
->
GetAmType
()
!=
TYPE_AM_ODBC
)
||
bitmap_is_set
(
table
->
write_set
,
fp
->
field_index
))
{
for
(
colp
=
tp
->
GetSetCols
();
colp
;
colp
=
colp
->
GetNext
())
if
(
!
stricmp
(
colp
->
GetName
(),
fp
->
field_name
))
...
...
@@ -2658,8 +2661,9 @@ int ha_connect::delete_all_rows()
PGLOBAL
g
=
xp
->
g
;
DBUG_ENTER
(
"ha_connect::delete_all_rows"
);
// Close and reopen the table so it will be deleted
rc
=
CloseTable
(
g
);
if
(
tdbp
&&
tdbp
->
GetAmType
()
!=
TYPE_AM_XML
)
// Close and reopen the table so it will be deleted
rc
=
CloseTable
(
g
);
if
(
!
(
OpenTable
(
g
)))
{
if
(
CntDeleteRow
(
g
,
tdbp
,
true
))
{
...
...
@@ -3462,7 +3466,7 @@ static bool add_field(String *sql, const char *field_name, int typ, int len,
{
bool
error
=
false
;
const
char
*
type
=
PLGtoMYSQLtype
(
typ
,
dbf
);
type
=
PLGtoMYSQLtype
(
typ
,
true
);
// type= PLGtoMYSQLtype(typ, true); ?????
error
|=
sql
->
append
(
'`'
);
error
|=
sql
->
append
(
field_name
);
...
...
@@ -3612,6 +3616,7 @@ static int init_table_share(THD *thd,
static
int
init_table_share
(
THD
*
thd
,
TABLE_SHARE
*
table_s
,
HA_CREATE_INFO
*
create_info
,
// char *dsn,
String
*
sql
)
{
bool
oom
=
false
;
...
...
@@ -3670,10 +3675,12 @@ static int init_table_share(THD* thd,
}
// endfor opt
if
(
create_info
->
connect_string
.
length
)
{
//if (dsn) {
oom
|=
sql
->
append
(
' '
);
oom
|=
sql
->
append
(
"CONNECTION='"
);
oom
|=
sql
->
append_for_single_quote
(
create_info
->
connect_string
.
str
,
create_info
->
connect_string
.
length
);
// oom|= sql->append_for_single_quote(dsn, strlen(dsn));
oom
|=
sql
->
append
(
'\''
);
if
(
oom
)
...
...
@@ -3715,6 +3722,25 @@ static void add_option(THD* thd, HA_CREATE_INFO *create_info,
#endif // NEW_WAY
}
// end of add_option
// Used to check whether a MYSQL table is created on itself
static
bool
CheckSelf
(
PGLOBAL
g
,
TABLE_SHARE
*
s
,
const
char
*
host
,
const
char
*
db
,
char
*
tab
,
const
char
*
src
,
int
port
)
{
if
(
src
)
return
false
;
else
if
(
host
&&
stricmp
(
host
,
"localhost"
)
&&
strcmp
(
host
,
"127.0.0.1"
))
return
false
;
else
if
(
db
&&
stricmp
(
db
,
s
->
db
.
str
))
return
false
;
else
if
(
tab
&&
stricmp
(
tab
,
s
->
table_name
.
str
))
return
false
;
else
if
(
port
&&
port
!=
(
signed
)
GetDefaultPort
())
return
false
;
strcpy
(
g
->
Message
,
"This MySQL table is defined on itself"
);
return
true
;
}
// end of CheckSelf
/**
@brief
connect_assisted_discovery() is called when creating a table with no columns.
...
...
@@ -3733,13 +3759,13 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
{
char
spc
=
','
,
qch
=
0
;
const
char
*
fncn
=
"?"
;
const
char
*
user
,
*
fn
,
*
db
,
*
host
,
*
pwd
,
*
prt
,
*
sep
,
*
tbl
,
*
src
;
const
char
*
user
,
*
fn
,
*
db
,
*
host
,
*
pwd
,
*
sep
,
*
tbl
,
*
src
;
const
char
*
col
,
*
ocl
,
*
rnk
,
*
pic
,
*
fcl
;
char
*
tab
,
*
dsn
;
#if defined(WIN32)
char
*
nsp
=
NULL
,
*
cls
=
NULL
;
#endif // WIN32
int
port
=
0
,
hdr
=
0
,
mxr
=
0
,
rc
=
0
;
int
port
=
0
,
hdr
=
0
,
mxr
=
0
,
rc
=
0
,
cop
=
0
;
uint
tm
,
fnc
=
FNC_NO
,
supfnc
=
(
FNC_NO
|
FNC_COL
);
bool
bif
,
ok
=
false
,
dbf
=
false
;
TABTYPE
ttp
=
TAB_UNDEF
;
...
...
@@ -3760,7 +3786,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
if
(
!
g
)
return
HA_ERR_INTERNAL_ERROR
;
user
=
host
=
pwd
=
prt
=
tbl
=
src
=
col
=
ocl
=
pic
=
fcl
=
rnk
=
dsn
=
NULL
;
user
=
host
=
pwd
=
tbl
=
src
=
col
=
ocl
=
pic
=
fcl
=
rnk
=
dsn
=
NULL
;
// Get the useful create options
ttp
=
GetTypeID
(
topt
->
type
);
...
...
@@ -3778,23 +3804,23 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
col
=
topt
->
colist
;
if
(
topt
->
oplist
)
{
host
=
GetListOption
(
g
,
"host"
,
topt
->
oplist
,
"localhost"
);
user
=
GetListOption
(
g
,
"user"
,
topt
->
oplist
,
"root"
);
host
=
GetListOption
(
g
,
"host"
,
topt
->
oplist
,
"localhost"
);
user
=
GetListOption
(
g
,
"user"
,
topt
->
oplist
,
"root"
);
// Default value db can come from the DBNAME=xxx option.
db
=
GetListOption
(
g
,
"database"
,
topt
->
oplist
,
db
);
col
=
GetListOption
(
g
,
"colist"
,
topt
->
oplist
,
col
);
ocl
=
GetListOption
(
g
,
"occurcol"
,
topt
->
oplist
,
NULL
);
pic
=
GetListOption
(
g
,
"pivotcol"
,
topt
->
oplist
,
NULL
);
fcl
=
GetListOption
(
g
,
"fnccol"
,
topt
->
oplist
,
NULL
);
rnk
=
GetListOption
(
g
,
"rankcol"
,
topt
->
oplist
,
NULL
);
pwd
=
GetListOption
(
g
,
"password"
,
topt
->
oplist
);
prt
=
GetListOption
(
g
,
"port"
,
topt
->
oplist
);
port
=
(
prt
)
?
atoi
(
prt
)
:
0
;
db
=
GetListOption
(
g
,
"database"
,
topt
->
oplist
,
db
);
col
=
GetListOption
(
g
,
"colist"
,
topt
->
oplist
,
col
);
ocl
=
GetListOption
(
g
,
"occurcol"
,
topt
->
oplist
,
NULL
);
pic
=
GetListOption
(
g
,
"pivotcol"
,
topt
->
oplist
,
NULL
);
fcl
=
GetListOption
(
g
,
"fnccol"
,
topt
->
oplist
,
NULL
);
rnk
=
GetListOption
(
g
,
"rankcol"
,
topt
->
oplist
,
NULL
);
pwd
=
GetListOption
(
g
,
"password"
,
topt
->
oplist
);
#if defined(WIN32)
nsp
=
GetListOption
(
g
,
"namespace"
,
topt
->
oplist
);
cls
=
GetListOption
(
g
,
"class"
,
topt
->
oplist
);
nsp
=
GetListOption
(
g
,
"namespace"
,
topt
->
oplist
);
cls
=
GetListOption
(
g
,
"class"
,
topt
->
oplist
);
#endif // WIN32
port
=
atoi
(
GetListOption
(
g
,
"port"
,
topt
->
oplist
,
"0"
));
mxr
=
atoi
(
GetListOption
(
g
,
"maxerr"
,
topt
->
oplist
,
"0"
));
cop
=
atoi
(
GetListOption
(
g
,
"checkdsn"
,
topt
->
oplist
,
"0"
));
}
else
{
host
=
"localhost"
;
user
=
"root"
;
...
...
@@ -3840,7 +3866,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
}
// endif p
}
else
if
(
ttp
!=
TAB_ODBC
||
!
(
fnc
&
(
FNC_TABLE
|
FNC_COL
)))
tab
=
(
char
*
)
create_info
->
alias
;
tab
=
table_s
->
table_name
.
str
;
// Default value
#if defined(NEW_WAY)
add_option
(
thd
,
create_info
,
"tabname"
,
tab
);
...
...
@@ -3850,8 +3876,18 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
switch
(
ttp
)
{
#if defined(ODBC_SUPPORT)
case
TAB_ODBC
:
if
(
!
(
dsn
=
create_info
->
connect_string
.
str
)
&&
!
(
fnc
&
(
FNC_DSN
|
FNC_DRIVER
)))
dsn
=
create_info
->
connect_string
.
str
;
if
(
fnc
&
(
FNC_DSN
|
FNC_DRIVER
))
ok
=
true
;
else
if
(
!
stricmp
(
thd
->
main_security_ctx
.
host
,
"localhost"
)
&&
cop
==
1
)
{
if
((
dsn
=
ODBCCheckConnection
(
g
,
dsn
,
cop
))
!=
NULL
)
{
thd
->
make_lex_string
(
&
create_info
->
connect_string
,
dsn
,
strlen
(
dsn
));
ok
=
true
;
}
// endif dsn
}
else
if
(
!
dsn
)
sprintf
(
g
->
Message
,
"Missing %s connection string"
,
topt
->
type
);
else
ok
=
true
;
...
...
@@ -3873,31 +3909,46 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
case
TAB_MYSQL
:
ok
=
true
;
if
((
dsn
=
create_info
->
connect_string
.
str
))
{
if
(
create_info
->
connect_string
.
str
)
{
int
len
=
create_info
->
connect_string
.
length
;
PMYDEF
mydef
=
new
(
g
)
MYSQLDEF
();
PDBUSER
dup
=
PlgGetUser
(
g
);
PCATLG
cat
=
(
dup
)
?
dup
->
Catalog
:
NULL
;
dsn
=
(
char
*
)
PlugSubAlloc
(
g
,
NULL
,
strlen
(
dsn
)
+
1
);
strncpy
(
dsn
,
create_info
->
connect_string
.
str
,
create_info
->
connect_string
.
length
);
dsn
[
create_info
->
connect_string
.
length
]
=
0
;
dsn
=
(
char
*
)
PlugSubAlloc
(
g
,
NULL
,
len
+
1
);
strncpy
(
dsn
,
create_info
->
connect_string
.
str
,
len
);
dsn
[
len
]
=
0
;
mydef
->
SetName
(
create_info
->
alias
);
mydef
->
SetCat
(
cat
);
if
(
!
mydef
->
ParseURL
(
g
,
dsn
))
{
host
=
mydef
->
GetHostname
();
user
=
mydef
->
GetUsername
();
pwd
=
mydef
->
GetPassword
();
db
=
mydef
->
GetDatabase
();
tab
=
mydef
->
GetTabname
();
port
=
mydef
->
GetPortnumber
();
if
(
!
mydef
->
ParseURL
(
g
,
dsn
,
false
))
{
if
(
mydef
->
GetHostname
())
host
=
mydef
->
GetHostname
();
if
(
mydef
->
GetUsername
())
user
=
mydef
->
GetUsername
();
if
(
mydef
->
GetPassword
())
pwd
=
mydef
->
GetPassword
();
if
(
mydef
->
GetDatabase
())
db
=
mydef
->
GetDatabase
();
if
(
mydef
->
GetTabname
())
tab
=
mydef
->
GetTabname
();
if
(
mydef
->
GetPortnumber
())
port
=
mydef
->
GetPortnumber
();
}
else
ok
=
false
;
}
else
if
(
!
user
)
user
=
"root"
;
if
(
CheckSelf
(
g
,
table_s
,
host
,
db
,
tab
,
src
,
port
))
ok
=
false
;
break
;
#endif // MYSQL_SUPPORT
#if defined(WIN32)
...
...
@@ -3946,7 +3997,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
else
return
HA_ERR_INTERNAL_ERROR
;
// Should never happen
if
(
src
&&
ttp
!=
TAB_PIVOT
)
{
if
(
src
&&
ttp
!=
TAB_PIVOT
&&
ttp
!=
TAB_ODBC
)
{
qrp
=
SrcColumns
(
g
,
host
,
db
,
user
,
pwd
,
src
,
port
);
if
(
qrp
&&
ttp
==
TAB_OCCUR
)
...
...
@@ -3964,7 +4015,12 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
switch
(
fnc
)
{
case
FNC_NO
:
case
FNC_COL
:
qrp
=
ODBCColumns
(
g
,
dsn
,
(
char
*
)
tab
,
NULL
,
fnc
==
FNC_COL
);
if
(
src
)
{
qrp
=
ODBCSrcCols
(
g
,
dsn
,
(
char
*
)
src
);
src
=
NULL
;
// for next tests
}
else
qrp
=
ODBCColumns
(
g
,
dsn
,
(
char
*
)
tab
,
NULL
,
fnc
==
FNC_COL
);
break
;
case
FNC_TABLE
:
qrp
=
ODBCTables
(
g
,
dsn
,
(
char
*
)
tab
,
true
);
...
...
@@ -4130,6 +4186,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
#else // !NEW_WAY
if
(
!
rc
)
rc
=
init_table_share
(
thd
,
table_s
,
create_info
,
&
sql
);
// rc= init_table_share(thd, table_s, create_info, dsn, &sql);
#endif // !NEW_WAY
return
rc
;
...
...
@@ -4250,6 +4307,54 @@ int ha_connect::create(const char *name, TABLE *table_arg,
DBUG_RETURN
(
HA_ERR_INTERNAL_ERROR
);
}
// endif tabname
case
TAB_MYSQL
:
{
const
char
*
src
=
options
->
srcdef
;
char
*
host
,
*
db
,
*
tab
=
(
char
*
)
options
->
tabname
;
int
port
;
host
=
GetListOption
(
g
,
"host"
,
options
->
oplist
,
NULL
);
db
=
GetListOption
(
g
,
"database"
,
options
->
oplist
,
NULL
);
port
=
atoi
(
GetListOption
(
g
,
"port"
,
options
->
oplist
,
"0"
));
if
(
create_info
->
connect_string
.
str
)
{
char
*
dsn
;
int
len
=
create_info
->
connect_string
.
length
;
PMYDEF
mydef
=
new
(
g
)
MYSQLDEF
();
PDBUSER
dup
=
PlgGetUser
(
g
);
PCATLG
cat
=
(
dup
)
?
dup
->
Catalog
:
NULL
;
dsn
=
(
char
*
)
PlugSubAlloc
(
g
,
NULL
,
len
+
1
);
strncpy
(
dsn
,
create_info
->
connect_string
.
str
,
len
);
dsn
[
len
]
=
0
;
mydef
->
SetName
(
create_info
->
alias
);
mydef
->
SetCat
(
cat
);
if
(
!
mydef
->
ParseURL
(
g
,
dsn
,
false
))
{
if
(
mydef
->
GetHostname
())
host
=
mydef
->
GetHostname
();
if
(
mydef
->
GetDatabase
())
db
=
mydef
->
GetDatabase
();
if
(
mydef
->
GetTabname
())
tab
=
mydef
->
GetTabname
();
if
(
mydef
->
GetPortnumber
())
port
=
mydef
->
GetPortnumber
();
}
else
{
my_message
(
ER_UNKNOWN_ERROR
,
g
->
Message
,
MYF
(
0
));
DBUG_RETURN
(
HA_ERR_INTERNAL_ERROR
);
}
// endif ParseURL
}
// endif connect_string
if
(
CheckSelf
(
g
,
table_arg
->
s
,
host
,
db
,
tab
,
src
,
port
))
{
my_message
(
ER_UNKNOWN_ERROR
,
g
->
Message
,
MYF
(
0
));
DBUG_RETURN
(
HA_ERR_INTERNAL_ERROR
);
}
// endif CheckSelf
}
break
;
default:
/* do nothing */
;
break
;
}
// endswitch ttp
...
...
storage/connect/ha_connect.h
View file @
7dc48ae3
...
...
@@ -208,7 +208,8 @@ public:
return
(
HA_NO_TRANSACTIONS
|
HA_REC_NOT_IN_SEQ
|
HA_HAS_RECORDS
|
HA_NO_AUTO_INCREMENT
|
HA_NO_PREFIX_CHAR_KEYS
|
HA_NO_COPY_ON_ALTER
|
HA_CAN_VIRTUAL_COLUMNS
|
/*HA_NULL_IN_KEY |*/
HA_BINLOG_ROW_CAPABLE
|
HA_BINLOG_STMT_CAPABLE
);
HA_BINLOG_ROW_CAPABLE
|
HA_BINLOG_STMT_CAPABLE
|
/*HA_NULL_IN_KEY |*/
HA_MUST_USE_TABLE_CONDITION_PUSHDOWN
);
}
/** @brief
...
...
storage/connect/libdoc.cpp
View file @
7dc48ae3
...
...
@@ -14,6 +14,10 @@
#include "my_global.h"
//#endif // !WIN32
#if !defined(LIBXML_TREE_ENABLED) || !defined(LIBXML_OUTPUT_ENABLED)
#error "tree support not compiled in"
#endif
#if !defined(LIBXML_XPATH_ENABLED) || !defined(LIBXML_SAX1_ENABLED)
#error "XPath not supported"
#endif
...
...
@@ -47,8 +51,6 @@ typedef struct _x2block { /* Loaded XML file block */
short
Type
;
/* TYPE_FB_XML */
int
Retcode
;
/* Return code from Load */
xmlDocPtr
Docp
;
/* Document interface pointer */
// xmlXPathContextPtr Ctxp;
// xmlXPathObjectPtr Xop;
}
X2BLOCK
,
*
PX2BLOCK
;
/******************************************************************/
...
...
@@ -91,6 +93,8 @@ class LIBXMLDOC : public XMLDOCUMENT {
xmlNodeSetPtr
Nlist
;
xmlXPathContextPtr
Ctxp
;
xmlXPathObjectPtr
Xop
;
xmlXPathObjectPtr
NlXop
;
xmlErrorPtr
Xerr
;
char
*
Buf
;
// Temporary
bool
Nofreelist
;
};
// end of class LIBXMLDOC
...
...
@@ -141,6 +145,7 @@ class XML2NODELIST : public XMLNODELIST {
// Methods
virtual
int
GetLength
(
void
);
virtual
PXNODE
GetItem
(
PGLOBAL
g
,
int
n
,
PXNODE
np
);
virtual
bool
DropItem
(
PGLOBAL
g
,
int
n
);
protected:
// Constructor
...
...
@@ -180,6 +185,23 @@ extern int trace;
}
// "C"
#if defined(MEMORY_TRACE)
static
int
m
=
0
;
static
char
s
[
500
];
/**************************************************************************/
/* Tracing output function. */
/**************************************************************************/
void
xtrc
(
char
const
*
fmt
,
...)
{
va_list
ap
;
va_start
(
ap
,
fmt
);
//vfprintf(stderr, fmt, ap);
vsprintf
(
s
,
fmt
,
ap
);
if
(
s
[
strlen
(
s
)
-
1
]
==
'\n'
)
s
[
strlen
(
s
)
-
1
]
=
0
;
va_end
(
ap
);
}
// end of htrc
static
xmlFreeFunc
Free
;
static
xmlMallocFunc
Malloc
;
static
xmlMallocFunc
MallocA
;
...
...
@@ -188,42 +210,53 @@ static xmlStrdupFunc Strdup;
void
xmlMyFree
(
void
*
mem
)
{
if
(
trace
)
htrc
(
"Freeing at %p
\n
"
,
mem
);
if
(
trace
)
{
htrc
(
"%.4d Freeing at %p %s
\n
"
,
++
m
,
mem
,
s
);
*
s
=
0
;
}
// endif trace
Free
(
mem
);
}
// end of xmlMyFree
void
*
xmlMyMalloc
(
size_t
size
)
{
void
*
p
=
Malloc
(
size
);
if
(
trace
)
htrc
(
"Allocating %.5d at %p
\n
"
,
size
,
p
);
if
(
trace
)
{
htrc
(
"%.4d Allocating %.5d at %p %s
\n
"
,
++
m
,
size
,
p
,
s
);
*
s
=
0
;
}
// endif trace
return
p
;
}
// end of xmlMyMalloc
void
*
xmlMyMallocAtomic
(
size_t
size
)
{
void
*
p
=
MallocA
(
size
);
if
(
trace
)
htrc
(
"Atom alloc %.5d at %p
\n
"
,
size
,
p
);
if
(
trace
)
{
htrc
(
"%.4d Atom alloc %.5d at %p %s
\n
"
,
++
m
,
size
,
p
,
s
);
*
s
=
0
;
}
// endif trace
return
p
;
}
// end of xmlMyMallocAtomic
void
*
xmlMyRealloc
(
void
*
mem
,
size_t
size
)
{
void
*
p
=
Realloc
(
mem
,
size
);
if
(
trace
)
htrc
(
"ReAlloc %.5d to %p from %p
\n
"
,
size
,
p
,
mem
);
if
(
trace
)
{
htrc
(
"%.4d ReAlloc %.5d to %p from %p %s
\n
"
,
++
m
,
size
,
p
,
mem
,
s
);
*
s
=
0
;
}
// endif trace
return
p
;
}
// end of xmlMyRealloc
char
*
xmlMyStrdup
(
const
char
*
str
)
{
char
*
p
=
Strdup
(
str
);
if
(
trace
)
htrc
(
"Duplicating to %p from %p %s
\n
"
,
p
,
str
,
str
);
if
(
trace
)
{
htrc
(
"%.4d Duplicating to %p from %p %s %s
\n
"
,
++
m
,
p
,
str
,
str
,
s
);
*
s
=
0
;
}
// endif trace
return
p
;
}
// end of xmlMyStrdup
#define htrc xtrc
#endif // MEMORY_TRACE
/******************************************************************/
...
...
@@ -295,6 +328,8 @@ LIBXMLDOC::LIBXMLDOC(char *nsl, char *nsdf, char *enc, PFBLOCK fp)
Nlist
=
NULL
;
Ctxp
=
NULL
;
Xop
=
NULL
;
NlXop
=
NULL
;
Xerr
=
NULL
;
Buf
=
NULL
;
Nofreelist
=
false
;
}
// end of LIBXMLDOC constructor
...
...
@@ -321,9 +356,10 @@ bool LIBXMLDOC::ParseFile(char *fn)
Encoding
=
(
char
*
)
Docp
->
encoding
;
return
false
;
}
else
return
true
;
}
else
if
((
Xerr
=
xmlGetLastError
()))
xmlResetError
(
Xerr
)
;
return
true
;
}
// end of ParseFile
/******************************************************************/
...
...
@@ -344,8 +380,6 @@ PFBLOCK LIBXMLDOC::LinkXblock(PGLOBAL g, MODE m, int rc, char *fn)
xp
->
Length
=
(
m
==
MODE_READ
)
?
1
:
0
;
xp
->
Retcode
=
rc
;
xp
->
Docp
=
Docp
;
// xp->Ctxp = Ctxp;
// xp->Xop = Xop;
// Return xp as a fp
return
(
PFBLOCK
)
xp
;
...
...
@@ -356,6 +390,9 @@ PFBLOCK LIBXMLDOC::LinkXblock(PGLOBAL g, MODE m, int rc, char *fn)
/******************************************************************/
bool
LIBXMLDOC
::
NewDoc
(
PGLOBAL
g
,
char
*
ver
)
{
if
(
trace
)
htrc
(
"NewDoc
\n
"
);
return
((
Docp
=
xmlNewDoc
(
BAD_CAST
ver
))
==
NULL
);
}
// end of NewDoc
...
...
@@ -462,8 +499,7 @@ int LIBXMLDOC::DumpDoc(PGLOBAL g, char *ofn)
if
(
xmlSaveFormatFileEnc
((
const
char
*
)
ofn
,
Docp
,
Encoding
,
0
)
<
0
)
{
xmlErrorPtr
err
=
xmlGetLastError
();
strcpy
(
g
->
Message
,
(
err
)
?
err
->
message
:
"Error saving XML doc"
);
strcpy
(
g
->
Message
,
(
err
)
?
err
->
message
:
"Error saving XML doc"
);
rc
=
-
1
;
}
// endif Save
// rc = xmlDocDump(of, Docp);
...
...
@@ -497,17 +533,44 @@ void LIBXMLDOC::CloseDoc(PGLOBAL g, PFBLOCK xp)
if
(
trace
)
htrc
(
"CloseDoc: xp=%p count=%d
\n
"
,
xp
,
(
xp
)
?
xp
->
Count
:
0
);
if
(
xp
&&
xp
->
Count
==
1
)
{
if
(
Nlist
)
//
if (xp && xp->Count == 1) {
if
(
Nlist
)
{
xmlXPathFreeNodeSet
(
Nlist
);
if
(
Xop
)
if
((
Xerr
=
xmlGetLastError
()))
xmlResetError
(
Xerr
);
Nlist
=
NULL
;
}
// endif Nlist
if
(
Xop
)
{
xmlXPathFreeObject
(
Xop
);
if
(
Ctxp
)
if
((
Xerr
=
xmlGetLastError
()))
xmlResetError
(
Xerr
);
Xop
=
NULL
;
}
// endif Xop
if
(
NlXop
)
{
xmlXPathFreeObject
(
NlXop
);
if
((
Xerr
=
xmlGetLastError
()))
xmlResetError
(
Xerr
);
NlXop
=
NULL
;
}
// endif NlXop
if
(
Ctxp
)
{
xmlXPathFreeContext
(
Ctxp
);
}
// endif Count
if
((
Xerr
=
xmlGetLastError
()))
xmlResetError
(
Xerr
);
Ctxp
=
NULL
;
}
// endif Ctxp
// } // endif Count
CloseXML2File
(
g
,
xp
,
false
);
}
// end of Close
...
...
@@ -560,18 +623,29 @@ xmlNodeSetPtr LIBXMLDOC::GetNodeList(PGLOBAL g, xmlNodePtr np, char *xp)
}
// endfor nsp
}
else
{
}
// endif Ctxp
if
(
Xop
)
{
if
(
trace
)
htrc
(
"Calling xmlXPathFreeNodeSetList Xop=%p
\n
"
,
Xop
);
htrc
(
"Calling xmlXPathFreeNodeSetList Xop=%p NOFREE=%d
\n
"
,
Xop
,
Nofreelist
);
if
(
Nofreelist
)
{
// Making Nlist that must not be freed yet
xmlXPathFreeNodeSetList
(
Xop
);
// Caused memory leak
// xmlXPathFreeNodeSetList(Xop); // Caused memory leak
assert
(
!
NlXop
);
NlXop
=
Xop
;
// Freed on closing
Nofreelist
=
false
;
}
else
xmlXPathFreeObject
(
Xop
);
// Caused node not found
}
// endif Ctxp
if
((
Xerr
=
xmlGetLastError
()))
{
strcpy
(
g
->
Message
,
Xerr
->
message
);
xmlResetError
(
Xerr
);
return
NULL
;
}
// endif Xerr
}
// endif Xop
// Set the context to the calling node
Ctxp
->
node
=
np
;
...
...
@@ -990,6 +1064,8 @@ void XML2NODE::AddText(PGLOBAL g, char *txtp)
/******************************************************************/
void
XML2NODE
::
DeleteChild
(
PGLOBAL
g
,
PXNODE
dnp
)
{
xmlErrorPtr
xerr
;
if
(
trace
)
htrc
(
"DeleteChild: node=%p
\n
"
,
dnp
);
...
...
@@ -999,12 +1075,39 @@ void XML2NODE::DeleteChild(PGLOBAL g, PXNODE dnp)
// This is specific to row nodes
if
(
text
&&
text
->
type
==
XML_TEXT_NODE
)
{
xmlUnlinkNode
(
text
);
if
((
xerr
=
xmlGetLastError
()))
goto
err
;
xmlFreeNode
(
text
);
if
((
xerr
=
xmlGetLastError
()))
goto
err
;
}
// endif type
xmlUnlinkNode
(
np
);
if
((
xerr
=
xmlGetLastError
()))
goto
err
;
xmlFreeNode
(
np
);
if
((
xerr
=
xmlGetLastError
()))
goto
err
;
Delete
(
dnp
);
if
((
xerr
=
xmlGetLastError
()))
goto
err
;
return
;
err:
if
(
trace
)
htrc
(
"DeleteChild: errmsg=%s
\n
"
,
xerr
->
message
);
xmlResetError
(
xerr
);
}
// end of DeleteChild
/* -------------------- class XML2NODELIST ---------------------- */
...
...
@@ -1045,6 +1148,22 @@ PXNODE XML2NODELIST::GetItem(PGLOBAL g, int n, PXNODE np)
}
// end of GetItem
/******************************************************************/
/* Reset the pointer on the deleted item. */
/******************************************************************/
bool
XML2NODELIST
::
DropItem
(
PGLOBAL
g
,
int
n
)
{
if
(
trace
)
htrc
(
"DropItem: n=%d
\n
"
,
n
);
// We should do something here
if
(
!
Listp
||
Listp
->
nodeNr
<=
n
)
return
true
;
Listp
->
nodeTab
[
n
]
=
NULL
;
// This was causing Valgrind warning
return
false
;
}
// end of DropItem
/* ---------------------- class XML2ATTR ------------------------ */
/******************************************************************/
...
...
storage/connect/myconn.cpp
View file @
7dc48ae3
...
...
@@ -89,7 +89,7 @@ PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db,
static
unsigned
int
length
[]
=
{
0
,
4
,
16
,
4
,
4
,
4
,
4
,
4
,
256
,
32
,
32
};
char
*
fld
,
*
fmt
,
cmd
[
128
];
int
i
,
n
,
nf
,
ncol
=
sizeof
(
buftyp
)
/
sizeof
(
int
);
int
len
,
type
,
prec
,
rc
,
k
=
0
;
int
len
,
type
,
prec
,
rc
,
k
=
0
;
PQRYRES
qrp
;
PCOLRES
crp
;
MYSQLC
myc
;
...
...
@@ -166,7 +166,7 @@ PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db,
// Get type, type name, and precision
fld
=
myc
.
GetCharField
(
1
);
prec
=
0
;
len
=
25
6
;
// Default for text or blob
len
=
25
5
;
// Default for text or blob
if
((
nf
=
sscanf
(
fld
,
"%[^(](%d,%d"
,
cmd
,
&
len
,
&
prec
))
<
1
)
{
sprintf
(
g
->
Message
,
MSG
(
BAD_FIELD_TYPE
),
fld
);
...
...
storage/connect/myconn.h
View file @
7dc48ae3
...
...
@@ -54,6 +54,7 @@ uint GetDefaultPort(void);
class
DllItem
MYSQLC
{
friend
class
TDBMYSQL
;
friend
class
MYSQLCOL
;
friend
class
TDBMYEXC
;
// Construction
public:
MYSQLC
(
void
);
...
...
storage/connect/mysql-test/connect/r/mysql.result
View file @
7dc48ae3
...
...
@@ -217,3 +217,24 @@ t2 CREATE TABLE `t2` (
SELECT * FROM t2;
a
DROP TABLE t2, t1;
#
# MDEV-4877 mysqldump dumps all data from a connect table
#
CREATE TABLE t1 (a INT);
INSERT INTO t1 VALUES (10),(20),(30);
CREATE TABLE t2 ENGINE=CONNECT TABLE_TYPE=MYSQL CONNECTION='mysql://root@localhost:PORT/test/t1';
SELECT * FROM t2;
a
10
20
30
# Start of mysqldump ------
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `t2` (
`a` int(11) DEFAULT NULL
) ENGINE=CONNECT DEFAULT CHARSET=latin1 CONNECTION='mysql://root@localhost:PORT/test/t1' `TABLE_TYPE`='MYSQL';
/*!40101 SET character_set_client = @saved_cs_client */;
# End of mysqldump ------
DROP TABLE t2;
DROP TABLE t1;
storage/connect/mysql-test/connect/r/xml.result
View file @
7dc48ae3
...
...
@@ -413,7 +413,7 @@ DROP TABLE t1;
SET @a=LOAD_FILE('MYSQLD_DATADIR/test/t1.xml');
SELECT CAST(@a AS CHAR CHARACTER SET latin1);
CAST(@a AS CHAR CHARACTER SET latin1) <?xml version="1.0" encoding="iso-8859-1"?>
<!-- Created by CONNECT Version 1.01.000
7 July 26
, 2013 -->
<!-- Created by CONNECT Version 1.01.000
8 August 18
, 2013 -->
<t1>
<line>
<node>ÀÁÂÃ</node>
...
...
storage/connect/mysql-test/connect/t/mysql.test
View file @
7dc48ae3
...
...
@@ -10,7 +10,7 @@ let $PORT= `select @@port`;
--
disable_query_log
--
replace_result
$PORT
PORT
--
error
0
,
ER_UNKNOWN_ERROR
--
eval
CREATE
TABLE
t1
(
a
INT
)
ENGINE
=
CONNECT
TABLE_TYPE
=
MYSQL
TABNAME
=
't1'
OPTION_LIST
=
'host=localhost,user=root,port=$PORT'
--
eval
CREATE
TABLE
t1
(
a
INT
)
ENGINE
=
CONNECT
TABLE_TYPE
=
MYSQL
TABNAME
=
't
x
1'
OPTION_LIST
=
'host=localhost,user=root,port=$PORT'
if
(
!
`SELECT count(*) FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA='test' AND TABLE_NAME='t1'
AND ENGINE='CONNECT'
...
...
@@ -420,3 +420,17 @@ DROP TABLE t2, t1;
# TODO: add test for YEAR
# TODO: add tests for fractional seconds
--
echo
#
--
echo
# MDEV-4877 mysqldump dumps all data from a connect table
--
echo
#
CREATE
TABLE
t1
(
a
INT
);
INSERT
INTO
t1
VALUES
(
10
),(
20
),(
30
);
--
replace_result
$PORT
PORT
--
eval
CREATE
TABLE
t2
ENGINE
=
CONNECT
TABLE_TYPE
=
MYSQL
CONNECTION
=
'mysql://root@localhost:$PORT/test/t1'
SELECT
*
FROM
t2
;
--
echo
# Start of mysqldump ------
--
replace_result
$PORT
PORT
--
exec
$MYSQL_DUMP
--
compact
test
t2
--
echo
# End of mysqldump ------
DROP
TABLE
t2
;
DROP
TABLE
t1
;
storage/connect/mysql-test/connect/t/mysql_grant.test
View file @
7dc48ae3
--
source
include
/
not_embedded
.
inc
let
$PORT
=
`select @@port`
;
--
disable_query_log
--
replace_result
$PORT
PORT
--
error
0
,
ER_UNKNOWN_ERROR
--
eval
CREATE
TABLE
t1
(
a
INT
)
ENGINE
=
CONNECT
TABLE_TYPE
=
MYSQL
TABNAME
=
't
1'
OPTION_LIST
=
'host=localhost,user=root,port=$PORT'
if
(
!
`SELECT count(*) FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA='test' AND TABLE_NAME='t1'
AND ENGINE='CONNECT'
AND CREATE_OPTIONS LIKE '%`
table_type
`=MySQL%'`
)
{
Skip
Need
MySQL
support
;
}
DROP
TABLE
t1
;
--
enable_query_log
--
echo
#
--
echo
# Testing FILE privilege
--
echo
#
GRANT
ALL
PRIVILEGES
ON
*.*
TO
user
@
localhost
;
REVOKE
FILE
ON
*.*
FROM
user
@
localhost
;
--
connect
(
user
,
localhost
,
user
,,)
--
connection
user
SELECT
user
();
--
replace_result
$PORT
PORT
--
error
ER_ACCESS_DENIED_ERROR
--
eval
CREATE
TABLE
t1
(
a
INT
NOT
NULL
)
ENGINE
=
CONNECT
TABLE_TYPE
=
MySQL
OPTION_LIST
=
'host=localhost,user=root1,port=$PORT'
--
connection
default
SELECT
user
();
CREATE
TABLE
t1remote
(
a
INT
NOT
NULL
);
INSERT
INTO
t1remote
VALUES
(
10
),(
20
),(
30
);
--
replace_result
$PORT
PORT
--
eval
CREATE
TABLE
t1
(
a
INT
NOT
NULL
)
ENGINE
=
CONNECT
TABLE_TYPE
=
MySQL
TABNAME
=
t1remote
OPTION_LIST
=
'host=localhost,user=root,port=$PORT'
SELECT
*
FROM
t1
;
--
connection
user
SELECT
user
();
--
error
ER_ACCESS_DENIED_ERROR
SELECT
*
FROM
t1
;
--
error
ER_ACCESS_DENIED_ERROR
INSERT
INTO
t1
VALUES
(
'xxx'
);
--
error
ER_ACCESS_DENIED_ERROR
DELETE
FROM
t1
WHERE
a
=
'xxx'
;
--
error
ER_ACCESS_DENIED_ERROR
UPDATE
t1
SET
a
=
'yyy'
WHERE
a
=
'xxx'
;
--
error
ER_ACCESS_DENIED_ERROR
TRUNCATE
TABLE
t1
;
--
error
ER_ACCESS_DENIED_ERROR
ALTER
TABLE
t1
READONLY
=
1
;
--
error
ER_ACCESS_DENIED_ERROR
CREATE
VIEW
v1
AS
SELECT
*
FROM
t1
;
--
echo
# Testing a VIEW created with FILE privileges but accessed with no FILE
--
connection
default
SELECT
user
();
CREATE
VIEW
v1
AS
SELECT
*
FROM
t1
;
--
connection
user
SELECT
user
();
--
error
ER_ACCESS_DENIED_ERROR
SELECT
*
FROM
v1
;
--
error
ER_ACCESS_DENIED_ERROR
INSERT
INTO
v1
VALUES
(
2
);
--
error
ER_ACCESS_DENIED_ERROR
UPDATE
v1
SET
a
=
123
;
--
error
ER_ACCESS_DENIED_ERROR
DELETE
FROM
v1
;
--
disconnect
user
--
connection
default
SELECT
user
();
DROP
VIEW
v1
;
DROP
TABLE
t1
,
t1remote
;
DROP
USER
user
@
localhost
;
--
echo
#
--
echo
# Testing FILE privileges done
--
echo
#
--
source
include
/
not_embedded
.
inc
let
$PORT
=
`select @@port`
;
--
disable_query_log
--
replace_result
$PORT
PORT
--
error
0
,
ER_UNKNOWN_ERROR
--
eval
CREATE
TABLE
t1
(
a
INT
)
ENGINE
=
CONNECT
TABLE_TYPE
=
MYSQL
TABNAME
=
't
x1'
OPTION_LIST
=
'host=localhost,user=root,port=$PORT'
if
(
!
`SELECT count(*) FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA='test' AND TABLE_NAME='t1'
AND ENGINE='CONNECT'
AND CREATE_OPTIONS LIKE '%`
table_type
`=MySQL%'`
)
{
Skip
Need
MySQL
support
;
}
DROP
TABLE
t1
;
--
enable_query_log
--
echo
#
--
echo
# Testing FILE privilege
--
echo
#
GRANT
ALL
PRIVILEGES
ON
*.*
TO
user
@
localhost
;
REVOKE
FILE
ON
*.*
FROM
user
@
localhost
;
--
connect
(
user
,
localhost
,
user
,,)
--
connection
user
SELECT
user
();
--
replace_result
$PORT
PORT
--
error
ER_ACCESS_DENIED_ERROR
--
eval
CREATE
TABLE
t1
(
a
INT
NOT
NULL
)
ENGINE
=
CONNECT
TABLE_TYPE
=
MySQL
OPTION_LIST
=
'host=localhost,user=root1,port=$PORT'
--
connection
default
SELECT
user
();
CREATE
TABLE
t1remote
(
a
INT
NOT
NULL
);
INSERT
INTO
t1remote
VALUES
(
10
),(
20
),(
30
);
--
replace_result
$PORT
PORT
--
eval
CREATE
TABLE
t1
(
a
INT
NOT
NULL
)
ENGINE
=
CONNECT
TABLE_TYPE
=
MySQL
TABNAME
=
t1remote
OPTION_LIST
=
'host=localhost,user=root,port=$PORT'
SELECT
*
FROM
t1
;
--
connection
user
SELECT
user
();
--
error
ER_ACCESS_DENIED_ERROR
SELECT
*
FROM
t1
;
--
error
ER_ACCESS_DENIED_ERROR
INSERT
INTO
t1
VALUES
(
'xxx'
);
--
error
ER_ACCESS_DENIED_ERROR
DELETE
FROM
t1
WHERE
a
=
'xxx'
;
--
error
ER_ACCESS_DENIED_ERROR
UPDATE
t1
SET
a
=
'yyy'
WHERE
a
=
'xxx'
;
--
error
ER_ACCESS_DENIED_ERROR
TRUNCATE
TABLE
t1
;
--
error
ER_ACCESS_DENIED_ERROR
ALTER
TABLE
t1
READONLY
=
1
;
--
error
ER_ACCESS_DENIED_ERROR
CREATE
VIEW
v1
AS
SELECT
*
FROM
t1
;
--
echo
# Testing a VIEW created with FILE privileges but accessed with no FILE
--
connection
default
SELECT
user
();
CREATE
VIEW
v1
AS
SELECT
*
FROM
t1
;
--
connection
user
SELECT
user
();
--
error
ER_ACCESS_DENIED_ERROR
SELECT
*
FROM
v1
;
--
error
ER_ACCESS_DENIED_ERROR
INSERT
INTO
v1
VALUES
(
2
);
--
error
ER_ACCESS_DENIED_ERROR
UPDATE
v1
SET
a
=
123
;
--
error
ER_ACCESS_DENIED_ERROR
DELETE
FROM
v1
;
--
disconnect
user
--
connection
default
SELECT
user
();
DROP
VIEW
v1
;
DROP
TABLE
t1
,
t1remote
;
DROP
USER
user
@
localhost
;
--
echo
#
--
echo
# Testing FILE privileges done
--
echo
#
storage/connect/odbccat.h
View file @
7dc48ae3
/***********************************************************************/
/* ODBC catalog function prototypes. */
/***********************************************************************/
char
*
ODBCCheckConnection
(
PGLOBAL
g
,
char
*
dsn
,
int
cop
);
PQRYRES
ODBCDataSources
(
PGLOBAL
g
,
bool
info
);
PQRYRES
ODBCColumns
(
PGLOBAL
g
,
char
*
dsn
,
char
*
table
,
char
*
colpat
,
bool
info
);
PQRYRES
ODBCSrcCols
(
PGLOBAL
g
,
char
*
dsn
,
char
*
src
);
PQRYRES
ODBCTables
(
PGLOBAL
g
,
char
*
dsn
,
char
*
tabpat
,
bool
info
);
PQRYRES
ODBCDrivers
(
PGLOBAL
g
,
bool
info
);
storage/connect/odbconn.cpp
View file @
7dc48ae3
/************ Odbconn C++ Functions Source Code File (.CPP) ************/
/* Name: ODBCONN.CPP Version 1.
6
*/
/* Name: ODBCONN.CPP Version 1.
7
*/
/* */
/* (C) Copyright to the author Olivier BERTRAND 1998-2013 */
/* */
...
...
@@ -13,6 +13,7 @@
#if defined(WIN32)
//nclude <io.h>
//nclude <fcntl.h>
#include <direct.h> // for getcwd
#if defined(__BORLANDC__)
#define __MFC_COMPAT__ // To define min/max as macro
#endif
...
...
@@ -76,8 +77,9 @@ static short GetSQLType(int type)
case
TYPE_SHORT
:
tp
=
SQL_SMALLINT
;
break
;
case
TYPE_INT
:
tp
=
SQL_INTEGER
;
break
;
case
TYPE_DATE
:
tp
=
SQL_TIMESTAMP
;
break
;
case
TYPE_BIGINT
:
tp
=
SQL_BIGINT
;
break
;
// (-5)
case
TYPE_BIGINT
:
tp
=
SQL_BIGINT
;
break
;
// (-5)
case
TYPE_FLOAT
:
tp
=
SQL_DOUBLE
;
break
;
case
TYPE_TINY
:
tp
=
SQL_TINYINT
;
break
;
}
// endswitch type
return
tp
;
...
...
@@ -97,6 +99,7 @@ static int GetSQLCType(int type)
case
TYPE_DATE
:
tp
=
SQL_C_TIMESTAMP
;
break
;
case
TYPE_BIGINT
:
tp
=
SQL_C_SBIGINT
;
break
;
case
TYPE_FLOAT
:
tp
=
SQL_C_DOUBLE
;
break
;
case
TYPE_TINY
:
tp
=
SQL_C_TINYINT
;
break
;
}
// endswitch type
return
tp
;
...
...
@@ -127,9 +130,11 @@ int TranslateSQLType(int stp, int prec, int& len)
type
=
TYPE_INT
;
break
;
case
SQL_SMALLINT
:
// 5
type
=
TYPE_SHORT
;
break
;
case
SQL_TINYINT
:
// (-6)
case
SQL_BIT
:
// (-7)
type
=
TYPE_
SHORT
;
type
=
TYPE_
TINY
;
break
;
case
SQL_FLOAT
:
// 6
case
SQL_REAL
:
// 7
...
...
@@ -168,10 +173,36 @@ int TranslateSQLType(int stp, int prec, int& len)
}
// end of TranslateSQLType
/***********************************************************************/
/* ODBC
onn static members initialization.
*/
/* ODBC
CheckConnection: Check completeness of connection string.
*/
/***********************************************************************/
//HENV ODBConn::m_henv = SQL_NULL_HENV;
//int ODBConn::m_nAlloc = 0; // per-Appl reference to HENV above
char
*
ODBCCheckConnection
(
PGLOBAL
g
,
char
*
dsn
,
int
cop
)
{
char
*
newdsn
,
dir
[
_MAX_PATH
],
buf
[
_MAX_PATH
];
int
rc
;
DWORD
options
=
ODBConn
::
openReadOnly
;
ODBConn
*
ocp
=
new
(
g
)
ODBConn
(
g
,
NULL
);
(
void
)
getcwd
(
dir
,
sizeof
(
dir
)
-
1
);
switch
(
cop
)
{
case
1
:
options
|=
ODBConn
::
forceOdbcDialog
;
break
;
case
2
:
options
|=
ODBConn
::
noOdbcDialog
;
break
;
}
// endswitch cop
if
(
ocp
->
Open
(
dsn
,
options
)
<
1
)
newdsn
=
NULL
;
else
newdsn
=
ocp
->
GetConnect
();
(
void
)
getcwd
(
buf
,
sizeof
(
buf
)
-
1
);
// Some data sources change the current directory
if
(
strcmp
(
dir
,
buf
))
rc
=
chdir
(
dir
);
ocp
->
Close
();
return
newdsn
;
// Return complete connection string
}
// end of ODBCCheckConnection
/***********************************************************************/
/* Allocate the structure used to refer to the result set. */
...
...
@@ -225,7 +256,6 @@ static void ResetNullValues(CATPARM *cap)
/***********************************************************************/
/* ODBCColumns: constructs the result blocks containing all columns */
/* of an ODBC table that will be retrieved by GetData commands. */
/* Note: The first two columns (Qualifier, Owner) are ignored. */
/***********************************************************************/
PQRYRES
ODBCColumns
(
PGLOBAL
g
,
char
*
dsn
,
char
*
table
,
char
*
colpat
,
bool
info
)
...
...
@@ -251,7 +281,7 @@ PQRYRES ODBCColumns(PGLOBAL g, char *dsn, char *table,
if
(
!
info
)
{
ocp
=
new
(
g
)
ODBConn
(
g
,
NULL
);
if
(
ocp
->
Open
(
dsn
,
2
)
<
1
)
// 2 is openReadOnly
if
(
ocp
->
Open
(
dsn
,
10
)
<
1
)
// openReadOnly + noODBCdialog
return
NULL
;
// We fix a MySQL limit because some data sources return 32767
...
...
@@ -314,6 +344,17 @@ PQRYRES ODBCColumns(PGLOBAL g, char *dsn, char *table,
return
qrp
;
}
// end of ODBCColumns
/**************************************************************************/
/* ODBCSrcCols: constructs the result blocks containing the */
/* description of all the columns of a Srcdef option. */
/**************************************************************************/
PQRYRES
ODBCSrcCols
(
PGLOBAL
g
,
char
*
dsn
,
char
*
src
)
{
ODBConn
*
ocp
=
new
(
g
)
ODBConn
(
g
,
NULL
);
return
ocp
->
GetMetaData
(
g
,
dsn
,
src
);
}
// end of ODBCSrcCols
#if 0
/**************************************************************************/
/* MyODBCCols: returns column info as required by ha_connect::pre_create. */
...
...
@@ -800,6 +841,17 @@ void DBX::BuildErrorMessage(ODBConn* pdb, HSTMT hstmt)
}
// end of BuildErrorMessage
const
char
*
DBX
::
GetErrorMessage
(
int
i
)
{
if
(
i
<
0
||
i
>=
MAX_NUM_OF_MSG
)
return
"No ODBC error"
;
else
if
(
m_ErrMsg
[
i
])
return
m_ErrMsg
[
i
];
else
return
(
m_Msg
)
?
m_Msg
:
"Unknown error"
;
}
// end of GetErrorMessage
/***********************************************************************/
/* ODBConn construction/destruction. */
/***********************************************************************/
...
...
@@ -818,7 +870,7 @@ ODBConn::ODBConn(PGLOBAL g, TDBODBC *tdbp)
m_Catver
=
(
tdbp
)
?
tdbp
->
Catver
:
0
;
m_Connect
=
NULL
;
m_Updatable
=
true
;
//m_Transactions
= false;
m_Transact
=
false
;
m_IDQuoteChar
=
'\''
;
//*m_ErrMsg = '\0';
}
// end of ODBConn
...
...
@@ -1061,7 +1113,7 @@ bool ODBConn::Connect(DWORD Options)
if
(
hWnd
==
NULL
)
hWnd
=
GetDesktopWindow
();
#else // !WIN32
HWND
hWnd
=
NULL
;
HWND
hWnd
=
1
;
#endif // !WIN32
PGLOBAL
&
g
=
m_G
;
PDBUSER
dup
=
PlgGetUser
(
g
);
...
...
@@ -1204,8 +1256,7 @@ int ODBConn::ExecDirectSQL(char *sql, ODBCCOL *tocols)
void
*
buffer
;
bool
b
;
UWORD
n
;
SWORD
ncol
,
len
,
tp
;
SQLLEN
afrw
;
SWORD
len
,
tp
,
ncol
=
0
;
ODBCCOL
*
colp
;
RETCODE
rc
;
HSTMT
hstmt
;
...
...
@@ -1240,26 +1291,44 @@ int ODBConn::ExecDirectSQL(char *sql, ODBCCOL *tocols)
if
(
trace
)
htrc
(
"ExecDirect hstmt=%p %.64s
\n
"
,
hstmt
,
sql
);
do
{
rc
=
SQLExecDirect
(
hstmt
,
(
PUCHAR
)
sql
,
SQL_NTS
);
}
while
(
rc
==
SQL_STILL_EXECUTING
);
if
(
m_Tdb
->
Srcdef
)
{
// Be sure this is a query returning a result set
do
{
rc
=
SQLPrepare
(
hstmt
,
(
PUCHAR
)
sql
,
SQL_NTS
);
}
while
(
rc
==
SQL_STILL_EXECUTING
);
if
(
!
Check
(
rc
))
ThrowDBX
(
rc
,
"SQLExecDirect
"
,
hstmt
);
if
(
!
Check
(
rc
))
ThrowDBX
(
rc
,
"SQLPrepare
"
,
hstmt
);
do
{
rc
=
SQLNumResultCols
(
hstmt
,
&
ncol
);
}
while
(
rc
==
SQL_STILL_EXECUTING
);
if
(
!
Check
(
rc
=
SQLNumResultCols
(
hstmt
,
&
ncol
)))
ThrowDBX
(
rc
,
"SQLNumResultCols"
,
hstmt
);
if
(
ncol
==
0
)
{
strcpy
(
g
->
Message
,
"This Srcdef does not return a result set"
);
return
-
1
;
}
// endif ncol
// Ok, now we can proceed
do
{
rc
=
SQLExecute
(
hstmt
);
}
while
(
rc
==
SQL_STILL_EXECUTING
);
if
(
ncol
==
0
)
{
// Update or Delete statement
rc
=
SQLRowCount
(
hstmt
,
&
afrw
);
if
(
!
Check
(
rc
))
ThrowDBX
(
rc
,
"SQLExecute"
,
hstmt
);
}
else
{
do
{
rc
=
SQLExecDirect
(
hstmt
,
(
PUCHAR
)
sql
,
SQL_NTS
);
}
while
(
rc
==
SQL_STILL_EXECUTING
);
if
(
!
Check
(
rc
))
ThrowDBX
(
rc
,
"SQL
RowCoun
t"
,
hstmt
);
ThrowDBX
(
rc
,
"SQL
ExecDirec
t"
,
hstmt
);
return
afrw
;
}
// endif ncol
do
{
rc
=
SQLNumResultCols
(
hstmt
,
&
ncol
);
}
while
(
rc
==
SQL_STILL_EXECUTING
);
}
// endif Srcdef
for
(
n
=
0
,
colp
=
tocols
;
colp
;
colp
=
(
PODBCCOL
)
colp
->
GetNext
())
if
(
!
colp
->
IsSpecial
())
...
...
@@ -1407,10 +1476,33 @@ int ODBConn::PrepareSQL(char *sql)
{
PGLOBAL
&
g
=
m_G
;
bool
b
;
UINT
txn
=
0
;
SWORD
nparm
;
RETCODE
rc
;
HSTMT
hstmt
;
if
(
m_Tdb
->
GetMode
()
!=
MODE_READ
)
{
// Does the data source support transactions
rc
=
SQLGetInfo
(
m_hdbc
,
SQL_TXN_CAPABLE
,
&
txn
,
0
,
NULL
);
if
(
Check
(
rc
)
&&
txn
!=
SQL_TC_NONE
)
try
{
rc
=
SQLSetConnectAttr
(
m_hdbc
,
SQL_ATTR_AUTOCOMMIT
,
SQL_AUTOCOMMIT_OFF
,
SQL_IS_UINTEGER
);
if
(
!
Check
(
rc
))
ThrowDBX
(
SQL_INVALID_HANDLE
,
"SQLSetConnectAttr"
);
m_Transact
=
true
;
}
catch
(
DBX
*
x
)
{
if
(
trace
)
for
(
int
i
=
0
;
i
<
MAX_NUM_OF_MSG
&&
x
->
m_ErrMsg
[
i
];
i
++
)
htrc
(
x
->
m_ErrMsg
[
i
]);
strcpy
(
g
->
Message
,
x
->
GetErrorMessage
(
0
));
}
// end try/catch
}
// endif Mode
try
{
b
=
false
;
...
...
@@ -1450,13 +1542,19 @@ int ODBConn::PrepareSQL(char *sql)
for
(
int
i
=
0
;
i
<
MAX_NUM_OF_MSG
&&
x
->
m_ErrMsg
[
i
];
i
++
)
htrc
(
x
->
m_ErrMsg
[
i
]);
strcpy
(
m_G
->
Message
,
x
->
GetErrorMessage
(
0
));
strcpy
(
g
->
Message
,
x
->
GetErrorMessage
(
0
));
if
(
b
)
SQLCancel
(
hstmt
);
rc
=
SQLFreeStmt
(
hstmt
,
SQL_DROP
);
m_hstmt
=
NULL
;
if
(
m_Transact
)
{
rc
=
SQLEndTran
(
SQL_HANDLE_DBC
,
m_hdbc
,
SQL_ROLLBACK
);
m_Transact
=
false
;
}
// endif m_Transact
return
-
1
;
}
// end try/catch
...
...
@@ -1465,27 +1563,59 @@ int ODBConn::PrepareSQL(char *sql)
}
// end of PrepareSQL
/***********************************************************************/
/*
Bind a parameter for inserting.
*/
/*
Execute a prepared statement.
*/
/***********************************************************************/
bool
ODBConn
::
ExecuteSQL
(
void
)
int
ODBConn
::
ExecuteSQL
(
bool
x
)
{
RETCODE
rc
;
PGLOBAL
&
g
=
m_G
;
SWORD
ncol
=
0
;
RETCODE
rc
;
SQLLEN
afrw
=
-
1
;
try
{
rc
=
SQLExecute
(
m_hstmt
);
do
{
rc
=
SQLExecute
(
m_hstmt
);
}
while
(
rc
==
SQL_STILL_EXECUTING
);
if
(
!
Check
(
rc
))
ThrowDBX
(
rc
,
"SQLExecute"
,
m_hstmt
);
if
(
!
Check
(
SQLNumResultCols
(
m_hstmt
,
&
ncol
)))
ThrowDBX
(
rc
,
"SQLNumResultCols"
,
m_hstmt
);
if
(
ncol
)
{
if
(
x
)
{
afrw
=
ncol
;
strcpy
(
g
->
Message
,
"Result set column number"
);
}
else
{
// This should never happen while inserting
strcpy
(
g
->
Message
,
"Logical error while inserting"
);
}
// endif ncol
}
else
{
// Insert, Update or Delete statement
if
(
!
Check
(
SQLRowCount
(
m_hstmt
,
&
afrw
)))
ThrowDBX
(
rc
,
"SQLRowCount"
,
m_hstmt
);
if
(
x
)
strcpy
(
g
->
Message
,
"Affected rows"
);
}
// endif ncol
}
catch
(
DBX
*
x
)
{
strcpy
(
m_G
->
Message
,
x
->
GetErrorMessage
(
0
));
SQLCancel
(
m_hstmt
);
rc
=
SQLFreeStmt
(
m_hstmt
,
SQL_DROP
);
m_hstmt
=
NULL
;
return
true
;
if
(
m_Transact
)
{
rc
=
SQLEndTran
(
SQL_HANDLE_DBC
,
m_hdbc
,
SQL_ROLLBACK
);
m_Transact
=
false
;
}
// endif m_Transact
}
// end try/catch
return
false
;
return
(
int
)
afrw
;
}
// end of ExecuteSQL
/***********************************************************************/
...
...
@@ -1537,6 +1667,132 @@ bool ODBConn::BindParam(ODBCCOL *colp)
return
false
;
}
// end of BindParam
/**************************************************************************/
/* GetMetaData: constructs the result blocks containing the */
/* description of all the columns of an SQL command. */
/**************************************************************************/
PQRYRES
ODBConn
::
GetMetaData
(
PGLOBAL
g
,
char
*
dsn
,
char
*
src
)
{
static
int
buftyp
[]
=
{
TYPE_STRING
,
TYPE_SHORT
,
TYPE_INT
,
TYPE_SHORT
,
TYPE_SHORT
};
static
XFLD
fldtyp
[]
=
{
FLD_NAME
,
FLD_TYPE
,
FLD_PREC
,
FLD_SCALE
,
FLD_NULL
};
static
unsigned
int
length
[]
=
{
0
,
6
,
10
,
6
,
6
};
unsigned
char
cn
[
60
];
int
qcol
=
5
;
short
nl
,
type
,
prec
,
nul
,
cns
=
(
short
)
sizeof
(
cn
);
PQRYRES
qrp
=
NULL
;
PCOLRES
crp
;
USHORT
i
;
SQLULEN
n
;
SWORD
ncol
;
RETCODE
rc
;
HSTMT
hstmt
;
if
(
Open
(
dsn
,
10
)
<
1
)
// openReadOnly + noOdbcDialog
return
NULL
;
try
{
rc
=
SQLAllocStmt
(
m_hdbc
,
&
hstmt
);
if
(
!
Check
(
rc
))
ThrowDBX
(
SQL_INVALID_HANDLE
,
"SQLAllocStmt"
);
OnSetOptions
(
hstmt
);
do
{
rc
=
SQLPrepare
(
hstmt
,
(
PUCHAR
)
src
,
SQL_NTS
);
// rc = SQLExecDirect(hstmt, (PUCHAR)src, SQL_NTS);
}
while
(
rc
==
SQL_STILL_EXECUTING
);
if
(
!
Check
(
rc
))
ThrowDBX
(
rc
,
"SQLExecDirect"
,
hstmt
);
do
{
rc
=
SQLNumResultCols
(
hstmt
,
&
ncol
);
}
while
(
rc
==
SQL_STILL_EXECUTING
);
if
(
!
Check
(
rc
))
ThrowDBX
(
rc
,
"SQLNumResultCols"
,
hstmt
);
if
(
ncol
)
for
(
i
=
1
;
i
<=
ncol
;
i
++
)
{
do
{
rc
=
SQLDescribeCol
(
hstmt
,
i
,
NULL
,
0
,
&
nl
,
NULL
,
NULL
,
NULL
,
NULL
);
}
while
(
rc
==
SQL_STILL_EXECUTING
);
if
(
!
Check
(
rc
))
ThrowDBX
(
rc
,
"SQLDescribeCol"
,
hstmt
);
length
[
0
]
=
max
(
length
[
0
],
(
UINT
)
nl
);
}
// endfor i
}
catch
(
DBX
*
x
)
{
strcpy
(
g
->
Message
,
x
->
GetErrorMessage
(
0
));
goto
err
;
}
// end try/catch
if
(
!
ncol
)
{
strcpy
(
g
->
Message
,
"Invalid Srcdef"
);
goto
err
;
}
// endif ncol
/************************************************************************/
/* Allocate the structures used to refer to the result set. */
/************************************************************************/
qrp
=
PlgAllocResult
(
g
,
qcol
,
ncol
,
IDS_COLUMNS
+
3
,
buftyp
,
fldtyp
,
length
,
false
,
true
);
// Some columns must be renamed
for
(
i
=
0
,
crp
=
qrp
->
Colresp
;
crp
;
crp
=
crp
->
Next
)
switch
(
++
i
)
{
case
3
:
crp
->
Name
=
"Precision"
;
break
;
case
4
:
crp
->
Name
=
"Scale"
;
break
;
case
5
:
crp
->
Name
=
"Nullable"
;
break
;
}
// endswitch i
/************************************************************************/
/* Now get the results into blocks. */
/************************************************************************/
try
{
for
(
i
=
0
;
i
<
ncol
;
i
++
)
{
do
{
rc
=
SQLDescribeCol
(
hstmt
,
i
+
1
,
cn
,
cns
,
&
nl
,
&
type
,
&
n
,
&
prec
,
&
nul
);
}
while
(
rc
==
SQL_STILL_EXECUTING
);
if
(
!
Check
(
rc
))
ThrowDBX
(
rc
,
"SQLDescribeCol"
,
hstmt
);
else
qrp
->
Nblin
++
;
crp
=
qrp
->
Colresp
;
// Column_Name
crp
->
Kdata
->
SetValue
((
char
*
)
cn
,
i
);
crp
=
crp
->
Next
;
// Data_Type
crp
->
Kdata
->
SetValue
(
type
,
i
);
crp
=
crp
->
Next
;
// Precision (length)
crp
->
Kdata
->
SetValue
((
int
)
n
,
i
);
crp
=
crp
->
Next
;
// Scale
crp
->
Kdata
->
SetValue
(
prec
,
i
);
crp
=
crp
->
Next
;
// Nullable
crp
->
Kdata
->
SetValue
(
nul
,
i
);
}
// endfor i
}
catch
(
DBX
*
x
)
{
strcpy
(
g
->
Message
,
x
->
GetErrorMessage
(
0
));
qrp
=
NULL
;
}
// end try/catch
/* Cleanup */
err:
SQLCancel
(
hstmt
);
rc
=
SQLFreeStmt
(
hstmt
,
SQL_DROP
);
Close
();
/************************************************************************/
/* Return the result pointer for use by GetData routines. */
/************************************************************************/
return
qrp
;
}
// end of GetMetaData
/***********************************************************************/
/* Get the list of Data Sources and set it in qrp. */
/***********************************************************************/
...
...
@@ -1840,6 +2096,11 @@ void ODBConn::Close()
}
// endif m_hstmt
if
(
m_hdbc
!=
SQL_NULL_HDBC
)
{
if
(
m_Transact
)
{
rc
=
SQLEndTran
(
SQL_HANDLE_DBC
,
m_hdbc
,
SQL_COMMIT
);
m_Transact
=
false
;
}
// endif m_Transact
rc
=
SQLDisconnect
(
m_hdbc
);
if
(
trace
&&
rc
!=
SQL_SUCCESS
)
...
...
storage/connect/odbconn.h
View file @
7dc48ae3
...
...
@@ -91,8 +91,7 @@ class DBX : public BLOCK {
// Implementation (use ThrowDBX to create)
RETCODE
GetRC
(
void
)
{
return
m_RC
;}
PSZ
GetMsg
(
void
)
{
return
m_Msg
;}
const
char
*
GetErrorMessage
(
int
i
)
{
return
(
i
>=
0
&&
i
<
MAX_NUM_OF_MSG
)
?
m_ErrMsg
[
i
]
:
"No ODBC error"
;}
const
char
*
GetErrorMessage
(
int
i
);
protected:
void
BuildErrorMessage
(
ODBConn
*
pdb
,
HSTMT
hstmt
=
SQL_NULL_HSTMT
);
...
...
@@ -107,6 +106,7 @@ class DBX : public BLOCK {
/* ODBConn class. */
/***********************************************************************/
class
ODBConn
:
public
BLOCK
{
friend
class
TDBODBC
;
friend
class
DBX
;
friend
PQRYRES
GetColumnInfo
(
PGLOBAL
,
char
*&
,
char
*
,
int
,
PVBLK
&
);
private:
...
...
@@ -142,11 +142,12 @@ class ODBConn : public BLOCK {
int
ExecDirectSQL
(
char
*
sql
,
ODBCCOL
*
tocols
);
int
Fetch
(
void
);
int
PrepareSQL
(
char
*
sql
);
bool
ExecuteSQL
(
void
);
int
ExecuteSQL
(
bool
x
);
bool
BindParam
(
ODBCCOL
*
colp
);
int
GetCatInfo
(
CATPARM
*
cap
);
bool
GetDataSources
(
PQRYRES
qrp
);
bool
GetDrivers
(
PQRYRES
qrp
);
PQRYRES
GetMetaData
(
PGLOBAL
g
,
char
*
dsn
,
char
*
src
);
public:
// Set special options
...
...
@@ -185,5 +186,6 @@ class ODBConn : public BLOCK {
int
m_Catver
;
PSZ
m_Connect
;
bool
m_Updatable
;
bool
m_Transact
;
char
m_IDQuoteChar
;
};
// end of ODBConn class definition
storage/connect/os.h
View file @
7dc48ae3
#ifndef _OS_H_INCLUDED
#define _OS_H_INCLUDED
#if defined(__FreeBSD__) || defined(__APPLE__)
#if defined(__FreeBSD__) || defined(__
NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(__
APPLE__)
typedef
off_t
off64_t
;
#define lseek64(fd, offset, whence) lseek((fd), (offset), (whence))
#define open64(path, flags, mode) open((path), (flags), (mode))
...
...
storage/connect/plgdbsem.h
View file @
7dc48ae3
...
...
@@ -111,6 +111,7 @@ enum AMT {TYPE_AM_ERROR = 0, /* Type not defined */
TYPE_AM_PIVOT
=
120
,
/* PIVOT access method type no */
TYPE_AM_SRC
=
121
,
/* PIVOT multiple column type no */
TYPE_AM_FNC
=
122
,
/* PIVOT source column type no */
TYPE_AM_XML
=
127
,
/* XML access method type no */
TYPE_AM_XTB
=
130
,
/* SYS table access method type */
TYPE_AM_MAC
=
137
,
/* MAC table access method type */
TYPE_AM_WMI
=
139
,
/* WMI table access method type */
...
...
@@ -582,5 +583,6 @@ FILE *global_fopen(GLOBAL *g, int msgid, const char *path, const char *mode);
int
global_open
(
GLOBAL
*
g
,
int
msgid
,
const
char
*
filename
,
int
flags
);
int
global_open
(
GLOBAL
*
g
,
int
msgid
,
const
char
*
filename
,
int
flags
,
int
mode
);
DllExport
LPCSTR
PlugSetPath
(
LPSTR
to
,
LPCSTR
name
,
LPCSTR
dir
);
char
*
MakeEscape
(
PGLOBAL
g
,
char
*
str
,
char
q
);
bool
PushWarning
(
PGLOBAL
,
PTDBASE
);
storage/connect/plgdbutl.cpp
View file @
7dc48ae3
...
...
@@ -731,6 +731,34 @@ bool EvalLikePattern(LPCSTR sp, LPCSTR tp)
return
(
b
);
}
/* end of EvalLikePattern */
/***********************************************************************/
/* MakeEscape: Escape some characters in a string. */
/***********************************************************************/
char
*
MakeEscape
(
PGLOBAL
g
,
char
*
str
,
char
q
)
{
char
*
bufp
;
int
i
,
k
,
n
=
0
,
len
=
(
int
)
strlen
(
str
);
for
(
i
=
0
;
i
<
len
;
i
++
)
if
(
str
[
i
]
==
q
||
str
[
i
]
==
'\\'
)
n
++
;
if
(
!
n
)
return
str
;
else
bufp
=
(
char
*
)
PlugSubAlloc
(
g
,
NULL
,
len
+
n
+
1
);
for
(
i
=
k
=
0
;
i
<
len
;
i
++
)
{
if
(
str
[
i
]
==
q
||
str
[
i
]
==
'\\'
)
bufp
[
k
++
]
=
'\\'
;
bufp
[
k
++
]
=
str
[
i
];
}
// endfor i
bufp
[
k
]
=
0
;
return
bufp
;
}
/* end of MakeEscape */
/***********************************************************************/
/* PlugConvertConstant: convert a Plug constant to an Xobject. */
/***********************************************************************/
...
...
storage/connect/plgxml.h
View file @
7dc48ae3
...
...
@@ -147,6 +147,7 @@ class XMLNODELIST : public BLOCK {
// Properties
virtual
int
GetLength
(
void
)
=
0
;
virtual
PXNODE
GetItem
(
PGLOBAL
,
int
,
PXNODE
=
NULL
)
=
0
;
virtual
bool
DropItem
(
PGLOBAL
,
int
)
=
0
;
protected:
// Constructor
...
...
storage/connect/tabfmt.cpp
View file @
7dc48ae3
...
...
@@ -93,7 +93,7 @@ PQRYRES CSVColumns(PGLOBAL g, const char *fn, char sep, char q,
PCOLRES
crp
;
if
(
info
)
{
imax
=
0
;
imax
=
hmax
=
0
;
length
[
0
]
=
128
;
goto
skipit
;
}
// endif info
...
...
storage/connect/tabmul.cpp
View file @
7dc48ae3
...
...
@@ -884,9 +884,11 @@ void TDBDIR::CloseDB(PGLOBAL g)
_findclose
(
Hsearch
);
Hsearch
=
-
1
;
#else // !WIN32
// Close the DIR handle.
closedir
(
Dir
);
Dir
=
NULL
;
// Close the DIR handle
if
(
Dir
)
{
closedir
(
Dir
);
Dir
=
NULL
;
}
// endif dir
#endif // !WIN32
iFile
=
0
;
}
// end of CloseDB
...
...
storage/connect/tabmysql.cpp
View file @
7dc48ae3
...
...
@@ -86,6 +86,7 @@ MYSQLDEF::MYSQLDEF(void)
Isview
=
FALSE
;
Bind
=
FALSE
;
Delayed
=
FALSE
;
Xsrc
=
FALSE
;
}
// end of MYSQLDEF constructor
/***********************************************************************/
...
...
@@ -171,7 +172,7 @@ bool MYSQLDEF::GetServerInfo(PGLOBAL g, const char *server_name)
/* true error */
/* */
/***********************************************************************/
bool
MYSQLDEF
::
ParseURL
(
PGLOBAL
g
,
char
*
url
)
bool
MYSQLDEF
::
ParseURL
(
PGLOBAL
g
,
char
*
url
,
bool
b
)
{
if
((
!
strstr
(
url
,
"://"
)
&&
(
!
strchr
(
url
,
'@'
))))
{
// No :// or @ in connection string. Must be a straight
...
...
@@ -248,34 +249,41 @@ bool MYSQLDEF::ParseURL(PGLOBAL g, char *url)
if
((
Database
=
strchr
(
Hostname
,
'/'
)))
{
*
Database
++
=
0
;
if
((
Tabname
=
strchr
(
Database
,
'/'
)))
if
((
Tabname
=
strchr
(
Database
,
'/'
)))
{
*
Tabname
++
=
0
;
// Make sure there's not an extra /
if
((
strchr
(
Tabname
,
'/'
)))
{
strcpy
(
g
->
Message
,
"Syntax error in URL"
);
return
true
;
}
// endif /
// Make sure there's not an extra /
if
((
strchr
(
Tabname
,
'/'
)))
{
strcpy
(
g
->
Message
,
"Syntax error in URL"
);
return
true
;
}
// endif /
}
// endif Tabname
}
// endif database
if
((
sport
=
strchr
(
Hostname
,
':'
)))
*
sport
++
=
0
;
Portnumber
=
(
sport
&&
sport
[
0
])
?
atoi
(
sport
)
:
GetDefaultPort
();
// For unspecified values, get the values of old style options
// but only if called from MYSQLDEF, else set them to NULL
Portnumber
=
(
sport
&&
sport
[
0
])
?
atoi
(
sport
)
:
(
b
)
?
Cat
->
GetIntCatInfo
(
"Port"
,
GetDefaultPort
())
:
0
;
if
(
Username
[
0
]
==
0
)
Username
=
Cat
->
GetStringCatInfo
(
g
,
"User"
,
"*"
)
;
Username
=
(
b
)
?
Cat
->
GetStringCatInfo
(
g
,
"User"
,
"*"
)
:
NULL
;
if
(
Hostname
[
0
]
==
0
)
Hostname
=
Cat
->
GetStringCatInfo
(
g
,
"Host"
,
"localhost"
)
;
Hostname
=
(
b
)
?
Cat
->
GetStringCatInfo
(
g
,
"Host"
,
"localhost"
)
:
NULL
;
if
(
!
Database
||
!*
Database
)
Database
=
Cat
->
GetStringCatInfo
(
g
,
"Database"
,
"*"
)
;
Database
=
(
b
)
?
Cat
->
GetStringCatInfo
(
g
,
"Database"
,
"*"
)
:
NULL
;
if
(
!
Tabname
||
!*
Tabname
)
Tabname
=
Name
;
Tabname
=
(
b
)
?
Cat
->
GetStringCatInfo
(
g
,
"Tabname"
,
Name
)
:
NULL
;
if
(
!
Password
)
Password
=
(
b
)
?
Cat
->
GetStringCatInfo
(
g
,
"Password"
,
NULL
)
:
NULL
;
}
// endif URL
#if 0
...
...
@@ -347,6 +355,7 @@ bool MYSQLDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
if
((
Srcdef
=
Cat
->
GetStringCatInfo
(
g
,
"Srcdef"
,
NULL
)))
Isview
=
TRUE
;
Xsrc
=
Cat
->
GetBoolCatInfo
(
"Execsrc"
,
FALSE
);
return
FALSE
;
}
// end of DefineAM
...
...
@@ -355,7 +364,9 @@ bool MYSQLDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
/***********************************************************************/
PTDB
MYSQLDEF
::
GetTable
(
PGLOBAL
g
,
MODE
m
)
{
if
(
Catfunc
==
FNC_COL
)
if
(
Xsrc
)
return
new
(
g
)
TDBMYEXC
(
this
);
else
if
(
Catfunc
==
FNC_COL
)
return
new
(
g
)
TDBMCL
(
this
);
else
return
new
(
g
)
TDBMYSQL
(
this
);
...
...
@@ -507,6 +518,9 @@ bool TDBMYSQL::MakeSelect(PGLOBAL g)
if
(
To_Filter
)
strcat
(
strcat
(
Query
,
" WHERE "
),
To_Filter
);
if
(
trace
)
htrc
(
"Query=%s
\n
"
,
Query
);
// Now we know how much to suballocate
PlugSubAlloc
(
g
,
NULL
,
strlen
(
Query
)
+
1
);
return
FALSE
;
...
...
@@ -1040,18 +1054,20 @@ int TDBMYSQL::DeleteDB(PGLOBAL g, int irc)
/***********************************************************************/
void
TDBMYSQL
::
CloseDB
(
PGLOBAL
g
)
{
if
(
Mode
==
MODE_INSERT
)
{
char
cmd
[
64
];
int
w
;
PDBUSER
dup
=
PlgGetUser
(
g
);
if
(
Myc
.
Connected
())
{
if
(
Mode
==
MODE_INSERT
)
{
char
cmd
[
64
];
int
w
;
PDBUSER
dup
=
PlgGetUser
(
g
);
dup
->
Step
=
"Enabling indexes"
;
sprintf
(
cmd
,
"ALTER TABLE `%s` ENABLE KEYS"
,
Tabname
);
Myc
.
m_Rows
=
-
1
;
// To execute the query
m_Rc
=
Myc
.
ExecSQL
(
g
,
cmd
,
&
w
);
}
// endif m_Rc
dup
->
Step
=
"Enabling indexes"
;
sprintf
(
cmd
,
"ALTER TABLE `%s` ENABLE KEYS"
,
Tabname
);
Myc
.
m_Rows
=
-
1
;
// To execute the query
m_Rc
=
Myc
.
ExecSQL
(
g
,
cmd
,
&
w
);
}
// endif m_Rc
Myc
.
Close
();
Myc
.
Close
();
}
// endif Myc
if
(
trace
)
htrc
(
"MySQL CloseDB: closing %s rc=%d
\n
"
,
Name
,
m_Rc
);
...
...
@@ -1275,6 +1291,212 @@ void MYSQLCOL::WriteColumn(PGLOBAL g)
}
// end of WriteColumn
/* ------------------------------------------------------------------- */
/***********************************************************************/
/* Implementation of the TDBMYSQL class. */
/***********************************************************************/
// Is this really useful ???
PTDB
TDBMYEXC
::
CopyOne
(
PTABS
t
)
{
PTDB
tp
;
PCOL
cp1
,
cp2
;
PGLOBAL
g
=
t
->
G
;
tp
=
new
(
g
)
TDBMYEXC
(
g
,
this
);
for
(
cp1
=
Columns
;
cp1
;
cp1
=
cp1
->
GetNext
())
{
cp2
=
new
(
g
)
MYXCOL
((
PMYXCOL
)
cp1
,
tp
);
NewPointer
(
t
,
cp1
,
cp2
);
}
// endfor cp1
return
tp
;
}
// end of CopyOne
/***********************************************************************/
/* Allocate MYSQL column description block. */
/***********************************************************************/
PCOL
TDBMYEXC
::
MakeCol
(
PGLOBAL
g
,
PCOLDEF
cdp
,
PCOL
cprec
,
int
n
)
{
PMYXCOL
colp
=
new
(
g
)
MYXCOL
(
cdp
,
this
,
cprec
,
n
);
if
(
!
colp
->
Flag
)
Cmdcol
=
colp
->
GetName
();
return
colp
;
}
// end of MakeCol
/***********************************************************************/
/* MakeCMD: make the SQL statement to send to MYSQL connection. */
/***********************************************************************/
char
*
TDBMYEXC
::
MakeCMD
(
PGLOBAL
g
)
{
char
*
xcmd
=
NULL
;
if
(
To_Filter
)
{
if
(
Cmdcol
)
{
char
col
[
128
],
cmd
[
1024
];
int
n
;
memset
(
cmd
,
0
,
sizeof
(
cmd
));
n
=
sscanf
(
To_Filter
,
"%s = '%1023c"
,
col
,
cmd
);
if
(
n
==
2
&&
!
stricmp
(
col
,
Cmdcol
))
{
xcmd
=
(
char
*
)
PlugSubAlloc
(
g
,
NULL
,
strlen
(
cmd
)
+
1
);
strcpy
(
xcmd
,
cmd
);
xcmd
[
strlen
(
xcmd
)
-
1
]
=
0
;
}
else
strcpy
(
g
->
Message
,
"Invalid command specification filter"
);
}
else
strcpy
(
g
->
Message
,
"No command column in select list"
);
}
else
if
(
!
Srcdef
)
strcpy
(
g
->
Message
,
"No Srcdef default command"
);
else
xcmd
=
Srcdef
;
return
xcmd
;
}
// end of MakeCMD
/***********************************************************************/
/* EXC GetMaxSize: returns the maximum number of rows in the table. */
/***********************************************************************/
int
TDBMYEXC
::
GetMaxSize
(
PGLOBAL
g
)
{
if
(
MaxSize
<
0
)
{
MaxSize
=
1
;
}
// endif MaxSize
return
MaxSize
;
}
// end of GetMaxSize
/***********************************************************************/
/* MySQL Exec Access Method opening routine. */
/***********************************************************************/
bool
TDBMYEXC
::
OpenDB
(
PGLOBAL
g
)
{
int
rc
;
if
(
Use
==
USE_OPEN
)
{
strcpy
(
g
->
Message
,
"Multiple execution is not allowed"
);
return
true
;
}
// endif use
/*********************************************************************/
/* Open a MySQL connection for this table. */
/* Note: this may not be the proper way to do. Perhaps it is better */
/* to test whether a connection is already open for this server */
/* and if so to allocate just a new result set. But this only for */
/* servers allowing concurency in getting results ??? */
/*********************************************************************/
if
(
!
Myc
.
Connected
())
if
(
Myc
.
Open
(
g
,
Host
,
Database
,
User
,
Pwd
,
Port
))
return
true
;
Use
=
USE_OPEN
;
// Do it now in case we are recursively called
if
(
Mode
!=
MODE_READ
)
{
strcpy
(
g
->
Message
,
"No INSERT/DELETE/UPDATE of MYSQL EXEC tables"
);
return
true
;
}
// endif Mode
/*********************************************************************/
/* Get the command to execute. */
/*********************************************************************/
if
(
!
(
Query
=
MakeCMD
(
g
)))
{
Myc
.
Close
();
return
true
;
}
// endif Query
if
((
rc
=
Myc
.
ExecSQL
(
g
,
Query
))
==
RC_NF
)
{
strcpy
(
g
->
Message
,
"Affected rows"
);
AftRows
=
Myc
.
m_Rows
;
}
else
if
(
rc
==
RC_OK
)
{
sprintf
(
g
->
Message
,
"Columns and %d rows"
,
Myc
.
m_Rows
);
AftRows
=
Myc
.
m_Fields
;
}
else
return
true
;
return
false
;
}
// end of OpenDB
/***********************************************************************/
/* Data Base read routine for MYSQL access method. */
/***********************************************************************/
int
TDBMYEXC
::
ReadDB
(
PGLOBAL
g
)
{
return
(
++
N
)
?
RC_EF
:
RC_OK
;
}
// end of ReadDB
/***********************************************************************/
/* WriteDB: Data Base write routine for Exec MYSQL access methods. */
/***********************************************************************/
int
TDBMYEXC
::
WriteDB
(
PGLOBAL
g
)
{
strcpy
(
g
->
Message
,
"EXEC MYSQL tables are read only"
);
return
RC_FX
;
}
// end of WriteDB
// ------------------------- MYXCOL functions ---------------------------
/***********************************************************************/
/* MYXCOL public constructor. */
/***********************************************************************/
MYXCOL
::
MYXCOL
(
PCOLDEF
cdp
,
PTDB
tdbp
,
PCOL
cprec
,
int
i
,
PSZ
am
)
:
MYSQLCOL
(
cdp
,
tdbp
,
cprec
,
i
,
am
)
{
// Set additional EXEC MYSQL access method information for column.
Flag
=
cdp
->
GetOffset
();
}
// end of MYSQLCOL constructor
/***********************************************************************/
/* MYSQLCOL public constructor. */
/***********************************************************************/
MYXCOL
::
MYXCOL
(
MYSQL_FIELD
*
fld
,
PTDB
tdbp
,
int
i
,
PSZ
am
)
:
MYSQLCOL
(
fld
,
tdbp
,
i
,
am
)
{
if
(
trace
)
htrc
(
" making new %sCOL C%d %s at %p
\n
"
,
am
,
Index
,
Name
,
this
);
}
// end of MYSQLCOL constructor
/***********************************************************************/
/* MYXCOL constructor used for copying columns. */
/* tdbp is the pointer to the new table descriptor. */
/***********************************************************************/
MYXCOL
::
MYXCOL
(
MYXCOL
*
col1
,
PTDB
tdbp
)
:
MYSQLCOL
(
col1
,
tdbp
)
{
Flag
=
col1
->
Flag
;
}
// end of MYXCOL copy constructor
/***********************************************************************/
/* ReadColumn: */
/***********************************************************************/
void
MYXCOL
::
ReadColumn
(
PGLOBAL
g
)
{
PTDBMYX
tdbp
=
(
PTDBMYX
)
To_Tdb
;
switch
(
Flag
)
{
case
0
:
Value
->
SetValue_psz
(
tdbp
->
Query
);
break
;
case
1
:
Value
->
SetValue
(
tdbp
->
AftRows
);
break
;
case
2
:
Value
->
SetValue_psz
(
g
->
Message
);
break
;
default:
Value
->
SetValue_psz
(
"Invalid Flag"
);
break
;
}
// endswitch Flag
}
// end of ReadColumn
/***********************************************************************/
/* WriteColumn: should never be called. */
/***********************************************************************/
void
MYXCOL
::
WriteColumn
(
PGLOBAL
g
)
{
assert
(
false
);
}
// end of WriteColumn
/* ---------------------------TDBMCL class --------------------------- */
/***********************************************************************/
...
...
storage/connect/tabmysql.h
View file @
7dc48ae3
...
...
@@ -3,8 +3,10 @@
typedef
class
MYSQLDEF
*
PMYDEF
;
typedef
class
TDBMYSQL
*
PTDBMY
;
typedef
class
MYSQLC
*
PMYC
;
typedef
class
MYSQLCOL
*
PMYCOL
;
typedef
class
TDBMYEXC
*
PTDBMYX
;
typedef
class
MYXCOL
*
PMYXCOL
;
typedef
class
MYSQLC
*
PMYC
;
/* ------------------------- MYSQL classes --------------------------- */
...
...
@@ -38,7 +40,7 @@ class MYSQLDEF : public TABDEF {/* Logical table description */
// Methods
virtual
bool
DefineAM
(
PGLOBAL
g
,
LPCSTR
am
,
int
poff
);
virtual
PTDB
GetTable
(
PGLOBAL
g
,
MODE
m
);
bool
ParseURL
(
PGLOBAL
g
,
char
*
url
);
bool
ParseURL
(
PGLOBAL
g
,
char
*
url
,
bool
b
=
true
);
bool
GetServerInfo
(
PGLOBAL
g
,
const
char
*
server_name
);
protected:
...
...
@@ -54,6 +56,7 @@ class MYSQLDEF : public TABDEF {/* Logical table description */
bool
Isview
;
/* TRUE if this table is a MySQL view */
bool
Bind
;
/* Use prepared statement on insert */
bool
Delayed
;
/* Delayed insert */
bool
Xsrc
;
/* Execution type */
};
// end of MYSQLDEF
/***********************************************************************/
...
...
@@ -158,6 +161,87 @@ class MYSQLCOL : public COLBLK {
int
Rank
;
// Rank (position) number in the query
};
// end of class MYSQLCOL
/***********************************************************************/
/* This is the class declaration for the exec command MYSQL table. */
/***********************************************************************/
class
TDBMYEXC
:
public
TDBMYSQL
{
friend
class
MYXCOL
;
public:
// Constructor
TDBMYEXC
(
PMYDEF
tdp
)
:
TDBMYSQL
(
tdp
)
{
Cmdcol
=
NULL
;}
TDBMYEXC
(
PGLOBAL
g
,
PTDBMYX
tdbp
)
:
TDBMYSQL
(
g
,
tdbp
)
{
Cmdcol
=
tdbp
->
Cmdcol
;}
// Implementation
//virtual AMT GetAmType(void) {return TYPE_AM_MYSQL;}
virtual
PTDB
Duplicate
(
PGLOBAL
g
)
{
return
(
PTDB
)
new
(
g
)
TDBMYEXC
(
g
,
this
);}
// Methods
virtual
PTDB
CopyOne
(
PTABS
t
);
//virtual int GetAffectedRows(void) {return AftRows;}
//virtual int GetRecpos(void) {return N;}
//virtual int GetProgMax(PGLOBAL g);
//virtual void ResetDB(void) {N = 0;}
//virtual int RowNumber(PGLOBAL g, bool b = FALSE);
virtual
bool
IsView
(
void
)
{
return
Isview
;}
//virtual PSZ GetServer(void) {return Server;}
// void SetDatabase(LPCSTR db) {Database = (char*)db;}
// Database routines
virtual
PCOL
MakeCol
(
PGLOBAL
g
,
PCOLDEF
cdp
,
PCOL
cprec
,
int
n
);
virtual
int
GetMaxSize
(
PGLOBAL
g
);
virtual
bool
OpenDB
(
PGLOBAL
g
);
virtual
int
ReadDB
(
PGLOBAL
g
);
virtual
int
WriteDB
(
PGLOBAL
g
);
//virtual int DeleteDB(PGLOBAL g, int irc);
//virtual void CloseDB(PGLOBAL g);
// Specific routines
// bool SetColumnRanks(PGLOBAL g);
// PCOL MakeFieldColumn(PGLOBAL g, char *name);
// PSZ FindFieldColumn(char *name);
protected:
// Internal functions
char
*
MakeCMD
(
PGLOBAL
g
);
//bool MakeSelect(PGLOBAL g);
//bool MakeInsert(PGLOBAL g);
//int BindColumns(PGLOBAL g);
// Members
char
*
Cmdcol
;
// The name of the Xsrc command column
};
// end of class TDBMYEXC
/***********************************************************************/
/* Class MYXCOL: MySQL exec command table column. */
/***********************************************************************/
class
MYXCOL
:
public
MYSQLCOL
{
friend
class
TDBMYEXC
;
public:
// Constructors
MYXCOL
(
PCOLDEF
cdp
,
PTDB
tdbp
,
PCOL
cprec
,
int
i
,
PSZ
am
=
"MYSQL"
);
MYXCOL
(
MYSQL_FIELD
*
fld
,
PTDB
tdbp
,
int
i
,
PSZ
am
=
"MYSQL"
);
MYXCOL
(
MYXCOL
*
colp
,
PTDB
tdbp
);
// Constructor used in copy process
// Implementation
//virtual int GetAmType(void) {return TYPE_AM_MYSQL;}
// void InitBind(PGLOBAL g);
// Methods
//virtual bool SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check);
virtual
void
ReadColumn
(
PGLOBAL
g
);
virtual
void
WriteColumn
(
PGLOBAL
g
);
// bool FindRank(PGLOBAL g);
protected:
// Default constructor not to be used
MYXCOL
(
void
)
{}
// Members
char
*
Buffer
;
// To get returned message
int
Flag
;
// Column content desc
};
// end of class MYXCOL
/***********************************************************************/
/* This is the class declaration for the MYSQL column catalog table. */
/***********************************************************************/
...
...
storage/connect/tabodbc.cpp
View file @
7dc48ae3
/************* Tabodbc C++ Program Source Code File (.CPP) *************/
/* PROGRAM NAME: TABODBC */
/* ------------- */
/* Version 2.
5
*/
/* Version 2.
6
*/
/* */
/* COPYRIGHT: */
/* ---------- */
...
...
@@ -90,8 +90,9 @@ extern int num_read, num_there, num_eq[2]; // Statistics
/***********************************************************************/
ODBCDEF
::
ODBCDEF
(
void
)
{
Connect
=
Tabname
=
Tabowner
=
Tabqual
=
Qchar
=
NULL
;
Catver
=
Options
=
0
;
Connect
=
Tabname
=
Tabowner
=
Tabqual
=
Srcdef
=
Qchar
=
NULL
;
Catver
=
Options
=
0
;
Xsrc
=
false
;
}
// end of ODBCDEF constructor
/***********************************************************************/
...
...
@@ -99,17 +100,17 @@ ODBCDEF::ODBCDEF(void)
/***********************************************************************/
bool
ODBCDEF
::
DefineAM
(
PGLOBAL
g
,
LPCSTR
am
,
int
poff
)
{
int
dop
=
ODBConn
::
noOdbcDialog
;
// Default for options
Desc
=
Connect
=
Cat
->
GetStringCatInfo
(
g
,
"Connect"
,
""
);
Tabname
=
Cat
->
GetStringCatInfo
(
g
,
"Name"
,
(
Catfunc
&
(
FNC_TABLE
|
FNC_COL
))
?
NULL
:
Name
);
Tabname
=
Cat
->
GetStringCatInfo
(
g
,
"Tabname"
,
Tabname
);
Tabowner
=
Cat
->
GetStringCatInfo
(
g
,
"Owner"
,
""
);
Tabqual
=
Cat
->
GetStringCatInfo
(
g
,
"Qualifier"
,
""
);
Srcdef
=
Cat
->
GetStringCatInfo
(
g
,
"Srcdef"
,
NULL
);
Qchar
=
Cat
->
GetStringCatInfo
(
g
,
"Qchar"
,
""
);
Catver
=
Cat
->
GetIntCatInfo
(
"Catver"
,
2
);
Options
=
Cat
->
GetIntCatInfo
(
"Options"
,
dop
);
Xsrc
=
Cat
->
GetBoolCatInfo
(
"Execsrc"
,
FALSE
);
Options
=
ODBConn
::
noOdbcDialog
;
Pseudo
=
2
;
// FILID is Ok but not ROWID
return
false
;
}
// end of DefineAM
...
...
@@ -125,7 +126,9 @@ PTDB ODBCDEF::GetTable(PGLOBAL g, MODE m)
/* Allocate a TDB of the proper type. */
/* Column blocks will be allocated only when needed. */
/*********************************************************************/
switch
(
Catfunc
)
{
if
(
Xsrc
)
tdbp
=
new
(
g
)
TDBXDBC
(
this
);
else
switch
(
Catfunc
)
{
case
FNC_COL
:
tdbp
=
new
(
g
)
TDBOCL
(
this
);
break
;
...
...
@@ -161,19 +164,21 @@ TDBODBC::TDBODBC(PODEF tdp) : TDBASE(tdp)
Cnp
=
NULL
;
if
(
tdp
)
{
Connect
=
tdp
->
GetConnect
();
TableName
=
tdp
->
GetTabname
();
Owner
=
tdp
->
GetTabowner
();
Qualifier
=
tdp
->
GetTabqual
();
Connect
=
tdp
->
Connect
;
TableName
=
tdp
->
Tabname
;
Owner
=
tdp
->
Tabowner
;
Qualifier
=
tdp
->
Tabqual
;
Srcdef
=
tdp
->
Srcdef
;
Quote
=
tdp
->
GetQchar
();
Options
=
tdp
->
GetOptions
()
;
Options
=
tdp
->
Options
;
Rows
=
tdp
->
GetElemt
();
Catver
=
tdp
->
GetCatver
()
;
Catver
=
tdp
->
Catver
;
}
else
{
Connect
=
NULL
;
TableName
=
NULL
;
Owner
=
NULL
;
Qualifier
=
NULL
;
Srcdef
=
NULL
;
Quote
=
NULL
;
Options
=
0
;
Rows
=
0
;
...
...
@@ -201,6 +206,7 @@ TDBODBC::TDBODBC(PTDBODBC tdbp) : TDBASE(tdbp)
TableName
=
tdbp
->
TableName
;
Owner
=
tdbp
->
Owner
;
Qualifier
=
tdbp
->
Qualifier
;
Srcdef
=
tdbp
->
Srcdef
;
Quote
=
tdbp
->
Quote
;
Query
=
tdbp
->
Query
;
Count
=
tdbp
->
Count
;
...
...
@@ -299,7 +305,6 @@ void TDBODBC::SetFile(PGLOBAL g, PSZ fn)
DBQ
=
fn
;
}
// end of SetFile
/******************************************************************/
/* Convert an UTF-8 string to latin characters. */
/******************************************************************/
...
...
@@ -314,7 +319,6 @@ int TDBODBC::Decode(char *txt, char *buf, size_t n)
return
0
;
}
// end of Decode
/***********************************************************************/
/* MakeSQL: make the SQL statement use with ODBC connection. */
/* Note: when implementing EOM filtering, column only used in local */
...
...
@@ -329,6 +333,9 @@ char *TDBODBC::MakeSQL(PGLOBAL g, bool cnt)
PTABLE
tablep
=
To_Table
;
PCOL
colp
;
if
(
Srcdef
)
return
Srcdef
;
if
(
!
cnt
)
{
// Normal SQL statement to retrieve results
for
(
colp
=
Columns
;
colp
;
colp
=
colp
->
GetNext
())
...
...
@@ -430,6 +437,83 @@ char *TDBODBC::MakeSQL(PGLOBAL g, bool cnt)
return
sql
;
}
// end of MakeSQL
/***********************************************************************/
/* MakeInsert: make the Insert statement used with ODBC connection. */
/***********************************************************************/
bool
TDBODBC
::
MakeInsert
(
PGLOBAL
g
)
{
char
*
colist
,
*
valist
;
// char *tk = "`";
int
len
=
0
;
bool
b
=
FALSE
;
PCOL
colp
;
if
(
Query
)
return
false
;
// already done
for
(
colp
=
Columns
;
colp
;
colp
=
colp
->
GetNext
())
if
(
colp
->
IsSpecial
())
{
strcpy
(
g
->
Message
,
MSG
(
NO_ODBC_SPECOL
));
return
true
;
}
else
{
len
+=
(
strlen
(
colp
->
GetName
())
+
4
);
((
PODBCCOL
)
colp
)
->
Rank
=
++
Nparm
;
}
// endif colp
colist
=
(
char
*
)
PlugSubAlloc
(
g
,
NULL
,
len
);
*
colist
=
'\0'
;
valist
=
(
char
*
)
PlugSubAlloc
(
g
,
NULL
,
2
*
Nparm
);
*
valist
=
'\0'
;
for
(
colp
=
Columns
;
colp
;
colp
=
colp
->
GetNext
())
{
if
(
b
)
{
strcat
(
colist
,
", "
);
strcat
(
valist
,
","
);
}
else
b
=
true
;
if
(
Quote
)
strcat
(
strcat
(
strcat
(
colist
,
Quote
),
colp
->
GetName
()),
Quote
);
else
strcat
(
colist
,
colp
->
GetName
());
strcat
(
valist
,
"?"
);
// Parameter marker
}
// endfor colp
// Below 32 is enough to contain the fixed part of the query
len
=
(
strlen
(
TableName
)
+
strlen
(
colist
)
+
strlen
(
valist
)
+
32
);
Query
=
(
char
*
)
PlugSubAlloc
(
g
,
NULL
,
len
);
strcpy
(
Query
,
"INSERT INTO "
);
if
(
Quote
)
strcat
(
strcat
(
strcat
(
Query
,
Quote
),
TableName
),
Quote
);
else
strcat
(
Query
,
TableName
);
strcat
(
strcat
(
strcat
(
Query
,
" ("
),
colist
),
") VALUES ("
);
strcat
(
strcat
(
Query
,
valist
),
")"
);
return
false
;
}
// end of MakeInsert
/***********************************************************************/
/* ODBC Bind Parameter function. */
/***********************************************************************/
bool
TDBODBC
::
BindParameters
(
PGLOBAL
g
)
{
PODBCCOL
colp
;
for
(
colp
=
(
PODBCCOL
)
Columns
;
colp
;
colp
=
(
PODBCCOL
)
colp
->
Next
)
{
colp
->
AllocateBuffers
(
g
,
0
);
if
(
Ocp
->
BindParam
(
colp
))
return
true
;
}
// endfor colp
return
false
;
}
// end of BindParameters
/***********************************************************************/
/* ResetSize: call by TDBMUL when calculating size estimate. */
/***********************************************************************/
...
...
@@ -448,6 +532,16 @@ void TDBODBC::ResetSize(void)
int
TDBODBC
::
GetMaxSize
(
PGLOBAL
g
)
{
if
(
MaxSize
<
0
)
{
// Make MariaDB happy
MaxSize
=
100
;
#if 0
// This is unuseful and takes time
if (Srcdef) {
// Return a reasonable guess
MaxSize = 100;
return MaxSize;
} // endif Srcdef
if (!Ocp)
Ocp = new(g) ODBConn(g, this);
...
...
@@ -466,19 +560,18 @@ int TDBODBC::GetMaxSize(PGLOBAL g)
if ((MaxSize = Ocp->GetResultSize(Count, Cnp)) < 0)
return -3;
#endif // 0
}
// endif MaxSize
return
MaxSize
;
}
// end of GetMaxSize
/***********************************************************************/
/* Return
0 in mode DELETE or UPDATE to tell that it is done.
*/
/* Return
max size value.
*/
/***********************************************************************/
int
TDBODBC
::
GetProgMax
(
PGLOBAL
g
)
{
return
(
Mode
==
MODE_DELETE
||
Mode
==
MODE_UPDATE
)
?
0
:
GetMaxSize
(
g
);
return
GetMaxSize
(
g
);
}
// end of GetProgMax
/***********************************************************************/
...
...
@@ -546,14 +639,24 @@ bool TDBODBC::OpenDB(PGLOBAL g)
if
(
!
colp
->
IsSpecial
())
colp
->
AllocateBuffers
(
g
,
Rows
);
}
else
rc
=
true
;
}
else
{
Ocp
->
Close
();
return
true
;
}
// endif Query
if
(
!
rc
)
rc
=
((
Rows
=
Ocp
->
ExecDirectSQL
(
Query
,
(
PODBCCOL
)
Columns
))
<
0
);
}
else
if
(
Mode
==
MODE_INSERT
)
{
if
(
!
(
rc
=
MakeInsert
(
g
)))
if
(
Nparm
!=
Ocp
->
PrepareSQL
(
Query
))
{
strcpy
(
g
->
Message
,
MSG
(
PARM_CNT_MISS
));
rc
=
true
;
}
else
rc
=
BindParameters
(
g
);
}
else
{
strcpy
(
g
->
Message
,
"
ODBC tables are read only in this version
"
);
strcpy
(
g
->
Message
,
"
No DELETE/UPDATE of ODBC tablesd
"
);
return
true
;
}
// endelse
...
...
@@ -592,30 +695,6 @@ int TDBODBC::ReadDB(PGLOBAL g)
// Direct access of ODBC tables is not implemented yet
strcpy
(
g
->
Message
,
MSG
(
NO_ODBC_DIRECT
));
longjmp
(
g
->
jumper
[
g
->
jump_level
],
GetAmType
());
#if 0
/*******************************************************************/
/* Reading is by an index table. */
/*******************************************************************/
int recpos = To_Kindex->Fetch(g);
switch (recpos) {
case -1: // End of file reached
return RC_EF;
case -2: // No match for join
return RC_NF;
case -3: // Same record as current one
num_there++;
return RC_OK;
default:
/***************************************************************/
/* Set the cursor position according to record to read. */
/***************************************************************/
//--------------------------------- TODO --------------------------------
break;
} // endswitch recpos
#endif // 0
}
// endif To_Kindex
/*********************************************************************/
...
...
@@ -641,8 +720,15 @@ int TDBODBC::ReadDB(PGLOBAL g)
/***********************************************************************/
int
TDBODBC
::
WriteDB
(
PGLOBAL
g
)
{
strcpy
(
g
->
Message
,
"ODBC tables are read only"
);
return
RC_FX
;
int
n
=
Ocp
->
ExecuteSQL
(
false
);
if
(
n
<
0
)
{
AftRows
=
n
;
return
RC_FX
;
}
else
AftRows
+=
n
;
return
RC_OK
;
}
// end of WriteDB
/***********************************************************************/
...
...
@@ -664,7 +750,8 @@ void TDBODBC::CloseDB(PGLOBAL g)
// To_Kindex = NULL;
// } // endif
Ocp
->
Close
();
if
(
Ocp
)
Ocp
->
Close
();
if
(
trace
)
htrc
(
"ODBC CloseDB: closing %s
\n
"
,
Name
);
...
...
@@ -892,7 +979,7 @@ void ODBCCOL::WriteColumn(PGLOBAL g)
/* Do convert the column value if necessary. */
/*********************************************************************/
if
(
Value
!=
To_Val
)
Value
->
SetValue_pval
(
To_Val
,
false
);
// Convert the inserted value
Value
->
SetValue_pval
(
To_Val
,
FALSE
);
// Convert the inserted value
if
(
Buf_Type
==
TYPE_DATE
)
{
struct
tm
tm
,
*
dbtime
=
((
DTVAL
*
)
Value
)
->
GetGmTime
(
&
tm
);
...
...
@@ -903,8 +990,245 @@ void ODBCCOL::WriteColumn(PGLOBAL g)
Sqlbuf
->
day
=
dbtime
->
tm_mday
;
Sqlbuf
->
month
=
dbtime
->
tm_mon
+
1
;
Sqlbuf
->
year
=
dbtime
->
tm_year
+
1900
;
Sqlbuf
->
fraction
=
0
;
}
// endif Buf_Type
if
(
Nullable
)
*
StrLen
=
(
Value
->
IsNull
())
?
SQL_NULL_DATA
:
(
IsTypeNum
(
Buf_Type
))
?
0
:
SQL_NTS
;
}
// end of WriteColumn
/* -------------------------- Class TDBXDBC -------------------------- */
/***********************************************************************/
/* Implementation of the TDBODBC class. */
/***********************************************************************/
PTDB
TDBXDBC
::
CopyOne
(
PTABS
t
)
{
PTDB
tp
;
PXSRCCOL
cp1
,
cp2
;
PGLOBAL
g
=
t
->
G
;
// Is this really useful ???
tp
=
new
(
g
)
TDBXDBC
(
this
);
for
(
cp1
=
(
PXSRCCOL
)
Columns
;
cp1
;
cp1
=
(
PXSRCCOL
)
cp1
->
GetNext
())
{
cp2
=
new
(
g
)
XSRCCOL
(
cp1
,
tp
);
// Make a copy
NewPointer
(
t
,
cp1
,
cp2
);
}
// endfor cp1
return
tp
;
}
// end of CopyOne
/***********************************************************************/
/* Allocate XSRC column description block. */
/***********************************************************************/
PCOL
TDBXDBC
::
MakeCol
(
PGLOBAL
g
,
PCOLDEF
cdp
,
PCOL
cprec
,
int
n
)
{
PXSRCCOL
colp
=
new
(
g
)
XSRCCOL
(
cdp
,
this
,
cprec
,
n
);
if
(
!
colp
->
Flag
)
Cmdcol
=
colp
->
GetName
();
return
colp
;
}
// end of MakeCol
/***********************************************************************/
/* MakeCMD: make the SQL statement to send to ODBC connection. */
/***********************************************************************/
char
*
TDBXDBC
::
MakeCMD
(
PGLOBAL
g
)
{
char
*
xcmd
=
NULL
;
if
(
To_Filter
)
{
if
(
Cmdcol
)
{
char
col
[
128
],
cmd
[
1024
];
int
n
;
memset
(
cmd
,
0
,
sizeof
(
cmd
));
n
=
sscanf
(
To_Filter
,
"%s = '%1023c"
,
col
,
cmd
);
if
(
n
==
2
&&
!
stricmp
(
col
,
Cmdcol
))
{
xcmd
=
(
char
*
)
PlugSubAlloc
(
g
,
NULL
,
strlen
(
cmd
)
+
1
);
strcpy
(
xcmd
,
cmd
);
xcmd
[
strlen
(
xcmd
)
-
1
]
=
0
;
}
else
strcpy
(
g
->
Message
,
"Invalid command specification filter"
);
}
else
strcpy
(
g
->
Message
,
"No command column in select list"
);
}
else
if
(
!
Srcdef
)
strcpy
(
g
->
Message
,
"No Srcdef default command"
);
else
xcmd
=
Srcdef
;
return
xcmd
;
}
// end of MakeCMD
#if 0
/***********************************************************************/
/* ODBC Bind Parameter function. */
/***********************************************************************/
bool TDBXDBC::BindParameters(PGLOBAL g)
{
PODBCCOL colp;
for (colp = (PODBCCOL)Columns; colp; colp = (PODBCCOL)colp->Next) {
colp->AllocateBuffers(g, 0);
if (Ocp->BindParam(colp))
return true;
} // endfor colp
return false;
} // end of BindParameters
#endif // 0
/***********************************************************************/
/* XDBC GetMaxSize: returns table size (always one row). */
/***********************************************************************/
int
TDBXDBC
::
GetMaxSize
(
PGLOBAL
g
)
{
if
(
MaxSize
<
0
)
MaxSize
=
1
;
return
MaxSize
;
}
// end of GetMaxSize
/***********************************************************************/
/* ODBC Access Method opening routine. */
/* New method now that this routine is called recursively (last table */
/* first in reverse order): index blocks are immediately linked to */
/* join block of next table if it exists or else are discarted. */
/***********************************************************************/
bool
TDBXDBC
::
OpenDB
(
PGLOBAL
g
)
{
bool
rc
=
false
;
if
(
g
->
Trace
)
htrc
(
"ODBC OpenDB: tdbp=%p tdb=R%d use=%dmode=%d
\n
"
,
this
,
Tdb_No
,
Use
,
Mode
);
if
(
Use
==
USE_OPEN
)
{
strcpy
(
g
->
Message
,
"Multiple execution is not allowed"
);
return
true
;
}
// endif use
/*********************************************************************/
/* Open an ODBC connection for this table. */
/* Note: this may not be the proper way to do. Perhaps it is better */
/* to test whether a connection is already open for this datasource */
/* and if so to allocate just a new result set. But this only for */
/* drivers allowing concurency in getting results ??? */
/*********************************************************************/
if
(
!
Ocp
)
Ocp
=
new
(
g
)
ODBConn
(
g
,
this
);
else
if
(
Ocp
->
IsOpen
())
Ocp
->
Close
();
if
(
Ocp
->
Open
(
Connect
,
Options
)
<
1
)
return
true
;
Use
=
USE_OPEN
;
// Do it now in case we are recursively called
if
(
Mode
!=
MODE_READ
)
{
strcpy
(
g
->
Message
,
"No INSERT/DELETE/UPDATE of XDBC tables"
);
return
true
;
}
// endif Mode
/*********************************************************************/
/* Get the command to execute. */
/*********************************************************************/
if
(
!
(
Query
=
MakeCMD
(
g
)))
{
Ocp
->
Close
();
return
true
;
}
// endif Query
Rows
=
1
;
if
(
Ocp
->
PrepareSQL
(
Query
))
{
strcpy
(
g
->
Message
,
"Parameters not supported"
);
AftRows
=
-
1
;
}
else
AftRows
=
0
;
return
false
;
}
// end of OpenDB
/***********************************************************************/
/* ReadDB: Data Base read routine for xdbc access method. */
/***********************************************************************/
int
TDBXDBC
::
ReadDB
(
PGLOBAL
g
)
{
if
(
trace
)
htrc
(
"XDBC ReadDB: query=%s
\n
"
,
SVP
(
Query
));
if
(
Rows
--
)
{
if
(
!
AftRows
)
AftRows
=
Ocp
->
ExecuteSQL
(
true
);
}
else
return
RC_EF
;
Fpos
++
;
// Used for progress info
return
RC_OK
;
}
// end of ReadDB
/***********************************************************************/
/* Data Base delete line routine for ODBC access method. */
/***********************************************************************/
int
TDBXDBC
::
WriteDB
(
PGLOBAL
g
)
{
strcpy
(
g
->
Message
,
"Execsrc tables are read only"
);
return
RC_FX
;
}
// end of DeleteDB
/* --------------------------- XSRCCOL ------------------------------- */
/***********************************************************************/
/* XSRCCOL public constructor. */
/***********************************************************************/
XSRCCOL
::
XSRCCOL
(
PCOLDEF
cdp
,
PTDB
tdbp
,
PCOL
cprec
,
int
i
,
PSZ
am
)
:
ODBCCOL
(
cdp
,
tdbp
,
cprec
,
i
,
am
)
{
// Set additional ODBC access method information for column.
Flag
=
cdp
->
GetOffset
();
}
// end of XSRCCOL constructor
/***********************************************************************/
/* XSRCCOL constructor used for copying columns. */
/* tdbp is the pointer to the new table descriptor. */
/***********************************************************************/
XSRCCOL
::
XSRCCOL
(
XSRCCOL
*
col1
,
PTDB
tdbp
)
:
ODBCCOL
(
col1
,
tdbp
)
{
Flag
=
col1
->
Flag
;
}
// end of XSRCCOL copy constructor
/***********************************************************************/
/* ReadColumn: set column value according to Flag. */
/***********************************************************************/
void
XSRCCOL
::
ReadColumn
(
PGLOBAL
g
)
{
PTDBXDBC
tdbp
=
(
PTDBXDBC
)
To_Tdb
;
switch
(
Flag
)
{
case
0
:
Value
->
SetValue_psz
(
tdbp
->
Query
);
break
;
case
1
:
Value
->
SetValue
(
tdbp
->
AftRows
);
break
;
case
2
:
Value
->
SetValue_psz
(
g
->
Message
);
break
;
default:
Value
->
SetValue_psz
(
"Invalid Flag"
);
break
;
}
// endswitch Flag
}
// end of ReadColumn
/***********************************************************************/
/* WriteColumn: Should never be called. */
/***********************************************************************/
void
XSRCCOL
::
WriteColumn
(
PGLOBAL
g
)
{
// Should never be called
}
// end of WriteColumn
/* ---------------------------TDBSRC class --------------------------- */
...
...
storage/connect/tabodbc.h
View file @
7dc48ae3
/*************** Tabodbc H Declares Source Code File (.H) **************/
/* Name: TABODBC.H Version 1.
5
*/
/* Name: TABODBC.H Version 1.
6
*/
/* */
/* (C) Copyright to the author Olivier BERTRAND 2000-2013 */
/* */
...
...
@@ -11,6 +11,8 @@
typedef
class
ODBCDEF
*
PODEF
;
typedef
class
TDBODBC
*
PTDBODBC
;
typedef
class
ODBCCOL
*
PODBCCOL
;
typedef
class
TDBXDBC
*
PTDBXDBC
;
typedef
class
XSRCCOL
*
PXSRCCOL
;
typedef
class
TDBOIF
*
PTDBOIF
;
typedef
class
OIFCOL
*
POIFCOL
;
typedef
class
TDBSRC
*
PTDBSRC
;
...
...
@@ -19,6 +21,8 @@ typedef class TDBSRC *PTDBSRC;
/* ODBC table. */
/***********************************************************************/
class
DllExport
ODBCDEF
:
public
TABDEF
{
/* Logical table description */
friend
class
TDBODBC
;
friend
class
TDBXDBC
;
public:
// Constructor
ODBCDEF
(
void
);
...
...
@@ -29,6 +33,7 @@ class DllExport ODBCDEF : public TABDEF { /* Logical table description */
PSZ
GetTabname
(
void
)
{
return
Tabname
;}
PSZ
GetTabowner
(
void
)
{
return
Tabowner
;}
PSZ
GetTabqual
(
void
)
{
return
Tabqual
;}
PSZ
GetSrcdef
(
void
)
{
return
Srcdef
;}
PSZ
GetQchar
(
void
)
{
return
(
Qchar
&&
*
Qchar
)
?
Qchar
:
NULL
;}
int
GetCatver
(
void
)
{
return
Catver
;}
int
GetOptions
(
void
)
{
return
Options
;}
...
...
@@ -43,9 +48,11 @@ class DllExport ODBCDEF : public TABDEF { /* Logical table description */
PSZ
Tabname
;
/* External table name */
PSZ
Tabowner
;
/* External table owner */
PSZ
Tabqual
;
/* External table qualifier */
PSZ
Srcdef
;
/* The source table SQL definition */
PSZ
Qchar
;
/* Identifier quoting character */
int
Catver
;
/* ODBC version for catalog functions */
int
Options
;
/* Open connection options */
bool
Xsrc
;
/* Execution type */
};
// end of ODBCDEF
#if !defined(NODBC)
...
...
@@ -92,10 +99,10 @@ class TDBODBC : public TDBASE {
int
Decode
(
char
*
utf
,
char
*
buf
,
size_t
n
);
char
*
MakeSQL
(
PGLOBAL
g
,
bool
cnt
);
//bool MakeUpdate(PGLOBAL g, PSELECT selist);
//
bool MakeInsert(PGLOBAL g);
bool
MakeInsert
(
PGLOBAL
g
);
//bool MakeDelete(PGLOBAL g);
//bool MakeFilter(PGLOBAL g, bool c);
//
bool BindParameters(PGLOBAL g);
bool
BindParameters
(
PGLOBAL
g
);
// Members
ODBConn
*
Ocp
;
// Points to an ODBC connection class
...
...
@@ -104,6 +111,7 @@ class TDBODBC : public TDBASE {
char
*
TableName
;
// Points to ODBC table name
char
*
Owner
;
// Points to ODBC table Owner
char
*
Qualifier
;
// Points to ODBC table Qualifier
char
*
Srcdef
;
// The source table SQL definition
char
*
Query
;
// Points to SQL statement
char
*
Count
;
// Points to count(*) SQL statement
//char *Where; // Points to local where clause
...
...
@@ -122,7 +130,7 @@ class TDBODBC : public TDBASE {
};
// end of class TDBODBC
/***********************************************************************/
/* Class ODBCCOL:
DOS access method column descriptor.
*/
/* Class ODBCCOL:
ODBC access method column descriptor.
*/
/* This A.M. is used for ODBC tables. */
/***********************************************************************/
class
ODBCCOL
:
public
COLBLK
{
...
...
@@ -153,16 +161,85 @@ class ODBCCOL : public COLBLK {
ODBCCOL
(
void
);
// Members
TIMESTAMP_STRUCT
*
Sqlbuf
;
// To get SQL_TIMESTAMP's
void
*
Bufp
;
// To extended buffer
TIMESTAMP_STRUCT
*
Sqlbuf
;
// To get SQL_TIMESTAMP's
void
*
Bufp
;
// To extended buffer
PVBLK
Blkp
;
// To Value Block
//char F_Date[12]; // Internal Date format
PVAL
To_Val
;
// To value used for Insert
SQLLEN
*
StrLen
;
// As returned by ODBC
SQLLEN
Slen
;
// Used with Fetch
int
Rank
;
// Rank (position) number in the query
SQLLEN
Slen
;
// Used with Fetch
int
Rank
;
// Rank (position) number in the query
};
// end of class ODBCCOL
/***********************************************************************/
/* This is the ODBC Access Method class declaration that send */
/* commands to be executed by other DB ODBC drivers. */
/***********************************************************************/
class
TDBXDBC
:
public
TDBODBC
{
friend
class
XSRCCOL
;
friend
class
ODBConn
;
public:
// Constructor
TDBXDBC
(
PODEF
tdp
=
NULL
)
:
TDBODBC
(
tdp
)
{
Cmdcol
=
NULL
;}
TDBXDBC
(
PTDBXDBC
tdbp
)
:
TDBODBC
(
tdbp
)
{
Cmdcol
=
tdbp
->
Cmdcol
;}
// Implementation
//virtual AMT GetAmType(void) {return TYPE_AM_ODBC;}
virtual
PTDB
Duplicate
(
PGLOBAL
g
)
{
return
(
PTDB
)
new
(
g
)
TDBXDBC
(
this
);}
// Methods
virtual
PTDB
CopyOne
(
PTABS
t
);
//virtual int GetRecpos(void);
//virtual PSZ GetFile(PGLOBAL g);
//virtual void SetFile(PGLOBAL g, PSZ fn);
//virtual void ResetSize(void);
//virtual int GetAffectedRows(void) {return AftRows;}
//virtual PSZ GetServer(void) {return "ODBC";}
// Database routines
virtual
PCOL
MakeCol
(
PGLOBAL
g
,
PCOLDEF
cdp
,
PCOL
cprec
,
int
n
);
//virtual int GetProgMax(PGLOBAL g);
virtual
int
GetMaxSize
(
PGLOBAL
g
);
virtual
bool
OpenDB
(
PGLOBAL
g
);
virtual
int
ReadDB
(
PGLOBAL
g
);
virtual
int
WriteDB
(
PGLOBAL
g
);
//virtual int DeleteDB(PGLOBAL g, int irc);
//virtual void CloseDB(PGLOBAL g);
protected:
// Internal functions
char
*
MakeCMD
(
PGLOBAL
g
);
//bool BindParameters(PGLOBAL g);
// Members
char
*
Cmdcol
;
// The name of the Xsrc command column
};
// end of class TDBXDBC
/***********************************************************************/
/* Used by table in source execute mode. */
/***********************************************************************/
class
XSRCCOL
:
public
ODBCCOL
{
friend
class
TDBXDBC
;
public:
// Constructors
XSRCCOL
(
PCOLDEF
cdp
,
PTDB
tdbp
,
PCOL
cprec
,
int
i
,
PSZ
am
=
"ODBC"
);
XSRCCOL
(
XSRCCOL
*
colp
,
PTDB
tdbp
);
// Constructor used in copy process
// Implementation
//virtual int GetAmType(void) {return TYPE_AM_ODBC;}
// Methods
virtual
void
ReadColumn
(
PGLOBAL
g
);
virtual
void
WriteColumn
(
PGLOBAL
g
);
// void Print(PGLOBAL g, FILE *, uint);
protected:
// Members
char
*
Buffer
;
// To get returned message
int
Flag
;
// Column content desc
};
// end of class XSRCCOL
/***********************************************************************/
/* This is the class declaration for the Data Sources catalog table. */
/***********************************************************************/
...
...
storage/connect/tabutil.cpp
View file @
7dc48ae3
...
...
@@ -591,6 +591,17 @@ bool PRXCOL::Init(PGLOBAL g)
return
FALSE
;
}
// end of Init
/***********************************************************************/
/* Reset the column descriptor to non evaluated yet. */
/***********************************************************************/
void
PRXCOL
::
Reset
(
void
)
{
if
(
Colp
)
Colp
->
Reset
();
Status
&=
~
BUF_READ
;
}
// end of Reset
/***********************************************************************/
/* ReadColumn: */
/***********************************************************************/
...
...
@@ -600,7 +611,7 @@ void PRXCOL::ReadColumn(PGLOBAL g)
htrc
(
"PRX ReadColumn: name=%s
\n
"
,
Name
);
if
(
Colp
)
{
Colp
->
ReadColumn
(
g
);
Colp
->
Eval
(
g
);
Value
->
SetValue_pval
(
To_Val
);
// Set null when applicable
...
...
storage/connect/tabutil.h
View file @
7dc48ae3
...
...
@@ -70,7 +70,7 @@ class DllExport TDBPRX : public TDBASE {
virtual
int
GetRecpos
(
void
)
{
return
Tdbp
->
GetRecpos
();}
virtual
void
ResetDB
(
void
)
{
Tdbp
->
ResetDB
();}
virtual
int
RowNumber
(
PGLOBAL
g
,
bool
b
=
FALSE
);
virtual
PSZ
GetServer
(
void
)
{
return
(
Tdbp
)
?
Tdbp
->
GetServer
()
:
(
char
*
)
"?"
;}
virtual
PSZ
GetServer
(
void
)
{
return
(
Tdbp
)
?
Tdbp
->
GetServer
()
:
(
PSZ
)
"?"
;}
// Database routines
virtual
PCOL
MakeCol
(
PGLOBAL
g
,
PCOLDEF
cdp
,
PCOL
cprec
,
int
n
);
...
...
@@ -105,6 +105,7 @@ class DllExport PRXCOL : public COLBLK {
virtual
int
GetAmType
(
void
)
{
return
TYPE_AM_PRX
;}
// Methods
virtual
void
Reset
(
void
);
virtual
bool
IsSpecial
(
void
)
{
return
Pseudo
;}
virtual
void
ReadColumn
(
PGLOBAL
g
);
bool
Init
(
PGLOBAL
g
);
...
...
storage/connect/tabxcl.cpp
View file @
7dc48ae3
...
...
@@ -253,7 +253,7 @@ XCLCOL::XCLCOL(PGLOBAL g, PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i)
void
XCLCOL
::
ReadColumn
(
PGLOBAL
g
)
{
if
(((
PTDBXCL
)
To_Tdb
)
->
New
)
{
Colp
->
ReadColumn
(
g
);
Colp
->
Eval
(
g
);
strcpy
(
Cbuf
,
To_Val
->
GetCharValue
());
Cp
=
Cbuf
;
}
// endif New
...
...
@@ -272,9 +272,11 @@ void XCLCOL::ReadColumn(PGLOBAL g)
}
else
if
(
Nullable
)
{
Value
->
Reset
();
Value
->
SetNull
(
true
);
}
else
}
else
{
// Skip that row
((
PTDBXCL
)
To_Tdb
)
->
RowFlag
=
2
;
Colp
->
Reset
();
}
// endif Cp
if
(
Cp
&&
*
Cp
)
// More to come from the same row
...
...
storage/connect/tabxcl.h
View file @
7dc48ae3
...
...
@@ -90,7 +90,7 @@ class XCLCOL : public PRXCOL {
XCLCOL
(
PGLOBAL
g
,
PCOLDEF
cdp
,
PTDB
tdbp
,
PCOL
cprec
,
int
i
);
// Methods
virtual
void
Reset
(
void
)
{
}
// Evaluated only by TDBXCL
virtual
void
Reset
(
void
)
{
Colp
->
Reset
();}
// Evaluated only by TDBXCL
virtual
void
ReadColumn
(
PGLOBAL
g
);
protected:
...
...
storage/connect/tabxml.cpp
View file @
7dc48ae3
...
...
@@ -78,7 +78,9 @@ XMLDEF::XMLDEF(void)
DefNs
=
NULL
;
Attrib
=
NULL
;
Hdattr
=
NULL
;
Coltype
=
1
;
Limit
=
0
;
Header
=
0
;
Xpand
=
false
;
Usedom
=
false
;
}
// end of XMLDEF constructor
...
...
@@ -338,17 +340,14 @@ PCOL TDBXML::InsertSpecialColumn(PGLOBAL g, PCOL colp)
/***********************************************************************/
/* LoadTableFile: Load and parse an XML file. */
/***********************************************************************/
int
TDBXML
::
LoadTableFile
(
PGLOBAL
g
)
int
TDBXML
::
LoadTableFile
(
PGLOBAL
g
,
char
*
filename
)
{
char
filename
[
_MAX_PATH
];
int
rc
=
RC_OK
,
type
=
(
Usedom
)
?
TYPE_FB_XML
:
TYPE_FB_XML2
;
PFBLOCK
fp
=
NULL
;
PDBUSER
dup
=
(
PDBUSER
)
g
->
Activityp
->
Aptr
;
/*********************************************************************/
/* We used the file name relative to recorded datapath. */
/*********************************************************************/
PlugSetPath
(
filename
,
Xfile
,
GetPath
());
if
(
Docp
)
return
rc
;
// Already done
if
(
trace
)
htrc
(
"TDBXML: loading %s
\n
"
,
filename
);
...
...
@@ -397,6 +396,7 @@ int TDBXML::LoadTableFile(PGLOBAL g)
}
else
rc
=
(
errno
==
ENOENT
)
?
RC_NF
:
RC_INFO
;
// Cannot make a Xblock until document is made
return
rc
;
}
// endif Docp
...
...
@@ -418,9 +418,8 @@ int TDBXML::LoadTableFile(PGLOBAL g)
/***********************************************************************/
bool
TDBXML
::
Initialize
(
PGLOBAL
g
)
{
char
tabpath
[
64
];
int
rc
;
PXMLCOL
colp
;
int
rc
;
PXMLCOL
colp
;
if
(
Void
)
return
false
;
...
...
@@ -440,8 +439,13 @@ bool TDBXML::Initialize(PGLOBAL g)
#else
if
(
!
Root
)
{
#endif
char
tabpath
[
64
],
filename
[
_MAX_PATH
];
// We used the file name relative to recorded datapath
PlugSetPath
(
filename
,
Xfile
,
GetPath
());
// Load or re-use the table file
rc
=
LoadTableFile
(
g
);
rc
=
LoadTableFile
(
g
,
filename
);
if
(
rc
==
RC_OK
)
{
// Get root node
...
...
@@ -503,6 +507,9 @@ bool TDBXML::Initialize(PGLOBAL g)
goto
error
;
}
// endif NewDoc
// Now we can link the Xblock
To_Xb
=
Docp
->
LinkXblock
(
g
,
Mode
,
rc
,
filename
);
// Add a CONNECT comment node
// sprintf(buf, MSG(CREATED_PLUGDB), version);
sprintf
(
buf
,
" Created by CONNECT %s "
,
version
);
...
...
@@ -893,12 +900,21 @@ int TDBXML::DeleteDB(PGLOBAL g, int irc)
if
((
RowNode
=
Nlist
->
GetItem
(
g
,
Irow
,
RowNode
))
==
NULL
)
{
sprintf
(
g
->
Message
,
MSG
(
MISSING_ROWNODE
),
Irow
);
return
RC_FX
;
}
else
}
else
{
TabNode
->
DeleteChild
(
g
,
RowNode
);
if
(
Nlist
->
DropItem
(
g
,
Irow
))
return
RC_FX
;
}
// endif RowNode
Changed
=
true
;
}
else
if
(
irc
!=
RC_EF
)
{
TabNode
->
DeleteChild
(
g
,
RowNode
);
if
(
Nlist
->
DropItem
(
g
,
Irow
))
return
RC_FX
;
Changed
=
true
;
}
// endif's irc
...
...
storage/connect/tabxml.h
View file @
7dc48ae3
...
...
@@ -6,8 +6,6 @@
/* */
/* This file contains the XML table classes declares. */
/***********************************************************************/
#define TYPE_AM_XML (AMT)127
typedef
class
XMLDEF
*
PXMLDEF
;
typedef
class
TDBXML
*
PTDBXML
;
typedef
class
XMLCOL
*
PXMLCOL
;
...
...
@@ -81,7 +79,7 @@ class DllExport TDBXML : public TDBASE {
virtual
void
ResetDB
(
void
)
{
N
=
0
;}
virtual
void
ResetSize
(
void
)
{
MaxSize
=
-
1
;}
virtual
int
RowNumber
(
PGLOBAL
g
,
bool
b
=
false
);
int
LoadTableFile
(
PGLOBAL
g
);
int
LoadTableFile
(
PGLOBAL
g
,
char
*
filename
);
bool
Initialize
(
PGLOBAL
g
);
bool
SetTabNode
(
PGLOBAL
g
);
void
SetNodeAttr
(
PGLOBAL
g
,
char
*
attr
,
PXNODE
node
);
...
...
storage/connect/valblk.cpp
View file @
7dc48ae3
...
...
@@ -447,13 +447,12 @@ int TYPBLK<TYPE>::Find(PVAL vp)
template
<
class
TYPE
>
int
TYPBLK
<
TYPE
>::
GetMaxLength
(
void
)
{
char
buf
[
1
2
];
int
i
,
n
;
char
buf
[
3
2
];
int
i
,
n
,
m
;
for
(
i
=
n
=
0
;
i
<
Nval
;
i
++
)
{
sprintf
(
buf
,
Fmt
,
Typp
[
i
]);
n
=
max
(
n
,
(
signed
)
strlen
(
buf
));
m
=
sprintf
(
buf
,
Fmt
,
Typp
[
i
]);
n
=
max
(
n
,
m
);
}
// endfor i
return
n
;
...
...
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