static SQLRETURN
MNDBTablePrivileges(ODBCStmt *stmt,
		    SQLCHAR *CatalogName,
		    SQLSMALLINT NameLength1,
		    SQLCHAR *SchemaName,
		    SQLSMALLINT NameLength2,
		    SQLCHAR *TableName,
		    SQLSMALLINT NameLength3)
{
	RETCODE rc;
	char *query = NULL;
	char *query_end = NULL;
	char *cat = NULL, *sch = NULL, *tab = NULL;

	fixODBCstring(CatalogName, NameLength1, SQLSMALLINT,
		      addStmtError, stmt, return SQL_ERROR);
	fixODBCstring(SchemaName, NameLength2, SQLSMALLINT,
		      addStmtError, stmt, return SQL_ERROR);
	fixODBCstring(TableName, NameLength3, SQLSMALLINT,
		      addStmtError, stmt, return SQL_ERROR);

#ifdef ODBCDEBUG
	ODBCLOG("\"%.*s\" \"%.*s\" \"%.*s\"\n",
		(int) NameLength1, (char *) CatalogName,
		(int) NameLength2, (char *) SchemaName,
		(int) NameLength3, (char *) TableName);
#endif

	if (stmt->Dbc->sql_attr_metadata_id == SQL_FALSE) {
		if (NameLength1 > 0) {
			cat = ODBCParseOA("e", "value",
					  (const char *) CatalogName,
					  (size_t) NameLength1);
			if (cat == NULL)
				goto nomem;
		}
		if (NameLength2 > 0) {
			sch = ODBCParsePV("s", "name",
					  (const char *) SchemaName,
					  (size_t) NameLength2);
			if (sch == NULL)
				goto nomem;
		}
		if (NameLength3 > 0) {
			tab = ODBCParsePV("t", "name",
					  (const char *) TableName,
					  (size_t) NameLength3);
			if (tab == NULL)
				goto nomem;
		}
	} else {
		if (NameLength1 > 0) {
			cat = ODBCParseID("e", "value",
					  (const char *) CatalogName,
					  (size_t) NameLength1);
			if (cat == NULL)
				goto nomem;
		}
		if (NameLength2 > 0) {
			sch = ODBCParseID("s", "name",
					  (const char *) SchemaName,
					  (size_t) NameLength2);
			if (sch == NULL)
				goto nomem;
		}
		if (NameLength3 > 0) {
			tab = ODBCParseID("t", "name",
					  (const char *) TableName,
					  (size_t) NameLength3);
			if (tab == NULL)
				goto nomem;
		}
	}

	/* construct the query now */
	query = malloc(1200 + (cat ? strlen(cat) : 0) +
		       (sch ? strlen(sch) : 0) + (tab ? strlen(tab) : 0));
	if (query == NULL)
		goto nomem;
	query_end = query;

	/* SQLTablePrivileges returns a table with the following columns:
	   table_cat    VARCHAR
	   table_schem  VARCHAR
	   table_name   VARCHAR NOT NULL
	   grantor      VARCHAR
	   grantee      VARCHAR NOT NULL
	   privilege    VARCHAR NOT NULL
	   is_grantable VARCHAR
	 */

	sprintf(query_end,
		"select e.value as table_cat, "
			"s.name as table_schem, "
			"t.name as table_name, "
			"case a.id "
			     "when s.owner then '_SYSTEM' "
			     "else g.name "
			     "end as grantor, "
			"case a.name "
			     "when 'public' then 'PUBLIC' "
			     "else a.name "
			     "end as grantee, "
			"case p.privileges "
			     "when 1 then 'SELECT' "
			     "when 2 then 'UPDATE' "
			     "when 4 then 'INSERT' "
			     "when 8 then 'DELETE' "
			     "when 16 then 'EXECUTE' "
			     "when 32 then 'GRANT' "
			     "end as privilege, "
			"case p.grantable "
			     "when 1 then 'YES' "
			     "when 0 then 'NO' "
			     "end as is_grantable "
		"from sys.schemas s, "
		      "sys._tables t, "
		      "sys.auths a, "
		      "sys.privileges p, "
		      "sys.auths g, "
		      "sys.env() e "
		"where p.obj_id = t.id "
		  "and p.auth_id = a.id "
		  "and t.schema_id = s.id "
		  "and t.system = false "
		  "and p.grantor = g.id "
		  "and e.name = 'gdk_dbname'");
	assert(strlen(query) < 1000);
	query_end += strlen(query_end);

	/* Construct the selection condition query part */
	if (cat) {
		/* filtering requested on catalog name */
		sprintf(query_end, " and %s", cat);
		query_end += strlen(query_end);
		free(cat);
	}
	if (sch) {
		/* filtering requested on schema name */
		sprintf(query_end, " and %s", sch);
		query_end += strlen(query_end);
		free(sch);
	}
	if (tab) {
		/* filtering requested on table name */
		sprintf(query_end, " and %s", tab);
		query_end += strlen(query_end);
		free(tab);
	}

	/* add the ordering */
	strcpy(query_end,
	       " order by table_cat, table_schem, table_name, privilege, grantee");
	query_end += strlen(query_end);

	/* query the MonetDB data dictionary tables */
	rc = MNDBExecDirect(stmt, (SQLCHAR *) query,
			    (SQLINTEGER) (query_end - query));

	free(query);

	return rc;

  nomem:
	/* note that query must be NULL when we get here */
	if (cat)
		free(cat);
	if (sch)
		free(sch);
	if (tab)
		free(tab);
	/* Memory allocation error */
	addStmtError(stmt, "HY001", NULL, 0);
	return SQL_ERROR;
}
Exemple #2
0
static SQLRETURN
MNDBProcedures(ODBCStmt *stmt,
	       SQLCHAR *CatalogName,
	       SQLSMALLINT NameLength1,
	       SQLCHAR *SchemaName,
	       SQLSMALLINT NameLength2,
	       SQLCHAR *ProcName,
	       SQLSMALLINT NameLength3)
{
	RETCODE rc;

	/* buffer for the constructed query to do meta data retrieval */
	char *query = NULL;
	char *query_end;
	char *cat = NULL, *sch = NULL, *pro = NULL;

	/* convert input string parameters to normal null terminated C strings */
	fixODBCstring(CatalogName, NameLength1, SQLSMALLINT,
		      addStmtError, stmt, return SQL_ERROR);
	fixODBCstring(SchemaName, NameLength2, SQLSMALLINT,
		      addStmtError, stmt, return SQL_ERROR);
	fixODBCstring(ProcName, NameLength3, SQLSMALLINT,
		      addStmtError, stmt, return SQL_ERROR);

#ifdef ODBCDEBUG
	ODBCLOG("\"%.*s\" \"%.*s\" \"%.*s\"\n",
		(int) NameLength1, (char *) CatalogName,
		(int) NameLength2, (char *) SchemaName,
		(int) NameLength3, (char *) ProcName);
#endif

	/* SQLProcedures returns a table with the following columns:
	   VARCHAR      procedure_cat
	   VARCHAR      procedure_schem
	   VARCHAR      procedure_name NOT NULL
	   n/a          num_input_params (reserved for future use)
	   n/a          num_output_params (reserved for future use)
	   n/a          num_result_sets (reserved for future use)
	   VARCHAR      remarks
	   SMALLINT     procedure_type
	 */

	if (stmt->Dbc->sql_attr_metadata_id == SQL_FALSE) {
		if (NameLength1 > 0) {
			cat = ODBCParseOA("e", "value",
					  (const char *) CatalogName,
					  (size_t) NameLength1);
			if (cat == NULL)
				goto nomem;
		}
		if (NameLength2 > 0) {
			sch = ODBCParsePV("s", "name",
					  (const char *) SchemaName,
					  (size_t) NameLength2);
			if (sch == NULL)
				goto nomem;
		}
		if (NameLength3 > 0) {
			pro = ODBCParsePV("p", "name",
					  (const char *) ProcName,
					  (size_t) NameLength3);
			if (pro == NULL)
				goto nomem;
		}
	} else {
		if (NameLength1 > 0) {
			cat = ODBCParseID("e", "value",
					  (const char *) CatalogName,
					  (size_t) NameLength1);
			if (cat == NULL)
				goto nomem;
		}
		if (NameLength2 > 0) {
			sch = ODBCParseID("s", "name",
					  (const char *) SchemaName,
					  (size_t) NameLength2);
			if (sch == NULL)
				goto nomem;
		}
		if (NameLength3 > 0) {
			pro = ODBCParseID("p", "name",
					  (const char *) ProcName,
					  (size_t) NameLength3);
			if (pro == NULL)
				goto nomem;
		}
	}

	query = malloc(1000 + (cat ? strlen(cat) : 0) +
		       (sch ? strlen(sch) : 0) + (pro ? strlen(pro) : 0));
	if (query == NULL)
		goto nomem;
	query_end = query;

/* see sql_catalog.h */
#define F_FUNC 1
#define F_PROC 2
#define F_UNION 5
	snprintf(query_end, 1000,
		 "select e.value as procedure_cat, "
			"s.name as procedure_schem, "
			"p.name as procedure_name, "
			"0 as num_input_params, "
			"0 as num_output_params, "
			"0 as num_result_sets, "
			"cast('' as varchar(1)) as remarks, "
			"cast(case when p.type = %d then %d else %d end as smallint) as procedure_type "
		 "from sys.schemas as s, "
		      "sys.env() as e, "
		      "sys.functions as p "
		 "where p.schema_id = s.id and "
		       "p.sql = true and "
		       "p.type in (%d, %d, %d) and "
		       "e.name = 'gdk_dbname'",
		 F_PROC, SQL_PT_PROCEDURE, SQL_PT_FUNCTION,
		 F_FUNC, F_PROC, F_UNION);
	assert(strlen(query) < 800);
	query_end += strlen(query_end);

	/* Construct the selection condition query part */
	if (cat) {
		/* filtering requested on catalog name */
		sprintf(query_end, " and %s", cat);
		query_end += strlen(query_end);
		free(cat);
	}
	if (sch) {
		/* filtering requested on schema name */
		sprintf(query_end, " and %s", sch);
		query_end += strlen(query_end);
		free(sch);
	}
	if (pro) {
		/* filtering requested on procedure name */
		sprintf(query_end, " and %s", pro);
		query_end += strlen(query_end);
		free(pro);
	}

	/* add the ordering */
	strcpy(query_end,
	       " order by procedure_cat, procedure_schem, procedure_name");
	query_end += strlen(query_end);

	/* query the MonetDB data dictionary tables */

	rc = MNDBExecDirect(stmt, (SQLCHAR *) query, SQL_NTS);

	free(query);

	return rc;

  nomem:
	/* note that query must be NULL when we get here */
	if (cat)
		free(cat);
	if (sch)
		free(sch);
	if (pro)
		free(pro);
	/* Memory allocation error */
	addStmtError(stmt, "HY001", NULL, 0);
	return SQL_ERROR;
}
static SQLRETURN
SQLForeignKeys_(ODBCStmt *stmt,
		SQLCHAR *PKCatalogName,
		SQLSMALLINT NameLength1,
		SQLCHAR *PKSchemaName,
		SQLSMALLINT NameLength2,
		SQLCHAR *PKTableName,
		SQLSMALLINT NameLength3,
		SQLCHAR *FKCatalogName,
		SQLSMALLINT NameLength4,
		SQLCHAR *FKSchemaName,
		SQLSMALLINT NameLength5,
		SQLCHAR *FKTableName,
		SQLSMALLINT NameLength6)
{
	RETCODE rc;

	/* buffer for the constructed query to do meta data retrieval */
	char *query = NULL;
	char *query_end = NULL;	/* pointer to end of built-up query */
	char *pcat = NULL, *psch = NULL, *ptab = NULL;
	char *fcat = NULL, *fsch = NULL, *ftab = NULL;

	/* deal with SQL_NTS and SQL_NULL_DATA */
	fixODBCstring(PKCatalogName, NameLength1, SQLSMALLINT,
		      addStmtError, stmt, return SQL_ERROR);
	fixODBCstring(PKSchemaName, NameLength2, SQLSMALLINT,
		      addStmtError, stmt, return SQL_ERROR);
	fixODBCstring(PKTableName, NameLength3, SQLSMALLINT,
		      addStmtError, stmt, return SQL_ERROR);
	fixODBCstring(FKCatalogName, NameLength4, SQLSMALLINT,
		      addStmtError, stmt, return SQL_ERROR);
	fixODBCstring(FKSchemaName, NameLength5, SQLSMALLINT,
		      addStmtError, stmt, return SQL_ERROR);
	fixODBCstring(FKTableName, NameLength6, SQLSMALLINT,
		      addStmtError, stmt, return SQL_ERROR);

#ifdef ODCBDEBUG
	ODBCLOG("\"%.*s\" \"%.*s\" \"%.*s\" \"%.*s\" \"%.*s\" \"%.*s\"\n",
		(int) NameLength1, PKCatalogName,
		(int) NameLength2, PKSchemaName,
		(int) NameLength3, PKTableName,
		(int) NameLength4, FKCatalogName,
		(int) NameLength5, FKSchemaName,
		(int) NameLength6, FKTableName);
#endif
	/* dependent on the input parameter values we must add a
	   variable selection condition dynamically */

	if (stmt->Dbc->sql_attr_metadata_id == SQL_FALSE) {
		if (NameLength1 > 0) {
			pcat = ODBCParseOA("e", "value",
					   (const char *) PKCatalogName,
					   (size_t) NameLength1);
		}
		if (NameLength2 > 0) {
			psch = ODBCParseOA("pks", "name",
					   (const char *) PKSchemaName,
					   (size_t) NameLength2);
		}
		if (NameLength3 > 0) {
			ptab = ODBCParseOA("pkt", "name",
					   (const char *) PKTableName,
					   (size_t) NameLength3);
		}
		if (NameLength4 > 0) {
			fcat = ODBCParseOA("e", "value",
					   (const char *) FKCatalogName,
					   (size_t) NameLength4);
		}
		if (NameLength5 > 0) {
			fsch = ODBCParseOA("fks", "name",
					   (const char *) FKSchemaName,
					   (size_t) NameLength5);
		}
		if (NameLength6 > 0) {
			ftab = ODBCParseOA("fkt", "name",
					   (const char *) FKTableName,
					   (size_t) NameLength6);
		}
	} else {
		if (NameLength1 > 0) {
			pcat = ODBCParseID("e", "value",
					   (const char *) PKCatalogName,
					   (size_t) NameLength1);
		}
		if (NameLength2 > 0) {
			psch = ODBCParseID("pks", "name",
					   (const char *) PKSchemaName,
					   (size_t) NameLength2);
		}
		if (NameLength3 > 0) {
			ptab = ODBCParseID("pkt", "name",
					   (const char *) PKTableName,
					   (size_t) NameLength3);
		}
		if (NameLength4 > 0) {
			fcat = ODBCParseID("e", "value",
					   (const char *) FKCatalogName,
					   (size_t) NameLength4);
		}
		if (NameLength5 > 0) {
			fsch = ODBCParseID("fks", "name",
					   (const char *) FKSchemaName,
					   (size_t) NameLength5);
		}
		if (NameLength6 > 0) {
			ftab = ODBCParseID("fkt", "name",
					   (const char *) FKTableName,
					   (size_t) NameLength6);
		}
	}

	/* first create a string buffer (1200 extra bytes is plenty:
	   we actually need just over 1000) */
	query = malloc(1200 + (pcat ? strlen(pcat) : 0) +
		       (psch ? strlen(psch) : 0) + (ptab ? strlen(ptab) : 0) +
		       (fcat ? strlen(fcat) : 0) + (fsch ? strlen(fsch) : 0) +
		       (ftab ? strlen(ftab) : 0));
	assert(query);
	query_end = query;

	/* SQLForeignKeys returns a table with the following columns:
	   VARCHAR      pktable_cat
	   VARCHAR      pktable_schem
	   VARCHAR      pktable_name NOT NULL
	   VARCHAR      pkcolumn_name NOT NULL
	   VARCHAR      fktable_cat
	   VARCHAR      fktable_schem
	   VARCHAR      fktable_name NOT NULL
	   VARCHAR      fkcolumn_name NOT NULL
	   SMALLINT     key_seq NOT NULL
	   SMALLINT     update_rule
	   SMALLINT     delete_rule
	   VARCHAR      fk_name
	   VARCHAR      pk_name
	   SMALLINT     deferrability
	 */

	sprintf(query_end,
		"select "
		"e.\"value\" as pktable_cat, "
		"pks.\"name\" as pktable_schem, "
		"pkt.\"name\" as pktable_name, "
		"pkkc.\"name\" as pkcolumn_name, "
		"e.\"value\" as fktable_cat, "
		"fks.\"name\" as fktable_schem, "
		"fkt.\"name\" as fktable_name, "
		"fkkc.\"name\" as fkcolumn_name, "
		"cast(fkkc.\"nr\" + 1 as smallint) as key_seq, "
		"cast(%d as smallint) as update_rule, "
		"cast(%d as smallint) as delete_rule, "
		"fkk.\"name\" as fk_name, "
		"pkk.\"name\" as pk_name, "
		"cast(%d as smallint) as deferrability "
		"from sys.\"schemas\" fks, sys.\"tables\" fkt, "
		"sys.\"objects\" fkkc, sys.\"keys\" as fkk, "
		"sys.\"schemas\" pks, sys.\"tables\" pkt, "
		"sys.\"objects\" pkkc, sys.\"keys\" as pkk, "
		"sys.\"env\"() e "
		"where fkt.\"id\" = fkk.\"table_id\" and "
		"pkt.\"id\" = pkk.\"table_id\" and "
		"fkk.\"id\" = fkkc.\"id\" and "
		"pkk.\"id\" = pkkc.\"id\" and "
		"fks.\"id\" = fkt.\"schema_id\" and "
		"pks.\"id\" = pkt.\"schema_id\" and "
		"fkk.\"rkey\" = pkk.\"id\" and "
		"fkkc.\"nr\" = pkkc.\"nr\" and "
		"e.\"name\" = 'gdk_dbname'",
		SQL_NO_ACTION, SQL_NO_ACTION, SQL_NOT_DEFERRABLE);
	assert(strlen(query) < 1100);
	query_end += strlen(query_end);

	/* Construct the selection condition query part */
	if (pcat) {
		/* filtering requested on catalog name */
		sprintf(query_end, " and %s", pcat);
		query_end += strlen(query_end);
		free(pcat);
	}
	if (psch) {
		/* filtering requested on schema name */
		sprintf(query_end, " and %s", psch);
		query_end += strlen(query_end);
		free(psch);
	}
	if (ptab) {
		/* filtering requested on table name */
		sprintf(query_end, " and %s", ptab);
		query_end += strlen(query_end);
		free(ptab);
	}
	if (fcat) {
		/* filtering requested on catalog name */
		sprintf(query_end, " and %s", fcat);
		query_end += strlen(query_end);
		free(fcat);
	}
	if (fsch) {
		/* filtering requested on schema name */
		sprintf(query_end, " and %s", fsch);
		query_end += strlen(query_end);
		free(fsch);
	}
	if (ftab) {
		/* filtering requested on table name */
		sprintf(query_end, " and %s", ftab);
		query_end += strlen(query_end);
		free(ftab);
	}

/* TODO finish the FROM and WHERE clauses */

	/* add the ordering */
	/* if PKTableName != NULL, selection on primary key, order
	   on FK output columns, else order on PK output columns */
	sprintf(query_end, " order by %stable_schem, %stable_name, key_seq",
		PKTableName != NULL ? "fk" : "pk",
		PKTableName != NULL ? "fk" : "pk");
	query_end += strlen(query_end);

	/* query the MonetDB data dictionary tables */
	rc = SQLExecDirect_(stmt, (SQLCHAR *) query,
			    (SQLINTEGER) (query_end - query));

	free(query);

	return rc;
}
static SQLRETURN
SQLTablePrivileges_(ODBCStmt *stmt,
		    SQLCHAR *CatalogName,
		    SQLSMALLINT NameLength1,
		    SQLCHAR *SchemaName,
		    SQLSMALLINT NameLength2,
		    SQLCHAR *TableName,
		    SQLSMALLINT NameLength3)
{
	RETCODE rc;
	char *query = NULL;
	char *query_end = NULL;
	char *cat = NULL, *sch = NULL, *tab = NULL;

	fixODBCstring(CatalogName, NameLength1, SQLSMALLINT,
		      addStmtError, stmt, return SQL_ERROR);
	fixODBCstring(SchemaName, NameLength2, SQLSMALLINT,
		      addStmtError, stmt, return SQL_ERROR);
	fixODBCstring(TableName, NameLength3, SQLSMALLINT,
		      addStmtError, stmt, return SQL_ERROR);

#ifdef ODBCDEBUG
	ODBCLOG("\"%.*s\" \"%.*s\" \"%.*s\"\n",
		(int) NameLength1, (char *) CatalogName,
		(int) NameLength2, (char *) SchemaName,
		(int) NameLength3, (char *) TableName);
#endif

	if (stmt->Dbc->sql_attr_metadata_id == SQL_FALSE) {
		if (NameLength1 > 0) {
			cat = ODBCParseOA("e", "value",
					  (const char *) CatalogName,
					  (size_t) NameLength1);
		}
		if (NameLength2 > 0) {
			sch = ODBCParsePV("s", "name",
					  (const char *) SchemaName,
					  (size_t) NameLength2);
		}
		if (NameLength3 > 0) {
			tab = ODBCParsePV("t", "name",
					  (const char *) TableName,
					  (size_t) NameLength3);
		}
	} else {
		if (NameLength1 > 0) {
			cat = ODBCParseID("e", "value",
					  (const char *) CatalogName,
					  (size_t) NameLength1);
		}
		if (NameLength2 > 0) {
			sch = ODBCParseID("s", "name",
					  (const char *) SchemaName,
					  (size_t) NameLength2);
		}
		if (NameLength3 > 0) {
			tab = ODBCParseID("t", "name",
					  (const char *) TableName,
					  (size_t) NameLength3);
		}
	}

	/* construct the query now */
	query = malloc(1200 + (cat ? strlen(cat) : 0) +
		       (sch ? strlen(sch) : 0) + (tab ? strlen(tab) : 0));
	query_end = query;

	/* SQLTablePrivileges returns a table with the following columns:
	   table_cat    VARCHAR
	   table_schem  VARCHAR
	   table_name   VARCHAR NOT NULL
	   grantor      VARCHAR
	   grantee      VARCHAR NOT NULL
	   privilege    VARCHAR NOT NULL
	   is_grantable VARCHAR
	 */

	sprintf(query_end,
		"select"
		" e.\"value\" as \"table_cat\","
		" \"s\".\"name\" as \"table_schem\","
		" \"t\".\"name\" as \"table_name\","
		" case \"a\".\"id\""
		"      when \"s\".\"owner\" then '_SYSTEM'"
		"      else \"g\".\"name\""
		"      end as \"grantor\","
		" case \"a\".\"name\""
		"      when 'public' then 'PUBLIC'"
		"      else \"a\".\"name\""
		"      end as \"grantee\","
		" case \"p\".\"privileges\""
		"      when 1 then 'SELECT'"
		"      when 2 then 'UPDATE'"
		"      when 4 then 'INSERT'"
		"      when 8 then 'DELETE'"
		"      when 16 then 'EXECUTE'"
		"      when 32 then 'GRANT'"
		"      end as \"privilege\","
		" case \"p\".\"grantable\""
		"      when 1 then 'YES'"
		"      when 0 then 'NO'"
		"      end as \"is_grantable\" "
		"from \"sys\".\"schemas\" \"s\","
		" \"sys\".\"_tables\" \"t\","
		" \"sys\".\"auths\" \"a\","
		" \"sys\".\"privileges\" \"p\","
		" \"sys\".\"auths\" \"g\","
		" \"sys\".\"env\"() \"e\" "
		"where \"p\".\"obj_id\" = \"t\".\"id\""
		" and \"p\".\"auth_id\" = \"a\".\"id\""
		" and \"t\".\"schema_id\" = \"s\".\"id\""
		" and \"t\".\"system\" = false"
		" and \"p\".\"grantor\" = \"g\".\"id\""
		" and \"e\".\"name\" = 'gdk_dbname'");
	assert(strlen(query) < 1000);
	query_end += strlen(query_end);

	/* Construct the selection condition query part */
	if (cat) {
		/* filtering requested on catalog name */
		sprintf(query_end, " and %s", cat);
		query_end += strlen(query_end);
		free(cat);
	}
	if (sch) {
		/* filtering requested on schema name */
		sprintf(query_end, " and %s", sch);
		query_end += strlen(query_end);
		free(sch);
	}
	if (tab) {
		/* filtering requested on table name */
		sprintf(query_end, " and %s", tab);
		query_end += strlen(query_end);
		free(tab);
	}

	/* add the ordering */
	strcpy(query_end,
	       " order by \"table_cat\", \"table_schem\", \"table_name\", \"privilege\", \"grantee\"");
	query_end += strlen(query_end);

	/* query the MonetDB data dictionary tables */
        rc = SQLExecDirect_(stmt, (SQLCHAR *) query,
			    (SQLINTEGER) (query_end - query));

	free(query);

	return rc;
}
Exemple #5
0
static SQLRETURN
SQLColumns_(ODBCStmt *stmt,
	    SQLCHAR *CatalogName,
	    SQLSMALLINT NameLength1,
	    SQLCHAR *SchemaName,
	    SQLSMALLINT NameLength2,
	    SQLCHAR *TableName,
	    SQLSMALLINT NameLength3,
	    SQLCHAR *ColumnName,
	    SQLSMALLINT NameLength4)
{
	RETCODE rc;

	/* buffer for the constructed query to do meta data retrieval */
	char *query = NULL;
	char *query_end = NULL;
	char *cat = NULL, *sch = NULL, *tab = NULL, *col = NULL;

	/* null pointers not allowed if arguments are identifiers */
	if (stmt->Dbc->sql_attr_metadata_id == SQL_TRUE &&
	    (SchemaName == NULL || TableName == NULL || ColumnName == NULL)) {
		addStmtError(stmt, "HY090", NULL, 0);
		return SQL_ERROR;
	}

	fixODBCstring(CatalogName, NameLength1, SQLSMALLINT,
		      addStmtError, stmt, return SQL_ERROR);
	fixODBCstring(SchemaName, NameLength2, SQLSMALLINT,
		      addStmtError, stmt, return SQL_ERROR);
	fixODBCstring(TableName, NameLength3, SQLSMALLINT,
		      addStmtError, stmt, return SQL_ERROR);
	fixODBCstring(ColumnName, NameLength4, SQLSMALLINT,
		      addStmtError, stmt, return SQL_ERROR);

#ifdef ODBCDEBUG
	ODBCLOG(" \"%.*s\" \"%.*s\" \"%.*s\" \"%.*s\"\n",
		(int) NameLength1, (char *) CatalogName,
		(int) NameLength2, (char *) SchemaName,
		(int) NameLength3, (char *) TableName,
		(int) NameLength4, (char *) ColumnName);
#endif

	if (stmt->Dbc->sql_attr_metadata_id == SQL_FALSE) {
		if (NameLength1 > 0) {
			cat = ODBCParseOA("e", "value",
					  (const char *) CatalogName,
					  (size_t) NameLength1);
		}
		if (NameLength2 > 0) {
			sch = ODBCParsePV("s", "name",
					  (const char *) SchemaName,
					  (size_t) NameLength2);
		}
		if (NameLength3 > 0) {
			tab = ODBCParsePV("t", "name",
					  (const char *) TableName,
					  (size_t) NameLength3);
		}
		if (NameLength4 > 0) {
			col = ODBCParsePV("c", "name",
					  (const char *) ColumnName,
					  (size_t) NameLength4);
		}
	} else {
		if (NameLength1 > 0) {
			cat = ODBCParseID("e", "value",
					  (const char *) CatalogName,
					  (size_t) NameLength1);
		}
		if (NameLength2 > 0) {
			sch = ODBCParseID("s", "name",
					  (const char *) SchemaName,
					  (size_t) NameLength2);
		}
		if (NameLength3 > 0) {
			tab = ODBCParseID("t", "name",
					  (const char *) TableName,
					  (size_t) NameLength3);
		}
		if (NameLength4 > 0) {
			col = ODBCParseID("c", "name",
					  (const char *) ColumnName,
					  (size_t) NameLength4);
		}
	}

	/* construct the query now */
	query = malloc(6500 + (cat ? strlen(cat) : 0) +
		       (sch ? strlen(sch) : 0) + (tab ? strlen(tab) : 0) +
		       (col ? strlen(col) : 0));
	assert(query);
	query_end = query;

	/* SQLColumns returns a table with the following columns:
	   VARCHAR      table_cat
	   VARCHAR      table_schem
	   VARCHAR      table_name NOT NULL
	   VARCHAR      column_name NOT NULL
	   SMALLINT     data_type NOT NULL
	   VARCHAR      type_name NOT NULL
	   INTEGER      column_size
	   INTEGER      buffer_length
	   SMALLINT     decimal_digits
	   SMALLINT     num_prec_radix
	   SMALLINT     nullable NOT NULL
	   VARCHAR      remarks
	   VARCHAR      column_def
	   SMALLINT     sql_data_type NOT NULL
	   SMALLINT     sql_datetime_sub
	   INTEGER      char_octet_length
	   INTEGER      ordinal_position NOT NULL
	   VARCHAR      is_nullable
	 */

	sprintf(query_end,
		"select e.\"value\" as table_cat,"
		      " s.\"name\" as table_schem,"
		      " t.\"name\" as table_name,"
		      " c.\"name\" as column_name,"
		      " case c.\"type\""
			   " when 'bigint' then %d"
			   " when 'blob' then %d"
			   " when 'boolean' then %d"
			   " when 'char' then %d"
			   " when 'clob' then %d"
			   " when 'date' then %d"
			   " when 'decimal' then %d"
			   " when 'double' then %d"
			   " when 'int' then %d"
			   " when 'month_interval' then"
				" case c.type_digits"
				     " when 1 then %d"
				     " when 2 then %d"
				     " when 3 then %d"
				" end"
			   " when 'real' then %d"
			   " when 'sec_interval' then"
				" case c.type_digits"
				     " when 4 then %d"
				     " when 5 then %d"
				     " when 6 then %d"
				     " when 7 then %d"
				     " when 8 then %d"
				     " when 9 then %d"
				     " when 10 then %d"
				     " when 11 then %d"
				     " when 12 then %d"
				     " when 13 then %d"
				" end"
			   " when 'smallint' then %d"
			   " when 'time' then %d"
			   " when 'timestamp' then %d"
			   " when 'timestamptz' then %d"
			   " when 'timetz' then %d"
			   " when 'tinyint' then %d"
			   " when 'varchar' then %d"
			   " when 'wrd' then"
				" case c.type_digits"
				     " when 32 then %d"
				     " when 64 then %d"
				" end"
		      " end as data_type,"
		      " case c.\"type\""
			   " when 'bigint' then 'BIGINT'"
			   " when 'blob' then 'BINARY LARGE OBJECT'"
			   " when 'boolean' then 'BOOLEAN'"
			   " when 'char' then 'CHARACTER'"
			   " when 'clob' then 'CHARACTER LARGE OBJECT'"
			   " when 'date' then 'DATE'"
			   " when 'decimal' then 'DECIMAL'"
			   " when 'double' then 'DOUBLE'"
			   " when 'int' then 'INTEGER'"
			   " when 'month_interval' then"
				" case c.type_digits"
				     " when 1 then 'INTERVAL YEAR'"
				     " when 2 then 'INTERVAL YEAR TO MONTH'"
				     " when 3 then 'INTERVAL MONTH'"
				" end"
			   " when 'real' then 'REAL'"
			   " when 'sec_interval' then"
				" case c.type_digits"
				     " when 4 then 'INTERVAL DAY'"
				     " when 5 then 'INTERVAL DAY TO HOUR'"
				     " when 6 then 'INTERVAL DAY TO MINUTE'"
				     " when 7 then 'INTERVAL DAY TO SECOND'"
				     " when 8 then 'INTERVAL HOUR'"
				     " when 9 then 'INTERVAL HOUR TO MINUTE'"
				     " when 10 then 'INTERVAL HOUR TO SECOND'"
				     " when 11 then 'INTERVAL MINUTE'"
				     " when 12 then 'INTERVAL MINUTE TO SECOND'"
				     " when 13 then 'INTERVAL SECOND'"
				" end"
			   " when 'smallint' then 'SMALLINT'"
			   " when 'time' then 'TIME'"
			   " when 'timestamp' then 'TIMESTAMP'"
			   " when 'timestamptz' then 'TIMESTAMP'"
			   " when 'timetz' then 'TIME'"
			   " when 'tinyint' then 'TINYINT'"
			   " when 'varchar' then 'VARCHAR'"
			   " when 'wrd' then"
				" case c.type_digits"
				     " when 32 then 'INTEGER'"
				     " when 64 then 'BIGINT'"
				" end"
		      " end as type_name,"
		      " case c.\"type\""
			   " when 'date' then 10"
			   " when 'month_interval' then"
				" case c.type_digits"
				     " when 1 then 26"
				     " when 2 then 38"
				     " when 3 then 27"
				" end"
			   " when 'sec_interval' then"
				" case c.type_digits"
				     " when 4 then 25"
				     " when 5 then 36"
				     " when 6 then 41"
				     " when 7 then 47"
				     " when 8 then 26"
				     " when 9 then 39"
				     " when 10 then 45"
				     " when 11 then 28"
				     " when 12 then 44"
				     " when 13 then 30"
				" end"
			   " when 'time' then 12"
			   " when 'timestamp' then 23"
			   " when 'timestamptz' then 23"
			   " when 'timetz' then 12"
			   " else c.type_digits"
		      " end as column_size,"
		      " case c.\"type\""
			   " when 'bigint' then 20"
			   " when 'char' then 2 * c.type_digits"
			   " when 'clob' then 2 * c.type_digits"
			   " when 'date' then 10"
			   " when 'double' then 24"
			   " when 'int' then 11"
			   " when 'month_interval' then"
				" case c.type_digits"
				     " when 1 then 26"
				     " when 2 then 38"
				     " when 3 then 27"
				" end"
			   " when 'real' then 14"
			   " when 'sec_interval' then"
				" case c.type_digits"
				     " when 4 then 25"
				     " when 5 then 36"
				     " when 6 then 41"
				     " when 7 then 47"
				     " when 8 then 26"
				     " when 9 then 39"
				     " when 10 then 45"
				     " when 11 then 28"
				     " when 12 then 44"
				     " when 13 then 30"
				" end"
			   " when 'smallint' then 6"
			   " when 'time' then 12"
			   " when 'timestamp' then 23"
			   " when 'timestamptz' then 23"
			   " when 'timetz' then 12"
			   " when 'tinyint' then 4"
			   " when 'varchar' then 2 * c.type_digits"
			   " when 'wrd' then"
				" case c.type_digits"
				     " when 32 then 11"
				     " when 64 then 20"
				" end"
			   " else c.type_digits"
		      " end as buffer_length,"
		      " case c.\"type\""
			   " when 'bigint' then 19"
			   " when 'decimal' then c.type_scale"
			   " when 'double' then"
				" case when c.type_digits = 53 and c.type_scale = 0 then 15"
				" else c.type_digits"
				" end"
			   " when 'int' then 10"
			   " when 'month_interval' then 0"
			   " when 'real' then"
				" case when c.type_digits = 24 and c.type_scale = 0 then 7"
				" else c.type_digits"
				" end"
			   " when 'sec_interval' then 0"
			   " when 'smallint' then 5"
			   " when 'time' then c.type_digits - 1"
			   " when 'timestamp' then c.type_digits - 1"
			   " when 'timestamptz' then c.type_digits - 1"
			   " when 'timetz' then c.type_digits - 1"
			   " when 'tinyint' then 3"
			   " when 'wrd' then"
				" case c.type_digits"
				     " when 32 then 10"
				     " when 64 then 19"
				" end"
			   " else cast(null as smallint)"
		      " end as decimal_digits,"
		      " case c.\"type\""
			   " when 'bigint' then 2"
			   " when 'decimal' then 10"
			   " when 'double' then"
				" case when c.type_digits = 53 and c.type_scale = 0 then 2"
				" else 10"
				" end"
			   " when 'int' then 2"
			   " when 'real' then"
				" case when c.type_digits = 24 and c.type_scale = 0 then 2"
				" else 10"
				" end"
			   " when 'smallint' then 2"
			   " when 'tinyint' then 2"
			   " when 'wrd' then 2"
			   " else cast(null as smallint)"
		      " end as num_prec_radix,"
		      " case c.\"null\""
			   " when true then cast(%d as smallint)"
			   " when false then cast(%d as smallint)"
		      " end as nullable,"
		      " cast('' as varchar(1)) as remarks,"
		      " c.\"default\" as column_def,"
		      " case c.\"type\""
			   " when 'bigint' then %d"
			   " when 'blob' then %d"
			   " when 'boolean' then %d"
			   " when 'char' then %d"
			   " when 'clob' then %d"
			   " when 'date' then %d"
			   " when 'decimal' then %d"
			   " when 'double' then %d"
			   " when 'int' then %d"
			   " when 'month_interval' then %d"
			   " when 'real' then %d"
			   " when 'sec_interval' then %d"
			   " when 'smallint' then %d"
			   " when 'time' then %d"
			   " when 'timestamp' then %d"
			   " when 'timestamptz' then %d"
			   " when 'timetz' then %d"
			   " when 'tinyint' then %d"
			   " when 'varchar' then %d"
			   " when 'wrd' then"
				" case c.type_digits"
				     " when 32 then %d"
				     " when 64 then %d"
				" end"
		      " end as sql_data_type,"
		      " case c.\"type\""
			   " when 'date' then %d"
			   " when 'month_interval' then"
				" case c.type_digits"
				     " when 1 then %d"
				     " when 2 then %d"
				     " when 3 then %d"
				" end"
			   " when 'sec_interval' then"
				" case c.type_digits"
				     " when 4 then %d"
				     " when 5 then %d"
				     " when 6 then %d"
				     " when 7 then %d"
				     " when 8 then %d"
				     " when 9 then %d"
				     " when 10 then %d"
				     " when 11 then %d"
				     " when 12 then %d"
				     " when 13 then %d"
				" end"
			   " when 'time' then %d"
			   " when 'timestamp' then %d"
			   " when 'timestamptz' then %d"
			   " when 'timetz' then %d"
			   " else cast(null as smallint)"
		      " end as sql_datetime_sub,"
		      " case c.\"type\""
			   " when 'char' then 2 * c.type_digits"
			   " when 'varchar' then 2 * c.type_digits"
			   " when 'clob' then 2 * c.type_digits"
			   " when 'blob' then c.type_digits"
			   " else cast(null as integer)"
		      " end as char_octet_length,"
		      " cast(c.\"number\" + 1 as integer) as ordinal_position,"
		      " case c.\"null\""
			   " when true then cast('YES' as varchar(3))"
			   " when false then cast('NO' as varchar(3))"
		      " end as is_nullable"
		" from sys.\"schemas\" s,"
		     " sys.\"tables\" t,"
		     " sys.\"columns\" c,"
		     " sys.\"env\"() e"
		" where s.\"id\" = t.\"schema_id\" and"
		      " t.\"id\" = c.\"table_id\" and"
		      " e.\"name\" = 'gdk_dbname'",
		/* data_type: */
		SQL_BIGINT, SQL_LONGVARBINARY, SQL_BIT, SQL_WCHAR,
		SQL_WLONGVARCHAR, SQL_TYPE_DATE, SQL_DECIMAL, SQL_DOUBLE,
		SQL_INTEGER, SQL_INTERVAL_YEAR, SQL_INTERVAL_YEAR_TO_MONTH,
		SQL_INTERVAL_MONTH, SQL_REAL, SQL_INTERVAL_DAY,
		SQL_INTERVAL_DAY_TO_HOUR, SQL_INTERVAL_DAY_TO_MINUTE,
		SQL_INTERVAL_DAY_TO_SECOND, SQL_INTERVAL_HOUR,
		SQL_INTERVAL_HOUR_TO_MINUTE, SQL_INTERVAL_HOUR_TO_SECOND,
		SQL_INTERVAL_MINUTE, SQL_INTERVAL_MINUTE_TO_SECOND,
		SQL_INTERVAL_SECOND, SQL_SMALLINT, SQL_TYPE_TIME,
		SQL_TYPE_TIMESTAMP, SQL_TYPE_TIMESTAMP, SQL_TYPE_TIME,
		SQL_TINYINT, SQL_WVARCHAR, SQL_INTEGER, SQL_BIGINT,
		/* nullable: */
		SQL_NULLABLE, SQL_NO_NULLS,
		/* sql_data_type: */
		SQL_BIGINT, SQL_LONGVARBINARY, SQL_BIT, SQL_WCHAR,
		SQL_WLONGVARCHAR, SQL_DATETIME, SQL_DECIMAL, SQL_DOUBLE,
		SQL_INTEGER, SQL_INTERVAL, SQL_REAL, SQL_INTERVAL,
		SQL_SMALLINT, SQL_DATETIME, SQL_DATETIME, SQL_DATETIME,
		SQL_DATETIME, SQL_TINYINT, SQL_WVARCHAR, SQL_INTEGER,
		SQL_BIGINT,
		/* sql_datetime_sub: */
		SQL_CODE_DATE, SQL_CODE_YEAR, SQL_CODE_YEAR_TO_MONTH,
		SQL_CODE_MONTH, SQL_CODE_DAY, SQL_CODE_DAY_TO_HOUR,
		SQL_CODE_DAY_TO_MINUTE, SQL_CODE_DAY_TO_SECOND,
		SQL_CODE_HOUR, SQL_CODE_HOUR_TO_MINUTE,
		SQL_CODE_HOUR_TO_SECOND, SQL_CODE_MINUTE,
		SQL_CODE_MINUTE_TO_SECOND, SQL_CODE_SECOND,
		SQL_CODE_TIME, SQL_CODE_TIMESTAMP, SQL_CODE_TIMESTAMP,
		SQL_CODE_TIME);
	assert(strlen(query) < 6300);
	query_end += strlen(query_end);

	/* depending on the input parameter values we must add a
	   variable selection condition dynamically */

	/* Construct the selection condition query part */
	if (cat) {
		/* filtering requested on catalog name */
		sprintf(query_end, " and %s", cat);
		query_end += strlen(query_end);
		free(cat);
	}
	if (sch) {
		/* filtering requested on schema name */
		sprintf(query_end, " and %s", sch);
		query_end += strlen(query_end);
		free(sch);
	}
	if (tab) {
		/* filtering requested on table name */
		sprintf(query_end, " and %s", tab);
		query_end += strlen(query_end);
		free(tab);
	}
	if (col) {
		/* filtering requested on column name */
		sprintf(query_end, " and %s", col);
		query_end += strlen(query_end);
		free(col);
	}

	/* add the ordering */
	strcpy(query_end,
	       " order by table_cat, table_schem, "
	       "table_name, ordinal_position");
	query_end += strlen(query_end);

	/* query the MonetDB data dictionary tables */
	rc = SQLExecDirect_(stmt, (SQLCHAR *) query,
			    (SQLINTEGER) (query_end - query));

	free(query);

	return rc;
}
Exemple #6
0
static SQLRETURN
MNDBSpecialColumns(ODBCStmt *stmt,
		   SQLUSMALLINT IdentifierType,
		   SQLCHAR *CatalogName,
		   SQLSMALLINT NameLength1,
		   SQLCHAR *SchemaName,
		   SQLSMALLINT NameLength2,
		   SQLCHAR *TableName,
		   SQLSMALLINT NameLength3,
		   SQLUSMALLINT Scope,
		   SQLUSMALLINT Nullable)
{
	RETCODE rc;

	/* buffer for the constructed query to do meta data retrieval */
	char *query = NULL;
	char *query_end = NULL;
	char *cat = NULL, *sch = NULL, *tab = NULL;

	fixODBCstring(CatalogName, NameLength1, SQLSMALLINT, addStmtError, stmt, return SQL_ERROR);
	fixODBCstring(SchemaName, NameLength2, SQLSMALLINT, addStmtError, stmt, return SQL_ERROR);
	fixODBCstring(TableName, NameLength3, SQLSMALLINT, addStmtError, stmt, return SQL_ERROR);

#ifdef ODBCDEBUG
	ODBCLOG("\"%.*s\" \"%.*s\" \"%.*s\" %s %s\n",
		(int) NameLength1, (char *) CatalogName,
		(int) NameLength2, (char *) SchemaName,
		(int) NameLength3, (char *) TableName,
		translateScope(Scope), translateNullable(Nullable));
#endif

	/* check for valid IdentifierType argument */
	switch (IdentifierType) {
	case SQL_BEST_ROWID:
	case SQL_ROWVER:
		break;
	default:
		/* Column type out of range */
		addStmtError(stmt, "HY097", NULL, 0);
		return SQL_ERROR;
	}

	/* check for valid Scope argument */
	switch (Scope) {
	case SQL_SCOPE_CURROW:
	case SQL_SCOPE_TRANSACTION:
	case SQL_SCOPE_SESSION:
		break;
	default:
		/* Scope type out of range */
		addStmtError(stmt, "HY098", NULL, 0);
		return SQL_ERROR;
	}

	/* check for valid Nullable argument */
	switch (Nullable) {
	case SQL_NO_NULLS:
	case SQL_NULLABLE:
		break;
	default:
		/* Nullable type out of range */
		addStmtError(stmt, "HY099", NULL, 0);
		return SQL_ERROR;
	}

	/* check if a valid (non null, not empty) table name is supplied */
	if (TableName == NULL) {
		/* Invalid use of null pointer */
		addStmtError(stmt, "HY009", NULL, 0);
		return SQL_ERROR;
	}
	if (NameLength3 == 0) {
		/* Invalid string or buffer length */
		addStmtError(stmt, "HY090", NULL, 0);
		return SQL_ERROR;
	}

	/* SQLSpecialColumns returns a table with the following columns:
	   SMALLINT     scope
	   VARCHAR      column_name NOT NULL
	   SMALLINT     data_type NOT NULL
	   VARCHAR      type_name NOT NULL
	   INTEGER      column_size
	   INTEGER      buffer_length
	   SMALLINT     decimal_digits
	   SMALLINT     pseudo_column
	 */
	if (IdentifierType == SQL_BEST_ROWID) {
		/* Select from the key table the (smallest) primary/unique key */
		if (stmt->Dbc->sql_attr_metadata_id == SQL_FALSE) {
			if (NameLength1 > 0) {
				cat = ODBCParseOA("e", "value",
						  (const char *) CatalogName,
						  (size_t) NameLength1);
				if (cat == NULL)
					goto nomem;
			}
			if (NameLength2 > 0) {
				sch = ODBCParseOA("s", "name",
						  (const char *) SchemaName,
						  (size_t) NameLength2);
				if (sch == NULL)
					goto nomem;
			}
			if (NameLength3 > 0) {
				tab = ODBCParseOA("t", "name",
						  (const char *) TableName,
						  (size_t) NameLength3);
				if (tab == NULL)
					goto nomem;
			}
		} else {
			if (NameLength1 > 0) {
				cat = ODBCParseID("e", "value",
						  (const char *) CatalogName,
						  (size_t) NameLength1);
				if (cat == NULL)
					goto nomem;
			}
			if (NameLength2 > 0) {
				sch = ODBCParseID("s", "name",
						  (const char *) SchemaName,
						  (size_t) NameLength2);
				if (sch == NULL)
					goto nomem;
			}
			if (NameLength3 > 0) {
				tab = ODBCParseID("t", "name",
						  (const char *) TableName,
						  (size_t) NameLength3);
				if (tab == NULL)
					goto nomem;
			}
		}

		/* first create a string buffer (1000 extra bytes is plenty */
		query = (char *) malloc(5000 + NameLength1 + NameLength2 + NameLength3);
		if (query == NULL)
			goto nomem;
		query_end = query;

		/* Note: SCOPE is SQL_SCOPE_TRANSACTION */
		/* Note: PSEUDO_COLUMN is SQL_PC_NOT_PSEUDO */
		sprintf(query_end,
			"with sc as ("
			"select t.id as table_id, k.type as type, "
			       "cast(%d as smallint) as scope, "
			       "c.name as column_name, "
			DATA_TYPE(c) ", "
			TYPE_NAME(c) ", "
			COLUMN_SIZE(c) ", "
			BUFFER_LENGTH(c) ", "
			DECIMAL_DIGITS(c) ", "
			       "cast(%d as smallint) as pseudo_column "
			 "from sys.schemas s, "
			      "sys.tables t, "
			      "sys.columns c, "
			      "sys.keys k, "
			      "sys.objects kc, "
			      "sys.env() e  "
			 "where s.id = t.schema_id and "
			       "t.id = c.table_id and "
			       "t.id = k.table_id and "
			       "c.name = kc.name and "
			       "kc.id = k.id and "
			       "k.type = 0 and "
			       "e.name = 'gdk_dbname'",
			/* scope: */
			SQL_SCOPE_TRANSACTION,
#ifdef DATA_TYPE_ARGS
			DATA_TYPE_ARGS,
#endif
#ifdef TYPE_NAME_ARGS
			TYPE_NAME_ARGS,
#endif
#ifdef COLUMN_SIZE_ARGS
			COLUMN_SIZE_ARGS,
#endif
#ifdef BUFFER_SIZE_ARGS
			BUFFER_SIZE_ARGS,
#endif
#ifdef DECIMAL_DIGITS_ARGS
			DECIMAL_DIGITS_ARGS,
#endif
			/* pseudo_column: */
			SQL_PC_NOT_PSEUDO);
		assert(strlen(query) < 4300);
		query_end += strlen(query_end);
		/* TODO: improve the SQL to get the correct result:
		   - only one set of columns should be returned, also
		     when multiple primary keys are available for this
		     table.
		   - when the table has NO primary key it should
		     return the columns of a unique key (only from ONE
		     unique key which is also the best/smallest key)
		   TODO: optimize SQL:
		   - when no SchemaName is set (see above) also no
		     filtering on SCHEMA NAME and join with table
		     SCHEMAS is needed!
		 */

		/* add the selection condition */
		if (cat) {
			/* filtering requested on catalog name */
			sprintf(query_end, " and %s", cat);
			query_end += strlen(query_end);
			free(cat);
		}
		if (sch) {
			/* filtering requested on schema name */
			sprintf(query_end, " and %s", sch);
			query_end += strlen(query_end);
			free(sch);
		}
		if (tab) {
			/* filtering requested on table name */
			sprintf(query_end, " and %s", tab);
			query_end += strlen(query_end);
			free(tab);
		}

		/* add an extra selection when SQL_NO_NULLS is requested */
		if (Nullable == SQL_NO_NULLS) {
			strcpy(query_end, " and c.\"null\" = false");
			query_end += strlen(query_end);
		}

		strcpy(query_end,
		       "), "
			"tid as ("
			   "select t.id as tid "
			    "from sys._tables t, sys.keys k "
			    "where t.id = k.table_id and k.type = 0"
		       ") "
			"select sc.scope, sc.column_name, sc.data_type, "
			       "sc.type_name, sc.column_size, "
			       "sc.buffer_length, sc.decimal_digits, "
			       "sc.pseudo_column "
			"from sc "
			"where (sc.type = 0 and "
			       "sc.table_id in (select tid from tid)) or "
			      "(sc.type = 1 and "
			       "sc.table_id not in (select tid from tid))");
		query_end += strlen(query_end);

		/* ordering on SCOPE not needed (since it is constant) */
	} else {
		assert(IdentifierType == SQL_ROWVER);
		/* The backend does not have such info available */
		/* create just a query which results in zero rows */
		/* Note: pseudo_column is sql_pc_unknown is 0 */
		query = strdup("select cast(null as smallint) as scope, "
				      "cast('' as varchar(1)) as column_name, "
				      "cast(1 as smallint) as data_type, "
				      "cast('char' as varchar(4)) as type_name, "
				      "cast(1 as integer) as column_size, "
				      "cast(1 as integer) as buffer_length, "
				      "cast(0 as smallint) as decimal_digits, "
				      "cast(0 as smallint) as pseudo_column "
			       "where 0 = 1");
		if (query == NULL)
			goto nomem;
		query_end = query + strlen(query);
	}

	/* query the MonetDB data dictionary tables */
	rc = MNDBExecDirect(stmt,
			    (SQLCHAR *) query,
			    (SQLINTEGER) (query_end - query));

	free(query);

	return rc;

  nomem:
	/* note that query must be NULL when we get here */
	if (cat)
		free(cat);
	if (sch)
		free(sch);
	if (tab)
		free(tab);
	/* Memory allocation error */
	addStmtError(stmt, "HY001", NULL, 0);
	return SQL_ERROR;
}
Exemple #7
0
static SQLRETURN
MNDBPrimaryKeys(ODBCStmt *stmt,
		SQLCHAR *CatalogName,
		SQLSMALLINT NameLength1,
		SQLCHAR *SchemaName,
		SQLSMALLINT NameLength2,
		SQLCHAR *TableName,
		SQLSMALLINT NameLength3)
{
	RETCODE rc;

	/* buffer for the constructed query to do meta data retrieval */
	char *query = NULL;
	char *query_end = NULL;	/* pointer to end of built-up query */
	char *cat = NULL, *sch = NULL, *tab = NULL;

	/* deal with SQL_NTS and SQL_NULL_DATA */
	fixODBCstring(CatalogName, NameLength1, SQLSMALLINT,
		      addStmtError, stmt, return SQL_ERROR);
	fixODBCstring(SchemaName, NameLength2, SQLSMALLINT,
		      addStmtError, stmt, return SQL_ERROR);
	fixODBCstring(TableName, NameLength3, SQLSMALLINT,
		      addStmtError, stmt, return SQL_ERROR);

	/* check if a valid (non null, not empty) table name is supplied */
	if (TableName == NULL) {
		/* Invalid use of null pointer */
		addStmtError(stmt, "HY009", NULL, 0);
		return SQL_ERROR;
	}
#ifdef ODBCDEBUG
	ODBCLOG("\"%.*s\" \"%.*s\" \"%.*s\"\n",
		(int) NameLength1, (char *) CatalogName,
		(int) NameLength2, (char *) SchemaName,
		(int) NameLength3, (char *) TableName);
#endif

	if (stmt->Dbc->sql_attr_metadata_id == SQL_FALSE) {
		if (NameLength1 > 0) {
			cat = ODBCParseOA("e", "value",
					  (const char *) CatalogName,
					  (size_t) NameLength1);
			if (cat == NULL)
				goto nomem;
		}
		if (NameLength2 > 0) {
			sch = ODBCParseOA("s", "name",
					  (const char *) SchemaName,
					  (size_t) NameLength2);
			if (sch == NULL)
				goto nomem;
		}
		if (NameLength3 > 0) {
			tab = ODBCParseOA("t", "name",
					  (const char *) TableName,
					  (size_t) NameLength3);
			if (tab == NULL)
				goto nomem;
		}
	} else {
		if (NameLength1 > 0) {
			cat = ODBCParseID("e", "value",
					  (const char *) CatalogName,
					  (size_t) NameLength1);
			if (cat == NULL)
				goto nomem;
		}
		if (NameLength2 > 0) {
			sch = ODBCParseID("s", "name",
					  (const char *) SchemaName,
					  (size_t) NameLength2);
			if (sch == NULL)
				goto nomem;
		}
		if (NameLength3 > 0) {
			tab = ODBCParseID("t", "name",
					  (const char *) TableName,
					  (size_t) NameLength3);
			if (tab == NULL)
				goto nomem;
		}
	}

	/* construct the query */
	query = malloc(1000 + (cat ? strlen(cat) : 0) +
		       (sch ? strlen(sch) : 0) + (tab ? strlen(tab) : 0));
	if (query == NULL)
		goto nomem;
	query_end = query;

	/* SQLPrimaryKeys returns a table with the following columns:
	   VARCHAR      table_cat
	   VARCHAR      table_schem
	   VARCHAR      table_name NOT NULL
	   VARCHAR      column_name NOT NULL
	   SMALLINT     key_seq NOT NULL
	   VARCHAR      pk_name
	 */
	strcpy(query_end,
	       "select e.value as table_cat, "
		      "s.name as table_schem, "
		      "t.name as table_name, "
		      "kc.name as column_name, "
		      "cast(kc.nr + 1 as smallint) as key_seq, "
		      "k.name as pk_name "
	       "from sys.schemas s, sys.tables t, "
		    "sys.keys k, sys.objects kc, "
		    "sys.env() e "
	       "where k.id = kc.id and "
		     "k.table_id = t.id and "
		     "t.schema_id = s.id and "
		     "k.type = 0 and "
		     "e.name = 'gdk_dbname'");
	assert(strlen(query) < 800);
	query_end += strlen(query_end);

	/* Construct the selection condition query part */
	if (cat) {
		/* filtering requested on catalog name */
		sprintf(query_end, " and %s", cat);
		query_end += strlen(query_end);
		free(cat);
	}
	if (sch) {
		/* filtering requested on schema name */
		sprintf(query_end, " and %s", sch);
		query_end += strlen(query_end);
		free(sch);
	}
	if (tab) {
		/* filtering requested on table name */
		sprintf(query_end, " and %s", tab);
		query_end += strlen(query_end);
		free(tab);
	}

	/* add the ordering */
	strcpy(query_end, " order by table_schem, table_name, key_seq");
	query_end += strlen(query_end);

	/* query the MonetDB data dictionary tables */
	rc = MNDBExecDirect(stmt,
			    (SQLCHAR *) query,
			    (SQLINTEGER) (query_end - query));

	free(query);

	return rc;

  nomem:
	/* note that query must be NULL when we get here */
	if (cat)
		free(cat);
	if (sch)
		free(sch);
	if (tab)
		free(tab);
	/* Memory allocation error */
	addStmtError(stmt, "HY001", NULL, 0);
	return SQL_ERROR;
}