getTablePrivileges() finds columns by names instead of numbers v_0
authorFrantišek Kučera <franta-hg@frantovo.cz>
Tue, 02 Jun 2020 20:57:12 +0200
branchv_0
changeset 43 7f396cdb9628
parent 42 7f668a5a435b
child 44 ec9694f3b343
getTablePrivileges() finds columns by names instead of numbers
src/Connection.cpp
src/Connection.h
src/ResultSet.cpp
src/ResultSet.h
--- a/src/Connection.cpp	Tue Jun 02 18:40:20 2020 +0200
+++ b/src/Connection.cpp	Tue Jun 02 20:57:12 2020 +0200
@@ -64,45 +64,31 @@
 	if (OdbcCommon::isNotSuccessful(result)) throw SqlException(L"Unable to ROLLBACK: " + std::to_wstring(result));
 }
 
-std::vector<Connection::TableMetaData> Connection::getTables() {
-	std::vector<TableMetaData> tables;
-	SQLHSTMT statementHandle = OdbcCommon::allocateHandle(SQL_HANDLE_STMT, connection);
-	SQLRETURN result = SQLTables(statementHandle, nullptr, 0, nullptr, 0, nullptr, 0, nullptr, 0);
-	if (OdbcCommon::isNotSuccessful(result)) {
-		OdbcCommon::freeHandle(SQL_HANDLE_STMT, statementHandle);
-		throw SqlException(L"Unable get tables (prepare)", result, SQL_HANDLE_DBC, connection); // TODO: SQL_HANDLE_STMT?
-	}
-	ResultSet resultSet(statementHandle);
-	while (resultSet.next()) {
-		TableMetaData tm;
-		tm.catalog = resultSet.getString(1); // FIXME: column name: table_cat
-		tm.schema = resultSet.getString(2); // FIXME: column name: table_schem
-		tm.name = resultSet.getString(3); // FIXME: column name: table_name
-		tm.type = resultSet.getString(4); // FIXME: column name: table_type
-		tables.emplace_back(tm);
-	}
-
-	return tables;
-}
-
 std::vector<Connection::TablePrivilege> Connection::getTablePrivileges() {
 	std::vector<TablePrivilege> tables;
 	SQLHSTMT statementHandle = OdbcCommon::allocateHandle(SQL_HANDLE_STMT, connection);
 	SQLRETURN result = SQLTablePrivileges(statementHandle, nullptr, 0, nullptr, 0, nullptr, 0);
-	if (OdbcCommon::isNotSuccessful(result)) {
-		OdbcCommon::freeHandle(SQL_HANDLE_STMT, statementHandle);
-		throw SqlException(L"Unable get tables (prepare)", result, SQL_HANDLE_DBC, connection); // TODO: SQL_HANDLE_STMT?
-	}
+	if (OdbcCommon::isNotSuccessful(result)) throw SqlException(L"Unable get tables (prepare)", result, SQL_HANDLE_STMT, statementHandle, true);
+
 	ResultSet resultSet(statementHandle);
+	std::shared_ptr<ResultSet::MetaData> metaData(resultSet.getMetaData());
+	SQLUSMALLINT catalogColumn = metaData->getColumnNumber(L"TABLE_CAT");
+	SQLUSMALLINT schemaColumn = metaData->getColumnNumber(L"TABLE_SCHEM");
+	SQLUSMALLINT nameColumn = metaData->getColumnNumber(L"TABLE_NAME");
+	SQLUSMALLINT grantorColumn = metaData->getColumnNumber(L"GRANTOR");
+	SQLUSMALLINT granteeColumn = metaData->getColumnNumber(L"GRANTEE");
+	SQLUSMALLINT privilegeColumn = metaData->getColumnNumber(L"PRIVILEGE");
+	SQLUSMALLINT isGrantableColumn = metaData->getColumnNumber(L"IS_GRANTABLE");
+
 	while (resultSet.next()) {
 		TablePrivilege tp;
-		tp.catalog = resultSet.getString(1); // FIXME: column name: table_cat
-		tp.schema = resultSet.getString(2); // FIXME: column name: table_schem
-		tp.name = resultSet.getString(3); // FIXME: column name: table_name
-		tp.grantor = resultSet.getString(4); // FIXME: column name: grantor
-		tp.grantee = resultSet.getString(5); // FIXME: column name: grantee
-		tp.privilege = resultSet.getString(6); // FIXME: column name: privilege
-		tp.isGrantable = resultSet.getString(7) == L"YES"; // FIXME: column name: is_grantable
+		tp.catalog = resultSet.getString(catalogColumn);
+		tp.schema = resultSet.getString(schemaColumn);
+		tp.name = resultSet.getString(nameColumn);
+		tp.grantor = resultSet.getString(grantorColumn);
+		tp.grantee = resultSet.getString(granteeColumn);
+		tp.privilege = resultSet.getString(privilegeColumn);
+		tp.isGrantable = resultSet.getString(isGrantableColumn) == L"YES";
 		tables.emplace_back(tp);
 	}
 
--- a/src/Connection.h	Tue Jun 02 18:40:20 2020 +0200
+++ b/src/Connection.h	Tue Jun 02 20:57:12 2020 +0200
@@ -48,7 +48,6 @@
 		relpipe::reader::string_t name;
 		relpipe::reader::string_t type;
 	};
-	std::vector<TableMetaData> getTables();
 
 	class TablePrivilege : public TableMetaData {
 	public:
--- a/src/ResultSet.cpp	Tue Jun 02 18:40:20 2020 +0200
+++ b/src/ResultSet.cpp	Tue Jun 02 20:57:12 2020 +0200
@@ -15,6 +15,9 @@
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <sstream>
+#include <algorithm>
+
 #include <sql.h>
 #include <sqlext.h>
 
@@ -107,7 +110,17 @@
 	else throw SqlException(L"Unable to describe column " + std::to_wstring(columnNumber) + L", out of bounds, column count is " + std::to_wstring(columnCount));
 }
 
+SQLUSMALLINT ResultSet::MetaData::getColumnNumber(relpipe::writer::string_t columnName) {
+	// TODO: also case insensitive mode
+	for (SQLUSMALLINT i = 0; i < columnDescriptors.size(); i++) {
+		if (columnDescriptors[i].name == columnName) return i + 1;
+	}
 
+	std::wstringstream errorMessage;
+	errorMessage << L"Unable to find column with name „" << columnName.c_str() << L"“ Availalable columns are: ";
+	for (MetaData::ColumnDescriptor cd : columnDescriptors) errorMessage << L"„" << cd.name.c_str() << L"“ ";
+	throw SqlException(errorMessage.str());
+}
 
 }
 }
--- a/src/ResultSet.h	Tue Jun 02 18:40:20 2020 +0200
+++ b/src/ResultSet.h	Tue Jun 02 20:57:12 2020 +0200
@@ -48,6 +48,7 @@
 		virtual ~MetaData();
 		unsigned short getColumnCount();
 		ColumnDescriptor describeColumn(unsigned short columnNumber);
+		unsigned short getColumnNumber(relpipe::writer::string_t columnName);
 	};
 private:
 	void* statement;