/** Unit test for TupleDesc.combine() */ @Test public void combine() { TupleDesc td1, td2, td3; td1 = Utility.getTupleDesc(1, "td1"); td2 = Utility.getTupleDesc(2, "td2"); // test td1.combine(td2) td3 = TupleDesc.merge(td1, td2); assertEquals(3, td3.numFields()); assertEquals(3 * Type.INT_TYPE.getLen(), td3.getSize()); for (int i = 0; i < 3; ++i) assertEquals(Type.INT_TYPE, td3.getFieldType(i)); assertEquals(combinedStringArrays(td1, td2, td3), true); // test td2.combine(td1) td3 = TupleDesc.merge(td2, td1); assertEquals(3, td3.numFields()); assertEquals(3 * Type.INT_TYPE.getLen(), td3.getSize()); for (int i = 0; i < 3; ++i) assertEquals(Type.INT_TYPE, td3.getFieldType(i)); assertEquals(combinedStringArrays(td2, td1, td3), true); // test td2.combine(td2) td3 = TupleDesc.merge(td2, td2); assertEquals(4, td3.numFields()); assertEquals(4 * Type.INT_TYPE.getLen(), td3.getSize()); for (int i = 0; i < 4; ++i) assertEquals(Type.INT_TYPE, td3.getFieldType(i)); assertEquals(combinedStringArrays(td2, td2, td3), true); }
/** Suck up tuples from the source file. */ private Tuple readNextTuple(DataInputStream dis, int slotId) throws NoSuchElementException { // if associated bit is not set, read forward to the next tuple, and // return null. if (!getSlot(slotId)) { for (int i = 0; i < td.getSize(); i++) { try { dis.readByte(); } catch (IOException e) { throw new NoSuchElementException("error reading empty tuple"); } } return null; } // read fields in the tuple Tuple t = new Tuple(td); RecordID rid = new RecordID(pid, slotId); t.setRecordID(rid); try { for (int j = 0; j < td.numFields(); j++) { Field f = td.getType(j).parse(dis); t.setField(j, f); } } catch (java.text.ParseException e) { // e.printStackTrace(); throw new NoSuchElementException("parsing error!"); } return t; }
/** Unit test for TupleDesc.numFields() */ @Test public void numFields() { int[] lengths = new int[] {1, 2, 1000}; for (int len : lengths) { TupleDesc td = Utility.getTupleDesc(len); assertEquals(len, td.numFields()); } }
/** * Generates a byte array representing the contents of this page. Used to serialize this page to * disk. * * <p>The invariant here is that it should be possible to pass the byte array generated by * getPageData to the HeapPage constructor and have it produce an identical HeapPage object. * * @see #HeapPage * @return A byte array correspond to the bytes of this page. */ public byte[] getPageData() { // int len = header.length*4 + BufferPool.PAGE_SIZE; int len = BufferPool.PAGE_SIZE; ByteArrayOutputStream baos = new ByteArrayOutputStream(len); DataOutputStream dos = new DataOutputStream(baos); // create the header of the page try { dos.write(header.getHeader()); } catch (IOException e) { // this really shouldn't happen e.printStackTrace(); } // create the tuples for (int i = 0; i < numSlots; i++) { // empty slot if (!getSlot(i)) { for (int j = 0; j < td.getSize(); j++) { try { dos.writeByte(0); } catch (IOException e) { e.printStackTrace(); } } continue; } // non-empty slot for (int j = 0; j < td.numFields(); j++) { Field f = tuples[i].getField(j); try { f.serialize(dos); } catch (IOException e) { e.printStackTrace(); } } } // padding int zerolen = BufferPool.PAGE_SIZE - numSlots * td.getSize() - header.length(); byte[] zeroes = new byte[zerolen]; try { dos.write(zeroes, 0, zerolen); } catch (IOException e) { e.printStackTrace(); } try { dos.flush(); } catch (IOException e) { e.printStackTrace(); } return baos.toByteArray(); }
private void createAliasedTd() { Catalog gc = Database.getCatalog(); TupleDesc old_td = gc.getTupleDesc(tableid); String[] newFieldAr = new String[old_td.numFields()]; Type[] typeAr = new Type[old_td.numFields()]; String field = null; for (int i = 0; i < newFieldAr.length; i++) { field = old_td.getFieldName(i); if (alias == null) { alias = "null"; } else if (field == null) { field = "null"; } newFieldAr[i] = alias + "." + field; typeAr[i] = old_td.getFieldType(i); } td = new TupleDesc(typeAr, newFieldAr); }
/** * Returns the TupleDesc with field names from the underlying HeapFile, prefixed with the * tableAlias string from the constructor. This prefix becomes useful when joining tables * containing a field(s) with the same name. * * @return the TupleDesc with field names from the underlying HeapFile, prefixed with the * tableAlias string from the constructor. */ public TupleDesc getTupleDesc() { TupleDesc tup = Database.getCatalog().getTupleDesc(id); int length = tup.numFields(); String[] field = new String[length]; Type[] types = new Type[length]; for (int i = 0; i < length; i++) { types[i] = tup.getFieldType(i); field[i] = alias + "." + tup.getFieldName(i); } return new TupleDesc(types, field); }
/** * Create a new TableStats object, that keeps track of statistics on each column of a table * * @param tableid The table over which to compute statistics * @param ioCostPerPage The cost per page of IO. This doesn't differentiate between * sequential-scan IO and disk seeks. */ public TableStats(int tableid, int ioCostPerPage) { // For this function, we use the DbFile for the table in question, // then scan through its tuples and calculate the values that you // to build the histograms. // TODO: Fill out the rest of the constructor. // Feel free to change anything already written, it's only a guideline this.ioCostPerPage = ioCostPerPage; DbFile file = Database.getCatalog().getDbFile(tableid); tupleDesc = file.getTupleDesc(); numPages = ((HeapFile) file).numPages(); numTuples = 0; int numFields = tupleDesc.numFields(); // TODO: what goes here? statistics = new ArrayList<Object>(); for (int i = 0; i < numFields; i++) { if (Type.INT_TYPE.equals(tupleDesc.getFieldType(i))) { statistics.add(new IntStatistics(NUM_HIST_BINS)); } else { statistics.add(new StringHistogram(NUM_HIST_BINS)); } } final DbFileIterator iter = file.iterator(null); try { iter.open(); while (iter.hasNext()) { Tuple t = iter.next(); numTuples++; // TODO: and here? for (int i = 0; i < numFields; i++) { if (Type.INT_TYPE.equals(tupleDesc.getFieldType(i))) { ((IntStatistics) statistics.get(i)).addValue(((IntField) t.getField(i)).getValue()); } else { ((StringHistogram) statistics.get(i)) .addValue(((StringField) t.getField(i)).getValue()); } } } iter.close(); } catch (DbException e) { e.printStackTrace(); } catch (TransactionAbortedException e) { e.printStackTrace(); } }
/** Ensures that combined's field names = td1's field names + td2's field names */ private boolean combinedStringArrays(TupleDesc td1, TupleDesc td2, TupleDesc combined) { for (int i = 0; i < td1.numFields(); i++) { if (!(((td1.getFieldName(i) == null) && (combined.getFieldName(i) == null)) || td1.getFieldName(i).equals(combined.getFieldName(i)))) { return false; } } for (int i = td1.numFields(); i < td1.numFields() + td2.numFields(); i++) { if (!(((td2.getFieldName(i - td1.numFields()) == null) && (combined.getFieldName(i) == null)) || td2.getFieldName(i - td1.numFields()).equals(combined.getFieldName(i)))) { return false; } } return true; }
/** * Returns the TupleDesc with field names from the underlying HeapFile, prefixed with the * tableAlias string from the constructor. This prefix becomes useful when joining tables * containing a field(s) with the same name. * * @return the TupleDesc with field names from the underlying HeapFile, prefixed with the * tableAlias string from the constructor. */ public TupleDesc getTupleDesc() { // some code goes here TupleDesc td = Database.getCatalog().getTupleDesc(tableid); Iterator<TDItem> tdIter = td.iterator(); int size = td.numFields(); Type[] typeAr = new Type[size]; String[] fieldAr = new String[size]; String aliasString = this.tableAlias; TDItem item; Type fieldType; String fieldName; int count = 0; if (aliasString == null) { aliasString = "null"; } // for (int i = 0; i < size; i++){ // item = tdIter.next(); // fieldType = item.fieldType; // fieldName = item.fieldName; while (tdIter.hasNext()) { item = tdIter.next(); fieldType = item.fieldType; fieldName = item.fieldName; if (fieldName == null) { fieldName = "null"; } typeAr[count] = fieldType; fieldAr[count] = aliasString + "." + fieldName; // "null.null case may occur" count++; } return new TupleDesc(typeAr, fieldAr); }