⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 odbcmetadatagenerator.java

📁 derby database source code.good for you.
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
		}		odbcMetaFile.write("\n\n");		return;	}	/* ****	 * renameColsForODBC	 * Renames any columns in the received query so that they are	 * ODBC-compliant.	 * @param queryName Name of the query being processed.	 * @param queryText Text of the query being processed.	 * @return All columns requiring renaming have been renamed IN	 *	PLACE in the received StringBuffer.  True is returned if	 *	at least one column was renamed; false otherwise.	 */	private boolean renameColsForODBC(String queryName, StringBuffer queryText) {		// If we know the received query doesn't have any columns to		// be renamed, then there's nothing to do here.		if (!stmtNeedsChange(queryName, COL_RENAME_CHANGE))			return false;		// Which columns are renamed, and what the new names are,		// depends on which query we're processing.		if (queryName.equals("getProcedures")) {			renameColForODBC(queryText, "RESERVED1", "NUM_INPUT_PARAMS");			renameColForODBC(queryText, "RESERVED2", "NUM_OUTPUT_PARAMS");			renameColForODBC(queryText, "RESERVED3", "NUM_RESULT_SETS");			return true;		}		else if (queryName.equals("getProcedureColumns")) {			renameColForODBC(queryText, "PRECISION", "COLUMN_SIZE");			renameColForODBC(queryText, "LENGTH", "BUFFER_LENGTH");			renameColForODBC(queryText, "SCALE", "DECIMAL_DIGITS");			renameColForODBC(queryText, "RADIX", "NUM_PREC_RADIX");			return true;		}		else if (queryName.equals("getTypeInfo")) {			renameColForODBC(queryText, "PRECISION", "COLUMN_SIZE");			renameColForODBC(queryText, "AUTO_INCREMENT", "AUTO_UNIQUE_VAL");			return true;		}		// No renaming was necessary.		return false;	}	/* ****	 * renameColForODBC	 * Searches for the old column name in the received String	 * buffer and replaces it with the new column name.  Note	 * that we only replace the old column name where it is	 * preceded by "AS", because this is the instance that	 * determines the column name in the final result set.	 * @param queryText The query text in which we're doing the	 *	rename operation.	 * @param oldVal The old column name.	 * @param newVal The new column name.	 * @return Occurence of <"AS " + oldVal> in the query text	 *	has been changed IN PLACE to newVal.	 */	private void renameColForODBC(StringBuffer queryText,		String oldVal, String newVal)	{		String queryString = queryText.toString();		int pos = queryString.indexOf(oldVal);		while (pos != -1) {			// Next line will set pos2 to be the index of the			// first (reading left-to-right) ignorable char			// preceding the old column name.  That means			// that the letters immediately preceding this			// position should be "AS".  If not, don't			// replace this instance.			int pos2 = trimIgnorable(PRECEDING, queryString, pos);			if (((pos2 - 2) > 0) && (queryString.charAt(pos2-2) == 'A')				&& (queryString.charAt(pos2-1) == 'S'))			{ // then this is the one we want to replace.				break;			}			else {			// look for next occurrence.				pos = queryString.indexOf(oldVal, pos+1);			}		}		if (pos == -1) {		// couldn't find the one to replace; leave unchanged.			return;		}		// Do the renaming.		queryText.replace(pos, pos + oldVal.length(), newVal);	}	/* ****	 * generateSELECTClause	 * Generates an outer SELECT clause that is then wrapped around a	 * JDBC query to change the types and/or values of the JDBC	 * result set.  The JDBC query thus becomes a subquery.	 *	 * Ex. if we have a JDBC query "SELECT A, B FROM T1" and ODBC	 * requires that "A" be a smallint, this method will generate	 * a select clause "SELECT CAST (T2.A AS SMALLINT), T2.B FROM"	 * that is then used to wrap the JDBC query, as follows:	 *	 *		SELECT CAST (T2.A AS SMALLINT), T2.B FROM	 *			(SELECT A, B FROM T1) T2	 *	 * @param queryName Name of the query being processed.	 * @param selectColDefs Array list of the SELECT columns that	 * 	exist for the JDBC version of the query.  For the above	 *  example, this would be an array list with two String	 *  elements, "A" and "B".	 * @param newQueryText StringBuffer to which the generated	 *  outer SELECT will be appended.	 * @return An outer SELECT clause has been generated and	 *  appended to the received buffer.  The "FROM" keyword	 *  has been appended, but the subquery itself is NOT	 *  added here.	 */	private void generateSELECTClause(String queryName,		ArrayList selectColDefs, StringBuffer newQueryText)	{		if (!stmtNeedsChange(queryName, TYPE_VALUE_CHANGE) &&			!stmtNeedsChange(queryName, ADD_COLUMN_CHANGE))		{ // then we don't need to generate a SELECT, because we		  // don't need to use a subquery (we're only renaming).			return;		}		// Begin the SELECT clause.		newQueryText.append("SELECT \\\n\\\n");		// For each of the SELECT columns in JDBC, either		// just grab the column name and use it directly in		// the generated clause, or else cast the column		// to the required type, if appropriate.		String colName;		String castInfo;		for (int i = 0; i < selectColDefs.size(); i++) {			if (i > 0)				newQueryText.append(", \\\n");			colName = extractColName((String)selectColDefs.get(i));			castInfo = getCastInfoForCol(queryName, colName);			if (castInfo != null)				newQueryText.append("CAST (");			newQueryText.append(SUBQUERY_NAME);			newQueryText.append(".");			newQueryText.append(colName);			if (castInfo != null) {				newQueryText.append(" AS ");				newQueryText.append(castInfo);				newQueryText.append(")");			}			if (!colName.equals(NEW_COL_PLACEHOLDER)) {			// don't append the "AS" clause if this is just our			// place-holder for adding new columns.				newQueryText.append(" AS ");				newQueryText.append(colName);			}		}		if (newQueryText.charAt(newQueryText.length() - 1) != '\\')			newQueryText.append(" \\");		// End the SELECT clause.		newQueryText.append("\nFROM ( ");		return;	}	/* ****	 * changeValuesForODBC	 * Searches for a JDBC column name in the received String	 * buffer and replaces the first occurrence with an ODBC-	 * compliant value.  This method determines what specific	 * columns need updated values for a given query, and then	 * makes the appropriate call for each column.	 * @param queryName Name of the query being processed.	 * @param newQueryText The query text in which we're doing the	 *	change-value operation.	 * @return All relevant columns have been updated IN PLACE	 *	to return the required ODBC-compliant values.	 */	private void changeValuesForODBC(String queryName,		StringBuffer newQueryText)	{		if (!stmtNeedsChange(queryName, TYPE_VALUE_CHANGE))			return;		// Which column values are changed, and what the new		// values are, depends on which query we're processing.		if (queryName.equals("getColumns")) {			changeColValueToODBC(queryName, "BUFFER_LENGTH", newQueryText);			changeColValueToODBC(queryName, "DECIMAL_DIGITS", newQueryText);			changeColValueToODBC(queryName, "NUM_PREC_RADIX", newQueryText);			changeColValueToODBC(queryName, "SQL_DATA_TYPE", newQueryText);			changeColValueToODBC(queryName, "SQL_DATETIME_SUB", newQueryText);			changeColValueToODBC(queryName, "CHAR_OCTET_LENGTH", newQueryText);		}		else if (queryName.startsWith("getBestRowIdentifier")) {			changeColValueToODBC(queryName, "BUFFER_LENGTH", newQueryText);			changeColValueToODBC(queryName, "DECIMAL_DIGITS", newQueryText);		}		else if (queryName.equals("getTypeInfo")) {			changeColValueToODBC(queryName, "NUM_PREC_RADIX", newQueryText);			changeColValueToODBC(queryName, "SQL_DATA_TYPE", newQueryText);			changeColValueToODBC(queryName, "SQL_DATETIME_SUB", newQueryText);			changeColValueToODBC(queryName, "UNSIGNED_ATTRIBUTE", newQueryText);			changeColValueToODBC(queryName, "AUTO_UNIQUE_VAL", newQueryText);		}		else if (queryName.equals("getProcedureColumns")) {			changeColValueToODBC(queryName, "NUM_PREC_RADIX", newQueryText);			changeColValueToODBC(queryName, "DECIMAL_DIGITS", newQueryText);		}	}	/* ****	 * changeColValueToODBC	 * Searches for the received column name in the received String	 * buffer and replaces it with an ODBC-compliant value.	 * @param queryName Name of the query being processed.	 * @param colName Name of the specific column to update.	 * @param newQueryText The query text in which we're doing	 *	the change-value operation.	 * @return The received column has been updated IN PLACE	 *	to return the required ODBC-compliant value.	 */	private void changeColValueToODBC(String queryName, String colName,		StringBuffer newQueryText)	{		colName = SUBQUERY_NAME + "." + colName;		int pos = newQueryText.toString().indexOf(colName);		if (pos == -1)		// column we're supposed to change isn't in the query.			return;		if (colName.endsWith("CHAR_OCTET_LENGTH")) {			newQueryText.replace(pos, pos + colName.length(),				getFragment("CHAR_OCTET_FOR_ODBC"));		}		else if (colName.endsWith("BUFFER_LENGTH")) {			newQueryText.replace(pos, pos + colName.length(),				getFragment("BUFFER_LEN_FOR_ODBC"));		}		else if (colName.endsWith("SQL_DATA_TYPE")) {			newQueryText.replace(pos, pos + colName.length(),				getFragment("SQL_DATA_TYPE_FOR_ODBC"));		}		else if (colName.endsWith("SQL_DATETIME_SUB")) {			newQueryText.replace(pos, pos + colName.length(),				getFragment("DATETIME_SUB_FOR_ODBC"));		}		else if (colName.endsWith("UNSIGNED_ATTRIBUTE")) {			newQueryText.replace(pos, pos + colName.length(),				getFragment("UNSIGNED_ATTR_FOR_ODBC"));		}		else if (colName.endsWith("AUTO_UNIQUE_VAL")) {			newQueryText.replace(pos, pos + colName.length(),				getFragment("AUTO_UNIQUE_FOR_ODBC"));		}		else if (colName.endsWith("DECIMAL_DIGITS")) {			newQueryText.replace(pos, pos + colName.length(),				getFragment("DECIMAL_DIGITS_FOR_ODBC"));		}		else if (colName.endsWith("NUM_PREC_RADIX")) {			newQueryText.replace(pos, pos + colName.length(),				getFragment("RADIX_FOR_ODBC"));		}		else if (colName.endsWith(NEW_COL_PLACEHOLDER)) {		// This is a special case indication that we need to add new columns.			if (queryName.equals("getProcedureColumns")) {				newQueryText.replace(pos, pos + colName.length(),					getFragment("GET_PROC_COLS_NEW_COLS"));			}			else if (queryName.equals("getTypeInfo")) {				newQueryText.replace(pos, pos + colName.length(),					getFragment("GET_TYPE_INFO_NEW_COLS"));			}		}	}	/* ****	 * getSelectColDefinitions	 * Parses the SELECT clause of a JDBC metadata SQL query	 * and returns a list of the columns being selected.  For	 * example, if the received statement was "SELECT A,	 * B AS C, D * 2 FROM T1", this method will return an	 * ArrayList with three string elements: 1) "A", 2) "B	 * AS C", and 3) "D * 2".	 * @param query The query from which we are extracting	 *	the SELECT columns.	 * @param colDefList ArrayList in which we want to	 * 	store the column definitions that we find.	 * @return Received ArrayList has one string value for	 *	each of the columns found in the received query.	 *	Also, an integer is returned indicating the index	 *	in the received query of the start of the FROM	 *	clause, for later use by the calling method.	 */	private int getSelectColDefinitions(StringBuffer queryText,		ArrayList colDefList)	{		// Create a string for purposes of using "indexOf"		// calls, which aren't allowed on a StringBuffer		// for JDBC 2.0.		String query = queryText.toString().trim();		char [] queryChars = query.toCharArray();		// Move beyond the "SELECT" keyword, if there is one.		int start = query.indexOf("SELECT");		if (start != -1)		// "+6" in the next line is length of "SELECT".			start += 6;		else		// just start at the first character.			start = 0;		// Have to read character-by-character in order to		// figure out where each column description ends.		int fromClauseIndex = -1;		int parenDepth = 0;		for (int i = start; i < queryChars.length; i++) {			if (queryChars[i] == '(')				parenDepth++;			else if (queryChars[i] == ')')				parenDepth--;			else if ((queryChars[i] == ',') && (parenDepth == 0)) {			// this is a naive way of determining the end of a			// column definition (it'll work so long as there are no			// string constants in the query that have commas in them,			// which was true at the time of writing.				colDefList.add(new String(queryChars, start, (i - start)).trim());				// Skip over non-important whitespace to find start				// of next column definition.  Next line will set i to				// just before the next non-whitespace character.				i = trimIgnorable(FOLLOWING, queryChars, i);				start = i + 1;			}			else if (((i+3) < queryChars.length)				&& (parenDepth == 0)				&& (queryChars[i] == 'F')				&& (queryChars[i+1] == 'R')				&& (queryChars[i+2] == 'O')				&& (queryChars[i+3] == 'M'))			{ // this is the end of final column definition; store it			  // and then exit the loop, after trimming off non-important			  // whitespace.  Next line will set i to just after the			  // last (reading left-to-right) non-whitespace character			  // before the FROM.				i = trimIgnorable(PRECEDING, queryChars, i);				fromClauseIndex = i;				colDefList.add(new String(queryChars, start, (i - start)).trim());				break;			}		}		return fromClauseIndex;	}	/* ****	 * addHelperColsToSubquery	 * For some of the metadata queries, the ODBC version	 * needs to access values that are only available in	 * the JDBC subquery.  In such cases, we want to add	 * those values as additional "helper" columns to	 * the subquery result set, so that they can be	 * referenced from the new ODBC outer query (without	 * requiring a join).  For example, assume we have 2	 * tables T1(int i, int j) and T2 (int a), and a	 * subquery "SELECT T1.i, T1.j + T2.a from T1, T2)".	 * Then we have an outer query that, instead of	 * returning "T1.j + T2.a", needs to return the	 * value of "2 * T2.a":	 *	 * SELECT VT.i, 2 * T2.a FROM	 *	(SELECT T1.i, T1.j + T2.a FROM T1, T2) VT	 *	 * The above statement WON'T work, because the outer	 * query can't see the value "T2.a".  So in such a	 * a case, this method will add "T2.a" to the list	 * of columns returned by the subquery, so that the	 * outer query can then access it:	 *	 * SELECT VT.i, 2 * VT.a FROM

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -