1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-08 11:22:35 +03:00

MDEV-5341 ConnectSE: discovery for ODBC tables does not work if tables

with the same names present in multiple schemas

The "TABNAME" option now supports qualified table names,
to connect to tables residing in a particular schema and catalog.

Qualified table names have the following format:

  [[CatalogName.]SchemaName.]TableName

Qualified table names can be used:

1. In "normal" tables:

CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC
CONNECTION='DSN=ConnectEng;UID=mtr;PWD=mtr'
TABNAME='schema1.t1';

2. In catalog tables (CATFUNC=Tables  and CATFUNC=Columns)

CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC
CONNECTION='DSN=postgresql;UID=user;PWD=password'
TABNAME='schema1.t1';

Note, the % and _ wildcards are supported in
the schema name and the table name parts:

CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC
CONNECTION='DSN=postgresql;UID=user;PWD=password'
TABNAME='%.t1';

CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC
CONNECTION='DSN=postgresql;UID=user;PWD=password'
TABNAME='schema1.%';
This commit is contained in:
Alexander Barkov
2013-12-11 18:47:46 +04:00
parent 57fcf1cbe4
commit f19f8f0ee4
5 changed files with 630 additions and 6 deletions

View File

@@ -1986,6 +1986,87 @@ bool ODBConn::GetDrivers(PQRYRES qrp)
return rv;
} // end of GetDrivers
/**
A helper class to split an optionally qualified table name into components.
These formats are understood:
"CatalogName.SchemaName.TableName"
"SchemaName.TableName"
"TableName"
*/
class SQLQualifiedName
{
static const uint max_parts= 3; /* Catalog.Schema.Table */
MYSQL_LEX_STRING m_part[max_parts];
char m_buf[512];
void lex_string_set(MYSQL_LEX_STRING *S, char *str, size_t length)
{
S->str= str;
S->length= length;
}
void lex_string_shorten_down(MYSQL_LEX_STRING *S, size_t offs)
{
DBUG_ASSERT(offs <= S->length);
S->str+= offs;
S->length-= offs;
}
/*
Find the rightmost '.' delimiter and return the length
of the qualifier, including the rightmost '.' delimier.
For example, for the string {"a.b.c",5} it will return 4,
which is the length of the qualifier "a.b."
*/
size_t lex_string_find_qualifier(MYSQL_LEX_STRING *S)
{
size_t i;
for (i= S->length; i > 0; i--)
{
if (S->str[i - 1] == '.')
{
S->str[i - 1]= '\0';
return i;
}
}
return 0;
}
public:
/*
Initialize to the given optionally qualified name.
NULL pointer in "name" is supported.
*/
SQLQualifiedName(const char *name)
{
size_t len, i= 0;
if (!name)
goto ret;
/* Initialize the first (rightmost) part */
lex_string_set(&m_part[0], m_buf,
strmake(m_buf, name, sizeof(m_buf) - 1) - m_buf);
/* Initialize the other parts, if exist. */
for (i= 1; i < max_parts; i++)
{
if (!(len= lex_string_find_qualifier(&m_part[i - 1])))
break;
lex_string_set(&m_part[i], m_part[i - 1].str, len - 1);
lex_string_shorten_down(&m_part[i - 1], len);
}
ret:
/* Initialize the remaining parts */
for ( ; i < max_parts; i++)
lex_string_set(&m_part[i], NULL, 0);
}
SQLCHAR *ptr(uint i)
{
DBUG_ASSERT(i < max_parts);
return (SQLCHAR *) (m_part[i].length ? m_part[i].str : NULL);
}
size_t length(uint i)
{
DBUG_ASSERT(i < max_parts);
return m_part[i].length;
}
};
/***********************************************************************/
/* Allocate recset and call SQLTables, SQLColumns or SQLPrimaryKeys. */
/***********************************************************************/
@@ -2048,29 +2129,38 @@ int ODBConn::GetCatInfo(CATPARM *cap)
} else
ThrowDBX("0-sized result");
SQLQualifiedName name((const char *) cap->Tab);
// Now do call the proper ODBC API
switch (cap->Id) {
case CAT_TAB:
// rc = SQLSetStmtAttr(hstmt, SQL_ATTR_METADATA_ID,
// (SQLPOINTER)false, 0);
fnc = "SQLTables";
rc = SQLTables(hstmt, NULL, 0, NULL, 0, cap->Tab, SQL_NTS,
cap->Pat, SQL_NTS);
rc = SQLTables(hstmt, name.ptr(2), name.length(2),
name.ptr(1), name.length(1),
name.ptr(0), name.length(0),
cap->Pat, SQL_NTS);
break;
case CAT_COL:
// rc = SQLSetStmtAttr(hstmt, SQL_ATTR_METADATA_ID,
// (SQLPOINTER)true, 0);
fnc = "SQLColumns";
rc = SQLColumns(hstmt, NULL, 0, NULL, 0, cap->Tab, SQL_NTS,
cap->Pat, SQL_NTS);
rc = SQLColumns(hstmt, name.ptr(2), name.length(2),
name.ptr(1), name.length(1),
name.ptr(0), name.length(0),
cap->Pat, SQL_NTS);
break;
case CAT_KEY:
fnc = "SQLPrimaryKeys";
rc = SQLPrimaryKeys(hstmt, NULL, 0, NULL, 0, cap->Tab, SQL_NTS);
rc = SQLPrimaryKeys(hstmt, name.ptr(2), name.length(2),
name.ptr(1), name.length(1),
name.ptr(0), name.length(0));
break;
case CAT_STAT:
fnc = "SQLStatistics";
rc = SQLStatistics(hstmt, NULL, 0, NULL, 0, cap->Tab, SQL_NTS,
rc = SQLStatistics(hstmt, name.ptr(2), name.length(2),
name.ptr(1), name.length(1),
name.ptr(0), name.length(0),
cap->Unique, cap->Accuracy);
break;
case CAT_SPC: