/* * Execute an SQL Select Statement */ protected virtual TsResultSet SelectStatement(java.util.Hashtable <Object, Object> t, java.util.Vector <Object> c, TinySQLWhere w, String ot, bool distinct, Object stmt) //throws TinySQLException { java.util.Hashtable <Object, Object> tables; java.util.Vector <Object> tableList; TsResultSet jrs; TsColumn columnObject; int i; /* * Instantiate a new, empty tsResultSet */ jrs = new TsResultSet(w, this); groupFunctions = new java.util.Hashtable <Object, Object>(); try { jrs.setFetchSize(((TinySQLStatement)stmt).getFetchSize()); jrs.setType(((TinySQLStatement)stmt).getResultSetType()); } catch (java.sql.SQLException) { Utils.log("Caught SQLException while setting Fetchsize and ResultSetType"); Utils.log(" This event is (should be) impossible!"); } tables = t; tableList = (java.util.Vector <Object>)tables.get("TABLE_SELECT_ORDER"); /* * Add the column objects to the ResultSet. */ for (i = 0; i < c.size(); i++) { columnObject = (TsColumn)c.elementAt(i); /* * The column object is now added to the ResultSet */ jrs.addColumn(columnObject); if (debug) { java.lang.SystemJ.outJ.println("Adding " + columnObject.contextToString() + " column " + newLine + columnObject.toString() + newLine); } } jrs.setState(1, tables, ot, distinct); contSelectStatement(jrs); return(jrs); }
/** * * Constructs a tinySQLResultSet; requires a TsResultSet object * @param result the TsResultSet object * */ public TinySQLResultSetMetaData(TsResultSet result) { tsql = result; }
/* * Support function for restartable queries. Continue to * read the query result. The current state is taken from * tsResultSet. Proceed until maxFetchSize has reached. */ protected internal virtual void contSelectStatement(TsResultSet jrs) //throws TinySQLException { /* * The table scan here is an iterative tree expansion, similar to * the algorithm shown in the outline example in Chapter 5. */ String columnName, columnString, whereStatus, tableAndAlias; bool addOK; int i; int level = jrs.getLevel(); TinySQLTable jtbl; TsColumn updateColumn; java.util.Hashtable <Object, Object> tables = jrs.getTableState(); TinySQLWhere wc = jrs.getWhereClause(); /* * Create a hashtable to enumerate the tables to be scanned and initialize * with the first table name. */ java.util.Hashtable <Object, Object> tbl_list = new java.util.Hashtable <Object, Object>(); java.util.Vector <Object> t = (java.util.Vector <Object>)tables.get("TABLE_SELECT_ORDER"); String current = (String)t.elementAt(0); tbl_list.put(current, new java.lang.Integer(1)); /* * Create a row object; this is added to the ResultSet. */ TsRow record = new TsRow(); java.util.Vector <Object> resultSet = new java.util.Vector <Object>(); /* * Keep retrieving rows until we run out of rows to process. */ while (level > 0) { bool levelFound = false; /* * Find an item within the tbl_list which has the same level as the * one we're on. */ java.util.Enumeration <Object> keys = tbl_list.keys(); while (keys.hasMoreElements()) { /* * Get the next element in the "to be processed" * Hashtable, and find out its level, storing this * value in currLevel. */ String hashkey = (String)keys.nextElement(); int currLevel = ((java.lang.Integer)tbl_list.get(hashkey)).intValue(); /* * As soon as an element is found whose level is equal to the * one currently being processed, grab it's primary key (the hashkey), * flag levelfound, and break! */ if (currLevel == level) { current = hashkey; levelFound = true; break; } } bool haveRecord = false; // did we get a record or not? /* * If a table was found at the current level, then we should * try to get another row from it. */ if (levelFound) { /* * Get the current table */ jtbl = (TinySQLTable)tables.get(current); tableAndAlias = jtbl.table + "->" + jtbl.tableAlias; if (TinySQLGlobals.WHERE_DEBUG) { java.lang.SystemJ.outJ.println("Processing level " + level + " table " + tableAndAlias + "\n"); } /* * The following code is the start of setting up simple indexes * for tinySQL. The concept involves creating a new tinySQLCondition * class, instances of which will be created by tinySQLWhere. At least * initially only conditions that are equal to a constant will be * considered. One of these conditions will be stored inside the * dbfFileTable object. Calls to NextRecord would then have to add * logic to check to see if an index exists. The presence of a * complete index would be indicated by a counter that was equal * to the number of rows in the table. In that case a single get * would deliver the record numbers required for the where condition. * The NextRecord function would return these record numbers in * sequence. If the index did not exist then new values in the * index Hashtable would be created. None of this code has been * developed or implemented, let alone tested. * * * if ( wc != (tinySQLWhere)null ) * jtbl.setIndexCondition(wc.getIndexCondition(tableAndAlias)); */ if (performDebug) { java.lang.SystemJ.outJ.println("Selecting records from " + jtbl.table); } /* * Skip to the next undeleted record; at some point, * this will run out of records, and found will be false. */ bool found = false; while (jtbl.NextRecord()) { /* * Clear the column values for this table before starting * to process the next row. */ for (i = 0; i < jrs.numcols(); i++) { updateColumn = jrs.columnAtIndex(i, true); updateColumn.clear(tableAndAlias); } if (wc != (TinySQLWhere)null) { wc.clearValues(tableAndAlias); } if (!jtbl.isDeleted()) { /* * Evaluate the where clause for each column in the table. If * it is false, skip to the next row. Otherwise, add the * column value to the output record. */ java.util.Enumeration <Object> cols = jtbl.column_info.keys(); found = true; whereStatus = "TRUE"; while (cols.hasMoreElements()) { columnName = tableAndAlias + "." + (String)cols.nextElement(); columnString = jtbl.GetCol(columnName); if (wc != (TinySQLWhere)null) { whereStatus = wc.evaluate(columnName, columnString); if (whereStatus.equals("FALSE")) { /* * This column value caused the where clause to * be FALSE. Go to the next row in the table. */ found = false; break; } } /* * Update the ResultSet tsColumn values */ jrs.updateColumns(columnName, columnString); } /* * If no where condition has evaluated to false then this * record is a candidate for output. Break to the next table * in this case for further WHERE processing. */ if (found) { break; } } } if (found) { if (TinySQLGlobals.DEBUG) { java.lang.SystemJ.outJ.println("Build candidate record."); } for (i = 0; i < jrs.numcols(); i++) { updateColumn = jrs.columnAtIndex(i, true); /* * Evaluate all functions before adding the * column to the output record. */ updateColumn.updateFunctions(); columnString = updateColumn.getString(); if (updateColumn.isNotNull()) { record.put(updateColumn.name, columnString); } else { record.remove(updateColumn.name); } } if (performDebug) { java.lang.SystemJ.outJ.println("Record is " + record.toString()); } /* * If the table we are processing is not the last in * the list, then we should increment level and loop to the top. */ if (level < t.size()) { /* * Increment level */ level++; /* * Add the next table in the list of tables to * the tbl_list, the Hashtable of "to be processed" tables. */ String next_tbl = (String)t.elementAt(level - 1); tbl_list.put(next_tbl, new java.lang.Integer(level)); } else { /* * If the table that was just processed is the last in * the list, then we have drilled down to the bottom; * all columns have values, and we can add it to the * result set. The next time through, the program * will try to read another row at this level; if it's * found, only columns for the table being read will * be overwritten in the tsRow. * * Columns for the other table will be left alone, and * another row will be added to the result set. Here * is the essence of the Cartesian Product which is * being built here. */ haveRecord = true; } } else { /* * We didn't find any more records at this level. * Reset the record pointer to the top of the table, * and decrement level. We have hit end of file here. */ if (wc != (TinySQLWhere)null) { wc.clearValues(tableAndAlias); } level--; jtbl.GoTop(); } } else { /* * No tables were found at this level; back up a level * and see if there's any up there. */ level--; } /* * If we got a record, then add it to the result set. */ if (haveRecord) { /* * If group functions are involved, add records only after a break, * which is defined as a change in all of the group columns. * Otherwise, update the current record. */ if (jrs.isGrouped()) { if (groupBreak) { addOK = jrs.addRow((TsRow)record.clone()); if (addOK == false) { jrs.setLevel(level); return; } groupBreak = false; } else { jrs.updateRow((TsRow)record.clone()); } } else { /* * No group functions are involved. Just add the record. */ addOK = jrs.addRow((TsRow)record.clone()); if (addOK == false) { jrs.setLevel(level); return; } } } } /* * Close all the tables */ for (i = 0; i < t.size(); i++) { jtbl = (TinySQLTable)tables.get((String)t.elementAt(i)); jtbl.close(); } /* * return a result set */ jrs.setLevel(0); }
/* * * Read SQL Statements from the SQLStream, and * return a result set for the last SQL Statement * executed. * * @returns the ResultSet or null, if no result set was created * @exception TinySQLException * */ protected virtual TsResultSet sql(Object s) //throws TinySQLException { /* * Build the ResultSet */ TsResultSet rs = null; TinySQLTable jtbl; TinySQLPreparedStatement pstmt = (TinySQLPreparedStatement)null; bool distinct = false; java.util.Vector <Object> actions, columns, columnDefs, values; String actionType, orderType, tableName, statementType, byteString; java.util.Hashtable <Object, Object> h, selectTables; byte[] bStream; java.io.ByteArrayInputStream st; int i; String actionString; groupBreak = false; statementType = s.getClass().getName(); try { /* * Instantiate a new parser object which reads from the SQLStream. This * should probably be changed to a String at some point. Note that * parsing is only done once for a PreparedStatement. */ actions = (java.util.Vector <Object>)null; if (statementType.endsWith("tinySQLPreparedStatement")) { pstmt = (TinySQLPreparedStatement)s; pstmt.updateActions(actions); actions = pstmt.getActions(); byteString = pstmt.getSQLString(); bStream = (byte[])null; if (pstmt.getSQLString() != (String)null) { bStream = pstmt.getSQLString().getBytes(); } } else if (statementType.endsWith("tinySQLStatement")) { bStream = ((TinySQLStatement)s).getSQLString().getBytes(); } else { throw new TinySQLException("Unknown statement type" + statementType); } if (actions == (java.util.Vector <Object>)null) { st = new java.io.ByteArrayInputStream(bStream); SQLStream = (java.io.InputStream)st; TinySQLParser tinyp = new TinySQLParser(SQLStream, this); TinySQLGlobals.writeLongNames(); actions = tinyp.getActions(); if (statementType.endsWith("tinySQLPreparedStatement")) { pstmt.updateActions(actions); } } /* * The actions Vector consists of a list of Hashtables. Each of these * action Hashtables contains elements required for a particular SQL * statement. The following elements are used for various actions; * * Type Name Description * * String tableName The name of the affected table for * CREATE,INSERT,UPDATE,DELETE actions. * * Hashtable selectTables Hashtable of tables in a SELECT action. * * Vector columns A list of column names used by the * the action. * * Vector columnContexts A list of Strings indicating the context * for the elements in the columns Vector. * Values can be SELECT,ORDER,GROUP. * * Vector columnDefs A list of column objects used by the * CREATE TABLE and ALTER TABLE ADD actions. * * Vector values A list of String values used in INSERT * and UPDATE actions. * * String oldColumnName Old column name for the * ALTER TABLE RENAME action. * * String newColumnName New column name for the * ALTER TABLE RENAME action. * * String orderType Type or ORDER BY - ASC or DESC. * * String distinct Distinct rows only - TRUE or NULL * * tinySQLWhere whereClause An object containing the where clause * which can be updated and queried. */ for (i = 0; i < actions.size(); i++) { h = (java.util.Hashtable <Object, Object>)actions.elementAt(i); actionType = (String)h.get("TYPE"); if (TinySQLGlobals.DEBUG) { java.lang.SystemJ.outJ.println("Action: " + actionType); } /* * Many actions have a table specification. If this one, build * a table object to update the where clause if there is one. */ tableName = (String)h.get("TABLE"); wc = (TinySQLWhere)h.get("WHERE"); if (tableName != (String)null & !actionType.equals("DROP_TABLE") & !actionType.equals("CREATE_TABLE") & !actionType.equals("INSERT") & !actionType.startsWith("ALTER")) { jtbl = getTable(tableName); /* * For prepared statements, store any table objects that * are created so that they can be explicitly closed when * the statement processing is complete. */ if (statementType.endsWith("tinySQLPreparedStatement")) { pstmt.addTable(jtbl); } } actionString = UtilString.actionToString(h); if (debug) { java.lang.SystemJ.outJ.println("ACTION: " + actionString); } if (actionType.equals("UPDATE")) { /* * SQL UPDATE */ columns = (java.util.Vector <Object>)h.get("COLUMNS"); values = (java.util.Vector <Object>)h.get("VALUES"); UpdateStatement(tableName, columns, values, wc); } else if (actionType.equals("DELETE")) { /* * SQL DELETE */ DeleteStatement(tableName, wc); } else if (actionType.equals("SELECT")) { /* * SQL SELECT */ selectTables = (java.util.Hashtable <Object, Object>)h.get("TABLES"); columns = (java.util.Vector <Object>)h.get("COLUMNS"); orderType = (String)h.get("ORDER_TYPE"); if ((String)h.get("DISTINCT") != (String)null) { distinct = true; } rs = SelectStatement(selectTables, columns, wc, orderType, distinct, s); } else if (actionType.equals("INSERT")) { /* * SQL INSERT */ columns = (java.util.Vector <Object>)h.get("COLUMNS"); values = (java.util.Vector <Object>)h.get("VALUES"); InsertStatement(statementType, tableName, columns, values); } else if (actionType.equals("CREATE_TABLE")) { /* * SQL CREATE TABLE * * CREATE TABLE User(user_oid NUMBER(8) NOT NULL, * userType VARCHAR(80) DEFAULT '-' NOT NULL, * PRIMARY KEY (user_oid)) * * -> DEFAULT / NOT NULL / PRIMARY KEY is not supported * */ columnDefs = (java.util.Vector <Object>)h.get("COLUMN_DEF"); CreateTable(tableName, columnDefs); } else if (actionType.equals("ALTER_ADD")) { /* * SQL ALTER TABLE ADD */ columnDefs = (java.util.Vector <Object>)h.get("COLUMN_DEF"); AlterTableAddCol(tableName, columnDefs); } else if (actionType.equals("ALTER_DROP")) { /* * SQL ALTER TABLE DROP */ columns = (java.util.Vector <Object>)h.get("COLUMNS"); AlterTableDropCol(tableName, columns); } else if (actionType.equals("ALTER_RENAME")) { /* * SQL ALTER TABLE RENAME */ String oldColumnName = (String)h.get("OLD_COLUMN"); String newColumnName = (String)h.get("NEW_COLUMN"); AlterTableRenameCol(tableName, oldColumnName, newColumnName); } else if (actionType.equals("DROP_TABLE")) { /* * SQL DROP TABLE */ DropTable(tableName); } else { java.lang.SystemJ.outJ.println("Unrecognized action " + actionType); } } } catch (java.lang.Throwable e) { if (TinySQLGlobals.EX_DEBUG) { e.printStackTrace(java.lang.SystemJ.outJ); } throw new TinySQLException(e.getMessage()); } return(rs); }
/** * Gets a description of table columns available in * the specified catalog. * * <P>Only column descriptions matching the catalog, schema, table * and column name criteria are returned. They are ordered by * TABLE_SCHEM, TABLE_NAME and ORDINAL_POSITION. * * <P>Each column description has the following columns: * <OL> * <LI><B>TABLE_CAT</B> String => table catalog (may be null) * <LI><B>TABLE_SCHEM</B> String => table schema (may be null)sRow record = new TsRow(); * * <LI><B>TABLE_NAME</B> String => table name * <LI><B>COLUMN_NAME</B> String => column name * <LI><B>DATA_TYPE</B> short => SQL type from java.sql.Types * <LI><B>TYPE_NAME</B> String => Data source dependent type name, * for a UDT the type name is fully qualified * <LI><B>COLUMN_SIZE</B> int => column size. For char or date * types this is the maximum number of characters, for numeric or * decimal types this is precision. * <LI><B>BUFFER_LENGTH</B> is not used. * <LI><B>DECIMAL_DIGITS</B> int => the number of fractional digits * <LI><B>NUM_PREC_RADIX</B> int => Radix (typically either 10 or 2) * <LI><B>NULLABLE</B> int => is NULL allowed? * <UL> * <LI> columnNoNulls - might not allow NULL values * <LI> columnNullable - definitely allows NULL values * <LI> columnNullableUnknown - nullability unknown * </UL> * <LI><B>REMARKS</B> String => comment describing column (may be null) * <LI><B>COLUMN_DEF</B> String => default value (may be null) * <LI><B>SQL_DATA_TYPE</B> int => unused * <LI><B>SQL_DATETIME_SUB</B> int => unused * <LI><B>CHAR_OCTET_LENGTH</B> int => for char types the * maximum number of bytes in the column * <LI><B>ORDINAL_POSITION</B> int => index of column in table * (starting at 1) * <LI><B>IS_NULLABLE</B> String => "NO" means column definitely * does not allow NULL values; "YES" means the column might * allow NULL values. An empty string means nobody knows. * </OL> * * @param catalog a catalog name; "" retrieves those without a * catalog; null means drop catalog name from the selection criteria * @param schemaPattern a schema name pattern; "" retrieves those * without a schema * @param tableNamePattern a table name pattern * @param columnNamePattern a column name pattern * @return ResultSet - each row is a column description * @exception SQLException if a database access error occurs * @see #getSearchStringEscape */ public override java.sql.ResultSet getColumns(String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern) { int i; String columnNameKey; try { String dataDir = getDataDir(); Utils.log("Entering getColumns(tableNamePattern='" + tableNamePattern + "')"); if (dataDir == null) { return(null); } java.sql.ResultSet tableRs = getTables(catalog, schemaPattern, tableNamePattern, null); TsResultSet jrs = new TsResultSet(); TsColumn jsc = new TsColumn("TABLE_CAT"); jsc.type = java.sql.Types.CHAR; jsc.size = 9; jrs.addColumn(jsc); jsc = new TsColumn("TABLE_SCHEM"); jsc.type = java.sql.Types.CHAR; jsc.size = 11; jrs.addColumn(jsc); jsc = new TsColumn("TABLE_NAME"); jsc.type = java.sql.Types.CHAR; jsc.size = 10; jrs.addColumn(jsc); jsc = new TsColumn("COLUMN_NAME"); jsc.type = java.sql.Types.CHAR; jsc.size = 11; jrs.addColumn(jsc); jsc = new TsColumn("DATA_TYPE"); jsc.type = java.sql.Types.INTEGER; jsc.size = 6; jrs.addColumn(jsc); jsc = new TsColumn("TYPE_NAME"); jsc.type = java.sql.Types.CHAR; jsc.size = 9; jrs.addColumn(jsc); jsc = new TsColumn("COLUMN_SIZE"); jsc.type = java.sql.Types.INTEGER; jsc.size = 8; jrs.addColumn(jsc); jsc = new TsColumn("BUFFER_LENGTH"); jsc.type = java.sql.Types.INTEGER; jsc.size = 8; jrs.addColumn(jsc); jsc = new TsColumn("DECIMAL_DIGITS"); jsc.type = java.sql.Types.INTEGER; jsc.size = 8; jrs.addColumn(jsc); jsc = new TsColumn("NUM_PREC_RADIX"); jsc.type = java.sql.Types.INTEGER; jsc.size = 8; jrs.addColumn(jsc); jsc = new TsColumn("NULLABLE"); jsc.type = java.sql.Types.INTEGER; jsc.size = 8; jrs.addColumn(jsc); jsc = new TsColumn("REMARKS"); jsc.type = java.sql.Types.CHAR; jsc.size = 128; jrs.addColumn(jsc); jsc = new TsColumn("COLUMN_DEF"); jsc.type = java.sql.Types.CHAR; jsc.size = 128; jrs.addColumn(jsc); jsc = new TsColumn("SQL_DATA_TYPE"); jsc.type = java.sql.Types.INTEGER; jsc.size = 128; jrs.addColumn(jsc); // Several parameters missing. jsc = new TsColumn("IS_NULLABLE"); jsc.type = java.sql.Types.CHAR; jsc.size = 3; jrs.addColumn(jsc); while (tableRs.next()) { // process each DBF file and extract column info ... String tableName = tableRs.getString("TABLE_NAME"); DBFFileTable tbl; try { tbl = new DBFFileTable(dataDir, tableName); } catch (Exception) { continue; // ignore buggy and empty (zero byte size) DBF files } Utils.log("Accessing column info for table " + tableName); java.util.Hashtable <Object, Object> column_info = tbl.column_info; for (i = 0; i < tbl.columnNameKeys.size(); i++) { columnNameKey = (String)tbl.columnNameKeys.elementAt(i); TsColumn tsc = (TsColumn)column_info.get(columnNameKey); // process each column of the current table ... TsRow record = new TsRow(); record.put("TABLE_CAT", ""); record.put("TABLE_SCHEM", ""); record.put("TABLE_NAME", tableName); record.put("COLUMN_NAME", TinySQLGlobals.getLongName(tsc.name)); record.put("DATA_TYPE", new java.lang.Integer(tsc.type).toString()); record.put("TYPE_NAME", DBFFile.typeToLiteral(tsc.type).toString()); record.put("COLUMN_SIZE", new java.lang.Integer(tsc.size).toString()); record.put("DECIMAL_DIGITS", new java.lang.Integer(tsc.decimalPlaces).toString()); int nullable = columnNoNulls; if (tsc.notNull == true) { nullable = columnNullable; } record.put("NULLABLE", new java.lang.Integer(nullable).toString()); record.put("REMARKS", "noRemarks"); String defaultVal = tsc.defaultVal; if (defaultVal == null) { defaultVal = ""; } record.put("COLUMN_DEF", defaultVal); String isNullable = "NO"; if (tsc.notNull == true) { isNullable = "YES"; } record.put("IS_NULLABLE", isNullable); /* * Suppress any sorting of the ResultSet. Column Metadata should * be presented in the order the columns exist in the dBase header. */ jrs.addRow(record, false); } tbl.close(); tbl = null; } return(new TinySQLResultSet(jrs, (TinySQLStatement)null)); } catch (Exception) { return(null); } }
/* * Gets a description of tables available in a catalog. * * Only table descriptions matching the catalog, schema, table * name and type criteria are returned. They are ordered by * TABLE_TYPE, TABLE_SCHEM and TABLE_NAME. * * Each table description has the following columns: * * TABLE_CAT String => table catalog (may be null) * TABLE_SCHEM String => table schema (may be null) * TABLE_NAME String => table name * TABLE_TYPE String => table type. Typical types are "TABLE", * "VIEW", "SYSTEM TABLE", "GLOBAL TEMPORARY", * "LOCAL TEMPORARY", "ALIAS", "SYNONYM". * REMARKS String => explanatory comment on the table * * Note: Some databases may not return information for * all tables. * * @param catalog a catalog name; "" retrieves those without a * catalog; null means drop catalog name from the selection criteria * THIS VALUE IS IGNORED * @param schemaPattern THIS VALUE IS IGNORED * @param tableNamePattern a table name pattern, ´null´ or "%" delivers all * token will be handled as substrings * @param types a list of table types to include; null returns all DBF types * only "TABLE" is supported, others like "VIEW", "SYSTEM TABLE", "SEQUENCE" * are ignored. * @return ResultSet - each row is a table description * @exception SQLException if a database access error occurs * @see #getSearchStringEscape * * @author Thomas Morgner <*****@*****.**> Fill all needed columns, or some query tools will crash :( */ public override java.sql.ResultSet getTables(String catalog, String schemaPattern, String tableNamePattern, String[] types) { String dataDir = getDataDir(); String tableName; java.io.File tableFile; TsColumn jsc; int i, dotAt; if (dataDir == null) { return(null); } if (types == null) { types = new String[1]; types[0] = "TABLE"; } TsResultSet jrs = new TsResultSet(); /* * Create the header for the tables ResultSet */ try { jsc = new TsColumn("TABLE_CAT"); jsc.type = java.sql.Types.CHAR; // CHAR max 254 bytes jsc.size = 10; jrs.addColumn(jsc); jsc = new TsColumn("TABLE_SCHEM"); jsc.type = java.sql.Types.CHAR; // CHAR max 254 bytes jsc.size = 10; jrs.addColumn(jsc); jsc = new TsColumn("TABLE_NAME"); jsc.type = java.sql.Types.CHAR; // CHAR max 254 bytes jsc.size = 10; jrs.addColumn(jsc); jsc = new TsColumn("TABLE_TYPE"); jsc.type = java.sql.Types.CHAR; // CHAR max 254 bytes jsc.size = 40; jsc.defaultVal = "TABLE"; jrs.addColumn(jsc); jsc = new TsColumn("TABLE_REMARKS"); jsc.type = java.sql.Types.CHAR; // CHAR max 254 bytes jsc.size = 254; jrs.addColumn(jsc); /* * Add the MetaData by examining all the DBF files in the current * directory. */ for (int itype = 0; itype < types.Length; itype++) { String type = types[itype]; if (type == null) { continue; } String extension = null; if (type.equalsIgnoreCase("TABLE")) { extension = DBFFileTable.dbfExtension; // ".DBF"; } if (extension == null) { continue; } java.util.Vector <Object> vec = Utils.getAllFiles(dataDir, extension); for (i = 0; i < vec.size(); i++) { tableFile = (java.io.File)vec.elementAt(i); tableName = tableFile.getName().toUpperCase(); dotAt = tableName.indexOf("."); if (dotAt > -1) { tableName = tableName.substring(0, dotAt); } if (tableNamePattern == null) { tableNamePattern = "%"; } if (tableNamePattern.equals("%") | tableName.equalsIgnoreCase(tableNamePattern)) { if (tableName.length() > jsc.size) { jsc.size = tableName.length(); } TsRow record = new TsRow(); record.put("TABLE_NAME", tableName.toUpperCase()); record.put("TABLE_TYPE", "TABLE"); jrs.addRow(record); } } } } catch (Exception ex) { java.lang.SystemJ.outJ.println("Unable to create MetaData"); java.lang.SystemJ.outJ.println(ex.ToString());// ex.printStackTrace(System.out); } // This Resultset is not created by an statement return(new TinySQLResultSet(jrs, (TinySQLStatement)null)); }
/** * Gets a description of all the standard SQL types supported by * this database. They are ordered by DATA_TYPE and then by how * closely the data type maps to the corresponding JDBC SQL type. * * <P>Each type description has the following columns: * <OL> * <LI><B>TYPE_NAME</B> String => Type name * <LI><B>DATA_TYPE</B> short => SQL data type from java.sql.Types * <LI><B>PRECISION</B> int => maximum precision * <LI><B>LITERAL_PREFIX</B> String => prefix used to quote a literal * (may be null) * <LI><B>LITERAL_SUFFIX</B> String => suffix used to quote a literal * (may be null) * <LI><B>CREATE_PARAMS</B> String => parameters used in creating * the type (may be null) * <LI><B>NULLABLE</B> short => can you use NULL for this type? * <UL> * <LI> typeNoNulls - does not allow NULL values * <LI> typeNullable - allows NULL values * <LI> typeNullableUnknown - nullability unknown * </UL> * <LI><B>CASE_SENSITIVE</B> boolean=> is it case sensitive? * <LI><B>SEARCHABLE</B> short => can you use "WHERE" based on this type: * <UL> * <LI> typePredNone - No support * <LI> typePredChar - Only supported with WHERE .. LIKE * <LI> typePredBasic - Supported except for WHERE .. LIKE * <LI> typeSearchable - Supported for all WHERE .. * </UL> * <LI><B>UNSIGNED_ATTRIBUTE</B> boolean => is it unsigned? * <LI><B>FIXED_PREC_SCALE</B> boolean => can it be a money value? * <LI><B>AUTO_INCREMENT</B> boolean => can it be used for an * auto-increment value? * <LI><B>LOCAL_TYPE_NAME</B> String => localized version of type name * (may be null) * <LI><B>MINIMUM_SCALE</B> short => minimum scale supported * <LI><B>MAXIMUM_SCALE</B> short => maximum scale supported * <LI><B>SQL_DATA_TYPE</B> int => unused * <LI><B>SQL_DATETIME_SUB</B> int => unused * <LI><B>NUM_PREC_RADIX</B> int => usually 2 or 10 * </OL> * * @return ResultSet - each row is a SQL type description * @exception SQLException if a database access error occurs */ public override java.sql.ResultSet getTypeInfo() {//throws SQLException { TsResultSet jrs = new TsResultSet(); TsColumn jsc = new TsColumn("TYPE_NAME"); jsc.type = java.sql.Types.CHAR; jsc.size = 10; jrs.addColumn(jsc); jsc = new TsColumn("DATA_TYPE"); jsc.type = java.sql.Types.INTEGER; jsc.size = 6; jrs.addColumn(jsc); jsc = new TsColumn("PRECISION"); jsc.type = java.sql.Types.INTEGER; jsc.size = 8; jrs.addColumn(jsc); jsc = new TsColumn("LITERAL_PREFIX"); jsc.type = java.sql.Types.CHAR; jsc.size = 1; jrs.addColumn(jsc); jsc = new TsColumn("LITERAL_SUFFIX"); jsc.type = java.sql.Types.CHAR; jsc.size = 1; jrs.addColumn(jsc); jsc = new TsColumn("CREATE_PARAMS"); jsc.type = java.sql.Types.CHAR; jsc.size = 20; jrs.addColumn(jsc); jsc = new TsColumn("NULLABLE"); jsc.type = java.sql.Types.INTEGER; jsc.size = 6; jrs.addColumn(jsc); jsc = new TsColumn("CASE_SENSITIVE"); jsc.type = java.sql.Types.BIT; jsc.size = 1; jrs.addColumn(jsc); jsc = new TsColumn("SEARCHABLE"); jsc.type = java.sql.Types.INTEGER; jsc.size = 6; jrs.addColumn(jsc); /* * <LI><B>UNSIGNED_ATTRIBUTE</B> boolean => is it unsigned? * <LI><B>FIXED_PREC_SCALE</B> boolean => can it be a money value? * <LI><B>AUTO_INCREMENT</B> boolean => can it be used for an * auto-increment value? * <LI><B>LOCAL_TYPE_NAME</B> String => localized version of type name * (may be null) * <LI><B>MINIMUM_SCALE</B> short => minimum scale supported * <LI><B>MAXIMUM_SCALE</B> short => maximum scale supported * <LI><B>NUM_PREC_RADIX</B> int => usually 2 or 10 */ // NOTE: the Hashtable in tsRow expects always a String as its value! // so i use the toString() method here // Perhaps in future the real type should be pushed into the Hashtable? TsRow record = new TsRow(); record.put("TYPE_NAME", DBFFile.typeToLiteral(java.sql.Types.CHAR)); // "CHAR", String record.put("DATA_TYPE", new java.lang.Integer(java.sql.Types.CHAR).toString()); record.put("PRECISION", new java.lang.Integer(254).toString()); record.put("LITERAL_PREFIX", "\""); record.put("LITERAL_SUFFIX", "\""); record.put("CREATE_PARAMS", new java.lang.Integer(0).toString()); record.put("NULLABLE", new java.lang.Integer(typeNullableUnknown).toString()); record.put("CASE_SENSITIVE", "N"); record.put("SEARCHABLE", new java.lang.Integer(typePredBasic).toString()); jrs.addRow(record); record = new TsRow(); record.put("TYPE_NAME", DBFFile.typeToLiteral(java.sql.Types.FLOAT)); // "FLOAT", double record.put("DATA_TYPE", new java.lang.Integer(java.sql.Types.FLOAT).toString()); record.put("PRECISION", new java.lang.Integer(19).toString()); record.put("LITERAL_PREFIX", emptyString); record.put("LITERAL_SUFFIX", emptyString); record.put("CREATE_PARAMS", new java.lang.Integer(0).toString()); record.put("NULLABLE", new java.lang.Integer(typeNullableUnknown).toString()); record.put("CASE_SENSITIVE", "N"); record.put("SEARCHABLE", new java.lang.Integer(typePredBasic).toString()); jrs.addRow(record); record = new TsRow(); record.put("TYPE_NAME", DBFFile.typeToLiteral(java.sql.Types.BIT)); // "CHAR", boolean "YyNnTtFf" record.put("DATA_TYPE", new java.lang.Integer(java.sql.Types.BIT).toString()); record.put("PRECISION", new java.lang.Integer(1).toString()); record.put("LITERAL_PREFIX", "\""); record.put("LITERAL_SUFFIX", "\""); record.put("CREATE_PARAMS", new java.lang.Integer(0).toString()); record.put("NULLABLE", new java.lang.Integer(typeNullableUnknown).toString()); record.put("CASE_SENSITIVE", "N"); record.put("SEARCHABLE", new java.lang.Integer(typePredBasic).toString()); jrs.addRow(record); record = new TsRow(); record.put("TYPE_NAME", DBFFile.typeToLiteral(java.sql.Types.INTEGER)); // "INT", unsigned long record.put("DATA_TYPE", new java.lang.Integer(java.sql.Types.INTEGER).toString()); record.put("PRECISION", new java.lang.Integer(19).toString()); record.put("LITERAL_PREFIX", emptyString); record.put("LITERAL_SUFFIX", emptyString); record.put("CREATE_PARAMS", new java.lang.Integer(0).toString()); record.put("NULLABLE", new java.lang.Integer(typeNullableUnknown).toString()); record.put("CASE_SENSITIVE", "N"); record.put("SEARCHABLE", new java.lang.Integer(typePredBasic).toString()); jrs.addRow(record); record = new TsRow(); record.put("TYPE_NAME", DBFFile.typeToLiteral(java.sql.Types.DATE)); // "DATE", date record.put("DATA_TYPE", new java.lang.Integer(java.sql.Types.DATE).toString()); record.put("PRECISION", new java.lang.Integer(8).toString()); record.put("LITERAL_PREFIX", "\""); record.put("LITERAL_SUFFIX", "\""); record.put("CREATE_PARAMS", new java.lang.Integer(0).toString()); record.put("NULLABLE", new java.lang.Integer(typeNullableUnknown).toString()); record.put("CASE_SENSITIVE", "N"); record.put("SEARCHABLE", new java.lang.Integer(typePredBasic).toString()); jrs.addRow(record); return(new TinySQLResultSet(jrs, (TinySQLStatement)null)); }