001: package com.quadcap.sql;
002:
003: /* Copyright 1999 - 2003 Quadcap Software. All rights reserved.
004: *
005: * This software is distributed under the Quadcap Free Software License.
006: * This software may be used or modified for any purpose, personal or
007: * commercial. Open Source redistributions are permitted. Commercial
008: * redistribution of larger works derived from, or works which bundle
009: * this software requires a "Commercial Redistribution License"; see
010: * http://www.quadcap.com/purchase.
011: *
012: * Redistributions qualify as "Open Source" under one of the following terms:
013: *
014: * Redistributions are made at no charge beyond the reasonable cost of
015: * materials and delivery.
016: *
017: * Redistributions are accompanied by a copy of the Source Code or by an
018: * irrevocable offer to provide a copy of the Source Code for up to three
019: * years at the cost of materials and delivery. Such redistributions
020: * must allow further use, modification, and redistribution of the Source
021: * Code under substantially the same terms as this license.
022: *
023: * Redistributions of source code must retain the copyright notices as they
024: * appear in each source code file, these license terms, and the
025: * disclaimer/limitation of liability set forth as paragraph 6 below.
026: *
027: * Redistributions in binary form must reproduce this Copyright Notice,
028: * these license terms, and the disclaimer/limitation of liability set
029: * forth as paragraph 6 below, in the documentation and/or other materials
030: * provided with the distribution.
031: *
032: * The Software is provided on an "AS IS" basis. No warranty is
033: * provided that the Software is free of defects, or fit for a
034: * particular purpose.
035: *
036: * Limitation of Liability. Quadcap Software shall not be liable
037: * for any damages suffered by the Licensee or any third party resulting
038: * from use of the Software.
039: */
040:
041: import java.io.IOException;
042:
043: import java.sql.SQLException;
044:
045: import com.quadcap.sql.file.BlockFile;
046: import com.quadcap.sql.file.ByteUtil;
047: import com.quadcap.sql.file.PageManager;
048: import com.quadcap.sql.file.SubPageManager;
049:
050: import com.quadcap.sql.index.BCursor;
051: import com.quadcap.sql.index.Btree;
052:
053: import com.quadcap.util.Debug;
054: import com.quadcap.util.Util;
055:
056: /**
057: * A special temp table used to implement <b>UNION</b> and <b>INTERSECT</b>
058: * expressions.
059: *
060: * <p>
061: * The temp table that we build has keys based on the union columns,
062: * and the data as 13 bytes:
063: * </p>
064: * <table>
065: * <tr><td>byte 0:</td> <td>if zero, the rowId refers to a real table row
066: * if one, the rowId refers to a temp row</td></tr>
067: * <tr><td>bytes 1-8:</td> <td>the rowId of the union row</td></tr>
068: * <tr><td>bytes 9-12:</td> <td>the duplicate count (from table 1)</td></tr>
069: * <tr><td>bytes 13-16:</td><td> the duplicate count (from table 2)</td></td>
070: * </table>
071: *
072: * @author Stan Bailes
073: */
074: public class TempTableMerge extends TempTable {
075:
076: /**
077: * Byte offset of 'isTemp' byte flag in a data row.
078: */
079: final static int fIS_TEMP = 0;
080:
081: /**
082: * The byte offset of the (long) row ID in data data row
083: */
084: final static int fROW_ID = 1;
085:
086: /**
087: * The byte offset of the two 'count' integers. in the data row
088: */
089: final static int fCOUNT = 9;
090:
091: /**
092: * Total size of the data buffer in our temp index
093: */
094: final static int BUFSIZE = 17;
095:
096: /**
097: * Constructor for session and key
098: */
099: public TempTableMerge(Session session, Key compare)
100: throws SQLException, IOException {
101: super (session, compare, null);
102: this .data = new byte[BUFSIZE];
103: }
104:
105: /**
106: * Add rows from one side of the {union/merge} operation, building a
107: * temporary index on the key.
108: */
109: public void addRows(Session session, Cursor cursor, int side,
110: int[] map) throws SQLException, IOException {
111: int cpos = fCOUNT + side * 4;
112: MapRow mapRow = new MapRow(map);
113: BCursor wc = index.getCursor();
114: //#ifdef DEBUG
115: if (trace) {
116: Debug
117: .println("TempTable[" + mySerial
118: + "].addRows() begin");
119: }
120: //#endif
121: try {
122: while (cursor.next()) {
123: final Row row = cursor.getRow();
124: mapRow.setRow(row);
125: final byte[] key = Key.makeKey(null, mapRow, null, 0,
126: false);
127: final boolean found = wc.seek(key);
128: if (found) {
129: byte[] tdata = wc.getValBuf();
130: final int cnt = ByteUtil.getInt(tdata, cpos);
131: ByteUtil.putInt(tdata, cpos, cnt + 1);
132: wc.replace(tdata, 0, BUFSIZE);
133: } else {
134: for (int i = 0; i < BUFSIZE; i++) {
135: data[i] = 0;
136: }
137: data[cpos + 3] = 1; //ByteUtil.putInt(data, cpos, 1);
138:
139: long rowId = cursor.getRowId();
140: if (map == null && rowId != 0) {
141: ByteUtil.putLong(data, fROW_ID, rowId);
142: } else {
143: rowId = session.getDatabase().putRow(session,
144: tempFile, cursor, mapRow);
145: //#ifdef DEBUG
146: if (trace) {
147: Debug.println("TempTable[" + mySerial
148: + "].putRow: " + toString(rowId));
149: }
150: //#endif
151: ByteUtil.putLong(data, fROW_ID, rowId);
152: data[fIS_TEMP] = 1;
153: }
154: wc.insert(key, data);
155: }
156: }
157: } finally {
158: wc.release();
159: }
160: //#ifdef DEBUG
161: if (trace) {
162: Debug.println("TempTable[" + mySerial
163: + "].addRows() complete");
164: }
165: //#endif
166: }
167:
168: public byte[] getData(byte[] key) throws IOException {
169: if (index.get(key, key.length, data) != data.length) {
170: return null;
171: }
172: return data;
173: }
174:
175: final int getCount(int side) {
176: return getCount(data, side);
177: }
178:
179: final static int getCount(byte[] data, int side) {
180: return ByteUtil.getInt(data, fCOUNT + (side * 4));
181: }
182:
183: }
|