jdbc/driver/mysql_metadata.cpp (3,913 lines of code) (raw):

/* * Copyright (c) 2008, 2024, Oracle and/or its affiliates. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2.0, as * published by the Free Software Foundation. * * This program is designed to work with certain software (including * but not limited to OpenSSL) that is licensed under separate terms, as * designated in a particular file or component or in included license * documentation. The authors of MySQL hereby grant you an additional * permission to link the program and your derivative works with the * separately licensed software that they have either included with * the program or referenced in the documentation. * * Without limiting anything contained in the foregoing, this file, * which is part of Connector/C++, is also subject to the * Universal FOSS Exception, version 1.0, a copy of which can be found at * https://oss.oracle.com/licenses/universal-foss-exception. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License, version 2.0, for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include <stdlib.h> #include <string> #include <sstream> #include <memory> #include <cppconn/exception.h> #include "mysql_util.h" #include "mysql_connection.h" #include "mysql_metadata.h" #include "mysql_art_resultset.h" #include "mysql_statement.h" #include "mysql_prepared_statement.h" #include "mysql_debug.h" #include "version_info.h" #include "nativeapi/native_connection_wrapper.h" // For snprintf #include <stdio.h> namespace sql { namespace mysql { struct TypeInfoDef { const char * const typeName; int dataType; unsigned long long precision; const char * const literalPrefix; const char * const literalSuffix; const char * const createParams; short nullable; bool caseSensitive; short searchable; bool isUnsigned; bool fixedPrecScale; bool autoIncrement; const char * localTypeName; int minScale; int maxScale; int sqlDataType; int sqlDateTimeSub; int numPrecRadix; }; static const TypeInfoDef mysqlc_types[] = { // ------------- MySQL-Type: BIT. DBC-Type: BIT ------------- { "BIT", // Typename sql::DataType::BIT, // dbc-type 1, // Precision "", // Literal prefix "", // Literal suffix "", // Create params DatabaseMetaData::typeNullable, // nullable false, // case sensitive DatabaseMetaData::typeSearchable, // searchable false, // unsigned_attribute false, // fixed_prec_scale false, // auto_increment "BIT", // local type name 0, // minimum scale 0, // maximum scale 0, // sql data type (unused) 0, // sql datetime sub (unused) 10 // num prec radix }, #ifdef ENABLE_ONCE_THE_SERVER_HAS_REAL_BOOL // ------------ MySQL-Type: BOOL. DBC-Type: BIT ------------- { "BOOL", // Typename sql::DataType::TINYINT, // dbc-type 1, // Precision "", // Literal prefix "", // Literal suffix "", // Create params DatabaseMetaData::typeNullable, // nullable false, // case sensitive DatabaseMetaData::typeSearchable, // searchable false, // unsigned_attribute false, // fixed_prec_scale false, // auto_increment "BOOL", // local type name 0, // minimum scale 0, // maximum scale 0, // sql data type (unused) 0, // sql datetime sub (unused) 10 // num prec radix }, #endif // --------- MySQL-Type: TINYINT DBC-Type: TINYINT ---------- { "TINYINT", // Typename sql::DataType::TINYINT, // dbc-type 3, // Precision "", // Literal prefix "", // Literal suffix "[(M)] [ZEROFILL]", // Create params DatabaseMetaData::typeNullable, // nullable false, // case sensitive DatabaseMetaData::typeSearchable, // searchable false, // unsigned_attribute false, // fixed_prec_scale true, // auto_increment "TINYINT", // local type name 0, // minimum scale 0, // maximum scale 0, // sql data type (unused) 0, // sql datetime sub (unused) 10 // num prec radix }, { "TINYINT UNSIGNED", // Typename sql::DataType::TINYINT, // dbc-type 3, // Precision "", // Literal prefix "", // Literal suffix "[(M)] [UNSIGNED] [ZEROFILL]", // Create params DatabaseMetaData::typeNullable, // nullable false, // case sensitive DatabaseMetaData::typeSearchable, // searchable true, // unsigned_attribute false, // fixed_prec_scale true, // auto_increment "TINYINT UNSIGNED", // local type name 0, // minimum scale 0, // maximum scale 0, // sql data type (unused) 0, // sql datetime sub (unused) 10 // num prec radix }, { "TINYINT UNSIGNED ZEROFILL", // Typename sql::DataType::TINYINT, // dbc-type 3, // Precision "", // Literal prefix "", // Literal suffix "[(M)] [UNSIGNED]", // Create params DatabaseMetaData::typeNullable, // nullable false, // case sensitive DatabaseMetaData::typeSearchable, // searchable true, // unsigned_attribute false, // fixed_prec_scale true, // auto_increment "TINYINT UNSIGNED ZEROFILL", // local type name 0, // minimum scale 0, // maximum scale 0, // sql data type (unused) 0, // sql datetime sub (unused) 10 // num prec radix }, // ----------- MySQL-Type: BIGINT DBC-Type: BIGINT ---------- { "BIGINT", // Typename sql::DataType::BIGINT, // dbc-type 19, // Precision "", // Literal prefix "", // Literal suffix "[(M)] [ZEROFILL]", // Create params DatabaseMetaData::typeNullable, // nullable false, // case sensitive DatabaseMetaData::typeSearchable, // searchable false, // unsigned_attribute false, // fixed_prec_scale true, // auto_increment "BIGINT", // local type name 0, // minimum scale 0, // maximum scale 0, // sql data type (unused) 0, // sql datetime sub (unused) 10 // num prec radix }, { "BIGINT UNSIGNED", // Typename sql::DataType::BIGINT, // dbc-type 19, // Precision "", // Literal prefix "", // Literal suffix "[(M)] [ZEROFILL]", // Create params DatabaseMetaData::typeNullable, // nullable false, // case sensitive DatabaseMetaData::typeSearchable, // searchable true, // unsigned_attribute false, // fixed_prec_scale true, // auto_increment "BIGINT UNSIGNED", // local type name 0, // minimum scale 0, // maximum scale 0, // sql data type (unused) 0, // sql datetime sub (unused) 10 // num prec radix }, { "BIGINT UNSIGNED ZEROFILL", // Typename sql::DataType::BIGINT, // dbc-type 19, // Precision "", // Literal prefix "", // Literal suffix "[(M)]", // Create params DatabaseMetaData::typeNullable, // nullable false, // case sensitive DatabaseMetaData::typeSearchable, // searchable true, // unsigned_attribute false, // fixed_prec_scale true, // auto_increment "BIGINT UNSIGNED ZEROFILL", // local type name 0, // minimum scale 0, // maximum scale 0, // sql data type (unused) 0, // sql datetime sub (unused) 10 // num prec radix }, // ----------- MySQL-Type: LONG VARBINARY DBC-Type: LONGVARBINARY ---------- { "LONG VARBINARY", // Typename sql::DataType::LONGVARBINARY, // dbc-type 16777215, // Precision "'", // Literal prefix "'", // Literal suffix "", // Create params DatabaseMetaData::typeNullable, // nullable true, // case sensitive DatabaseMetaData::typeSearchable, // searchable false, // unsigned_attribute false, // fixed_prec_scale false, // auto_increment "LONG VARBINARY", // local type name 0, // minimum scale 0, // maximum scale 0, // sql data type (unused) 0, // sql datetime sub (unused) 10 // num prec radix }, // ----------- MySQL-Type: MEDIUMBLOB DBC-Type: LONGVARBINARY ---------- { "MEDIUMBLOB", // Typename sql::DataType::LONGVARBINARY, // dbc-type 16777215, // Precision "'", // Literal prefix "'", // Literal suffix "", // Create params DatabaseMetaData::typeNullable, // nullable true, // case sensitive DatabaseMetaData::typeSearchable, // searchable false, // unsigned_attribute false, // fixed_prec_scale false, // auto_increment "MEDIUMBLOB", // local type name 0, // minimum scale 0, // maximum scale 0, // sql data type (unused) 0, // sql datetime sub (unused) 10 // num prec radix }, // ----------- MySQL-Type: LONGBLOB DBC-Type: LONGVARBINARY ---------- { "LONGBLOB", // Typename sql::DataType::LONGVARBINARY, // dbc-type 0xFFFFFFFF, // Precision "'", // Literal prefix "'", // Literal suffix "", // Create params DatabaseMetaData::typeNullable, // nullable true, // case sensitive DatabaseMetaData::typeSearchable, // searchable false, // unsigned_attribute false, // fixed_prec_scale false, // auto_increment "LONGBLOB", // local type name 0, // minimum scale 0, // maximum scale 0, // sql data type (unused) 0, // sql datetime sub (unused) 10 // num prec radix }, // ----------- MySQL-Type: BLOB DBC-Type: LONGVARBINARY ---------- { "BLOB", // Typename sql::DataType::LONGVARBINARY, // dbc-type 0xFFFF, // Precision "'", // Literal prefix "'", // Literal suffix "", // Create params DatabaseMetaData::typeNullable, // nullable true, // case sensitive DatabaseMetaData::typeSearchable, // searchable false, // unsigned_attribute false, // fixed_prec_scale false, // auto_increment "BLOB", // local type name 0, // minimum scale 0, // maximum scale 0, // sql data type (unused) 0, // sql datetime sub (unused) 10 // num prec radix }, // ----------- MySQL-Type: TINYBLOB DBC-Type: LONGVARBINARY ---------- { "TINYBLOB", // Typename sql::DataType::LONGVARBINARY, // dbc-type 0xFF, // Precision "'", // Literal prefix "'", // Literal suffix "", // Create params DatabaseMetaData::typeNullable, // nullable true, // case sensitive DatabaseMetaData::typeSearchable, // searchable false, // unsigned_attribute false, // fixed_prec_scale false, // auto_increment "TINYBLOB", // local type name 0, // minimum scale 0, // maximum scale 0, // sql data type (unused) 0, // sql datetime sub (unused) 10 // num prec radix }, // ----------- MySQL-Type: VARBINARY DBC-Type: VARBINARY ---------- { "VARBINARY", // Typename sql::DataType::VARBINARY, // dbc-type 0xFF, // Precision "'", // Literal prefix "'", // Literal suffix "(M)", // Create params DatabaseMetaData::typeNullable, // nullable true, // case sensitive DatabaseMetaData::typeSearchable, // searchable false, // unsigned_attribute false, // fixed_prec_scale false, // auto_increment "VARBINARY", // local type name 0, // minimum scale 0, // maximum scale 0, // sql data type (unused) 0, // sql datetime sub (unused) 10 // num prec radix }, // ----------- MySQL-Type: BINARY DBC-Type: BINARY ---------- { "BINARY", // Typename sql::DataType::BINARY, // dbc-type 0xFF, // Precision "'", // Literal prefix "'", // Literal suffix "(M)", // Create params DatabaseMetaData::typeNullable, // nullable true, // case sensitive DatabaseMetaData::typeSearchable, // searchable false, // unsigned_attribute false, // fixed_prec_scale false, // auto_increment "BINARY", // local type name 0, // minimum scale 0, // maximum scale 0, // sql data type (unused) 0, // sql datetime sub (unused) 10 // num prec radix }, // ----------- MySQL-Type: LONG VARCHAR DBC-Type: LONG VARCHAR ---------- { "LONG VARCHAR", // Typename sql::DataType::LONGVARCHAR, // dbc-type 0xFFFFFF, // Precision "'", // Literal prefix "'", // Literal suffix "", // Create params DatabaseMetaData::typeNullable, // nullable false, // case sensitive DatabaseMetaData::typeSearchable, // searchable false, // unsigned_attribute false, // fixed_prec_scale false, // auto_increment "LONG VARCHAR", // local type name 0, // minimum scale 0, // maximum scale 0, // sql data type (unused) 0, // sql datetime sub (unused) 10 // num prec radix }, // ----------- MySQL-Type: MEDIUMTEXT DBC-Type: LONG VARCHAR ---------- { "MEDIUMTEXT", // Typename sql::DataType::LONGVARCHAR, // dbc-type 0xFFFFFF, // Precision "'", // Literal prefix "'", // Literal suffix "", // Create params DatabaseMetaData::typeNullable, // nullable false, // case sensitive DatabaseMetaData::typeSearchable, // searchable false, // unsigned_attribute false, // fixed_prec_scale false, // auto_increment "MEDIUMTEXT", // local type name 0, // minimum scale 0, // maximum scale 0, // sql data type (unused) 0, // sql datetime sub (unused) 10 // num prec radix }, // ----------- MySQL-Type: LONGTEXT DBC-Type: LONG VARCHAR ---------- { "LONGTEXT", // Typename sql::DataType::LONGVARCHAR, // dbc-type 0xFFFFFF, // Precision "'", // Literal prefix "'", // Literal suffix "", // Create params DatabaseMetaData::typeNullable, // nullable false, // case sensitive DatabaseMetaData::typeSearchable, // searchable false, // unsigned_attribute false, // fixed_prec_scale false, // auto_increment "LONGTEXT", // local type name 0, // minimum scale 0, // maximum scale 0, // sql data type (unused) 0, // sql datetime sub (unused) 10 // num prec radix }, // ----------- MySQL-Type: TEXT DBC-Type: LONG VARCHAR ---------- { "TEXT", // Typename sql::DataType::LONGVARCHAR, // dbc-type 0xFFFF, // Precision "'", // Literal prefix "'", // Literal suffix "", // Create params DatabaseMetaData::typeNullable, // nullable false, // case sensitive DatabaseMetaData::typeSearchable, // searchable false, // unsigned_attribute false, // fixed_prec_scale false, // auto_increment "TEXT", // local type name 0, // minimum scale 0, // maximum scale 0, // sql data type (unused) 0, // sql datetime sub (unused) 10 // num prec radix }, // ----------- MySQL-Type: TINYTEXT DBC-Type: LONG VARCHAR ---------- { "TINYTEXT", // Typename sql::DataType::LONGVARCHAR, // dbc-type 0xFF, // Precision "'", // Literal prefix "'", // Literal suffix "", // Create params DatabaseMetaData::typeNullable, // nullable false, // case sensitive DatabaseMetaData::typeSearchable, // searchable false, // unsigned_attribute false, // fixed_prec_scale false, // auto_increment "TINYTEXT", // local type name 0, // minimum scale 0, // maximum scale 0, // sql data type (unused) 0, // sql datetime sub (unused) 10 // num prec radix }, // ----------- MySQL-Type: CHAR DBC-Type: CHAR ---------- { "CHAR", // Typename sql::DataType::CHAR, // dbc-type 0xFF, // Precision "'", // Literal prefix "'", // Literal suffix "(M)", // Create params DatabaseMetaData::typeNullable, // nullable false, // case sensitive DatabaseMetaData::typeSearchable, // searchable false, // unsigned_attribute false, // fixed_prec_scale false, // auto_increment "CHAR", // local type name 0, // minimum scale 0, // maximum scale 0, // sql data type (unused) 0, // sql datetime sub (unused) 10 // num prec radix }, // ToDo : The maximum number of digits for DECIMAL or NUMERIC is 65 (64 from MySQL 5.0.3 to 5.0.5). // ----------- MySQL-Type: NUMERIC (silently conv. to DECIMAL) DBC-Type: NUMERIC ---------- { "NUMERIC", // Typename sql::DataType::NUMERIC, // dbc-type 64, // Precision "", // Literal prefix "", // Literal suffix "[(M[,D])] [ZEROFILL]", // Create params DatabaseMetaData::typeNullable, // nullable false, // case sensitive DatabaseMetaData::typeSearchable, // searchable false, // unsigned_attribute false, // fixed_prec_scale true, // auto_increment "NUMERIC", // local type name -308, // minimum scale 308, // maximum scale 0, // sql data type (unused) 0, // sql datetime sub (unused) 10 // num prec radix }, // ----------- MySQL-Type: DECIMAL DBC-Type: DECIMAL ---------- { "DECIMAL", // Typename sql::DataType::DECIMAL, // dbc-type 64, // Precision "", // Literal prefix "", // Literal suffix "[(M[,D])] [ZEROFILL] [UNSIGNED]", // Create params DatabaseMetaData::typeNullable, // nullable false, // case sensitive DatabaseMetaData::typeSearchable, // searchable false, // unsigned_attribute false, // fixed_prec_scale true, // auto_increment "DECIMAL", // local type name -308, // minimum scale 308, // maximum scale 0, // sql data type (unused) 0, // sql datetime sub (unused) 10 // num prec radix }, { "DECIMAL UNSIGNED", // Typename sql::DataType::DECIMAL, // dbc-type 64, // Precision "", // Literal prefix "", // Literal suffix "[(M[,D])] [ZEROFILL]", // Create params DatabaseMetaData::typeNullable, // nullable false, // case sensitive DatabaseMetaData::typeSearchable, // searchable true, // unsigned_attribute false, // fixed_prec_scale true, // auto_increment "DECIMAL UNSIGNED", // local type name -308, // minimum scale 308, // maximum scale 0, // sql data type (unused) 0, // sql datetime sub (unused) 10 // num prec radix }, { "DECIMAL UNSIGNED ZEROFILL", // Typename sql::DataType::DECIMAL, // dbc-type 64, // Precision "", // Literal prefix "", // Literal suffix "[(M[,D])]", // Create params DatabaseMetaData::typeNullable, // nullable false, // case sensitive DatabaseMetaData::typeSearchable, // searchable true, // unsigned_attribute false, // fixed_prec_scale true, // auto_increment "DECIMAL UNSIGNED ZEROFILL", // local type name -308, // minimum scale 308, // maximum scale 0, // sql data type (unused) 0, // sql datetime sub (unused) 10 // num prec radix }, #ifdef LETS_HAVE_JUST_ONLY_ONE_INT_TYPE // ----------- MySQL-Type: INTEGER DBC-Type: INTEGER ---------- { "INTEGER", // Typename sql::DataType::INTEGER, // dbc-type 10, // Precision "", // Literal prefix "", // Literal suffix "[(M)] [UNSIGNED] [ZEROFILL]", // Create params DatabaseMetaData::typeNullable, // nullable false, // case sensitive DatabaseMetaData::typeSearchable, // searchable false, // unsigned_attribute false, // fixed_prec_scale true, // auto_increment "INTEGER", // local type name 0, // minimum scale 0, // maximum scale 0, // sql data type (unused) 0, // sql datetime sub (unused) 10 // num prec radix }, { "INTEGER UNSIGNED", // Typename sql::DataType::INTEGER, // dbc-type 10, // Precision "", // Literal prefix "", // Literal suffix "[(M)] [ZEROFILL]", // Create params DatabaseMetaData::typeNullable, // nullable false, // case sensitive DatabaseMetaData::typeSearchable, // searchable false, // unsigned_attribute false, // fixed_prec_scale true, // auto_increment "INTEGER UNSIGNED", // local type name 0, // minimum scale 0, // maximum scale 0, // sql data type (unused) 0, // sql datetime sub (unused) 10 // num prec radix }, #endif // ----------- MySQL-Type: INT DBC-Type: INTEGER ---------- { "INT", // Typename sql::DataType::INTEGER, // dbc-type 10, // Precision "", // Literal prefix "", // Literal suffix "[(M)] [UNSIGNED] [ZEROFILL]", // Create params DatabaseMetaData::typeNullable, // nullable false, // case sensitive DatabaseMetaData::typeSearchable, // searchable false, // unsigned_attribute false, // fixed_prec_scale true, // auto_increment "INT", // local type name 0, // minimum scale 0, // maximum scale 0, // sql data type (unused) 0, // sql datetime sub (unused) 10 // num prec radix }, { "INT UNSIGNED", // Typename sql::DataType::INTEGER, // dbc-type 10, // Precision "", // Literal prefix "", // Literal suffix "[(M)] [ZEROFILL]", // Create params DatabaseMetaData::typeNullable, // nullable false, // case sensitive DatabaseMetaData::typeSearchable, // searchable false, // unsigned_attribute false, // fixed_prec_scale true, // auto_increment "INT UNSIGNED", // local type name 0, // minimum scale 0, // maximum scale 0, // sql data type (unused) 0, // sql datetime sub (unused) 10 // num prec radix }, { "INT UNSIGNED ZEROFILL", // Typename sql::DataType::INTEGER, // dbc-type 10, // Precision "", // Literal prefix "", // Literal suffix "[(M)]", // Create params DatabaseMetaData::typeNullable, // nullable false, // case sensitive DatabaseMetaData::typeSearchable, // searchable false, // unsigned_attribute false, // fixed_prec_scale true, // auto_increment "INT UNSIGNED ZEROFILL", // local type name 0, // minimum scale 0, // maximum scale 0, // sql data type (unused) 0, // sql datetime sub (unused) 10 // num prec radix }, // ----------- MySQL-Type: MEDIUMINT DBC-Type: MEDIUMINT ---------- { "MEDIUMINT", // Typename sql::DataType::MEDIUMINT, // dbc-type 7, // Precision "", // Literal prefix "", // Literal suffix "[(M)] [UNSIGNED] [ZEROFILL]", // Create params DatabaseMetaData::typeNullable, // nullable false, // case sensitive DatabaseMetaData::typeSearchable, // searchable false, // unsigned_attribute false, // fixed_prec_scale true, // auto_increment "MEDIUMINT", // local type name 0, // minimum scale 0, // maximum scale 0, // sql data type (unused) 0, // sql datetime sub (unused) 10 // num prec radix }, { "MEDIUMINT UNSIGNED", // Typename sql::DataType::MEDIUMINT, // dbc-type 7, // Precision "", // Literal prefix "", // Literal suffix "[(M)] [ZEROFILL]", // Create params DatabaseMetaData::typeNullable, // nullable false, // case sensitive DatabaseMetaData::typeSearchable, // searchable true, // unsigned_attribute false, // fixed_prec_scale true, // auto_increment "MEDIUMINT UNSIGNED", // local type name 0, // minimum scale 0, // maximum scale 0, // sql data type (unused) 0, // sql datetime sub (unused) 10 // num prec radix }, { "MEDIUMINT UNSIGNED ZEROFILL", // Typename sql::DataType::MEDIUMINT, // dbc-type 7, // Precision "", // Literal prefix "", // Literal suffix "[(M)]", // Create params DatabaseMetaData::typeNullable, // nullable false, // case sensitive DatabaseMetaData::typeSearchable, // searchable true, // unsigned_attribute false, // fixed_prec_scale true, // auto_increment "MEDIUMINT UNSIGNED ZEROFILL", // local type name 0, // minimum scale 0, // maximum scale 0, // sql data type (unused) 0, // sql datetime sub (unused) 10 // num prec radix }, // ----------- MySQL-Type: SMALLINT DBC-Type: SMALLINT ---------- { "SMALLINT", // Typename sql::DataType::SMALLINT, // dbc-type 5, // Precision "", // Literal prefix "", // Literal suffix "[(M)] [UNSIGNED] [ZEROFILL]", // Create params DatabaseMetaData::typeNullable, // nullable false, // case sensitive DatabaseMetaData::typeSearchable, // searchable false, // unsigned_attribute false, // fixed_prec_scale true, // auto_increment "SMALLINT", // local type name 0, // minimum scale 0, // maximum scale 0, // sql data type (unused) 0, // sql datetime sub (unused) 10 // num prec radix }, { "SMALLINT UNSIGNED", // Typename sql::DataType::SMALLINT, // dbc-type 5, // Precision "", // Literal prefix "", // Literal suffix "[(M)] [ZEROFILL]", // Create params DatabaseMetaData::typeNullable, // nullable false, // case sensitive DatabaseMetaData::typeSearchable, // searchable true, // unsigned_attribute false, // fixed_prec_scale true, // auto_increment "SMALLINT UNSIGNED", // local type name 0, // minimum scale 0, // maximum scale 0, // sql data type (unused) 0, // sql datetime sub (unused) 10 // num prec radix }, { "SMALLINT UNSIGNED ZEROFILL", // Typename sql::DataType::SMALLINT, // dbc-type 5, // Precision "", // Literal prefix "", // Literal suffix "[(M)]", // Create params DatabaseMetaData::typeNullable, // nullable false, // case sensitive DatabaseMetaData::typeSearchable, // searchable true, // unsigned_attribute false, // fixed_prec_scale true, // auto_increment "SMALLINT UNSIGNED ZEROFILL", // local type name 0, // minimum scale 0, // maximum scale 0, // sql data type (unused) 0, // sql datetime sub (unused) 10 // num prec radix }, /* * MySQL Type: FLOAT JDBC Type: REAL (this is the SINGLE PERCISION * floating point type) */ // ----------- MySQL-Type: FLOAT DBC-Type: REAL ---------- { "FLOAT", // Typename sql::DataType::REAL, // dbc-type 10, // Precision "", // Literal prefix "", // Literal suffix "[(M,D)] [ZEROFILL] [UNSIGNED]", // Create params DatabaseMetaData::typeNullable, // nullable false, // case sensitive DatabaseMetaData::typeSearchable, // searchable false, // unsigned_attribute false, // fixed_prec_scale true, // auto_increment "FLOAT", // local type name -38, // minimum scale 38, // maximum scale 0, // sql data type (unused) 0, // sql datetime sub (unused) 10 // num prec radix }, { "FLOAT UNSIGNED", // Typename sql::DataType::REAL, // dbc-type 10, // Precision "", // Literal prefix "", // Literal suffix "[(M,D)] [ZEROFILL]", // Create params DatabaseMetaData::typeNullable, // nullable false, // case sensitive DatabaseMetaData::typeSearchable, // searchable true, // unsigned_attribute false, // fixed_prec_scale true, // auto_increment "FLOAT UNSIGNED", // local type name -38, // minimum scale 38, // maximum scale 0, // sql data type (unused) 0, // sql datetime sub (unused) 10 // num prec radix }, { "FLOAT UNSIGNED ZEROFILL", // Typename sql::DataType::REAL, // dbc-type 10, // Precision "", // Literal prefix "", // Literal suffix "[(M,D)]", // Create params DatabaseMetaData::typeNullable, // nullable false, // case sensitive DatabaseMetaData::typeSearchable, // searchable true, // unsigned_attribute false, // fixed_prec_scale true, // auto_increment "FLOAT UNSIGNED ZEROFILL", // local type name -38, // minimum scale 38, // maximum scale 0, // sql data type (unused) 0, // sql datetime sub (unused) 10 // num prec radix }, // ----------- MySQL-Type: DOUBLE DBC-Type: DOUBLE ---------- { "DOUBLE", // Typename sql::DataType::DOUBLE, // dbc-type 17, // Precision "", // Literal prefix "", // Literal suffix "[(M,D)] [ZEROFILL] [UNSIGNED]", // Create params DatabaseMetaData::typeNullable, // nullable false, // case sensitive DatabaseMetaData::typeSearchable, // searchable false, // unsigned_attribute false, // fixed_prec_scale true, // auto_increment "DOUBLE", // local type name -308, // minimum scale 308, // maximum scale 0, // sql data type (unused) 0, // sql datetime sub (unused) 10 // num prec radix }, { "DOUBLE UNSIGNED", // Typename sql::DataType::DOUBLE, // dbc-type 17, // Precision "", // Literal prefix "", // Literal suffix "[(M,D)] [ZEROFILL]", // Create params DatabaseMetaData::typeNullable, // nullable false, // case sensitive DatabaseMetaData::typeSearchable, // searchable true, // unsigned_attribute false, // fixed_prec_scale true, // auto_increment "DOUBLE UNSIGNED", // local type name -308, // minimum scale 308, // maximum scale 0, // sql data type (unused) 0, // sql datetime sub (unused) 10 // num prec radix }, { "DOUBLE UNSIGNED ZEROFILL", // Typename sql::DataType::DOUBLE, // dbc-type 17, // Precision "", // Literal prefix "", // Literal suffix "[(M,D)]", // Create params DatabaseMetaData::typeNullable, // nullable false, // case sensitive DatabaseMetaData::typeSearchable, // searchable true, // unsigned_attribute false, // fixed_prec_scale true, // auto_increment "DOUBLE UNSIGNED ZEROFILL", // local type name -308, // minimum scale 308, // maximum scale 0, // sql data type (unused) 0, // sql datetime sub (unused) 10 // num prec radix }, /* * MySQL Type: REAL (does not map to Types.REAL) JDBC Type: DOUBLE */ // ----------- MySQL-Type: REAL DBC-Type: DOUBLE ---------- { "REAL", // Typename sql::DataType::DOUBLE, // dbc-type 17, // Precision "", // Literal prefix "", // Literal suffix "[(M,D)] [ZEROFILL] [UNSIGNED]", // Create params DatabaseMetaData::typeNullable, // nullable false, // case sensitive DatabaseMetaData::typeSearchable, // searchable false, // unsigned_attribute false, // fixed_prec_scale true, // auto_increment "REAL", // local type name -308, // minimum scale 308, // maximum scale 0, // sql data type (unused) 0, // sql datetime sub (unused) 10 // num prec radix }, { "REAL UNSIGNED", // Typename sql::DataType::DOUBLE, // dbc-type 17, // Precision "", // Literal prefix "", // Literal suffix "[(M,D)] [ZEROFILL]", // Create params DatabaseMetaData::typeNullable, // nullable false, // case sensitive DatabaseMetaData::typeSearchable, // searchable true, // unsigned_attribute false, // fixed_prec_scale true, // auto_increment "REAL UNSIGNED", // local type name -308, // minimum scale 308, // maximum scale 0, // sql data type (unused) 0, // sql datetime sub (unused) 10 // num prec radix }, // ----------- MySQL-Type: VARCHAR DBC-Type: VARCHAR ---------- { "VARCHAR", // Typename sql::DataType::VARCHAR, // dbc-type 255, // Precision "'", // Literal prefix "'", // Literal suffix "(M)", // Create params DatabaseMetaData::typeNullable, // nullable false, // case sensitive DatabaseMetaData::typeSearchable, // searchable false, // unsigned_attribute false, // fixed_prec_scale false, // auto_increment "VARCHAR", // local type name 0, // minimum scale 0, // maximum scale 0, // sql data type (unused) 0, // sql datetime sub (unused) 10 // num prec radix }, // ----------- MySQL-Type: ENUM DBC-Type: VARCHAR ---------- { "ENUM", // Typename sql::DataType::ENUM, // dbc-type 0xFFFF, // Precision "'", // Literal prefix "'", // Literal suffix "", // Create params DatabaseMetaData::typeNullable, // nullable false, // case sensitive DatabaseMetaData::typeSearchable, // searchable false, // unsigned_attribute false, // fixed_prec_scale false, // auto_increment "ENUM", // local type name 0, // minimum scale 0, // maximum scale 0, // sql data type (unused) 0, // sql datetime sub (unused) 10 // num prec radix }, // ----------- MySQL-Type: SET DBC-Type: VARCHAR ---------- { "SET", // Typename sql::DataType::SET, // dbc-type 64, // Precision "'", // Literal prefix "'", // Literal suffix "", // Create params DatabaseMetaData::typeNullable, // nullable false, // case sensitive DatabaseMetaData::typeSearchable, // searchable false, // unsigned_attribute false, // fixed_prec_scale false, // auto_increment "SET", // local type name 0, // minimum scale 0, // maximum scale 0, // sql data type (unused) 0, // sql datetime sub (unused) 10 // num prec radix }, // ----------- MySQL-Type: DATE DBC-Type: DATE ---------- { "DATE", // Typename sql::DataType::DATE, // dbc-type 0, // Precision "'", // Literal prefix "'", // Literal suffix "", // Create params DatabaseMetaData::typeNullable, // nullable false, // case sensitive DatabaseMetaData::typeSearchable, // searchable false, // unsigned_attribute false, // fixed_prec_scale false, // auto_increment "DATE", // local type name 0, // minimum scale 0, // maximum scale 0, // sql data type (unused) 0, // sql datetime sub (unused) 10 // num prec radix }, // ----------- MySQL-Type: TIME DBC-Type: TIME ---------- { "TIME", // Typename sql::DataType::TIME, // dbc-type 0, // Precision "", // Literal prefix "", // Literal suffix "", // Create params DatabaseMetaData::typeNullable, // nullable false, // case sensitive DatabaseMetaData::typeSearchable, // searchable false, // unsigned_attribute false, // fixed_prec_scale false, // auto_increment "TIME", // local type name 0, // minimum scale 0, // maximum scale 0, // sql data type (unused) 0, // sql datetime sub (unused) 10 // num prec radix }, // ----------- MySQL-Type: DATETIME DBC-Type: TIMESTAMP ---------- { "DATETIME", // Typename sql::DataType::TIMESTAMP, // dbc-type 0, // Precision "", // Literal prefix "", // Literal suffix "", // Create params DatabaseMetaData::typeNullable, // nullable false, // case sensitive DatabaseMetaData::typeSearchable, // searchable false, // unsigned_attribute false, // fixed_prec_scale false, // auto_increment "DATETIME", // local type name 0, // minimum scale 0, // maximum scale 0, // sql data type (unused) 0, // sql datetime sub (unused) 10 // num prec radix }, // ----------- MySQL-Type: TIMESTAMP DBC-Type: TIMESTAMP ---------- { "TIMESTAMP", // Typename sql::DataType::TIMESTAMP, // dbc-type 0, // Precision "'", // Literal prefix "'", // Literal suffix "[(M)]", // Create params DatabaseMetaData::typeNullable, // nullable false, // case sensitive DatabaseMetaData::typeSearchable, // searchable false, // unsigned_attribute false, // fixed_prec_scale false, // auto_increment "TIMESTAMP", // local type name 0, // minimum scale 0, // maximum scale 0, // sql data type (unused) 0, // sql datetime sub (unused) 10 // num prec radix }, // ----------- MySQL-Type: DATE DBC-Type: DATE ---------- { "YEAR", // Typename sql::DataType::YEAR, // dbc-type 0, // Precision "'", // Literal prefix "'", // Literal suffix "", // Create params DatabaseMetaData::typeNullable, // nullable false, // case sensitive DatabaseMetaData::typeSearchable, // searchable false, // unsigned_attribute false, // fixed_prec_scale false, // auto_increment "YEAR", // local type name 0, // minimum scale 0, // maximum scale 0, // sql data type (unused) 0, // sql datetime sub (unused) 10 // num prec radix }, // ----------- MySQL-Type: TIMESTAMP DBC-Type: TIMESTAMP ---------- { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }; /* {{{ my_i_to_a() -I- */ static inline const char * my_i_to_a(char * buf, size_t buf_size, int a) { snprintf(buf, buf_size, "%d", a); return buf; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::MySQL_ConnectionMetaData() -I- */ MySQL_ConnectionMetaData::MySQL_ConnectionMetaData( sql::Statement *const service, std::shared_ptr<NativeAPI::NativeConnectionWrapper> _proxy, std::shared_ptr<MySQL_DebugLogger> &l) : stmt(service), connection(dynamic_cast<MySQL_Connection *>(service->getConnection())), logger(l), proxy(_proxy) { CPP_ENTER("MySQL_ConnectionMetaData::MySQL_ConnectionMetaData"); server_version = proxy->get_server_version(); } /* }}} */ /* {{{ MySQL_ConnectionMetaData::~MySQL_ConnectionMetaData() -I- */ MySQL_ConnectionMetaData::~MySQL_ConnectionMetaData() { CPP_ENTER("MySQL_ConnectionMetaData::~MySQL_ConnectionMetaData"); CPP_INFO_FMT("this=%p", this); } /* }}} */ /* {{{ MySQL_ConnectionMetaData::getSchemata() -I- */ sql::ResultSet * MySQL_ConnectionMetaData::getSchemata(const sql::SQLString& /*catalogName*/) { CPP_ENTER("MySQL_ConnectionMetaData::getSchemata"); return stmt->executeQuery("SHOW DATABASES"); } /* }}} */ /* {{{ MySQL_ConnectionMetaData::getSchemaObjects() -I- */ sql::ResultSet * MySQL_ConnectionMetaData::getSchemaObjects(const sql::SQLString& /* catalogName */, const sql::SQLString& schemaName, const sql::SQLString& objectType, bool includingDdl, const sql::SQLString& objectName, const sql::SQLString& contextTableName) { CPP_ENTER("MySQL_ConnectionMetaData::getSchemaObjects"); // for now catalog name is ignored sql::SQLString query; sql::SQLString escapedSchemaName = connection->escapeString(schemaName); sql::SQLString escapedObjectName = connection->escapeString(objectName); sql::SQLString escapedContextTableName = connection->escapeString(contextTableName); sql::SQLString schemata_where_clause; sql::SQLString tables_where_clause; sql::SQLString views_where_clause; sql::SQLString routines_where_clause; sql::SQLString triggers_where_clause; const sql::SQLString schemata_select_items("'schema' AS 'OBJECT_TYPE', CATALOG_NAME as 'CATALOG', SCHEMA_NAME as 'SCHEMA', SCHEMA_NAME as 'NAME'"); const sql::SQLString tables_select_items("'table' AS 'OBJECT_TYPE', TABLE_CATALOG as 'CATALOG', TABLE_SCHEMA as 'SCHEMA', TABLE_NAME as 'NAME'"); const sql::SQLString views_select_items("'view' AS 'OBJECT_TYPE', TABLE_CATALOG as 'CATALOG', TABLE_SCHEMA as 'SCHEMA', TABLE_NAME as 'NAME'"); const sql::SQLString routines_select_items("ROUTINE_TYPE AS 'OBJECT_TYPE', ROUTINE_CATALOG as 'CATALOG', ROUTINE_SCHEMA as 'SCHEMA', ROUTINE_NAME as 'NAME'"); const sql::SQLString triggers_select_items("'trigger' AS 'OBJECT_TYPE', TRIGGER_CATALOG as 'CATALOG', TRIGGER_SCHEMA as 'SCHEMA', TRIGGER_NAME as 'NAME'"); const sql::SQLString schema_ddl_column("Create Database"); const sql::SQLString table_ddl_column("Create Table"); const sql::SQLString view_ddl_column("Create View"); const sql::SQLString procedure_ddl_column("Create Procedure"); const sql::SQLString function_ddl_column("Create Function"); const sql::SQLString trigger_ddl_column("SQL Original Statement"); if (escapedSchemaName.length() > 0) { schemata_where_clause.append(" WHERE schema_name = '").append(escapedSchemaName).append("' "); tables_where_clause.append(" WHERE table_type<>'VIEW' AND table_schema = '").append(escapedSchemaName).append("' "); views_where_clause.append(" WHERE table_schema = '").append(escapedSchemaName).append("' "); routines_where_clause.append(" WHERE routine_schema = '").append(escapedSchemaName).append("' "); triggers_where_clause.append(" WHERE trigger_schema = '").append(escapedSchemaName).append("' "); } if (escapedObjectName.length() > 0) { std::string predicate_mediator= (escapedSchemaName.length() > 0) ? " AND " : " WHERE "; predicate_mediator += "'" + escapedObjectName + "'="; schemata_where_clause += predicate_mediator + "SCHEMA_NAME"; tables_where_clause += predicate_mediator + "TABLE_NAME"; views_where_clause += predicate_mediator + "TABLE_NAME"; routines_where_clause += predicate_mediator + "ROUTINE_NAME"; triggers_where_clause += predicate_mediator + "TRIGGER_NAME"; } if (escapedContextTableName.length() > 0) { std::string predicate_mediator= ((escapedSchemaName.length() > 0) || (escapedObjectName.length() > 0)) ? " AND " : " WHERE "; predicate_mediator += "'" + escapedContextTableName + "'="; triggers_where_clause += predicate_mediator + "EVENT_OBJECT_TABLE"; } if (objectType.length() == 0) { query.append("SELECT ").append(tables_select_items) .append(" FROM information_schema.tables ").append(tables_where_clause) .append("UNION SELECT ").append(views_select_items) .append(" FROM information_schema.views ").append(views_where_clause) .append("UNION SELECT ").append(routines_select_items) .append(" FROM information_schema.routines ").append(routines_where_clause) .append("UNION SELECT ").append(triggers_select_items) .append(" FROM information_schema.triggers ").append(triggers_where_clause) ; } else { if (objectType.compare("schema") == 0) { query.append("SELECT ") .append(schemata_select_items) .append(" FROM information_schema.schemata") .append(schemata_where_clause); } else if (objectType.compare("table") == 0) { query.append("SELECT ") .append(tables_select_items) .append(" FROM information_schema.tables") .append(tables_where_clause); } else if (objectType.compare("view") == 0) { query.append("SELECT ") .append(views_select_items) .append(" FROM information_schema.views") .append(views_where_clause); } else if (objectType.compare("routine") == 0) { query.append("SELECT ") .append(routines_select_items) .append(" FROM information_schema.routines") .append(routines_where_clause); } else if (objectType.compare("trigger") == 0) { query.append("SELECT ") .append(triggers_select_items) .append(" FROM information_schema.triggers") .append(triggers_where_clause); } else { throw sql::InvalidArgumentException("MySQLMetadata::getSchemaObjects: invalid 'objectType'"); } } std::unique_ptr<sql::ResultSet> native_rs(stmt->executeQuery(query)); int objtype_field_index = native_rs->findColumn("OBJECT_TYPE"); int catalog_field_index = native_rs->findColumn("CATALOG"); int schema_field_index = native_rs->findColumn("SCHEMA"); int name_field_index = native_rs->findColumn("NAME"); std::map< sql::SQLString, sql::SQLString > trigger_name_map; std::map< sql::SQLString, sql::SQLString > trigger_ddl_map; // if we fetch triggers, then build DDL for them if ((objectType.compare("trigger") == 0) || !objectType.length()) { sql::SQLString trigger_ddl_query("SELECT "); trigger_ddl_query .append(triggers_select_items) .append(", EVENT_MANIPULATION, EVENT_OBJECT_SCHEMA, EVENT_OBJECT_TABLE, ACTION_ORDER, " " ACTION_CONDITION, ACTION_STATEMENT, ACTION_ORIENTATION, ACTION_TIMING, DEFINER" " FROM information_schema.triggers ") .append(triggers_where_clause); std::unique_ptr<sql::ResultSet> trigger_ddl_rs( stmt->executeQuery(trigger_ddl_query)); // trigger specific fields: exclusion from the rule - 'show create trigger' is not supported by versions below 5.1.21 // reproducing ddl based on metadata int event_manipulation_index = trigger_ddl_rs->findColumn("EVENT_MANIPULATION"); int event_object_schema_index = trigger_ddl_rs->findColumn("EVENT_OBJECT_SCHEMA"); int event_object_table_index = trigger_ddl_rs->findColumn("EVENT_OBJECT_TABLE"); int action_statement_index = trigger_ddl_rs->findColumn("ACTION_STATEMENT"); int action_timing_index = trigger_ddl_rs->findColumn("ACTION_TIMING"); int definer_index = trigger_ddl_rs->findColumn("DEFINER"); while (trigger_ddl_rs->next()) { sql::SQLString trigger_ddl; // quote definer, which is stored as unquoted string std::string quoted_definer; { quoted_definer = trigger_ddl_rs->getString(definer_index); const char * quot_sym = "`\0"; size_t i = quoted_definer.find('@'); if (std::string::npos != i) { quoted_definer.reserve(quoted_definer.length()+4); quoted_definer.insert(i+1, quot_sym); quoted_definer.insert(i, quot_sym); } quoted_definer.insert(0, quot_sym); quoted_definer.push_back(quot_sym[0]); } sql::SQLString key; key.append("`").append(trigger_ddl_rs->getString("SCHEMA")) .append("`.`").append(trigger_ddl_rs->getString("NAME")).append("`"); { trigger_ddl .append("CREATE\nDEFINER=").append(quoted_definer) .append("\nTRIGGER ").append("`") .append(trigger_ddl_rs->getString("SCHEMA")).append("`.`").append(trigger_ddl_rs->getString("NAME")).append("`") .append("\n").append(trigger_ddl_rs->getString(action_timing_index)) .append(" ").append(trigger_ddl_rs->getString(event_manipulation_index)) .append(" ON `").append(trigger_ddl_rs->getString(event_object_schema_index)) .append("`.`").append(trigger_ddl_rs->getString(event_object_table_index)).append("`") .append("\nFOR EACH ROW\n") .append(trigger_ddl_rs->getString(action_statement_index)) .append("\n"); trigger_ddl_map[key] = trigger_ddl; } { sql::SQLString trigger_name; trigger_name .append(trigger_ddl_rs->getString(event_object_table_index)) .append(".") .append(trigger_ddl_rs->getString("NAME")); trigger_name_map[key] = trigger_name; } } } std::list< sql::SQLString > rs_field_data; rs_field_data.push_back("OBJECT_TYPE"); rs_field_data.push_back("CATALOG"); rs_field_data.push_back("SCHEMA"); rs_field_data.push_back("NAME"); rs_field_data.push_back("DDL"); std::shared_ptr<MySQL_ArtResultSet::rset_t> rs_data( new MySQL_ArtResultSet::rset_t()); while (native_rs->next()) { MySQL_ArtResultSet::row_t rs_data_row; sql::SQLString obj_type(native_rs->getString(objtype_field_index)); sql::SQLString schema(native_rs->getString(schema_field_index)); sql::SQLString name(native_rs->getString(name_field_index)); if ((obj_type.compare("PROCEDURE") == 0) || (obj_type.compare("FUNCTION") == 0)) { rs_data_row.push_back("routine"); } else { rs_data_row.push_back(obj_type); } rs_data_row.push_back(native_rs->getString(catalog_field_index)); rs_data_row.push_back(schema); if (obj_type.compare("trigger") == 0) { sql::SQLString key; key.append("`").append(schema).append("`.`").append(name).append("`"); rs_data_row.push_back(trigger_name_map[key]); } else { rs_data_row.push_back(name); } sql::SQLString ddl_query; sql::SQLString ddl_column; if (obj_type.compare("schema") == 0) { ddl_column = schema_ddl_column; ddl_query.append("SHOW CREATE SCHEMA `").append(name).append("`"); } else if (obj_type.compare("table") == 0) { ddl_column = table_ddl_column; ddl_query.append("SHOW CREATE TABLE `") .append(schema).append("`.`") .append(name).append("`"); } else if (obj_type.compare("view") == 0) { ddl_column = view_ddl_column; ddl_query.append("SHOW CREATE VIEW `") .append(schema).append("`.`") .append(name).append("`"); } else if (obj_type.compare("PROCEDURE") == 0) { ddl_column = procedure_ddl_column; ddl_query.append("SHOW CREATE PROCEDURE `") .append(schema).append("`.`") .append(name).append("`"); } else if (obj_type.compare("FUNCTION") == 0) { ddl_column = function_ddl_column; ddl_query.append("SHOW CREATE FUNCTION `") .append(schema).append("`.`") .append(name).append("`"); } else if (obj_type.compare("trigger") == 0) { /* ddl_column= trigger_ddl_column; ddl_query.append("SHOW CREATE TRIGGER `") .append(schema).append("`.`") .append(name).append("`"); */ } else { throw sql::InvalidArgumentException("MySQL_DatabaseMetaData::getSchemaObjects: invalid OBJECT_TYPE returned from query"); } if (includingDdl) { // due to bugs in server code some queries can fail. // here we want to gather as much info as possible try { sql::SQLString ddl; if (obj_type.compare("trigger") == 0) { //ddl // .append("CREATE\nDEFINER=").append(trigger_ddl_rs->getString(definer_index)) // .append("\nTRIGGER ").append("`") // .append(schema).append("`.`").append(name).append("`") // .append("\n").append(trigger_ddl_rs->getString(action_timing_index)) // .append(" ").append(trigger_ddl_rs->getString(event_manipulation_index)) // .append(" ON `").append(trigger_ddl_rs->getString(event_object_schema_index)) // .append("`.`").append(trigger_ddl_rs->getString(event_object_table_index)).append("`") // .append("\nFOR EACH ROW\n") // .append(trigger_ddl_rs->getString(action_statement_index)) // .append("\n"); sql::SQLString key; key.append("`").append(schema).append("`.`").append(name).append("`"); std::map< sql::SQLString, sql::SQLString >::const_iterator it = trigger_ddl_map.find(key); if (it != trigger_ddl_map.end()) { ddl.append(it->second); } } else { std::unique_ptr<sql::ResultSet> sql_rs(stmt->executeQuery(ddl_query)); sql_rs->next(); // this is a hack for views listed as tables int colIdx = sql_rs->findColumn(ddl_column); if ((colIdx == 0) && (obj_type.compare("table") == 0)) colIdx = sql_rs->findColumn(view_ddl_column); ddl = sql_rs->getString(colIdx); } rs_data_row.push_back(ddl); } catch (SQLException&) { rs_data_row.push_back(""); } } else { rs_data_row.push_back(""); } rs_data->push_back(rs_data_row); } MySQL_ArtResultSet * ret = new MySQL_ArtResultSet(rs_field_data, rs_data, logger); return ret; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::getSchemaObjectTypes() -I- */ sql::ResultSet * MySQL_ConnectionMetaData::getSchemaObjectTypes() { CPP_ENTER("MySQL_ConnectionMetaData::getSchemaObjectTypes"); std::shared_ptr<MySQL_ArtResultSet::rset_t> rs_data( new MySQL_ArtResultSet::rset_t()); std::list<sql::SQLString> rs_field_data; rs_field_data.push_back("OBJECT_TYPE"); { MySQL_ArtResultSet::row_t rs_data_row; rs_data_row.push_back("table"); rs_data->push_back(rs_data_row); } { MySQL_ArtResultSet::row_t rs_data_row; rs_data_row.push_back("view"); rs_data->push_back(rs_data_row); } { MySQL_ArtResultSet::row_t rs_data_row; rs_data_row.push_back("routine"); rs_data->push_back(rs_data_row); } { MySQL_ArtResultSet::row_t rs_data_row; rs_data_row.push_back("trigger"); rs_data->push_back(rs_data_row); } MySQL_ArtResultSet * ret = new MySQL_ArtResultSet(rs_field_data, rs_data, logger); return ret; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::allProceduresAreCallable() -I- */ bool MySQL_ConnectionMetaData::allProceduresAreCallable() { CPP_ENTER("MySQL_ConnectionMetaData::allProceduresAreCallable"); return false; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::allTablesAreSelectable() -I- */ bool MySQL_ConnectionMetaData::allTablesAreSelectable() { CPP_ENTER("MySQL_ConnectionMetaData::allTablesAreSelectable"); return false; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::dataDefinitionCausesTransactionCommit() -I- */ bool MySQL_ConnectionMetaData::dataDefinitionCausesTransactionCommit() { CPP_ENTER("MySQL_ConnectionMetaData::dataDefinitionCausesTransactionCommit"); return true; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::dataDefinitionIgnoredInTransactions() -I- */ bool MySQL_ConnectionMetaData::dataDefinitionIgnoredInTransactions() { CPP_ENTER("MySQL_ConnectionMetaData::dataDefinitionIgnoredInTransactions"); return false; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::deletesAreDetected() -I- */ bool MySQL_ConnectionMetaData::deletesAreDetected(int /*type*/) { CPP_ENTER("MySQL_ConnectionMetaData::deletesAreDetected"); return false; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::doesMaxRowSizeIncludeBlobs() -I- */ bool MySQL_ConnectionMetaData::doesMaxRowSizeIncludeBlobs() { CPP_ENTER("MySQL_ConnectionMetaData::doesMaxRowSizeIncludeBlobs"); return true; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::getAttributes() -I- */ sql::ResultSet * MySQL_ConnectionMetaData::getAttributes(const sql::SQLString& /*catalog*/, const sql::SQLString& /*schemaPattern*/, const sql::SQLString& /*typeNamePattern*/, const sql::SQLString& /*attributeNamePattern*/) { CPP_ENTER("MySQL_ConnectionMetaData::getAttributes"); std::shared_ptr<MySQL_ArtResultSet::rset_t> rs_data( new MySQL_ArtResultSet::rset_t()); std::list<sql::SQLString> rs_field_data; rs_field_data.push_back("TYPE_CAT"); rs_field_data.push_back("TYPE_SCHEM"); rs_field_data.push_back("TYPE_NAME"); rs_field_data.push_back("ATTR_NAME"); rs_field_data.push_back("DATA_TYPE"); rs_field_data.push_back("ATTR_TYPE_NAME"); rs_field_data.push_back("ATTR_SIZE"); rs_field_data.push_back("DECIMAL_DIGITS"); rs_field_data.push_back("NUM_PREC_RADIX"); rs_field_data.push_back("NULLABLE"); rs_field_data.push_back("REMARKS"); rs_field_data.push_back("ATTR_DEF"); rs_field_data.push_back("SQL_DATA_TYPE"); rs_field_data.push_back("SQL_DATETIME_SUB"); rs_field_data.push_back("CHAR_OCTET_LENGTH"); rs_field_data.push_back("ORDINAL_POSITION"); rs_field_data.push_back("IS_NULLABLE"); rs_field_data.push_back("SCOPE_CATALOG"); rs_field_data.push_back("SCOPE_SCHEMA"); rs_field_data.push_back("SCOPE_TABLE"); rs_field_data.push_back("SOURCE_DATA_TYPE"); MySQL_ArtResultSet * ret = new MySQL_ArtResultSet(rs_field_data, rs_data, logger); return ret; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::getBestRowIdentifier() -I- */ sql::ResultSet * MySQL_ConnectionMetaData::getBestRowIdentifier(const sql::SQLString& catalog, const sql::SQLString& schema, const sql::SQLString& table, int /* scope */, bool /* nullable */) { CPP_ENTER("MySQL_ConnectionMetaData::getBestRowIdentifier"); std::shared_ptr<MySQL_ArtResultSet::rset_t> rs_data( new MySQL_ArtResultSet::rset_t()); std::list<sql::SQLString> rs_field_data; rs_field_data.push_back("SCOPE"); rs_field_data.push_back("COLUMN_NAME"); rs_field_data.push_back("DATA_TYPE"); rs_field_data.push_back("TYPE_NAME"); rs_field_data.push_back("COLUMN_SIZE"); rs_field_data.push_back("BUFFER_LENGTH"); rs_field_data.push_back("DECIMAL_DIGITS"); rs_field_data.push_back("PSEUDO_COLUMN"); std::unique_ptr<sql::ResultSet> rs(getPrimaryKeys(catalog, schema, table)); if (!rs->rowsCount()) rs.reset(getUniqueNonNullableKeys(catalog, schema, table)); while (rs->next()) { sql::SQLString columnNamePattern(rs->getString(4)); std::unique_ptr<sql::ResultSet> rsCols( getColumns(catalog, schema, table, columnNamePattern)); if (rsCols->next()) { MySQL_ArtResultSet::row_t rs_data_row; rs_data_row.push_back((int64_t) DatabaseMetaData::bestRowSession); // SCOPE rs_data_row.push_back(rs->getString(4)); // COLUMN_NAME rs_data_row.push_back(rsCols->getString(5)); // DATA_TYPE rs_data_row.push_back(rsCols->getString(6)); // TYPE_NAME rs_data_row.push_back(rsCols->getString(7)); // COLUMN_SIZE rs_data_row.push_back(rsCols->getString(8)); // BUFFER_LENGTH rs_data_row.push_back(rsCols->getString(9)); // DECIMAL_DIGITS rs_data_row.push_back((int64_t) DatabaseMetaData::bestRowNotPseudo); // PSEUDO_COLUMN rs_data->push_back(rs_data_row); } } MySQL_ArtResultSet * ret = new MySQL_ArtResultSet(rs_field_data, rs_data, logger); return ret; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::getCatalogs() -I- */ sql::ResultSet * MySQL_ConnectionMetaData::getCatalogs() { std::shared_ptr<MySQL_ArtResultSet::rset_t> rs_data( new MySQL_ArtResultSet::rset_t()); std::list<sql::SQLString> rs_field_data; rs_field_data.push_back("TABLE_CAT"); { MySQL_ArtResultSet::row_t rs_data_row; rs_data_row.push_back("def"); rs_data->push_back(rs_data_row); } MySQL_ArtResultSet * ret = new MySQL_ArtResultSet(rs_field_data, rs_data, logger); return ret; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::getCatalogSeparator() -I- */ const sql::SQLString& MySQL_ConnectionMetaData::getCatalogSeparator() { CPP_ENTER("MySQL_ConnectionMetaData::getCatalogSeparator"); static const sql::SQLString separator(""); return separator; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::getCatalogTerm() -I- */ const sql::SQLString& MySQL_ConnectionMetaData::getCatalogTerm() { CPP_ENTER("MySQL_ConnectionMetaData::getCatalogTerm"); static const sql::SQLString term("n/a"); return term; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::getColumnPrivileges() -I- */ sql::ResultSet * MySQL_ConnectionMetaData::getColumnPrivileges(const sql::SQLString& /*catalog*/, const sql::SQLString& schema, const sql::SQLString& table, const sql::SQLString& columnNamePattern) { CPP_ENTER("MySQL_ConnectionMetaData::getColumnPrivileges"); sql::SQLString escapedSchema = connection->escapeString(schema); sql::SQLString escapedTableName = connection->escapeString(table); sql::SQLString escapedColumnNamePattern = connection->escapeString(columnNamePattern); std::list<sql::SQLString> rs_field_data; rs_field_data.push_back("TABLE_CAT"); rs_field_data.push_back("TABLE_SCHEM"); rs_field_data.push_back("TABLE_NAME"); rs_field_data.push_back("COLUMN_NAME"); rs_field_data.push_back("GRANTOR"); rs_field_data.push_back("GRANTEE"); rs_field_data.push_back("PRIVILEGE"); rs_field_data.push_back("IS_GRANTABLE"); std::shared_ptr<MySQL_ArtResultSet::rset_t> rs_data( new MySQL_ArtResultSet::rset_t()); /* I_S seems currently (20080220) not to work */ #if A0 if (server_version > 69999) { sql::SQLString query("SELECT TABLE_CATALOG AS TABLE_CAT, TABLE_SCHEMA AS TABLE_SCHEM, TABLE_NAME," "COLUMN_NAME, NULL AS GRANTOR, GRANTEE, PRIVILEGE_TYPE AS PRIVILEGE, IS_GRANTABLE\n" "FROM INFORMATION_SCHEMA.COLUMN_PRIVILEGES\n" "WHERE TABLE_SCHEMA LIKE ? AND TABLE_NAME=? AND COLUMN_NAME LIKE ?\n" "ORDER BY COLUMN_NAME, PRIVILEGE_TYPE"); std::unique_ptr<sql::PreparedStatement> pStmt( connection->prepareStatement(query)); pStmt->setString(1, escapedSchema); pStmt->setString(2, escapedTableName); pStmt->setString(3, escapedColumnNamePattern); std::unique_ptr<sql::ResultSet> rs(pStmt->executeQuery()); while (rs->next()) { MySQL_ArtResultSet::row_t rs_data_row; rs_data_row.push_back(rs->getString(1)); // TABLE_CAT rs_data_row.push_back(rs->getString(2)); // TABLE_SCHEM rs_data_row.push_back(rs->getString(3)); // TABLE_NAME rs_data_row.push_back(rs->getString(4)); // COLUMN_NAME rs_data_row.push_back(rs->getString(5)); // KEY_SEQ rs_data_row.push_back(rs->getString(6)); // PK_NAME rs_data->push_back(rs_data_row); } } else #endif { size_t idx; sql::SQLString query("SHOW FULL COLUMNS FROM `"); query.append(schema).append("`.`").append(table).append("` LIKE '").append(escapedColumnNamePattern).append("'"); std::unique_ptr<sql::ResultSet> res; try { res.reset(stmt->executeQuery(query)); } catch (SQLException&) { // schema and/or table doesn't exist. return empty set // do nothing here } while (res.get() && res->next()) { size_t pos = 0; sql::SQLString privs = res->getString(8); do { MySQL_ArtResultSet::row_t rs_data_row; sql::SQLString privToken; while (privs[pos] == ' ') ++pos; // Eat the whitespace idx = privs.find(",", pos); if (idx != sql::SQLString::npos) { privToken = privs.substr(pos, idx - pos); pos = idx + 1; /* skip ',' */ } else { privToken = privs.substr(pos, privs.length() - pos); } rs_data_row.push_back("def"); // TABLE_CAT rs_data_row.push_back(schema); // TABLE_SCHEM rs_data_row.push_back(table); // TABLE_NAME rs_data_row.push_back(res->getString(1)); // COLUMN_NAME rs_data_row.push_back(""); // GRANTOR rs_data_row.push_back(getUserName()); // GRANTEE rs_data_row.push_back(privToken); // PRIVILEGE rs_data_row.push_back(""); // IS_GRANTABLE rs_data->push_back(rs_data_row); } while (idx != sql::SQLString::npos); } } MySQL_ArtResultSet * ret = new MySQL_ArtResultSet(rs_field_data, rs_data, logger); return ret; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::getColumns() -I- */ sql::ResultSet * MySQL_ConnectionMetaData::getColumns(const sql::SQLString& /*catalog*/, const sql::SQLString& schemaPattern, const sql::SQLString& tableNamePattern, const sql::SQLString& columnNamePattern) { CPP_ENTER("MySQL_ConnectionMetaData::getColumns"); sql::SQLString escapedSchemaPattern = connection->escapeString(schemaPattern); sql::SQLString escapedTableNamePattern = connection->escapeString(tableNamePattern); sql::SQLString escapedColumnNamePattern = connection->escapeString(columnNamePattern); std::shared_ptr<MySQL_ArtResultSet::rset_t> rs_data( new MySQL_ArtResultSet::rset_t()); std::list<sql::SQLString> rs_field_data; rs_field_data.push_back("TABLE_CAT"); rs_field_data.push_back("TABLE_SCHEM"); rs_field_data.push_back("TABLE_NAME"); rs_field_data.push_back("COLUMN_NAME"); rs_field_data.push_back("DATA_TYPE"); rs_field_data.push_back("TYPE_NAME"); rs_field_data.push_back("COLUMN_SIZE"); rs_field_data.push_back("BUFFER_LENGTH"); rs_field_data.push_back("DECIMAL_DIGITS"); rs_field_data.push_back("NUM_PREC_RADIX"); rs_field_data.push_back("NULLABLE"); rs_field_data.push_back("REMARKS"); rs_field_data.push_back("COLUMN_DEF"); rs_field_data.push_back("SQL_DATA_TYPE"); rs_field_data.push_back("SQL_DATETIME_SUB"); rs_field_data.push_back("CHAR_OCTET_LENGTH"); rs_field_data.push_back("ORDINAL_POSITION"); rs_field_data.push_back("IS_NULLABLE"); /* The following are not known by SDBC */ rs_field_data.push_back("SCOPE_CATALOG"); rs_field_data.push_back("SCOPE_SCHEMA"); rs_field_data.push_back("SCOPE_TABLE"); rs_field_data.push_back("SOURCE_DATA_TYPE"); rs_field_data.push_back("IS_AUTOINCREMENT"); char buf[5]; sql::SQLString query("SELECT TABLE_CATALOG AS TABLE_CAT, TABLE_SCHEMA AS TABLE_SCHEM, TABLE_NAME, COLUMN_NAME, DATA_TYPE," "CASE " "WHEN LOCATE('unsigned', COLUMN_TYPE) != 0 AND LOCATE('unsigned', DATA_TYPE) = 0 THEN " " CASE" " WHEN LOCATE('zerofill', COLUMN_TYPE) != 0 AND LOCATE('zerofill', DATA_TYPE) = 0 THEN CONCAT(UCASE(DATA_TYPE), ' UNSIGNED ZEROFILL')" " ELSE CONCAT(UCASE(DATA_TYPE), ' UNSIGNED')" " END " // "ELSE" // " CASE" // " WHEN LCASE(DATA_TYPE)='set' THEN 'VARCHAR'" // " WHEN LCASE(DATA_TYPE)='enum' THEN 'VARCHAR'" // " WHEN LCASE(DATA_TYPE)='year' THEN 'YEAR'" " ELSE UCASE(DATA_TYPE)" // " END " "END AS TYPE_NAME," "CASE " "WHEN LCASE(DATA_TYPE)='year' THEN SUBSTRING(COLUMN_TYPE, 6, 1) -- 'year('=5\n" "WHEN LCASE(DATA_TYPE)='date' THEN 10 " "WHEN LCASE(DATA_TYPE)='time' THEN 8 " "WHEN LCASE(DATA_TYPE)='datetime' THEN 19 " "WHEN LCASE(DATA_TYPE)='timestamp' THEN 19 " "WHEN CHARACTER_MAXIMUM_LENGTH IS NULL THEN NUMERIC_PRECISION " "ELSE CHARACTER_MAXIMUM_LENGTH END AS COLUMN_SIZE, " "'' AS BUFFER_LENGTH," "NUMERIC_SCALE AS DECIMAL_DIGITS," "10 AS NUM_PREC_RADIX," "CASE WHEN IS_NULLABLE='NO' THEN "); query.append(my_i_to_a(buf, sizeof(buf) - 1, columnNoNulls)); query.append(" ELSE CASE WHEN IS_NULLABLE='YES' THEN "); query.append(my_i_to_a(buf, sizeof(buf) - 1, columnNullable)); query.append(" ELSE "); query.append(my_i_to_a(buf, sizeof(buf) - 1, columnNullableUnknown)); query.append(" END END AS NULLABLE," "COLUMN_COMMENT AS REMARKS," "COLUMN_DEFAULT AS COLUMN_DEF," "0 AS SQL_DATA_TYPE," "0 AS SQL_DATETIME_SUB," "CHARACTER_OCTET_LENGTH," "ORDINAL_POSITION," "IS_NULLABLE," "NULL AS SCOPE_CATALOG," "NULL AS SCOPE_SCHEMA," "NULL AS SCOPE_TABLE," "NULL AS SOURCE_DATA_TYPE," "IF (EXTRA LIKE '%auto_increment%','YES','NO') AS IS_AUTOINCREMENT " "FROM INFORMATION_SCHEMA.COLUMNS WHERE "); if (schemaPattern.length()) { query.append(" TABLE_SCHEMA LIKE ? "); } else { query.append(" TABLE_SCHEMA = DATABASE() "); } query.append("AND TABLE_NAME LIKE ? AND COLUMN_NAME LIKE ? " "ORDER BY TABLE_SCHEMA, TABLE_NAME, ORDINAL_POSITION"); std::unique_ptr<sql::PreparedStatement> pStmt( connection->prepareStatement(query)); if (schemaPattern.length()) { pStmt->setString(1, escapedSchemaPattern); pStmt->setString(2, escapedTableNamePattern); pStmt->setString(3, escapedColumnNamePattern); } else { pStmt->setString(1, escapedTableNamePattern); pStmt->setString(2, escapedColumnNamePattern); } std::unique_ptr<sql::ResultSet> rs(pStmt->executeQuery()); while (rs->next()) { MySQL_ArtResultSet::row_t rs_data_row; rs_data_row.push_back(rs->getString(1)); // TABLE_CAT rs_data_row.push_back(rs->getString(2)); // TABLE_SCHEM rs_data_row.push_back(rs->getString(3)); // TABLE_NAME rs_data_row.push_back(rs->getString(4)); // COLUMN_NAME rs_data_row.push_back((int64_t) sql::mysql::util::mysql_string_type_to_datatype(rs->getString(5))); // DATA_TYPE rs_data_row.push_back(rs->getString(6)); // TYPE_NAME rs_data_row.push_back(rs->getInt64(7)); // COLUMN_SIZE rs_data_row.push_back(rs->getInt64(8)); // BUFFER_LENGTH rs_data_row.push_back(rs->getInt64(9)); // DECIMAL_DIGITS rs_data_row.push_back(rs->getInt64(10)); // NUM_PREC_RADIX rs_data_row.push_back(rs->getString(11)); // NULLABLE rs_data_row.push_back(rs->getString(12)); // REMARKS rs_data_row.push_back(rs->getString(13)); // COLUMN_DEFAULT rs_data_row.push_back(rs->getString(14)); // SQL_DATA_TYPE rs_data_row.push_back(rs->getString(15)); // SQL_DATETIME_SUB rs_data_row.push_back(rs->getString(16)); // CHAR_OCTET_LENGTH rs_data_row.push_back(rs->getString(17)); // ORDINAL_POSITION rs_data_row.push_back(rs->getString(18)); // IS_NULLABLE /* The following are not currently used by C/OOO*/ rs_data_row.push_back(rs->getString(19)); // SCOPE_CATALOG rs_data_row.push_back(rs->getString(20)); // SCOPE_SCHEMA rs_data_row.push_back(rs->getString(21)); // SCOPE_TABLE rs_data_row.push_back(rs->getString(22)); // SOURCE_DATA_TYPE rs_data_row.push_back(rs->getString(23)); // IS_AUTOINCREMENT rs_data->push_back(rs_data_row); } MySQL_ArtResultSet * ret = new MySQL_ArtResultSet(rs_field_data, rs_data, logger); return ret; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::getConnection() -I- */ Connection * MySQL_ConnectionMetaData::getConnection() { CPP_ENTER("MySQL_ConnectionMetaData::getConnection"); return this->connection; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::getCrossReference() -I- */ sql::ResultSet * MySQL_ConnectionMetaData::getCrossReference(const sql::SQLString& primaryCatalog, const sql::SQLString& primarySchema, const sql::SQLString& primaryTable, const sql::SQLString& foreignCatalog , const sql::SQLString& foreignSchema, const sql::SQLString& foreignTable) { CPP_ENTER("MySQL_ConnectionMetaData::getCrossReference"); CPP_INFO_FMT("p_catalog=%s f_catalog=%s p_schema=%s f_schema=%s p_table=%s f_table=%s", primaryCatalog.c_str(), foreignCatalog.c_str(), primarySchema.c_str(), foreignSchema.c_str(), primaryTable.c_str(), foreignTable.c_str()); std::shared_ptr<MySQL_ArtResultSet::rset_t> rs_data( new MySQL_ArtResultSet::rset_t()); std::list<sql::SQLString> rs_field_data; rs_field_data.push_back("PKTABLE_CAT"); rs_field_data.push_back("PKTABLE_SCHEM"); rs_field_data.push_back("PKTABLE_NAME"); rs_field_data.push_back("PKCOLUMN_NAME"); rs_field_data.push_back("FKTABLE_CAT"); rs_field_data.push_back("FKTABLE_SCHEM"); rs_field_data.push_back("FKTABLE_NAME"); rs_field_data.push_back("FKCOLUMN_NAME"); rs_field_data.push_back("KEY_SEQ"); rs_field_data.push_back("UPDATE_RULE"); rs_field_data.push_back("DELETE_RULE"); rs_field_data.push_back("FK_NAME"); rs_field_data.push_back("PK_NAME"); rs_field_data.push_back("DEFERRABILITY"); /* This just doesn't work */ /* currently this doesn't work - we have to wait for implementation of REFERENTIAL_CONSTRAINTS */ char buf[10]; my_i_to_a(buf, sizeof(buf) - 1, importedKeyCascade); sql::SQLString importedKeyCascadeStr(buf); my_i_to_a(buf, sizeof(buf) - 1, importedKeySetNull); sql::SQLString importedKeySetNullStr(buf); my_i_to_a(buf, sizeof(buf) - 1, importedKeySetDefault); sql::SQLString importedKeySetDefaultStr(buf); my_i_to_a(buf, sizeof(buf) - 1, importedKeyRestrict); sql::SQLString importedKeyRestrictStr(buf); my_i_to_a(buf, sizeof(buf) - 1, importedKeyNoAction); sql::SQLString importedKeyNoActionStr(buf); my_i_to_a(buf, sizeof(buf) - 1, importedKeyNotDeferrable); sql::SQLString importedKeyNotDeferrableStr(buf); sql::SQLString UpdateRuleClause; UpdateRuleClause.append("CASE WHEN R.UPDATE_RULE='CASCADE' THEN ").append(importedKeyCascadeStr). append(" WHEN R.UPDATE_RULE='SET NULL' THEN ").append(importedKeySetNullStr). append(" WHEN R.UPDATE_RULE='SET DEFAULT' THEN ").append(importedKeySetDefaultStr). append(" WHEN R.UPDATE_RULE='RESTRICT' THEN ").append(importedKeyRestrictStr). append(" WHEN R.UPDATE_RULE='NO ACTION' THEN ").append(importedKeyNoActionStr). append(" ELSE ").append(importedKeyNoActionStr).append(" END "); sql::SQLString DeleteRuleClause; DeleteRuleClause.append("CASE WHEN R.DELETE_RULE='CASCADE' THEN ").append(importedKeyCascadeStr). append(" WHEN R.DELETE_RULE='SET NULL' THEN ").append(importedKeySetNullStr). append(" WHEN R.DELETE_RULE='SET DEFAULT' THEN ").append(importedKeySetDefaultStr). append(" WHEN R.DELETE_RULE='RESTRICT' THEN ").append(importedKeyRestrictStr). append(" WHEN R.DELETE_RULE='NO ACTION' THEN ").append(importedKeyNoActionStr). append(" ELSE ").append(importedKeyNoActionStr).append(" END "); sql::SQLString OptionalRefConstraintJoinStr( "JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS R ON " "(R.CONSTRAINT_NAME = B.CONSTRAINT_NAME AND R.TABLE_NAME = B.TABLE_NAME AND R.CONSTRAINT_SCHEMA = B.TABLE_SCHEMA) "); sql::SQLString query("SELECT \n"); query.append("A.TABLE_CATALOG AS PKTABLE_CAT, A.REFERENCED_TABLE_SCHEMA AS PKTABLE_SCHEM, A.REFERENCED_TABLE_NAME AS PKTABLE_NAME," "A.REFERENCED_COLUMN_NAME AS PKCOLUMN_NAME, A.TABLE_CATALOG AS FKTABLE_CAT, A.TABLE_SCHEMA AS FKTABLE_SCHEM," "A.TABLE_NAME AS FKTABLE_NAME, A.COLUMN_NAME AS FKCOLUMN_NAME, A.ORDINAL_POSITION AS KEY_SEQ,"); query.append(UpdateRuleClause); query.append(" AS UPDATE_RULE,"); query.append(DeleteRuleClause); query.append(" AS DELETE_RULE, A.CONSTRAINT_NAME AS FK_NAME," "(SELECT CONSTRAINT_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE TABLE_SCHEMA = REFERENCED_TABLE_SCHEMA AND" " TABLE_NAME = A.REFERENCED_TABLE_NAME AND CONSTRAINT_TYPE IN ('UNIQUE','PRIMARY KEY') LIMIT 1) AS PK_NAME,"); query.append(importedKeyNotDeferrableStr); query.append(" AS DEFERRABILITY FROM\nINFORMATION_SCHEMA.KEY_COLUMN_USAGE A JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS B\n" "ON (A.TABLE_SCHEMA = B.TABLE_SCHEMA AND A.TABLE_NAME = B.TABLE_NAME AND A.CONSTRAINT_NAME = B.CONSTRAINT_NAME AND\n" "B.CONSTRAINT_TYPE = 'FOREIGN KEY' AND A.REFERENCED_TABLE_SCHEMA LIKE ? AND A.REFERENCED_TABLE_NAME=?\n" "AND A.TABLE_SCHEMA LIKE ? AND A.TABLE_NAME=?)\n"); query.append(OptionalRefConstraintJoinStr); query.append("\nORDER BY A.TABLE_SCHEMA, A.TABLE_NAME, A.ORDINAL_POSITION"); std::unique_ptr<sql::PreparedStatement> pStmt( connection->prepareStatement(query)); pStmt->setString(1, primarySchema); pStmt->setString(2, primaryTable); pStmt->setString(3, foreignSchema); pStmt->setString(4, foreignTable); std::unique_ptr<sql::ResultSet> rs(pStmt->executeQuery()); while (rs->next()) { MySQL_ArtResultSet::row_t rs_data_row; rs_data_row.push_back(rs->getString(1)); // PKTABLE_CAT rs_data_row.push_back(rs->getString(2)); // PKTABLE_SCHEMA rs_data_row.push_back(rs->getString(3)); // PKTABLE_NAME rs_data_row.push_back(rs->getString(4)); // PKCOLUMN_NAME rs_data_row.push_back(rs->getString(5)); // FKTABLE_CAT rs_data_row.push_back(rs->getString(6)); // FKTABLE_SCHEMA rs_data_row.push_back(rs->getString(7)); // FKTABLE_NAME rs_data_row.push_back(rs->getString(8)); // FKCOLUMN_NAME rs_data_row.push_back(rs->getString(9)); // KEY_SEQ rs_data_row.push_back(rs->getString(10)); // UPDATE_RULE rs_data_row.push_back(rs->getString(11)); // DELETE_RULE rs_data_row.push_back(rs->getString(12)); // FK_NAME rs_data_row.push_back(rs->getString(13)); // PK_NAME rs_data_row.push_back(rs->getString(14)); // DEFERRABILITY rs_data->push_back(rs_data_row); } MySQL_ArtResultSet * ret = new MySQL_ArtResultSet(rs_field_data, rs_data, logger); return ret; return NULL; // This will shut up compilers } /* }}} */ /* {{{ MySQL_ConnectionMetaData::getDatabaseMajorVersion() -I- */ unsigned int MySQL_ConnectionMetaData::getDatabaseMajorVersion() { CPP_ENTER("MySQL_ConnectionMetaData::getDatabaseMajorVersion"); return server_version / 10000; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::getDatabaseMinorVersion() -I- */ unsigned int MySQL_ConnectionMetaData::getDatabaseMinorVersion() { CPP_ENTER("MySQL_ConnectionMetaData::getDatabaseMinorVersion"); return (server_version % 10000) / 100; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::getDatabasePatchVersion() -I- */ unsigned int MySQL_ConnectionMetaData::getDatabasePatchVersion() { CPP_ENTER("MySQL_ConnectionMetaData::getDatabasePatchVersion"); return server_version % 100; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::getDatabaseProductName() -I- */ const sql::SQLString& MySQL_ConnectionMetaData::getDatabaseProductName() { CPP_ENTER("MySQL_ConnectionMetaData::getDatabaseProductName"); static const sql::SQLString product_name("MySQL"); return product_name; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::getDatabaseProductVersion() -I- */ SQLString MySQL_ConnectionMetaData::getDatabaseProductVersion() { CPP_ENTER("MySQL_ConnectionMetaData::getDatabaseProductVersion"); return proxy->get_server_info(); } /* }}} */ /* {{{ MySQL_ConnectionMetaData::getDefaultTransactionIsolation() -I- */ int MySQL_ConnectionMetaData::getDefaultTransactionIsolation() { CPP_ENTER("MySQL_ConnectionMetaData::getDefaultTransactionIsolation"); if (server_version >= 32336) { return TRANSACTION_READ_COMMITTED; } return TRANSACTION_NONE; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::getDriverMajorVersion() -I- */ unsigned int MySQL_ConnectionMetaData::getDriverMajorVersion() { CPP_ENTER("MySQL_ConnectionMetaData::getDriverMajorVersion"); return MYCPPCONN_MAJOR_VERSION; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::getDriverMinorVersion() -I- */ unsigned int MySQL_ConnectionMetaData::getDriverMinorVersion() { CPP_ENTER("MySQL_ConnectionMetaData::getDriverMinorVersion"); return MYCPPCONN_MINOR_VERSION; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::getDriverPatchVersion() -I- */ unsigned int MySQL_ConnectionMetaData::getDriverPatchVersion() { CPP_ENTER("MySQL_ConnectionMetaData::getDriverPatchVersion"); return MYCPPCONN_PATCH_VERSION; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::getDriverVersion() -I- */ const sql::SQLString& MySQL_ConnectionMetaData::getDriverVersion() { CPP_ENTER("MySQL_ConnectionMetaData::getDriverVersion"); static const sql::SQLString version(MYCPPCONN_STRVERSION); return version; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::getDriverName() -I- */ const sql::SQLString& MySQL_ConnectionMetaData::getDriverName() { CPP_ENTER("MySQL_ConnectionMetaData::getDriverName"); static const sql::SQLString product_version("MySQL Connector/C++"); return product_version; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::getExportedKeys() -I- */ sql::ResultSet * MySQL_ConnectionMetaData::getExportedKeys(const sql::SQLString& catalog, const sql::SQLString& schema, const sql::SQLString& table) { CPP_ENTER("MySQL_ConnectionMetaData::getExportedKeys"); CPP_INFO_FMT("catalog=%s schema=%s table=%s", catalog.c_str(), schema.c_str(), table.c_str()); std::shared_ptr<MySQL_ArtResultSet::rset_t> rs_data( new MySQL_ArtResultSet::rset_t()); std::list<sql::SQLString> rs_field_data; rs_field_data.push_back("PKTABLE_CAT"); rs_field_data.push_back("PKTABLE_SCHEM"); rs_field_data.push_back("PKTABLE_NAME"); rs_field_data.push_back("PKCOLUMN_NAME"); rs_field_data.push_back("FKTABLE_CAT"); rs_field_data.push_back("FKTABLE_SCHEM"); rs_field_data.push_back("FKTABLE_NAME"); rs_field_data.push_back("FKCOLUMN_NAME"); rs_field_data.push_back("KEY_SEQ"); rs_field_data.push_back("UPDATE_RULE"); rs_field_data.push_back("DELETE_RULE"); rs_field_data.push_back("FK_NAME"); rs_field_data.push_back("PK_NAME"); rs_field_data.push_back("DEFERRABILITY"); /* This just doesn't work */ /* currently this doesn't work - we have to wait for implementation of REFERENTIAL_CONSTRAINTS */ char buf[10]; my_i_to_a(buf, sizeof(buf) - 1, importedKeyCascade); sql::SQLString importedKeyCascadeStr(buf); my_i_to_a(buf, sizeof(buf) - 1, importedKeySetNull); sql::SQLString importedKeySetNullStr(buf); my_i_to_a(buf, sizeof(buf) - 1, importedKeySetDefault); sql::SQLString importedKeySetDefaultStr(buf); my_i_to_a(buf, sizeof(buf) - 1, importedKeyRestrict); sql::SQLString importedKeyRestrictStr(buf); my_i_to_a(buf, sizeof(buf) - 1, importedKeyNoAction); sql::SQLString importedKeyNoActionStr(buf); my_i_to_a(buf, sizeof(buf) - 1, importedKeyNotDeferrable); sql::SQLString importedKeyNotDeferrableStr(buf); sql::SQLString UpdateRuleClause; UpdateRuleClause.append("CASE WHEN R.UPDATE_RULE='CASCADE' THEN ").append(importedKeyCascadeStr). append(" WHEN R.UPDATE_RULE='SET NULL' THEN ").append(importedKeySetNullStr). append(" WHEN R.UPDATE_RULE='SET DEFAULT' THEN ").append(importedKeySetDefaultStr). append(" WHEN R.UPDATE_RULE='RESTRICT' THEN ").append(importedKeyRestrictStr). append(" WHEN R.UPDATE_RULE='NO ACTION' THEN ").append(importedKeyNoActionStr). append(" ELSE ").append(importedKeyNoActionStr).append(" END "); sql::SQLString DeleteRuleClause; DeleteRuleClause.append("CASE WHEN R.DELETE_RULE='CASCADE' THEN ").append(importedKeyCascadeStr). append(" WHEN R.DELETE_RULE='SET NULL' THEN ").append(importedKeySetNullStr). append(" WHEN R.DELETE_RULE='SET DEFAULT' THEN ").append(importedKeySetDefaultStr). append(" WHEN R.DELETE_RULE='RESTRICT' THEN ").append(importedKeyRestrictStr). append(" WHEN R.DELETE_RULE='NO ACTION' THEN ").append(importedKeyNoActionStr). append(" ELSE ").append(importedKeyNoActionStr).append(" END "); sql::SQLString OptionalRefConstraintJoinStr( "JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS R ON " "(R.CONSTRAINT_NAME = B.CONSTRAINT_NAME AND R.TABLE_NAME = B.TABLE_NAME AND R.CONSTRAINT_SCHEMA = B.TABLE_SCHEMA) "); sql::SQLString query("SELECT \n"); query.append("A.TABLE_CATALOG AS PKTABLE_CAT, A.REFERENCED_TABLE_SCHEMA AS PKTABLE_SCHEM, A.REFERENCED_TABLE_NAME AS PKTABLE_NAME,\n" "A.REFERENCED_COLUMN_NAME AS PKCOLUMN_NAME, A.TABLE_CATALOG AS FKTABLE_CAT, A.TABLE_SCHEMA AS FKTABLE_SCHEM,\n" "A.TABLE_NAME AS FKTABLE_NAME, A.COLUMN_NAME AS FKCOLUMN_NAME, A.ORDINAL_POSITION AS KEY_SEQ,"); query.append(UpdateRuleClause); query.append(" AS UPDATE_RULE,"); query.append(DeleteRuleClause); query.append(" AS DELETE_RULE, A.CONSTRAINT_NAME AS FK_NAME," "(SELECT CONSTRAINT_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE TABLE_SCHEMA = REFERENCED_TABLE_SCHEMA AND" " TABLE_NAME = A.REFERENCED_TABLE_NAME AND CONSTRAINT_TYPE IN ('UNIQUE','PRIMARY KEY') LIMIT 1) AS PK_NAME,"); query.append(importedKeyNotDeferrableStr); query.append(" AS DEFERRABILITY FROM\nINFORMATION_SCHEMA.KEY_COLUMN_USAGE A JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS B\n" "ON (A.TABLE_SCHEMA = B.TABLE_SCHEMA AND A.TABLE_NAME = B.TABLE_NAME AND A.CONSTRAINT_NAME=B.CONSTRAINT_NAME AND\n" "B.CONSTRAINT_TYPE = 'FOREIGN KEY' AND A.REFERENCED_TABLE_SCHEMA LIKE ? AND A.REFERENCED_TABLE_NAME=?)\n"); query.append(OptionalRefConstraintJoinStr); query.append("ORDER BY A.TABLE_SCHEMA, A.TABLE_NAME, A.ORDINAL_POSITION\n"); std::unique_ptr<sql::PreparedStatement> pStmt( connection->prepareStatement(query)); pStmt->setString(1, schema); pStmt->setString(2, table); std::unique_ptr<sql::ResultSet> rs(pStmt->executeQuery()); while (rs->next()) { MySQL_ArtResultSet::row_t rs_data_row; rs_data_row.push_back(rs->getString(1)); // PKTABLE_CAT rs_data_row.push_back(rs->getString(2)); // PKTABLE_SCHEMA rs_data_row.push_back(rs->getString(3)); // PKTABLE_NAME rs_data_row.push_back(rs->getString(4)); // PKCOLUMN_NAME rs_data_row.push_back(rs->getString(5)); // FKTABLE_CAT rs_data_row.push_back(rs->getString(6)); // FKTABLE_SCHEMA rs_data_row.push_back(rs->getString(7)); // FKTABLE_NAME rs_data_row.push_back(rs->getString(8)); // FKCOLUMN_NAME rs_data_row.push_back(rs->getString(9)); // KEY_SEQ rs_data_row.push_back(rs->getString(10)); // UPDATE_RULE rs_data_row.push_back(rs->getString(11)); // DELETE_RULE rs_data_row.push_back(rs->getString(12)); // FK_NAME rs_data_row.push_back(rs->getString(13)); // PK_NAME rs_data_row.push_back(rs->getString(14)); // DEFERRABILITY rs_data->push_back(rs_data_row); } MySQL_ArtResultSet * ret = new MySQL_ArtResultSet(rs_field_data, rs_data, logger); return ret; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::getExtraNameCharacters() -I- */ const sql::SQLString& MySQL_ConnectionMetaData::getExtraNameCharacters() { CPP_ENTER("MySQL_ConnectionMetaData::getExtraNameCharacters"); static const sql::SQLString extra("#@"); return extra; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::getIdentifierQuoteString() -I- */ const sql::SQLString& MySQL_ConnectionMetaData::getIdentifierQuoteString() { CPP_ENTER("MySQL_ConnectionMetaData::getIdentifierQuoteString"); static const sql::SQLString empty(" "), tick("`"), quote("\""); if (server_version >= 32306) { /* Ask the server for sql_mode and decide for a tick or a quote */ sql::SQLString sql_mode(connection->getSessionVariable("SQL_MODE")); if (sql_mode.find("ANSI_QUOTES") != sql::SQLString::npos) { return quote; } else { return tick; } } return empty; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::parseImportedKeys() -I- */ bool MySQL_ConnectionMetaData::parseImportedKeys( const sql::SQLString& def, sql::SQLString & constraint_name, std::map< sql::SQLString, sql::SQLString > & keywords_names, std::map< sql::SQLString, std::list< sql::SQLString > > & referenced_fields, std::map< sql::SQLString, int > & update_cascade ) { CPP_ENTER("MySQL_ConnectionMetaData::parseImportedKeys"); size_t idx, pos; /* check if line contains 'CONSTRAINT' */ idx = def.find("CONSTRAINT"); if (idx == sql::SQLString::npos) { return false; } pos = idx + sizeof("CONSTRAINT") - 1; sql::SQLString cQuote(getIdentifierQuoteString()); { { size_t end_pos; if (cQuote.length()) { while (def[pos] != cQuote[0]) ++pos; end_pos = ++pos; while (def[end_pos] != cQuote[0] && def[end_pos - 1] != '\\') ++end_pos; } else { while (def[pos] == ' ') ++pos; end_pos = ++pos; while (def[end_pos] != ' ') ++end_pos; } constraint_name = def.substr(pos, end_pos - pos); pos = end_pos + 1; } std::list< sql::SQLString > keywords; keywords.push_back("FOREIGN KEY"); keywords.push_back("REFERENCES"); std::list< sql::SQLString >::const_iterator keywords_it = keywords.begin(); for (; keywords_it != keywords.end(); ++keywords_it) { idx = def.find(*keywords_it, pos); pos = idx + keywords_it->length(); while (def[pos] == ' ') ++pos; // Here comes optional constraint name if (def[pos] != '(') { if (cQuote.length()) { size_t end_pos = ++pos; while (def[end_pos] != cQuote[0] && def[end_pos - 1] != '\\') ++end_pos; keywords_names[*keywords_it] = def.substr(pos, end_pos - pos); pos = end_pos + 1; } else { size_t end_pos = pos; while (def[end_pos] != ' ' && def[end_pos] != '(') ++end_pos; keywords_names[*keywords_it] = def.substr(pos, end_pos - pos - 1); pos = end_pos + 1; // Now find the opening bracket } // skip to the open bracket while (def[pos] != '(') ++pos; } ++pos; // skip the bracket // Here come the referenced fields { size_t end_bracket; end_bracket = def.find(")", pos); size_t comma_pos; do { // Look within a range // , end_bracket - pos comma_pos = def.find("," , pos); // there is something in the implementation of find(",", pos, end_bracket - pos) - so I have to emulate it if (comma_pos >= end_bracket || comma_pos == sql::SQLString::npos) { referenced_fields[*keywords_it].push_back(def.substr(pos + cQuote.length(), end_bracket - pos - cQuote.length() * 2)); break; } else { referenced_fields[*keywords_it].push_back(def.substr(pos + cQuote.length(), comma_pos - pos - cQuote.length() * 2)); pos = comma_pos + 1; // skip the comma while (def[pos] == ' ') ++pos; // skip whitespace after the comma } } while (1); pos = end_bracket + 1; } } } // Check optional (UPDATE | DELETE) CASCADE { std::list< sql::SQLString > keywords; keywords.push_back("ON DELETE"); keywords.push_back("ON UPDATE"); std::list< sql::SQLString >::const_iterator keywords_it = keywords.begin(); for (; keywords_it != keywords.end(); ++keywords_it) { int action = importedKeyNoAction; idx = def.find(*keywords_it, pos); if (idx != sql::SQLString::npos) { pos = idx + keywords_it->length(); while (def[pos] == ' ') ++pos; if (def[pos] == 'R') { // RESTRICT action = importedKeyRestrict; pos += sizeof("RESTRICT"); } else if (def[pos] == 'C') { // CASCADE action = importedKeyCascade; pos += sizeof("CASCADE"); } else if (def[pos] == 'S') { // SET NULL action = importedKeySetNull; pos += sizeof("SET NULL"); } else if (def[pos] == 'N') { // NO ACTION action = importedKeyNoAction; pos += sizeof("NO ACTION"); } } update_cascade[*keywords_it] = action; } } return true; } /* }}} */ /* ORDER BY PKTABLE_SCHEM, PKTABLE_NAME, KEY_SEQ 1,2,8 */ bool compareImportedKeys(std::vector< MyVal > &first, std::vector< MyVal > &second) { return (first[1].getString().compare(second[1].getString()) < 0) || ((first[1].getString().compare(second[1].getString()) == 0) && (first[2].getString().compare(second[2].getString()) < 0)) || ((first[1].getString().compare(second[1].getString()) == 0) && (first[2].getString().compare(second[2].getString()) == 0) && (first[8].getString().caseCompare(second[8].getString()) < 0 )); } /* {{{ MySQL_ConnectionMetaData::getImportedKeys() -I- */ sql::ResultSet * MySQL_ConnectionMetaData::getImportedKeys(const sql::SQLString& catalog, const sql::SQLString& schema, const sql::SQLString& table) { CPP_ENTER("MySQL_ConnectionMetaData::getImportedKeys"); CPP_INFO_FMT("catalog=%s schema=%s table=%s", catalog.c_str(), schema.c_str(), table.c_str()); std::shared_ptr<MySQL_ArtResultSet::rset_t> rs_data( new MySQL_ArtResultSet::rset_t()); std::list<sql::SQLString> rs_field_data; rs_field_data.push_back("PKTABLE_CAT"); rs_field_data.push_back("PKTABLE_SCHEM"); rs_field_data.push_back("PKTABLE_NAME"); rs_field_data.push_back("PKCOLUMN_NAME"); rs_field_data.push_back("FKTABLE_CAT"); rs_field_data.push_back("FKTABLE_SCHEM"); rs_field_data.push_back("FKTABLE_NAME"); rs_field_data.push_back("FKCOLUMN_NAME"); rs_field_data.push_back("KEY_SEQ"); rs_field_data.push_back("UPDATE_RULE"); rs_field_data.push_back("DELETE_RULE"); rs_field_data.push_back("FK_NAME"); rs_field_data.push_back("PK_NAME"); rs_field_data.push_back("DEFERRABILITY"); /* This just doesn't work */ /* currently this doesn't work - we have to wait for implementation of REFERENTIAL_CONSTRAINTS */ char buf[10]; my_i_to_a(buf, sizeof(buf) - 1, importedKeyCascade); sql::SQLString importedKeyCascadeStr(buf); my_i_to_a(buf, sizeof(buf) - 1, importedKeySetNull); sql::SQLString importedKeySetNullStr(buf); my_i_to_a(buf, sizeof(buf) - 1, importedKeySetDefault); sql::SQLString importedKeySetDefaultStr(buf); my_i_to_a(buf, sizeof(buf) - 1, importedKeyRestrict); sql::SQLString importedKeyRestrictStr(buf); my_i_to_a(buf, sizeof(buf) - 1, importedKeyNoAction); sql::SQLString importedKeyNoActionStr(buf); my_i_to_a(buf, sizeof(buf) - 1, importedKeyNotDeferrable); sql::SQLString importedKeyNotDeferrableStr(buf); sql::SQLString UpdateRuleClause; UpdateRuleClause.append("CASE WHEN R.UPDATE_RULE='CASCADE' THEN ").append(importedKeyCascadeStr). append(" WHEN R.UPDATE_RULE='SET NULL' THEN ").append(importedKeySetNullStr). append(" WHEN R.UPDATE_RULE='SET DEFAULT' THEN ").append(importedKeySetDefaultStr). append(" WHEN R.UPDATE_RULE='RESTRICT' THEN ").append(importedKeyRestrictStr). append(" WHEN R.UPDATE_RULE='NO ACTION' THEN ").append(importedKeyNoActionStr). append(" ELSE ").append(importedKeyNoActionStr).append(" END "); sql::SQLString DeleteRuleClause; DeleteRuleClause.append("CASE WHEN R.DELETE_RULE='CASCADE' THEN ").append(importedKeyCascadeStr). append(" WHEN R.DELETE_RULE='SET NULL' THEN ").append(importedKeySetNullStr). append(" WHEN R.DELETE_RULE='SET DEFAULT' THEN ").append(importedKeySetDefaultStr). append(" WHEN R.DELETE_RULE='RESTRICT' THEN ").append(importedKeyRestrictStr). append(" WHEN R.DELETE_RULE='NO ACTION' THEN ").append(importedKeyNoActionStr). append(" ELSE ").append(importedKeyNoActionStr).append(" END "); sql::SQLString OptionalRefConstraintJoinStr( "JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS R ON " "(R.CONSTRAINT_NAME = B.CONSTRAINT_NAME AND R.TABLE_NAME = B.TABLE_NAME AND R.CONSTRAINT_SCHEMA = B.TABLE_SCHEMA) "); sql::SQLString query("SELECT \n" "A.TABLE_CATALOG AS PKTABLE_CAT, A.REFERENCED_TABLE_SCHEMA AS PKTABLE_SCHEM, A.REFERENCED_TABLE_NAME AS PKTABLE_NAME,\n" "A.REFERENCED_COLUMN_NAME AS PKCOLUMN_NAME, A.TABLE_CATALOG AS FKTABLE_CAT, A.TABLE_SCHEMA AS FKTABLE_SCHEM,\n" "A.TABLE_NAME AS FKTABLE_NAME, A.COLUMN_NAME AS FKCOLUMN_NAME, A.ORDINAL_POSITION AS KEY_SEQ,\n"); query.append(UpdateRuleClause); query.append(" AS UPDATE_RULE,\n"); query.append(DeleteRuleClause); query.append(" AS DELETE_RULE, A.CONSTRAINT_NAME AS FK_NAME,\n" "(SELECT TC.CONSTRAINT_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS AS TC\n" "WHERE TABLE_SCHEMA = A.REFERENCED_TABLE_SCHEMA AND TABLE_NAME = A.REFERENCED_TABLE_NAME \n" "AND CONSTRAINT_TYPE IN ('UNIQUE','PRIMARY KEY') LIMIT 1) AS PK_NAME,\n"); query.append(importedKeyNotDeferrableStr); query.append(" AS DEFERRABILITY FROM " "INFORMATION_SCHEMA.KEY_COLUMN_USAGE A JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS B \n" "ON(A.CONSTRAINT_NAME = B.CONSTRAINT_NAME AND A.TABLE_NAME = B.TABLE_NAME AND \n" "B.CONSTRAINT_TYPE = 'FOREIGN KEY' AND A.TABLE_SCHEMA LIKE ? AND A.TABLE_NAME=? AND\n" "A.REFERENCED_TABLE_SCHEMA IS NOT NULL) \n"); query.append(OptionalRefConstraintJoinStr); query.append("\nORDER BY A.REFERENCED_TABLE_SCHEMA, A.REFERENCED_TABLE_NAME, A.ORDINAL_POSITION"); std::unique_ptr<sql::PreparedStatement> pStmt( connection->prepareStatement(query)); pStmt->setString(1, schema); pStmt->setString(2, table); std::unique_ptr<sql::ResultSet> rs(pStmt->executeQuery()); while (rs->next()) { MySQL_ArtResultSet::row_t rs_data_row; rs_data_row.push_back(rs->getString(1)); // PKTABLE_CAT rs_data_row.push_back(rs->getString(2)); // PKTABLE_SCHEMA rs_data_row.push_back(rs->getString(3)); // PKTABLE_NAME rs_data_row.push_back(rs->getString(4)); // PKCOLUMN_NAME rs_data_row.push_back(rs->getString(5)); // FKTABLE_CAT rs_data_row.push_back(rs->getString(6)); // FKTABLE_SCHEMA rs_data_row.push_back(rs->getString(7)); // FKTABLE_NAME rs_data_row.push_back(rs->getString(8)); // FKCOLUMN_NAME rs_data_row.push_back(rs->getString(9)); // KEY_SEQ rs_data_row.push_back(rs->getString(10)); // UPDATE_RULE rs_data_row.push_back(rs->getString(11)); // DELETE_RULE rs_data_row.push_back(rs->getString(12)); // FK_NAME rs_data_row.push_back(rs->getString(13)); // PK_NAME rs_data_row.push_back(rs->getString(14)); // DEFERRABILITY rs_data->push_back(rs_data_row); } MySQL_ArtResultSet * ret = new MySQL_ArtResultSet(rs_field_data, rs_data, logger); return ret; } /* }}} */ /* ORDER BY NON_UNIQUE, TYPE, INDEX_NAME, ORDINAL_POSITION */ bool compareIndexInfo(std::vector< MyVal > &first, std::vector< MyVal > &second) { return (first[3].getBool() < second[3].getBool()) || ((first[3].getBool() == second[3].getBool()) && (first[6].getString().compare(second[6].getString()) < 0)) || ((first[3].getBool() == second[3].getBool()) && (first[6].getString().compare(second[6].getString()) == 0) && (first[5].getString().caseCompare(second[5].getString()) < 0 )) || ((first[3].getBool() == second[3].getBool()) && (first[6].getString().compare(second[6].getString()) == 0) && (first[5].getString().caseCompare(second[5].getString()) == 0 ) && (first[7].getString().caseCompare(second[7].getString()) < 0 )); } /* {{{ MySQL_ConnectionMetaData::getIndexInfo() -I- */ sql::ResultSet * MySQL_ConnectionMetaData::getIndexInfo(const sql::SQLString& /*catalog*/, const sql::SQLString& schema, const sql::SQLString& table, bool unique, bool /* approximate */) { CPP_ENTER("MySQL_ConnectionMetaData::getIndexInfo"); std::shared_ptr<MySQL_ArtResultSet::rset_t> rs_data( new MySQL_ArtResultSet::rset_t()); std::list<sql::SQLString> rs_field_data; rs_field_data.push_back("TABLE_CAT"); rs_field_data.push_back("TABLE_SCHEM"); rs_field_data.push_back("TABLE_NAME"); rs_field_data.push_back("NON_UNIQUE"); rs_field_data.push_back("INDEX_QUALIFIER"); rs_field_data.push_back("INDEX_NAME"); rs_field_data.push_back("TYPE"); rs_field_data.push_back("ORDINAL_POSITION"); rs_field_data.push_back("COLUMN_NAME"); rs_field_data.push_back("ASC_OR_DESC"); rs_field_data.push_back("CARDINALITY"); rs_field_data.push_back("PAGES"); rs_field_data.push_back("FILTER_CONDITION"); char indexOther[5]; char indexHash[5]; snprintf(indexOther, sizeof(indexOther), "%d", DatabaseMetaData::tableIndexOther); snprintf(indexHash, sizeof(indexHash), "%d", DatabaseMetaData::tableIndexHashed); sql::SQLString query("SELECT TABLE_CATALOG AS TABLE_CAT, TABLE_SCHEMA AS TABLE_SCHEM, TABLE_NAME, NON_UNIQUE, " "TABLE_SCHEMA AS INDEX_QUALIFIER, INDEX_NAME, CASE WHEN INDEX_TYPE='HASH' THEN "); query.append(indexHash).append(" ELSE ").append(indexOther); query.append(" END AS TYPE, SEQ_IN_INDEX AS ORDINAL_POSITION, COLUMN_NAME, COLLATION AS ASC_OR_DESC, CARDINALITY," "NULL AS PAGES, NULL AS FILTER_CONDITION " "FROM INFORMATION_SCHEMA.STATISTICS WHERE TABLE_SCHEMA LIKE ? AND TABLE_NAME LIKE ?\n"); if (unique) { query.append(" AND NON_UNIQUE=0"); } query.append(" ORDER BY NON_UNIQUE, TYPE, INDEX_NAME, ORDINAL_POSITION"); std::unique_ptr<sql::PreparedStatement> pStmt( connection->prepareStatement(query)); pStmt->setString(1, schema); pStmt->setString(2, table); std::unique_ptr<sql::ResultSet> rs(pStmt->executeQuery()); while (rs->next()) { MySQL_ArtResultSet::row_t rs_data_row; rs_data_row.push_back(rs->getString(1)); // TABLE_CAT rs_data_row.push_back(rs->getString(2)); // TABLE_SCHEM rs_data_row.push_back(rs->getString(3)); // TABLE_NAME rs_data_row.push_back(rs->getString(4)); // NON_UNIQUE rs_data_row.push_back(rs->getString(5)); // INDEX_QUALIFIER rs_data_row.push_back(rs->getString(6)); // INDEX_NAME rs_data_row.push_back(rs->getString(7)); // TYPE rs_data_row.push_back(rs->getString(8)); // ORDINAL_POSITION rs_data_row.push_back(rs->getString(9)); // COLUMN_NAME rs_data_row.push_back(rs->getString(10)); // ASC_OR_DESC rs_data_row.push_back(rs->getString(11)); // CARDINALITY rs_data_row.push_back(rs->getString(12)); // PAGES rs_data_row.push_back(rs->getString(13)); // FILTER_CONDITION rs_data->push_back(rs_data_row); } MySQL_ArtResultSet * ret = new MySQL_ArtResultSet(rs_field_data, rs_data, logger); return ret; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::getCDBCMajorVersion() -I- */ unsigned int MySQL_ConnectionMetaData::getCDBCMajorVersion() { CPP_ENTER("MySQL_ConnectionMetaData::getCDBCMajorVersion"); return 3; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::getCDBCMinorVersion() -I- */ unsigned int MySQL_ConnectionMetaData::getCDBCMinorVersion() { CPP_ENTER("MySQL_ConnectionMetaData::getCDBCMinorVersion"); return 0; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::getMaxBinaryLiteralLength() -I- */ unsigned int MySQL_ConnectionMetaData::getMaxBinaryLiteralLength() { CPP_ENTER("MySQL_ConnectionMetaData::getMaxBinaryLiteralLength"); return 16777208L; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::getMaxCatalogNameLength() -I- */ unsigned int MySQL_ConnectionMetaData::getMaxCatalogNameLength() { CPP_ENTER("MySQL_ConnectionMetaData::getMaxCatalogNameLength"); return 32; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::getMaxCharLiteralLength() -I- */ unsigned int MySQL_ConnectionMetaData::getMaxCharLiteralLength() { CPP_ENTER("MySQL_ConnectionMetaData::getMaxCharLiteralLength"); return 16777208; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::getMaxColumnNameLength() -I- */ unsigned int MySQL_ConnectionMetaData::getMaxColumnNameLength() { CPP_ENTER("MySQL_ConnectionMetaData::getMaxColumnNameLength"); return 64; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::getMaxColumnsInGroupBy() -I- */ unsigned int MySQL_ConnectionMetaData::getMaxColumnsInGroupBy() { CPP_ENTER("MySQL_ConnectionMetaData::getMaxColumnsInGroupBy"); return 64; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::getMaxColumnsInIndex() -I- */ unsigned int MySQL_ConnectionMetaData::getMaxColumnsInIndex() { CPP_ENTER("MySQL_ConnectionMetaData::getMaxColumnsInIndex"); return 16; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::getMaxColumnsInOrderBy() -I- */ unsigned int MySQL_ConnectionMetaData::getMaxColumnsInOrderBy() { CPP_ENTER("MySQL_ConnectionMetaData::getMaxColumnsInOrderBy"); return 64; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::getMaxColumnsInSelect() -I- */ unsigned int MySQL_ConnectionMetaData::getMaxColumnsInSelect() { CPP_ENTER("MySQL_ConnectionMetaData::getMaxColumnsInSelect"); return 256; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::getMaxColumnsInTable() -I- */ unsigned int MySQL_ConnectionMetaData::getMaxColumnsInTable() { CPP_ENTER("MySQL_ConnectionMetaData::getMaxColumnsInTable"); return 512; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::getMaxConnections() -I- */ unsigned int MySQL_ConnectionMetaData::getMaxConnections() { CPP_ENTER("MySQL_ConnectionMetaData::getMaxConnections"); return atoi(connection->getSessionVariable("max_connections").c_str()); } /* }}} */ /* {{{ MySQL_ConnectionMetaData::getMaxCursorNameLength() -I- */ unsigned int MySQL_ConnectionMetaData::getMaxCursorNameLength() { CPP_ENTER("MySQL_ConnectionMetaData::getMaxCursorNameLength"); return 64; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::getMaxIndexLength() -I- */ unsigned int MySQL_ConnectionMetaData::getMaxIndexLength() { CPP_ENTER("MySQL_ConnectionMetaData::getMaxIndexLength"); return 256; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::getMaxProcedureNameLength() -I- */ unsigned int MySQL_ConnectionMetaData::getMaxProcedureNameLength() { CPP_ENTER("MySQL_ConnectionMetaData::getMaxProcedureNameLength"); return 64; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::getMaxRowSize() -I- */ unsigned int MySQL_ConnectionMetaData::getMaxRowSize() { CPP_ENTER("MySQL_ConnectionMetaData::getMaxRowSize"); return 2147483647L - 8; // Max buffer size - HEADER } /* }}} */ /* {{{ MySQL_ConnectionMetaData::getMaxSchemaNameLength() -I- */ unsigned int MySQL_ConnectionMetaData::getMaxSchemaNameLength() { CPP_ENTER("MySQL_ConnectionMetaData::getMaxSchemaNameLength"); return 64; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::getMaxStatementLength() -I- */ unsigned int MySQL_ConnectionMetaData::getMaxStatementLength() { CPP_ENTER("MySQL_ConnectionMetaData::getMaxStatementLength"); return atoi(connection->getSessionVariable("max_allowed_packet").c_str()) - 4; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::getMaxStatements() -I- */ unsigned int MySQL_ConnectionMetaData::getMaxStatements() { CPP_ENTER("MySQL_ConnectionMetaData::getMaxStatements"); return 0; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::getMaxTableNameLength() -I- */ unsigned int MySQL_ConnectionMetaData::getMaxTableNameLength() { CPP_ENTER("MySQL_ConnectionMetaData::getMaxTableNameLength"); return 64; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::getMaxTablesInSelect() -I- */ unsigned int MySQL_ConnectionMetaData::getMaxTablesInSelect() { CPP_ENTER("MySQL_ConnectionMetaData::getMaxTablesInSelect"); return 256; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::getMaxUserNameLength() -I- */ unsigned int MySQL_ConnectionMetaData::getMaxUserNameLength() { CPP_ENTER("MySQL_ConnectionMetaData::getMaxUserNameLength"); return 16; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::getNumericFunctions() -I- */ const sql::SQLString & MySQL_ConnectionMetaData::getNumericFunctions() { CPP_ENTER("MySQL_ConnectionMetaData::getNumericFunctions"); static const sql::SQLString funcs("ABS,ACOS,ASIN,ATAN,ATAN2,BIT_COUNT,CEILING,COS," "COT,DEGREES,EXP,FLOOR,LOG,LOG10,MAX,MIN,MOD,PI,POW," "POWER,RADIANS,RAND,ROUND,SIN,SQRT,TAN,TRUNCATE"); return funcs; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::getPrimaryKeys() -I- */ sql::ResultSet * MySQL_ConnectionMetaData::getPrimaryKeys(const sql::SQLString& catalog, const sql::SQLString& schema, const sql::SQLString& table) { CPP_ENTER("MySQL_ConnectionMetaData::getPrimaryKeys"); CPP_INFO_FMT("catalog=%s schema=%s table=%s", catalog.c_str(), schema.c_str(), table.c_str()); std::list<sql::SQLString> rs_field_data; rs_field_data.push_back("TABLE_CAT"); rs_field_data.push_back("TABLE_SCHEM"); rs_field_data.push_back("TABLE_NAME"); rs_field_data.push_back("COLUMN_NAME"); rs_field_data.push_back("KEY_SEQ"); rs_field_data.push_back("PK_NAME"); std::shared_ptr<MySQL_ArtResultSet::rset_t> rs_data( new MySQL_ArtResultSet::rset_t()); /* Bind Problems with 49999, check later why */ const sql::SQLString query("SELECT TABLE_CATALOG AS TABLE_CAT, TABLE_SCHEMA AS TABLE_SCHEM, TABLE_NAME, " "COLUMN_NAME, SEQ_IN_INDEX AS KEY_SEQ, INDEX_NAME AS PK_NAME FROM INFORMATION_SCHEMA.STATISTICS " "WHERE TABLE_SCHEMA LIKE ? AND TABLE_NAME LIKE ? AND INDEX_NAME='PRIMARY' " "ORDER BY TABLE_SCHEMA, TABLE_NAME, INDEX_NAME, SEQ_IN_INDEX"); std::unique_ptr<sql::PreparedStatement> pStmt( connection->prepareStatement(query)); pStmt->setString(1, schema); pStmt->setString(2, table); std::unique_ptr<sql::ResultSet> rs(pStmt->executeQuery()); while (rs->next()) { MySQL_ArtResultSet::row_t rs_data_row; rs_data_row.push_back(rs->getString(1)); // TABLE_CAT rs_data_row.push_back(rs->getString(2)); // TABLE_SCHEM rs_data_row.push_back(rs->getString(3)); // TABLE_NAME rs_data_row.push_back(rs->getString(4)); // COLUMN_NAME rs_data_row.push_back(rs->getString(5)); // KEY_SEQ rs_data_row.push_back(rs->getString(6)); // PK_NAME rs_data->push_back(rs_data_row); } MySQL_ArtResultSet * ret = new MySQL_ArtResultSet(rs_field_data, rs_data, logger); return ret; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::getUniqueNonNullableKeys() -I- */ sql::ResultSet * MySQL_ConnectionMetaData::getUniqueNonNullableKeys(const sql::SQLString& catalog, const sql::SQLString& schema, const sql::SQLString& table) { CPP_ENTER("MySQL_ConnectionMetaData::getPrimaryKeys"); CPP_INFO_FMT("catalog=%s schema=%s table=%s", catalog.c_str(), schema.c_str(), table.c_str()); std::list<sql::SQLString> rs_field_data; rs_field_data.push_back("TABLE_CAT"); rs_field_data.push_back("TABLE_SCHEM"); rs_field_data.push_back("TABLE_NAME"); rs_field_data.push_back("COLUMN_NAME"); rs_field_data.push_back("KEY_SEQ"); rs_field_data.push_back("PK_NAME"); std::shared_ptr<MySQL_ArtResultSet::rset_t> rs_data( new MySQL_ArtResultSet::rset_t()); /* Bind Problems with 49999, check later why */ const sql::SQLString query("SELECT TABLE_CATALOG AS TABLE_CAT, TABLE_SCHEMA AS TABLE_SCHEM, TABLE_NAME," " COLUMN_NAME, SEQ_IN_INDEX AS KEY_SEQ, INDEX_NAME AS PK_NAME " "FROM INFORMATION_SCHEMA.STATISTICS " "WHERE TABLE_SCHEMA LIKE ? AND TABLE_NAME LIKE ? AND INDEX_NAME <> 'PRIMARY'" " AND NON_UNIQUE = 0 AND NULLABLE <> 'YES'" "ORDER BY TABLE_SCHEMA, TABLE_NAME, INDEX_NAME, SEQ_IN_INDEX"); std::unique_ptr<sql::PreparedStatement> stmt( connection->prepareStatement(query)); stmt->setString(1, schema); stmt->setString(2, table); return stmt->executeQuery(); std::unique_ptr<sql::ResultSet> rs(stmt->executeQuery()); while (rs->next()) { MySQL_ArtResultSet::row_t rs_data_row; rs_data_row.push_back(rs->getString(1)); // TABLE_CAT rs_data_row.push_back(rs->getString(2)); // TABLE_SCHEM rs_data_row.push_back(rs->getString(3)); // TABLE_NAME rs_data_row.push_back(rs->getString(4)); // COLUMN_NAME rs_data_row.push_back(rs->getString(5)); // KEY_SEQ rs_data_row.push_back(rs->getString(6)); // PK_NAME rs_data->push_back(rs_data_row); } MySQL_ArtResultSet * ret = new MySQL_ArtResultSet(rs_field_data, rs_data, logger); return ret; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::getProcedureColumns() -U- */ sql::ResultSet * MySQL_ConnectionMetaData::getProcedureColumns(const sql::SQLString& /* catalog */, const sql::SQLString& /* schemaPattern */, const sql::SQLString& /* procedureNamePattern */, const sql::SQLString& /* columnNamePattern */) { CPP_ENTER("MySQL_ConnectionMetaData::getProcedureColumns"); throw sql::MethodNotImplementedException("MySQL_ConnectionMetaData::getURL"); return NULL; // fool compiler #if A0 std::list<sql::SQLString> rs_field_data; rs_field_data.push_back("PROCEDURE_CAT"); rs_field_data.push_back("PROCEDURE_SCHEM"); rs_field_data.push_back("PROCEDURE_NAME"); rs_field_data.push_back("COLUMN_NAME"); rs_field_data.push_back("COLUMN_TYPE"); rs_field_data.push_back("DATA_TYPE"); rs_field_data.push_back("TYPE_NAME"); rs_field_data.push_back("PRECISION"); rs_field_data.push_back("LENGTH"); rs_field_data.push_back("SCALE"); rs_field_data.push_back("RADIX"); rs_field_data.push_back("NULLABLE"); rs_field_data.push_back("REMARKS"); std::shared_ptr<MySQL_ArtResultSet::rset_t> rs_data( new MySQL_ArtResultSet::rset_t()); MySQL_ArtResultSet * ret = new MySQL_ArtResultSet(rs_field_data, rs_data, logger); return ret; #endif } /* }}} */ /* {{{ MySQL_ConnectionMetaData::getProcedures() -I- */ sql::ResultSet * MySQL_ConnectionMetaData::getProcedures(const sql::SQLString& /*catalog*/, const sql::SQLString& schemaPattern, const sql::SQLString& procedureNamePattern) { CPP_ENTER("MySQL_ConnectionMetaData::getProcedures"); sql::SQLString escapedSchemaPattern = connection->escapeString(schemaPattern); sql::SQLString escapedProcedureNamePattern = connection->escapeString(procedureNamePattern); std::list<sql::SQLString> rs_field_data; rs_field_data.push_back("PROCEDURE_CAT"); rs_field_data.push_back("PROCEDURE_SCHEM"); rs_field_data.push_back("PROCEDURE_NAME"); rs_field_data.push_back("RESERVERD_1"); rs_field_data.push_back("RESERVERD_2"); rs_field_data.push_back("RESERVERD_3"); rs_field_data.push_back("REMARKS"); rs_field_data.push_back("PROCEDURE_TYPE"); std::shared_ptr<MySQL_ArtResultSet::rset_t> rs_data( new MySQL_ArtResultSet::rset_t()); char procRetNoRes[5]; my_i_to_a(procRetNoRes, sizeof(procRetNoRes) - 1, procedureNoResult); char procRetRes[5]; my_i_to_a(procRetRes, sizeof(procRetRes) - 1, procedureReturnsResult); char procRetUnknown[5]; my_i_to_a(procRetUnknown, sizeof(procRetUnknown) - 1, procedureResultUnknown); sql::SQLString query("SELECT ROUTINE_CATALOG AS PROCEDURE_CAT, ROUTINE_SCHEMA AS PROCEDURE_SCHEM, " "ROUTINE_NAME AS PROCEDURE_NAME, NULL AS RESERVED_1, NULL AS RESERVERD_2, NULL as RESERVED_3," "ROUTINE_COMMENT AS REMARKS, " "CASE WHEN ROUTINE_TYPE = 'PROCEDURE' THEN "); query.append(procRetNoRes); query.append(" WHEN ROUTINE_TYPE='FUNCTION' THEN "); query.append(procRetRes); query.append(" ELSE "); query.append(procRetUnknown); query.append(" END AS PROCEDURE_TYPE\nFROM INFORMATION_SCHEMA.ROUTINES\n" "WHERE ROUTINE_SCHEMA LIKE ? AND ROUTINE_NAME LIKE ?\n" "ORDER BY ROUTINE_SCHEMA, ROUTINE_NAME"); std::unique_ptr<sql::PreparedStatement> pStmt( connection->prepareStatement(query)); pStmt->setString(1, escapedSchemaPattern); pStmt->setString(2, escapedProcedureNamePattern.length() ? escapedProcedureNamePattern : "%"); std::unique_ptr<sql::ResultSet> rs(pStmt->executeQuery()); while (rs->next()) { MySQL_ArtResultSet::row_t rs_data_row; rs_data_row.push_back(rs->getString(1)); // PROCEDURE_CAT rs_data_row.push_back(rs->getString(2)); // PROCEDURE_SCHEM rs_data_row.push_back(rs->getString(3)); // PROCEDURE_NAME rs_data_row.push_back(rs->getString(4)); // reserved1 rs_data_row.push_back(rs->getString(5)); // reserved2 rs_data_row.push_back(rs->getString(6)); // reserved3 rs_data_row.push_back(rs->getString(7)); // REMARKS rs_data_row.push_back(rs->getString(8)); // PROCEDURE_TYPE rs_data->push_back(rs_data_row); } MySQL_ArtResultSet * ret = new MySQL_ArtResultSet(rs_field_data, rs_data, logger); return ret; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::getProcedureTerm() -I- */ const sql::SQLString & MySQL_ConnectionMetaData::getProcedureTerm() { CPP_ENTER("MySQL_ConnectionMetaData::getProcedureTerm"); static const sql::SQLString term("procedure"); return term; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::getResultSetHoldability() -I- */ int MySQL_ConnectionMetaData::getResultSetHoldability() { CPP_ENTER("MySQL_ConnectionMetaData::getResultSetHoldability"); return sql::ResultSet::HOLD_CURSORS_OVER_COMMIT; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::getSchemas() -I- */ sql::ResultSet * MySQL_ConnectionMetaData::getSchemas() { CPP_ENTER("MySQL_ConnectionMetaData::getSchemas"); std::shared_ptr<MySQL_ArtResultSet::rset_t> rs_data( new MySQL_ArtResultSet::rset_t()); std::list<sql::SQLString> rs_field_data; rs_field_data.push_back("TABLE_SCHEM"); rs_field_data.push_back("TABLE_CATALOG"); std::unique_ptr<sql::ResultSet> rs(stmt->executeQuery( "SELECT SCHEMA_NAME AS TABLE_SCHEM, CATALOG_NAME AS TABLE_CATALOG FROM " "INFORMATION_SCHEMA.SCHEMATA ORDER BY SCHEMA_NAME")); while (rs->next()) { MySQL_ArtResultSet::row_t rs_data_row; rs_data_row.push_back(rs->getString(1)); rs_data_row.push_back(rs->getString(2)); rs_data->push_back(rs_data_row); } MySQL_ArtResultSet* ret = new MySQL_ArtResultSet(rs_field_data, rs_data, logger); return ret; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::getSchemaTerm() -I- */ const sql::SQLString& MySQL_ConnectionMetaData::getSchemaTerm() { CPP_ENTER("MySQL_ConnectionMetaData::getSchemaTerm"); static const sql::SQLString term("database"); return term; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::getSchemaCollation() -I- */ sql::ResultSet * MySQL_ConnectionMetaData::getSchemaCollation(const sql::SQLString& /* catalog */, const sql::SQLString& schemaPattern) { CPP_ENTER("MySQL_ConnectionMetaData::getSchemaCollation"); CPP_INFO_FMT("schemaPattern=%s", schemaPattern.c_str()); sql::SQLString escapedSchemaPattern = connection->escapeString(schemaPattern); std::shared_ptr<MySQL_ArtResultSet::rset_t> rs_data( new MySQL_ArtResultSet::rset_t()); std::list<sql::SQLString> rs_field_data; rs_field_data.push_back("SCHEMA_CAT"); rs_field_data.push_back("SCHEMA_NAME"); rs_field_data.push_back("SCHEMA_COLLATION"); sql::SQLString query("SELECT CATALOG_NAME AS SCHEMA_CAT, SCHEMA_NAME, " "DEFAULT_COLLATION_NAME AS SCHEMA_COLLATION FROM INFORMATION_SCHEMA.SCHEMATA " "where SCHEMA_NAME LIKE '"); query.append(escapedSchemaPattern).append("'"); std::unique_ptr<sql::Statement> stmt(connection->createStatement()); std::unique_ptr<sql::ResultSet> rs(stmt->executeQuery(query)); while (rs->next()) { MySQL_ArtResultSet::row_t rs_data_row; rs_data_row.push_back(rs->getString(1)); // SCHEMA_CAT rs_data_row.push_back(rs->getString(2)); // SCHEMA_NAME rs_data_row.push_back(rs->getString(3)); // SCHEMA_COLLATION rs_data->push_back(rs_data_row); } MySQL_ArtResultSet * ret = new MySQL_ArtResultSet(rs_field_data, rs_data, logger); return ret; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::getSchemaCharset() -I- */ sql::ResultSet * MySQL_ConnectionMetaData::getSchemaCharset(const sql::SQLString& /* catalog */, const sql::SQLString& schemaPattern) { CPP_ENTER("MySQL_ConnectionMetaData::getSchemaCharset"); CPP_INFO_FMT("schemaPattern=%s", schemaPattern.c_str()); sql::SQLString escapedSchemaPattern = connection->escapeString(schemaPattern); std::shared_ptr<MySQL_ArtResultSet::rset_t> rs_data( new MySQL_ArtResultSet::rset_t()); std::list<sql::SQLString> rs_field_data; rs_field_data.push_back("SCHEMA_CAT"); rs_field_data.push_back("SCHEMA_NAME"); rs_field_data.push_back("SCHEMA_CHARSET"); sql::SQLString query("SELECT CATALOG_NAME AS SCHEMA_CAT, SCHEMA_NAME, " "DEFAULT_CHARACTER_SET_NAME AS SCHEMA_CHARSET FROM INFORMATION_SCHEMA.SCHEMATA " "where SCHEMA_NAME LIKE '"); query.append(escapedSchemaPattern).append("'"); std::unique_ptr<sql::Statement> stmt(connection->createStatement()); std::unique_ptr<sql::ResultSet> rs(stmt->executeQuery(query)); while (rs->next()) { MySQL_ArtResultSet::row_t rs_data_row; rs_data_row.push_back(rs->getString(1)); // SCHEMA_CAT rs_data_row.push_back(rs->getString(2)); // SCHEMA_NAME rs_data_row.push_back(rs->getString(3)); // SCHEMA_CHARSET rs_data->push_back(rs_data_row); } MySQL_ArtResultSet * ret = new MySQL_ArtResultSet(rs_field_data, rs_data, logger); return ret; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::getSearchStringEscape() -I- */ const sql::SQLString& MySQL_ConnectionMetaData::getSearchStringEscape() { CPP_ENTER("MySQL_ConnectionMetaData::getSearchStringEscape"); static const sql::SQLString escape("\\"); return escape; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::getSQLKeywords() -I- */ const sql::SQLString& MySQL_ConnectionMetaData::getSQLKeywords() { CPP_ENTER("MySQL_ConnectionMetaData::getSQLKeywords"); if (server_version < 80022) { static const sql::SQLString keywords( "ACCESSIBLE, ADD, ALL,"\ "ALTER, ANALYZE, AND, AS, ASC, ASENSITIVE, BEFORE,"\ "BETWEEN, BIGINT, BINARY, BLOB, BOTH, BY, CALL,"\ "CASCADE, CASE, CHANGE, CHAR, CHARACTER, CHECK,"\ "COLLATE, COLUMN, CONDITION, CONNECTION, CONSTRAINT,"\ "CONTINUE, CONVERT, CREATE, CROSS, CURRENT_DATE,"\ "CURRENT_TIME, CURRENT_TIMESTAMP, CURRENT_USER, CURSOR,"\ "DATABASE, DATABASES, DAY_HOUR, DAY_MICROSECOND,"\ "DAY_MINUTE, DAY_SECOND, DEC, DECIMAL, DECLARE,"\ "DEFAULT, DELAYED, DELETE, DESC, DESCRIBE,"\ "DETERMINISTIC, DISTINCT, DISTINCTROW, DIV, DOUBLE,"\ "DROP, DUAL, EACH, ELSE, ELSEIF, ENCLOSED,"\ "ESCAPED, EXISTS, EXIT, EXPLAIN, FALSE, FETCH,"\ "FLOAT, FLOAT4, FLOAT8, FOR, FORCE, FOREIGN, FROM,"\ "FULLTEXT, GRANT, GROUP, HAVING, HIGH_PRIORITY,"\ "HOUR_MICROSECOND, HOUR_MINUTE, HOUR_SECOND, IF,"\ "IGNORE, IN, INDEX, INFILE, INNER, INOUT,"\ "INSENSITIVE, INSERT, INT, INT1, INT2, INT3, INT4,"\ "INT8, INTEGER, INTERVAL, INTO, IS, ITERATE, JOIN,"\ "KEY, KEYS, KILL, LEADING, LEAVE, LEFT, LIKE,"\ "LOCALTIMESTAMP, LOCK, LONG, LONGBLOB, LONGTEXT,"\ "LOOP, LOW_PRIORITY, MATCH, MEDIUMBLOB, MEDIUMINT,"\ "MEDIUMTEXT, MIDDLEINT, MINUTE_MICROSECOND,"\ "MINUTE_SECOND, MOD, MODIFIES, NATURAL, NOT,"\ "NO_WRITE_TO_BINLOG, NULL, NUMERIC, ON, OPTIMIZE,"\ "OPTION, OPTIONALLY, OR, ORDER, OUT, OUTER,"\ "OUTFILE, PRECISION, PRIMARY, PROCEDURE, PURGE,"\ "RANGE, READ, READS, READ_ONLY, READ_WRITE, REAL,"\ "REFERENCES, REGEXP, RELEASE, RENAME, REPEAT,"\ "REPLACE, REQUIRE, RESTRICT, RETURN, REVOKE, RIGHT,"\ "RLIKE, SCHEMA, SCHEMAS, SECOND_MICROSECOND, SELECT,"\ "SENSITIVE, SEPARATOR, SET, SHOW, SMALLINT, SPATIAL,"\ "SPECIFIC, SQL, SQLEXCEPTION, SQLSTATE, SQLWARNING,"\ "SQL_BIG_RESULT, SQL_CALC_FOUND_ROWS, SQL_SMALL_RESULT,"\ "SSL, STARTING, STRAIGHT_JOIN, TABLE, TERMINATED,"\ "THEN, TINYBLOB, TINYINT, TINYTEXT, TO, TRAILING,"\ "TRIGGER, TRUE, UNDO, UNION, UNIQUE, UNLOCK,"\ "UNSIGNED, UPDATE, USAGE, USE, USING, UTC_DATE,"\ "UTC_TIME, UTC_TIMESTAMP, VALUES, VARBINARY, VARCHAR,"\ "VARCHARACTER, VARYING, WHEN, WHERE, WHILE, WITH,"\ "WRITE, X509, XOR, YEAR_MONTH, ZEROFILL," \ "GENERAL, IGNORE_SERVER_IDS,"\ "\x4D\x41\x53\x54\x45\x52_HEARTBEAT_PERIOD," \ "MAXVALUE, RESIGNAL, SIGNAL, SLOW"); return keywords; } static const sql::SQLString keywords( "ACCESSIBLE, ADD, ALL,"\ "ALTER, ANALYZE, AND, AS, ASC, ASENSITIVE, BEFORE,"\ "BETWEEN, BIGINT, BINARY, BLOB, BOTH, BY, CALL,"\ "CASCADE, CASE, CHANGE, CHAR, CHARACTER, CHECK,"\ "COLLATE, COLUMN, CONDITION, CONNECTION, CONSTRAINT,"\ "CONTINUE, CONVERT, CREATE, CROSS, CURRENT_DATE,"\ "CURRENT_TIME, CURRENT_TIMESTAMP, CURRENT_USER, CURSOR,"\ "DATABASE, DATABASES, DAY_HOUR, DAY_MICROSECOND,"\ "DAY_MINUTE, DAY_SECOND, DEC, DECIMAL, DECLARE,"\ "DEFAULT, DELAYED, DELETE, DESC, DESCRIBE,"\ "DETERMINISTIC, DISTINCT, DISTINCTROW, DIV, DOUBLE,"\ "DROP, DUAL, EACH, ELSE, ELSEIF, ENCLOSED,"\ "ESCAPED, EXISTS, EXIT, EXPLAIN, FALSE, FETCH,"\ "FLOAT, FLOAT4, FLOAT8, FOR, FORCE, FOREIGN, FROM,"\ "FULLTEXT, GRANT, GROUP, HAVING, HIGH_PRIORITY,"\ "HOUR_MICROSECOND, HOUR_MINUTE, HOUR_SECOND, IF,"\ "IGNORE, IN, INDEX, INFILE, INNER, INOUT,"\ "INSENSITIVE, INSERT, INT, INT1, INT2, INT3, INT4,"\ "INT8, INTEGER, INTERVAL, INTO, IS, ITERATE, JOIN,"\ "KEY, KEYS, KILL, LEADING, LEAVE, LEFT, LIKE,"\ "LOCALTIMESTAMP, LOCK, LONG, LONGBLOB, LONGTEXT,"\ "LOOP, LOW_PRIORITY, MATCH, MEDIUMBLOB, MEDIUMINT,"\ "MEDIUMTEXT, MIDDLEINT, MINUTE_MICROSECOND,"\ "MINUTE_SECOND, MOD, MODIFIES, NATURAL, NOT,"\ "NO_WRITE_TO_BINLOG, NULL, NUMERIC, ON, OPTIMIZE,"\ "OPTION, OPTIONALLY, OR, ORDER, OUT, OUTER,"\ "OUTFILE, PRECISION, PRIMARY, PROCEDURE, PURGE,"\ "RANGE, READ, READS, READ_ONLY, READ_WRITE, REAL,"\ "REFERENCES, REGEXP, RELEASE, RENAME, REPEAT,"\ "REPLACE, REQUIRE, RESTRICT, RETURN, REVOKE, RIGHT,"\ "RLIKE, SCHEMA, SCHEMAS, SECOND_MICROSECOND, SELECT,"\ "SENSITIVE, SEPARATOR, SET, SHOW, SMALLINT, SPATIAL,"\ "SPECIFIC, SQL, SQLEXCEPTION, SQLSTATE, SQLWARNING,"\ "SQL_BIG_RESULT, SQL_CALC_FOUND_ROWS, SQL_SMALL_RESULT,"\ "SSL, STARTING, STRAIGHT_JOIN, TABLE, TERMINATED,"\ "THEN, TINYBLOB, TINYINT, TINYTEXT, TO, TRAILING,"\ "TRIGGER, TRUE, UNDO, UNION, UNIQUE, UNLOCK,"\ "UNSIGNED, UPDATE, USAGE, USE, USING, UTC_DATE,"\ "UTC_TIME, UTC_TIMESTAMP, VALUES, VARBINARY, VARCHAR,"\ "VARCHARACTER, VARYING, WHEN, WHERE, WHILE, WITH,"\ "WRITE, X509, XOR, YEAR_MONTH, ZEROFILL," \ "GENERAL, IGNORE_SERVER_IDS, SOURCE_HEARTBEAT_PERIOD," \ "MAXVALUE, RESIGNAL, SIGNAL, SLOW"); return keywords; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::getSQLStateType() -I- */ int MySQL_ConnectionMetaData::getSQLStateType() { CPP_ENTER("MySQL_ConnectionMetaData::getSQLStateType"); return sqlStateSQL99; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::getStringFunctions() -I- */ const sql::SQLString& MySQL_ConnectionMetaData::getStringFunctions() { CPP_ENTER("MySQL_ConnectionMetaData::getStringFunctions"); static const sql::SQLString funcs( "ASCII,BIN,BIT_LENGTH,CHAR,CHARACTER_LENGTH,CHAR_LENGTH,CONCAT," "CONCAT_WS,CONV,ELT,EXPORT_SET,FIELD,FIND_IN_SET,HEX,INSERT," "INSTR,LCASE,LEFT,LENGTH,LOAD_FILE,LOCATE,LOCATE,LOWER,LPAD," "LTRIM,MAKE_SET,MATCH,MID,OCT,OCTET_LENGTH,ORD,POSITION," "QUOTE,REPEAT,REPLACE,REVERSE,RIGHT,RPAD,RTRIM,SOUNDEX," "SPACE,STRCMP,SUBSTRING,SUBSTRING,SUBSTRING,SUBSTRING," "SUBSTRING_INDEX,TRIM,UCASE,UPPER"); return funcs; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::getSuperTables() -I- */ sql::ResultSet * MySQL_ConnectionMetaData::getSuperTables(const sql::SQLString& /*catalog*/, const sql::SQLString& /*schemaPattern*/, const sql::SQLString& /*tableNamePattern*/) { CPP_ENTER("MySQL_ConnectionMetaData::getSuperTables"); std::list<sql::SQLString> rs_field_data; rs_field_data.push_back("TABLE_CAT"); rs_field_data.push_back("TABLE_SCHEM"); rs_field_data.push_back("TABLE_NAME"); rs_field_data.push_back("SUPERTABLE_NAME"); std::shared_ptr<MySQL_ArtResultSet::rset_t> rs_data( new MySQL_ArtResultSet::rset_t()); MySQL_ArtResultSet * ret = new MySQL_ArtResultSet(rs_field_data, rs_data, logger); return ret; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::getSuperTypes() -I- */ sql::ResultSet * MySQL_ConnectionMetaData::getSuperTypes(const sql::SQLString& /*catalog*/, const sql::SQLString& /*schemaPattern*/, const sql::SQLString& /*typeNamePattern*/) { CPP_ENTER("MySQL_ConnectionMetaData::getSuperTypes"); std::list<sql::SQLString> rs_field_data; rs_field_data.push_back("TYPE_CAT"); rs_field_data.push_back("TYPE_SCHEM"); rs_field_data.push_back("TYPE_NAME"); rs_field_data.push_back("SUPERTYPE_CAT"); rs_field_data.push_back("SUPERTYPE_SCHEM"); rs_field_data.push_back("SUPERTYPE_NAME"); std::shared_ptr<MySQL_ArtResultSet::rset_t> rs_data( new MySQL_ArtResultSet::rset_t()); MySQL_ArtResultSet * ret = new MySQL_ArtResultSet(rs_field_data, rs_data, logger); return ret; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::getSystemFunctions() -I- */ const sql::SQLString& MySQL_ConnectionMetaData::getSystemFunctions() { CPP_ENTER("MySQL_ConnectionMetaData::getSystemFunctions"); static const sql::SQLString funcs( "DATABASE,USER,SYSTEM_USER," "SESSION_USER,PASSWORD,ENCRYPT,LAST_INSERT_ID,VERSION"); return funcs; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::getTablePrivileges() -I- */ sql::ResultSet * MySQL_ConnectionMetaData::getTablePrivileges(const sql::SQLString& catalog, const sql::SQLString& schemaPattern, const sql::SQLString& tableNamePattern) { CPP_ENTER("MySQL_ConnectionMetaData::getTablePrivileges"); std::unique_ptr<sql::ResultSet> rs(stmt->executeQuery("SHOW GRANTS")); std::list< sql::SQLString > aPrivileges, aSchemas, aTables; sql::SQLString strAllPrivs("ALTER, DELETE, DROP, INDEX, INSERT, LOCK TABLES, SELECT, UPDATE"); sql::SQLString cQuote(getIdentifierQuoteString()); while (rs->next() ) { sql::SQLString aGrant = rs->getString(1); aGrant = aGrant.replace(0, 6, ""); size_t pos = aGrant.find("ALL PRIVILEGES"); if (pos != sql::SQLString::npos) { aGrant = aGrant.replace(pos, sizeof("ALL PRIVILEGES") - 1, strAllPrivs); } pos = aGrant.find("ON"); //ASSERT(pos != sql::SQLString::npos); aPrivileges.push_back(aGrant.substr(0, pos - 1)); /* -1 for trim */ aGrant = aGrant.substr(pos + 3); /* remove "ON " */ if (aGrant[0] != '*') { pos = 1; do { pos = aGrant.find(cQuote, pos); } while (pos != sql::SQLString::npos && aGrant[pos - 1] == '\\'); aSchemas.push_back(aGrant.substr(1, pos - 1)); /* From pos 1, without the quoting */ aGrant = aGrant.replace(0, pos + 1 + 1, ""); // remove the quote, the dot too } else { aSchemas.push_back("*"); aGrant = aGrant.replace(0, 1 + 1, ""); // remove the star, the dot too } /* first char is the quotestring, the last too "`xyz`." Dot is at 5, copy from 1, 5 - 1 - 1 = xyz */ if (aGrant[0] != '*') { // What if the names are not quoted. They should be, no? int idx = 1; pos = idx; do { pos = aGrant.find(cQuote, pos); } while (pos != sql::SQLString::npos && aGrant[pos - 1] == '\\'); aTables.push_back(aGrant.substr(1, pos - 1)); } else { aTables.push_back("*"); } /* `aaa`.`xyz` - jump over the dot and the quote . = 5 ` = 6 x = 7 = idx ` = 10 ` - x = 10 - 7 = 3 -> xyz */ } std::list<sql::SQLString> rs_field_data; rs_field_data.push_back("TABLE_CAT"); rs_field_data.push_back("TABLE_SCHEM"); rs_field_data.push_back("TABLE_NAME"); rs_field_data.push_back("GRANTOR"); rs_field_data.push_back("GRANTEE"); rs_field_data.push_back("PRIVILEGE"); rs_field_data.push_back("IS_GRANTABLE"); std::shared_ptr<MySQL_ArtResultSet::rset_t> rs_data( new MySQL_ArtResultSet::rset_t()); std::list< sql::SQLString > tableTypes; tableTypes.push_back(sql::SQLString("TABLE")); std::unique_ptr<sql::ResultSet> tables( getTables(catalog, schemaPattern, tableNamePattern, tableTypes)); sql::SQLString schema, table; while (tables->next()) { schema = tables->getString(2); table = tables->getString(3); std::list<sql::SQLString>::const_iterator it_priv, it_schemas, it_tables; it_priv = aPrivileges.begin(); it_schemas = aSchemas.begin(); it_tables = aTables.begin(); for (; it_priv != aPrivileges.end(); ++it_priv, ++it_schemas, ++it_tables) { /* skip usage */ if (it_priv->compare("USAGE") && matchTable(*it_schemas, *it_tables, schema, table)) { size_t pos, idx; pos = 0; do { while ((*it_priv)[pos] == ' ') ++pos; // Eat the whitespace idx = it_priv->find(",", pos); sql::SQLString privToken; // check for sql::SQLString::npos if (idx != sql::SQLString::npos) { privToken = it_priv->substr(pos, idx - pos); pos = idx + 1; /* skip ',' */ } else { privToken = it_priv->substr(pos, it_priv->length() - pos); } // ToDo: Why? if (privToken.find_first_of('/') == sql::SQLString::npos) { MySQL_ArtResultSet::row_t rs_data_row; rs_data_row.push_back("def"); // TABLE_CAT rs_data_row.push_back(schema); // TABLE_SCHEM rs_data_row.push_back(table); // TABLE_NAME rs_data_row.push_back(""); // GRANTOR rs_data_row.push_back(getUserName()); // GRANTEE rs_data_row.push_back(privToken); // PRIVILEGE rs_data_row.push_back(""); // IS_GRANTABLE - ToDo maybe here WITH GRANT OPTION?? rs_data->push_back(rs_data_row); } } while (idx != sql::SQLString::npos); break; } } } MySQL_ArtResultSet * ret = new MySQL_ArtResultSet(rs_field_data, rs_data, logger); return ret; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::getTables() -I- */ sql::ResultSet * MySQL_ConnectionMetaData::getTables(const sql::SQLString& /* catalog */, const sql::SQLString& schemaPattern, const sql::SQLString& tableNamePattern, std::list<sql::SQLString> &types) { CPP_ENTER("MySQL_ConnectionMetaData::getTables"); CPP_INFO_FMT("schemaPattern=%s tablePattern=%s", schemaPattern.c_str(), tableNamePattern.c_str()); sql::SQLString escapedSchemaPattern = connection->escapeString(schemaPattern); sql::SQLString escapedTableNamePattern = connection->escapeString(tableNamePattern); std::shared_ptr<MySQL_ArtResultSet::rset_t> rs_data( new MySQL_ArtResultSet::rset_t()); std::list<sql::SQLString> rs_field_data; rs_field_data.push_back("TABLE_CAT"); rs_field_data.push_back("TABLE_SCHEM"); rs_field_data.push_back("TABLE_NAME"); rs_field_data.push_back("TABLE_TYPE"); rs_field_data.push_back("REMARKS"); const sql::SQLString query( "SELECT TABLE_CATALOG AS TABLE_CAT, TABLE_SCHEMA AS TABLE_SCHEM, " "TABLE_NAME," "IF(STRCMP(TABLE_TYPE,'BASE TABLE'), " "IF(STRCMP(TABLE_TYPE,'SYSTEM VIEW'), TABLE_TYPE, 'VIEW')," " 'TABLE') AS TABLE_TYPE, TABLE_COMMENT AS REMARKS\n" "FROM INFORMATION_SCHEMA.TABLES\nWHERE TABLE_SCHEMA LIKE ? AND " "TABLE_NAME LIKE ?\n" "ORDER BY TABLE_TYPE, TABLE_SCHEMA, TABLE_NAME"); std::unique_ptr<sql::PreparedStatement> pStmt( connection->prepareStatement(query)); pStmt->setString(1, escapedSchemaPattern); pStmt->setString(2, escapedTableNamePattern); std::unique_ptr<sql::ResultSet> rs(pStmt->executeQuery()); while (rs->next()) { std::list<sql::SQLString>::const_iterator it = types.begin(); for (; it != types.end(); ++it) { if (*it == rs->getString(4)) { MySQL_ArtResultSet::row_t rs_data_row; rs_data_row.push_back(rs->getString(1)); // TABLE_CAT rs_data_row.push_back(rs->getString(2)); // TABLE_SCHEM rs_data_row.push_back(rs->getString(3)); // TABLE_NAME rs_data_row.push_back(rs->getString(4)); // TABLE_TYPE rs_data_row.push_back(rs->getString(5)); // REMARKS rs_data->push_back(rs_data_row); break; } } } MySQL_ArtResultSet * ret = new MySQL_ArtResultSet(rs_field_data, rs_data, logger); return ret; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::getTableTypes() -I- */ sql::ResultSet * MySQL_ConnectionMetaData::getTableTypes() { CPP_ENTER("MySQL_ConnectionMetaData::getTableTypes"); static const char * const table_types[] = {"TABLE", "VIEW", "LOCAL TEMPORARY"}; static unsigned int requiredVersion[] = {32200, 50000, 32200}; std::list<sql::SQLString> rs_field_data; rs_field_data.push_back("TABLE_TYPE"); std::shared_ptr<MySQL_ArtResultSet::rset_t> rs_data( new MySQL_ArtResultSet::rset_t()); for (unsigned int i = 0; i < 3; ++i) { if (server_version >= requiredVersion[i]) { MySQL_ArtResultSet::row_t rs_data_row; rs_data_row.push_back(table_types[i]); rs_data->push_back(rs_data_row); } } MySQL_ArtResultSet * ret = new MySQL_ArtResultSet(rs_field_data, rs_data, logger); return ret; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::getTableCollation() -I- */ sql::ResultSet * MySQL_ConnectionMetaData::getTableCollation(const sql::SQLString& /* catalog */, const sql::SQLString& schemaPattern, const sql::SQLString& tableNamePattern) { CPP_ENTER("MySQL_ConnectionMetaData::getTableCollation"); CPP_INFO_FMT("schemaPattern=%s tablePattern=%s", schemaPattern.c_str(), tableNamePattern.c_str()); sql::SQLString escapedSchemaPattern = connection->escapeString(schemaPattern); sql::SQLString escapedTableNamePattern = connection->escapeString(tableNamePattern); std::shared_ptr<MySQL_ArtResultSet::rset_t> rs_data( new MySQL_ArtResultSet::rset_t()); std::list<sql::SQLString> rs_field_data; rs_field_data.push_back("TABLE_CAT"); rs_field_data.push_back("TABLE_SCHEMA"); rs_field_data.push_back("TABLE_NAME"); rs_field_data.push_back("TABLE_COLLATION"); sql::SQLString query("SELECT TABLE_CATALOG AS TABLE_CAT, TABLE_SCHEMA AS TABLE_SCHEMA, " "TABLE_NAME, TABLE_COLLATION FROM INFORMATION_SCHEMA.TABLES where TABLE_NAME LIKE '"); query.append(escapedTableNamePattern).append("' ").append("AND TABLE_SCHEMA LIKE '"); query.append(escapedSchemaPattern).append("'"); std::unique_ptr<sql::Statement> stmt(connection->createStatement()); std::unique_ptr<sql::ResultSet> rs(stmt->executeQuery(query)); while (rs->next()) { MySQL_ArtResultSet::row_t rs_data_row; rs_data_row.push_back(rs->getString(1)); // TABLE_CAT rs_data_row.push_back(rs->getString(2)); // TABLE_SCHEM rs_data_row.push_back(rs->getString(3)); // TABLE_NAME rs_data_row.push_back(rs->getString(4)); // TABLE_COLLATION rs_data->push_back(rs_data_row); } MySQL_ArtResultSet * ret = new MySQL_ArtResultSet(rs_field_data, rs_data, logger); return ret; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::getTableCharset() -I- */ sql::ResultSet * MySQL_ConnectionMetaData::getTableCharset(const sql::SQLString& /* catalog */, const sql::SQLString& schemaPattern, const sql::SQLString& tableNamePattern) { CPP_ENTER("MySQL_ConnectionMetaData::getTableCharset"); CPP_INFO_FMT("schemaPattern=%s tablePattern=%s", schemaPattern.c_str(), tableNamePattern.c_str()); sql::SQLString escapedSchemaPattern = connection->escapeString(schemaPattern); sql::SQLString escapedTableNamePattern = connection->escapeString(tableNamePattern); std::shared_ptr<MySQL_ArtResultSet::rset_t> rs_data( new MySQL_ArtResultSet::rset_t()); std::list<sql::SQLString> rs_field_data; rs_field_data.push_back("TABLE_CAT"); rs_field_data.push_back("TABLE_SCHEMA"); rs_field_data.push_back("TABLE_NAME"); rs_field_data.push_back("TABLE_CHARSET"); sql::SQLString query("SELECT t.TABLE_CATALOG AS TABLE_CAT, t.TABLE_SCHEMA AS TABLE_SCHEMA, t.TABLE_NAME, " "c.CHARACTER_SET_NAME AS TABLE_CHARSET FROM INFORMATION_SCHEMA.TABLES t, " "INFORMATION_SCHEMA.COLLATION_CHARACTER_SET_APPLICABILITY c " "WHERE t.TABLE_COLLATION = c.COLLATION_NAME AND t.TABLE_NAME LIKE '"); query.append(escapedTableNamePattern).append("' ").append("AND t.TABLE_SCHEMA LIKE '"); query.append(escapedSchemaPattern).append("'"); std::unique_ptr<sql::Statement> stmt(connection->createStatement()); std::unique_ptr<sql::ResultSet> rs(stmt->executeQuery(query)); while (rs->next()) { MySQL_ArtResultSet::row_t rs_data_row; rs_data_row.push_back(rs->getString(1)); // TABLE_CAT rs_data_row.push_back(rs->getString(2)); // TABLE_SCHEM rs_data_row.push_back(rs->getString(3)); // TABLE_NAME rs_data_row.push_back(rs->getString(4)); // TABLE_CHARSET rs_data->push_back(rs_data_row); } MySQL_ArtResultSet * ret = new MySQL_ArtResultSet(rs_field_data, rs_data, logger); return ret; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::getTimeDateFunctions() -I- */ const sql::SQLString& MySQL_ConnectionMetaData::getTimeDateFunctions() { CPP_ENTER("MySQL_ConnectionMetaData::getTimeDateFunctions"); static const sql::SQLString funcs( "DAYOFWEEK,WEEKDAY,DAYOFMONTH,DAYOFYEAR,MONTH,DAYNAME," "MONTHNAME,QUARTER,WEEK,YEAR,HOUR,MINUTE,SECOND,PERIOD_ADD," "PERIOD_DIFF,TO_DAYS,FROM_DAYS,DATE_FORMAT,TIME_FORMAT," "CURDATE,CURRENT_DATE,CURTIME,CURRENT_TIME,NOW,SYSDATE," "CURRENT_TIMESTAMP,UNIX_TIMESTAMP,FROM_UNIXTIME," "SEC_TO_TIME,TIME_TO_SEC"); return funcs; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::getTypeInfo() -I- */ sql::ResultSet * MySQL_ConnectionMetaData::getTypeInfo() { CPP_ENTER("MySQL_ConnectionMetaData::getTypeInfo"); std::list<sql::SQLString> rs_field_data; rs_field_data.push_back("TYPE_NAME"); rs_field_data.push_back("DATA_TYPE"); rs_field_data.push_back("PRECISION"); rs_field_data.push_back("LITERAL_PREFIX"); rs_field_data.push_back("LITERAL_SUFFIX"); rs_field_data.push_back("CREATE_PARAMS"); rs_field_data.push_back("NULLABLE"); rs_field_data.push_back("CASE_SENSITIVE"); rs_field_data.push_back("SEARCHABLE"); rs_field_data.push_back("UNSIGNED_ATTRIBUTE"); rs_field_data.push_back("FIXED_PREC_SCALE"); rs_field_data.push_back("AUTO_INCREMENT"); rs_field_data.push_back("LOCAL_TYPE_NAME"); rs_field_data.push_back("MINIMUM_SCALE"); rs_field_data.push_back("MAXIMUM_SCALE"); rs_field_data.push_back("SQL_DATA_TYPE"); rs_field_data.push_back("SQL_DATETIME_SUB"); rs_field_data.push_back("NUM_PREC_RADIX"); std::shared_ptr<MySQL_ArtResultSet::rset_t> rs_data( new MySQL_ArtResultSet::rset_t()); int i = 0; while (mysqlc_types[i].typeName) { MySQL_ArtResultSet::row_t rs_data_row; const TypeInfoDef * const curr = &mysqlc_types[i]; rs_data_row.push_back(curr->typeName); rs_data_row.push_back((int64_t) curr->dataType); rs_data_row.push_back((int64_t) curr->precision); rs_data_row.push_back(curr->literalPrefix); rs_data_row.push_back(curr->literalSuffix); rs_data_row.push_back(curr->createParams); rs_data_row.push_back((int64_t) curr->nullable); rs_data_row.push_back((int64_t) curr->caseSensitive); rs_data_row.push_back((int64_t) curr->searchable); rs_data_row.push_back((int64_t) curr->isUnsigned); rs_data_row.push_back((int64_t) curr->fixedPrecScale); rs_data_row.push_back((int64_t) curr->autoIncrement); rs_data_row.push_back(curr->localTypeName); rs_data_row.push_back((int64_t) curr->minScale); rs_data_row.push_back((int64_t) curr->maxScale); rs_data_row.push_back((int64_t) curr->sqlDataType); rs_data_row.push_back((int64_t) curr->sqlDateTimeSub); rs_data_row.push_back((int64_t) curr->numPrecRadix); rs_data->push_back(rs_data_row); ++i; } MySQL_ArtResultSet * ret = new MySQL_ArtResultSet(rs_field_data, rs_data, logger); return ret; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::getUDTs() -I- */ sql::ResultSet * MySQL_ConnectionMetaData::getUDTs(const sql::SQLString& /*catalog*/, const sql::SQLString& /*schemaPattern*/, const sql::SQLString& /*typeNamePattern*/, std::list<int> & /*types*/) { CPP_ENTER("MySQL_ConnectionMetaData::getUDTs"); std::list<sql::SQLString> rs_field_data; rs_field_data.push_back("TYPE_CAT"); rs_field_data.push_back("TYPE_SCHEM"); rs_field_data.push_back("TYPE_NAME"); rs_field_data.push_back("CLASS_NAME"); rs_field_data.push_back("DATA_TYPE"); rs_field_data.push_back("REMARKS"); std::shared_ptr<MySQL_ArtResultSet::rset_t> rs_data( new MySQL_ArtResultSet::rset_t()); MySQL_ArtResultSet * ret = new MySQL_ArtResultSet(rs_field_data, rs_data, logger); return ret; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::getURL() -U- */ SQLString MySQL_ConnectionMetaData::getURL() { CPP_ENTER("MySQL_ConnectionMetaData::getURL"); throw sql::MethodNotImplementedException("MySQL_ConnectionMetaData::getURL"); return ""; // This will shut up compilers } /* }}} */ /* {{{ MySQL_ConnectionMetaData::getUserName() -I- */ SQLString MySQL_ConnectionMetaData::getUserName() { CPP_ENTER("MySQL_ConnectionMetaData::getUserName"); std::unique_ptr<sql::ResultSet> rset(stmt->executeQuery("SELECT USER()")); if (rset->next()) { return sql::SQLString(rset->getString(1)); } return ""; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::getVersionColumns() -I- */ sql::ResultSet * MySQL_ConnectionMetaData::getVersionColumns(const sql::SQLString& /*catalog*/, const sql::SQLString& /*schema*/, const sql::SQLString& /*table*/) { CPP_ENTER("MySQL_ConnectionMetaData::getVersionColumns"); std::list<sql::SQLString> rs_field_data; rs_field_data.push_back("SCOPE"); rs_field_data.push_back("COLUMN_NAME"); rs_field_data.push_back("DATA_TYPE"); rs_field_data.push_back("TYPE_NAME"); rs_field_data.push_back("COLUMN_SIZE"); rs_field_data.push_back("BUFFER_LENGTH"); rs_field_data.push_back("DECIMAL_DIGITS"); rs_field_data.push_back("PSEUDO_COLUMN"); std::shared_ptr<MySQL_ArtResultSet::rset_t> rs_data( new MySQL_ArtResultSet::rset_t()); MySQL_ArtResultSet * ret = new MySQL_ArtResultSet(rs_field_data, rs_data, logger); return ret; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::insertsAreDetected() -I- */ bool MySQL_ConnectionMetaData::insertsAreDetected(int /* type */) { CPP_ENTER("MySQL_ConnectionMetaData::insertsAreDetected"); return false; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::isCatalogAtStart() -I- */ bool MySQL_ConnectionMetaData::isCatalogAtStart() { CPP_ENTER("MySQL_ConnectionMetaData::isCatalogAtStart"); return true; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::isReadOnly() -I- */ bool MySQL_ConnectionMetaData::isReadOnly() { return false; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::locatorsUpdateCopy() -U- */ bool MySQL_ConnectionMetaData::locatorsUpdateCopy() { CPP_ENTER("MySQL_ConnectionMetaData::locatorsUpdateCopy"); throw sql::MethodNotImplementedException("MySQL_ConnectionMetaData::locatorsUpdateCopy"); return false; // This will shut up compilers } /* }}} */ /* {{{ MySQL_ConnectionMetaData::nullPlusNonNullIsNull() -I- */ bool MySQL_ConnectionMetaData::nullPlusNonNullIsNull() { CPP_ENTER("MySQL_ConnectionMetaData::nullPlusNonNullIsNull"); return true; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::nullsAreSortedAtEnd() -I- */ bool MySQL_ConnectionMetaData::nullsAreSortedAtEnd() { CPP_ENTER("MySQL_ConnectionMetaData::nullsAreSortedAtEnd"); return false; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::nullsAreSortedAtStart() -I- */ bool MySQL_ConnectionMetaData::nullsAreSortedAtStart() { CPP_ENTER("MySQL_ConnectionMetaData::nullsAreSortedAtStart"); return server_version > 40001 && server_version < 40011; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::nullsAreSortedHigh() -I- */ bool MySQL_ConnectionMetaData::nullsAreSortedHigh() { CPP_ENTER("MySQL_ConnectionMetaData::nullsAreSortedHigh"); return false; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::nullsAreSortedLow() -I- */ bool MySQL_ConnectionMetaData::nullsAreSortedLow() { CPP_ENTER("MySQL_ConnectionMetaData::nullsAreSortedLow"); return !nullsAreSortedHigh(); } /* }}} */ /* {{{ MySQL_ConnectionMetaData::othersDeletesAreVisible() -I- */ bool MySQL_ConnectionMetaData::othersDeletesAreVisible(int /* type */) { CPP_ENTER("MySQL_ConnectionMetaData::othersDeletesAreVisible"); return false; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::othersInsertsAreVisible() -I- */ bool MySQL_ConnectionMetaData::othersInsertsAreVisible(int /* type */) { CPP_ENTER("MySQL_ConnectionMetaData::othersInsertsAreVisible"); return false; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::othersUpdatesAreVisible() -I- */ bool MySQL_ConnectionMetaData::othersUpdatesAreVisible(int /* type */) { CPP_ENTER("MySQL_ConnectionMetaData::othersUpdatesAreVisible"); return false; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::ownDeletesAreVisible() -I- */ bool MySQL_ConnectionMetaData::ownDeletesAreVisible(int /* type */) { CPP_ENTER("MySQL_ConnectionMetaData::ownDeletesAreVisible"); return false; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::ownInsertsAreVisible() -I- */ bool MySQL_ConnectionMetaData::ownInsertsAreVisible(int /* type */) { CPP_ENTER("MySQL_ConnectionMetaData::ownInsertsAreVisible"); return false; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::ownUpdatesAreVisible() -I- */ bool MySQL_ConnectionMetaData::ownUpdatesAreVisible(int /* type */) { CPP_ENTER("MySQL_ConnectionMetaData::ownUpdatesAreVisible"); return false; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::storesLowerCaseIdentifiers() -I- */ bool MySQL_ConnectionMetaData::storesLowerCaseIdentifiers() { CPP_ENTER("MySQL_ConnectionMetaData::storesLowerCaseIdentifiers"); if(lower_case_table_names->empty()) lower_case_table_names = connection->getSessionVariable("lower_case_table_names"); return (lower_case_table_names.compare("1")==0 || lower_case_table_names.compare("2")==0); } /* }}} */ /* {{{ MySQL_ConnectionMetaData::storesLowerCaseQuotedIdentifiers() -I- */ bool MySQL_ConnectionMetaData::storesLowerCaseQuotedIdentifiers() { CPP_ENTER("MySQL_ConnectionMetaData::storesLowerCaseQuotedIdentifiers"); if(lower_case_table_names->empty()) lower_case_table_names = connection->getSessionVariable("lower_case_table_names"); return (lower_case_table_names.compare("1")==0 || lower_case_table_names.compare("2")==0); } /* }}} */ /* {{{ MySQL_ConnectionMetaData::storesMixedCaseIdentifiers() -I- */ bool MySQL_ConnectionMetaData::storesMixedCaseIdentifiers() { CPP_ENTER("MySQL_ConnectionMetaData::storesMixedCaseIdentifiers"); if(lower_case_table_names->empty()) lower_case_table_names = connection->getSessionVariable("lower_case_table_names"); return !(lower_case_table_names.compare("1")==0 || lower_case_table_names.compare("2")==0); } /* }}} */ /* {{{ MySQL_ConnectionMetaData::storesMixedCaseQuotedIdentifiers() -I- */ bool MySQL_ConnectionMetaData::storesMixedCaseQuotedIdentifiers() { CPP_ENTER("MySQL_ConnectionMetaData::storesMixedCaseQuotedIdentifiers"); if(lower_case_table_names->empty()) lower_case_table_names = connection->getSessionVariable("lower_case_table_names"); return !(lower_case_table_names.compare("1")==0 || lower_case_table_names.compare("2")==0); } /* }}} */ /* {{{ MySQL_ConnectionMetaData::storesUpperCaseIdentifiers() -I- */ bool MySQL_ConnectionMetaData::storesUpperCaseIdentifiers() { CPP_ENTER("MySQL_ConnectionMetaData::storesUpperCaseIdentifiers"); return false; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::storesUpperCaseQuotedIdentifiers() -I- */ bool MySQL_ConnectionMetaData::storesUpperCaseQuotedIdentifiers() { CPP_ENTER("MySQL_ConnectionMetaData::storesUpperCaseQuotedIdentifiers"); return true; // not actually true, but required by JDBC spec!? } /* }}} */ /* {{{ MySQL_ConnectionMetaData::supportsAlterTableWithAddColumn() -I- */ bool MySQL_ConnectionMetaData::supportsAlterTableWithAddColumn() { CPP_ENTER("MySQL_ConnectionMetaData::supportsAlterTableWithAddColumn"); return true; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::supportsAlterTableWithDropColumn() -I- */ bool MySQL_ConnectionMetaData::supportsAlterTableWithDropColumn() { CPP_ENTER("MySQL_ConnectionMetaData::supportsAlterTableWithDropColumn"); return true; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::supportsANSI92EntryLevelSQL -I- */ bool MySQL_ConnectionMetaData::supportsANSI92EntryLevelSQL() { CPP_ENTER("MySQL_ConnectionMetaData::supportsANSI92EntryLevelSQL"); return true; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::supportsANSI92FullSQL() -I- */ bool MySQL_ConnectionMetaData::supportsANSI92FullSQL() { CPP_ENTER("MySQL_ConnectionMetaData::supportsANSI92FullSQL"); return false; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::supportsANSI92IntermediateSQL() -I- */ bool MySQL_ConnectionMetaData::supportsANSI92IntermediateSQL() { CPP_ENTER("MySQL_ConnectionMetaData::supportsANSI92IntermediateSQL"); return false; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::supportsBatchUpdates() -I- */ bool MySQL_ConnectionMetaData::supportsBatchUpdates() { CPP_ENTER("MySQL_ConnectionMetaData::supportsBatchUpdates"); return true; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::supportsCatalogsInDataManipulation() -I- */ bool MySQL_ConnectionMetaData::supportsCatalogsInDataManipulation() { CPP_ENTER("MySQL_ConnectionMetaData::supportsCatalogsInDataManipulation"); return false; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::supportsCatalogsInIndexDefinitions() -I- */ bool MySQL_ConnectionMetaData::supportsCatalogsInIndexDefinitions() { CPP_ENTER("MySQL_ConnectionMetaData::supportsCatalogsInIndexDefinitions"); return false; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::supportsCatalogsInPrivilegeDefinitions() -I- */ bool MySQL_ConnectionMetaData::supportsCatalogsInPrivilegeDefinitions() { CPP_ENTER("MySQL_ConnectionMetaData::supportsCatalogsInPrivilegeDefinitions"); return false; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::supportsCatalogsInProcedureCalls() -I- */ bool MySQL_ConnectionMetaData::supportsCatalogsInProcedureCalls() { CPP_ENTER("MySQL_ConnectionMetaData::supportsCatalogsInProcedureCalls"); return false; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::supportsCatalogsInTableDefinitions() -I- */ bool MySQL_ConnectionMetaData::supportsCatalogsInTableDefinitions() { CPP_ENTER("MySQL_ConnectionMetaData::supportsCatalogsInTableDefinitions"); return false; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::supportsColumnAliasing() -I- */ bool MySQL_ConnectionMetaData::supportsColumnAliasing() { CPP_ENTER("MySQL_ConnectionMetaData::supportsColumnAliasing"); return true; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::supportsConvert() -I- */ bool MySQL_ConnectionMetaData::supportsConvert() { CPP_ENTER("MySQL_ConnectionMetaData::supportsConvert"); return false; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::supportsConvert() -I- */ bool MySQL_ConnectionMetaData::supportsConvert(int fromType, int toType) { CPP_ENTER("MySQL_ConnectionMetaData::supportsConvert"); switch (fromType) { // The char/binary types can be converted to pretty much anything. case sql::DataType::BINARY: case sql::DataType::VARBINARY: case sql::DataType::LONGVARBINARY: #if HAVE_TYPE_VECTOR // Binary types can be converted to VECTOR if (toType == sql::DataType::VECTOR) return true; #endif case sql::DataType::CHAR: case sql::DataType::VARCHAR: case sql::DataType::LONGVARCHAR: { switch (toType) { case sql::DataType::DECIMAL: case sql::DataType::NUMERIC: case sql::DataType::REAL: case sql::DataType::TINYINT: case sql::DataType::SMALLINT: case sql::DataType::INTEGER: case sql::DataType::BIGINT: case sql::DataType::DOUBLE: case sql::DataType::CHAR: case sql::DataType::VARCHAR: case sql::DataType::LONGVARCHAR: case sql::DataType::BINARY: case sql::DataType::VARBINARY: case sql::DataType::LONGVARBINARY: case sql::DataType::DATE: case sql::DataType::TIME: case sql::DataType::TIMESTAMP: return true; default: return false; } } // We don't handle the BIT type yet. case sql::DataType::BIT: return false; // The numeric types. Basically they can convert among themselves, and case sql::DataType::DECIMAL: case sql::DataType::NUMERIC: case sql::DataType::REAL: case sql::DataType::TINYINT: case sql::DataType::SMALLINT: case sql::DataType::INTEGER: case sql::DataType::BIGINT: case sql::DataType::DOUBLE: { switch (toType) { case sql::DataType::DECIMAL: case sql::DataType::NUMERIC: case sql::DataType::REAL: case sql::DataType::TINYINT: case sql::DataType::SMALLINT: case sql::DataType::INTEGER: case sql::DataType::BIGINT: case sql::DataType::DOUBLE: case sql::DataType::CHAR: case sql::DataType::VARCHAR: case sql::DataType::LONGVARCHAR: case sql::DataType::BINARY: case sql::DataType::VARBINARY: case sql::DataType::LONGVARBINARY: return true; default: return false; } } // MySQL doesn't support a NULL type case sql::DataType::SQLNULL: return false; // Dates can be converted to char/binary types case sql::DataType::DATE: { switch (toType) { case sql::DataType::CHAR: case sql::DataType::VARCHAR: case sql::DataType::LONGVARCHAR: case sql::DataType::BINARY: case sql::DataType::VARBINARY: case sql::DataType::LONGVARBINARY: return true; default: return false; } } // Time can be converted to char/binary types case sql::DataType::TIME: { switch (toType) { case sql::DataType::CHAR: case sql::DataType::VARCHAR: case sql::DataType::LONGVARCHAR: case sql::DataType::BINARY: case sql::DataType::VARBINARY: case sql::DataType::LONGVARBINARY: return true; default: return false; } } // Timestamp can be converted to char/binary types and date/time types (with loss of precision). case sql::DataType::TIMESTAMP: { switch (toType) { case sql::DataType::CHAR: case sql::DataType::VARCHAR: case sql::DataType::LONGVARCHAR: case sql::DataType::BINARY: case sql::DataType::VARBINARY: case sql::DataType::LONGVARBINARY: case sql::DataType::TIME: case sql::DataType::DATE: return true; default: return false; } } #if HAVE_TYPE_VECTOR // VECTOR can only be converted to binary types case sql::DataType::VECTOR: { switch (toType) { case sql::DataType::BINARY: case sql::DataType::VARBINARY: case sql::DataType::LONGVARBINARY: return true; default: return false; } } #endif // We shouldn't get here! default: return false; // not sure } } /* }}} */ /* {{{ MySQL_ConnectionMetaData::supportsCoreSQLGrammar() -I- */ bool MySQL_ConnectionMetaData::supportsCoreSQLGrammar() { CPP_ENTER("MySQL_ConnectionMetaData::supportsCoreSQLGrammar"); return true; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::supportsCorrelatedSubqueries() -I- */ bool MySQL_ConnectionMetaData::supportsCorrelatedSubqueries() { CPP_ENTER("MySQL_ConnectionMetaData::supportsCorrelatedSubqueries"); return server_version >= 40100; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::supportsDataDefinitionAndDataManipulationTransactions() -I- */ bool MySQL_ConnectionMetaData::supportsDataDefinitionAndDataManipulationTransactions() { CPP_ENTER("MySQL_ConnectionMetaData::supportsDataDefinitionAndDataManipulationTransactions"); return false; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::supportsDataManipulationTransactionsOnly() -I- */ bool MySQL_ConnectionMetaData::supportsDataManipulationTransactionsOnly() { CPP_ENTER("MySQL_ConnectionMetaData::supportsDataManipulationTransactionsOnly"); return false; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::supportsDifferentTableCorrelationNames() -I- */ bool MySQL_ConnectionMetaData::supportsDifferentTableCorrelationNames() { CPP_ENTER("MySQL_ConnectionMetaData::supportsDifferentTableCorrelationNames"); return true; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::supportsExpressionsInOrderBy() -I- */ bool MySQL_ConnectionMetaData::supportsExpressionsInOrderBy() { CPP_ENTER("MySQL_ConnectionMetaData::supportsExpressionsInOrderBy"); return true; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::supportsExtendedSQLGrammar() -I- */ bool MySQL_ConnectionMetaData::supportsExtendedSQLGrammar() { CPP_ENTER("MySQL_ConnectionMetaData::supportsExtendedSQLGrammar"); return false; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::supportsFullOuterJoins() -I- */ bool MySQL_ConnectionMetaData::supportsFullOuterJoins() { CPP_ENTER("MySQL_ConnectionMetaData::supportsFullOuterJoins"); return false; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::supportsGetGeneratedKeys() -I- */ bool MySQL_ConnectionMetaData::supportsGetGeneratedKeys() { CPP_ENTER("MySQL_ConnectionMetaData::supportsGetGeneratedKeys"); return true; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::supportsGroupBy() -I- */ bool MySQL_ConnectionMetaData::supportsGroupBy() { CPP_ENTER("MySQL_ConnectionMetaData::supportsGroupBy"); return true; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::supportsGroupByBeyondSelect() -I- */ bool MySQL_ConnectionMetaData::supportsGroupByBeyondSelect() { CPP_ENTER("MySQL_ConnectionMetaData::supportsGroupByBeyondSelect"); return true; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::supportsGroupByUnrelated() -I- */ bool MySQL_ConnectionMetaData::supportsGroupByUnrelated() { CPP_ENTER("MySQL_ConnectionMetaData::supportsGroupByUnrelated"); return true; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::supportsIntegrityEnhancementFacility() -U- */ bool MySQL_ConnectionMetaData::supportsIntegrityEnhancementFacility() { CPP_ENTER("MySQL_ConnectionMetaData::supportsIntegrityEnhancementFacility"); throw sql::MethodNotImplementedException("MySQL_ConnectionMetaData::supportsIntegrityEnhancementFacility"); return false; // This will shut up compilers } /* }}} */ /* {{{ MySQL_ConnectionMetaData::supportsLikeEscapeClause() -I- */ bool MySQL_ConnectionMetaData::supportsLikeEscapeClause() { CPP_ENTER("MySQL_ConnectionMetaData::supportsLikeEscapeClause"); return true; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::supportsLimitedOuterJoins() -I- */ bool MySQL_ConnectionMetaData::supportsLimitedOuterJoins() { CPP_ENTER("MySQL_ConnectionMetaData::supportsLimitedOuterJoins"); return true; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::supportsMinimumSQLGrammar() -I- */ bool MySQL_ConnectionMetaData::supportsMinimumSQLGrammar() { CPP_ENTER("MySQL_ConnectionMetaData::supportsMinimumSQLGrammar"); return true; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::supportsMixedCaseIdentifiers() -I- */ bool MySQL_ConnectionMetaData::supportsMixedCaseIdentifiers() { CPP_ENTER("MySQL_ConnectionMetaData::supportsMixedCaseIdentifiers"); if(lower_case_table_names->empty()) lower_case_table_names = connection->getSessionVariable("lower_case_table_names"); return !((lower_case_table_names.compare("1") || lower_case_table_names.compare("2"))); } /* }}} */ /* {{{ MySQL_ConnectionMetaData::supportsMixedCaseQuotedIdentifiers() -I- */ bool MySQL_ConnectionMetaData::supportsMixedCaseQuotedIdentifiers() { CPP_ENTER("MySQL_ConnectionMetaData::supportsMixedCaseQuotedIdentifiers"); if(lower_case_table_names->empty()) lower_case_table_names = connection->getSessionVariable("lower_case_table_names"); return !((lower_case_table_names.compare("1") || lower_case_table_names.compare("2"))); } /* }}} */ /* {{{ MySQL_ConnectionMetaData::supportsMultipleOpenResults() -I- */ bool MySQL_ConnectionMetaData::supportsMultipleOpenResults() { CPP_ENTER("MySQL_ConnectionMetaData::supportsMultipleOpenResults"); return true; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::supportsMultipleResultSets() -I- */ bool MySQL_ConnectionMetaData::supportsMultipleResultSets() { CPP_ENTER("MySQL_ConnectionMetaData::supportsMultipleResultSets"); return false; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::supportsMultipleTransactions() -I- */ bool MySQL_ConnectionMetaData::supportsMultipleTransactions() { CPP_ENTER("MySQL_ConnectionMetaData::supportsMultipleTransactions"); return true; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::supportsNamedParameters() -I- */ bool MySQL_ConnectionMetaData::supportsNamedParameters() { CPP_ENTER("MySQL_ConnectionMetaData::supportsNamedParameters"); return false; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::supportsNonNullableColumns() -I- */ bool MySQL_ConnectionMetaData::supportsNonNullableColumns() { CPP_ENTER("MySQL_ConnectionMetaData::supportsNonNullableColumns"); return true; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::supportsOpenCursorsAcrossCommit() -I- */ bool MySQL_ConnectionMetaData::supportsOpenCursorsAcrossCommit() { CPP_ENTER("MySQL_ConnectionMetaData::supportsOpenCursorsAcrossCommit"); return false; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::supportsOpenCursorsAcrossRollback() -I- */ bool MySQL_ConnectionMetaData::supportsOpenCursorsAcrossRollback() { CPP_ENTER("MySQL_ConnectionMetaData::supportsOpenCursorsAcrossRollback"); return false; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::supportsOpenStatementsAcrossCommit() -I- */ bool MySQL_ConnectionMetaData::supportsOpenStatementsAcrossCommit() { CPP_ENTER("MySQL_ConnectionMetaData::supportsOpenStatementsAcrossCommit"); return false; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::supportsOpenStatementsAcrossRollback() -I- */ bool MySQL_ConnectionMetaData::supportsOpenStatementsAcrossRollback() { CPP_ENTER("MySQL_ConnectionMetaData::supportsOpenStatementsAcrossRollback"); return false; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::supportsOrderByUnrelated() -I- */ bool MySQL_ConnectionMetaData::supportsOrderByUnrelated() { CPP_ENTER("MySQL_ConnectionMetaData::supportsOrderByUnrelated"); return false; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::supportsOuterJoins() -I- */ bool MySQL_ConnectionMetaData::supportsOuterJoins() { CPP_ENTER("MySQL_ConnectionMetaData::supportsOuterJoins"); return true; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::supportsPositionedDelete() -I- */ bool MySQL_ConnectionMetaData::supportsPositionedDelete() { CPP_ENTER("MySQL_ConnectionMetaData::supportsPositionedDelete"); return false; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::supportsPositionedUpdate() -I- */ bool MySQL_ConnectionMetaData::supportsPositionedUpdate() { CPP_ENTER("MySQL_ConnectionMetaData::supportsPositionedUpdate"); return false; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::supportsResultSetConcurrency() -U- */ bool MySQL_ConnectionMetaData::supportsResultSetConcurrency(int /* type */, int /* concurrency */) { CPP_ENTER("MySQL_ConnectionMetaData::supportsResultSetConcurrency"); throw sql::MethodNotImplementedException("MySQL_ConnectionMetaData::supportsResultSetConcurrency"); return false; // This will shut up compilers } /* }}} */ /* {{{ MySQL_ConnectionMetaData::supportsResultSetHoldability() -I- */ bool MySQL_ConnectionMetaData::supportsResultSetHoldability(int holdability) { CPP_ENTER("MySQL_ConnectionMetaData::supportsResultSetHoldability"); return (holdability == sql::ResultSet::HOLD_CURSORS_OVER_COMMIT); } /* }}} */ /* {{{ MySQL_ConnectionMetaData::supportsResultSetType() -I- */ bool MySQL_ConnectionMetaData::supportsResultSetType(int type) { CPP_ENTER("MySQL_ConnectionMetaData::supportsResultSetType"); return (type == sql::ResultSet::TYPE_SCROLL_INSENSITIVE); } /* }}} */ /* {{{ MySQL_ConnectionMetaData::supportsSavepoints() -I- */ bool MySQL_ConnectionMetaData::supportsSavepoints() { CPP_ENTER("MySQL_ConnectionMetaData::supportsSavepoints"); return (server_version >= 40014 || server_version >= 40101); } /* }}} */ /* {{{ MySQL_ConnectionMetaData::supportsSchemasInDataManipulation() -I- */ bool MySQL_ConnectionMetaData::supportsSchemasInDataManipulation() { CPP_ENTER("MySQL_ConnectionMetaData::supportsSchemasInDataManipulation"); return server_version >= 32200; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::supportsSchemasInIndexDefinitions() -I- */ bool MySQL_ConnectionMetaData::supportsSchemasInIndexDefinitions() { CPP_ENTER("MySQL_ConnectionMetaData::supportsSchemasInIndexDefinitions"); return server_version >= 32200; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::supportsSchemasInPrivilegeDefinitions() -I- */ bool MySQL_ConnectionMetaData::supportsSchemasInPrivilegeDefinitions() { CPP_ENTER("MySQL_ConnectionMetaData::supportsSchemasInPrivilegeDefinitions"); return server_version > 32200; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::supportsSchemasInProcedureCalls() -I- */ bool MySQL_ConnectionMetaData::supportsSchemasInProcedureCalls() { CPP_ENTER("MySQL_ConnectionMetaData::supportsSchemasInProcedureCalls"); return server_version >= 32200; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::supportsSchemasInTableDefinitions() -I- */ bool MySQL_ConnectionMetaData::supportsSchemasInTableDefinitions() { CPP_ENTER("MySQL_ConnectionMetaData::supportsSchemasInTableDefinitions"); return server_version >= 32200; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::supportsSelectForUpdate() -I- */ bool MySQL_ConnectionMetaData::supportsSelectForUpdate() { CPP_ENTER("MySQL_ConnectionMetaData::supportsSelectForUpdate"); return server_version >= 40000; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::supportsStatementPooling() -I- */ bool MySQL_ConnectionMetaData::supportsStatementPooling() { CPP_ENTER("MySQL_ConnectionMetaData::supportsStatementPooling"); return false; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::supportsStoredProcedures() -I- */ bool MySQL_ConnectionMetaData::supportsStoredProcedures() { CPP_ENTER("MySQL_ConnectionMetaData::supportsStoredProcedures"); return server_version >= 50000; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::supportsSubqueriesInComparisons() -I- */ bool MySQL_ConnectionMetaData::supportsSubqueriesInComparisons() { CPP_ENTER("MySQL_ConnectionMetaData::supportsSubqueriesInComparisons"); return server_version >= 40100; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::supportsSubqueriesInExists() -I- */ bool MySQL_ConnectionMetaData::supportsSubqueriesInExists() { CPP_ENTER("MySQL_ConnectionMetaData::supportsSubqueriesInExists"); return server_version >= 40100; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::supportsSubqueriesInIns() -I- */ bool MySQL_ConnectionMetaData::supportsSubqueriesInIns() { CPP_ENTER("MySQL_ConnectionMetaData::supportsSubqueriesInIns"); return server_version >= 40100; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::supportsSubqueriesInQuantifieds() -I- */ bool MySQL_ConnectionMetaData::supportsSubqueriesInQuantifieds() { CPP_ENTER("MySQL_ConnectionMetaData::supportsSubqueriesInQuantifieds"); return server_version >= 40100; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::supportsTableCorrelationNames() -I- */ bool MySQL_ConnectionMetaData::supportsTableCorrelationNames() { CPP_ENTER("MySQL_ConnectionMetaData::supportsTableCorrelationNames"); return true; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::supportsTransactionIsolationLevel() -I- */ bool MySQL_ConnectionMetaData::supportsTransactionIsolationLevel(int /* level */) { CPP_ENTER("MySQL_ConnectionMetaData::supportsTransactionIsolationLevel"); return server_version >= 32336; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::supportsTransactions() -I- */ bool MySQL_ConnectionMetaData::supportsTransactions() { CPP_ENTER("MySQL_ConnectionMetaData::supportsTransactions"); return server_version >= 32315; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::supportsTypeConversion() -I- */ bool MySQL_ConnectionMetaData::supportsTypeConversion() { CPP_ENTER("MySQL_ConnectionMetaData::supportsTypeConversion"); return true; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::supportsUnion() -I- */ bool MySQL_ConnectionMetaData::supportsUnion() { CPP_ENTER("MySQL_ConnectionMetaData::supportsUnion"); return server_version >= 40000; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::supportsUnionAll() -I- */ bool MySQL_ConnectionMetaData::supportsUnionAll() { CPP_ENTER("MySQL_ConnectionMetaData::supportsUnionAll"); return server_version >= 40000; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::updatesAreDetected() -I- */ bool MySQL_ConnectionMetaData::updatesAreDetected(int /* type */) { CPP_ENTER("MySQL_ConnectionMetaData::updatesAreDetected"); return false; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::usesLocalFilePerTable() -I- */ bool MySQL_ConnectionMetaData::usesLocalFilePerTable() { CPP_ENTER("MySQL_ConnectionMetaData::usesLocalFilePerTable"); return false; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::usesLocalFiles() -I- */ bool MySQL_ConnectionMetaData::usesLocalFiles() { CPP_ENTER("MySQL_ConnectionMetaData::usesLocalFiles"); return false; } /* }}} */ /* {{{ MySQL_ConnectionMetaData::matchTable() -I- */ bool MySQL_ConnectionMetaData::matchTable(const sql::SQLString & sPattern, const sql::SQLString & tPattern, const sql::SQLString & schema, const sql::SQLString & table) { CPP_ENTER("MySQL_ConnectionMetaData::matchTable"); return (!sPattern.compare("*") || !sPattern.compare(schema)) && (!tPattern.compare("*") || !tPattern.compare(table)); } } /* namespace mysql */ } /* namespace sql */ /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: * vim600: noet sw=4 ts=4 fdm=marker * vim<600: noet sw=4 ts=4 */