/** * * Gives the display size for this column. * @see java.sql.ResultSetMetaData#getColumnDisplaySize * */ public int getColumnDisplaySize(int column) {//throws SQLException { // get a column object. Remember, tinySQL uses a column // offset of zero, but JDBC columns start numbering at one. // That's why there's a -1 in the columnAtIndex invocation. // TsColumn col = tsql.columnAtIndex(column - 1); return(col.size); }
/* * 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); }