Quadcap Embeddable Database

com/quadcap/sql/JoinCursor.java

Go to the documentation of this file.
00001 package com.quadcap.sql; 00002 00003 /* Copyright 1999 - 2003 Quadcap Software. All rights reserved. 00004 * 00005 * This software is distributed under the Quadcap Free Software License. 00006 * This software may be used or modified for any purpose, personal or 00007 * commercial. Open Source redistributions are permitted. Commercial 00008 * redistribution of larger works derived from, or works which bundle 00009 * this software requires a "Commercial Redistribution License"; see 00010 * http://www.quadcap.com/purchase. 00011 * 00012 * Redistributions qualify as "Open Source" under one of the following terms: 00013 * 00014 * Redistributions are made at no charge beyond the reasonable cost of 00015 * materials and delivery. 00016 * 00017 * Redistributions are accompanied by a copy of the Source Code or by an 00018 * irrevocable offer to provide a copy of the Source Code for up to three 00019 * years at the cost of materials and delivery. Such redistributions 00020 * must allow further use, modification, and redistribution of the Source 00021 * Code under substantially the same terms as this license. 00022 * 00023 * Redistributions of source code must retain the copyright notices as they 00024 * appear in each source code file, these license terms, and the 00025 * disclaimer/limitation of liability set forth as paragraph 6 below. 00026 * 00027 * Redistributions in binary form must reproduce this Copyright Notice, 00028 * these license terms, and the disclaimer/limitation of liability set 00029 * forth as paragraph 6 below, in the documentation and/or other materials 00030 * provided with the distribution. 00031 * 00032 * The Software is provided on an "AS IS" basis. No warranty is 00033 * provided that the Software is free of defects, or fit for a 00034 * particular purpose. 00035 * 00036 * Limitation of Liability. Quadcap Software shall not be liable 00037 * for any damages suffered by the Licensee or any third party resulting 00038 * from use of the Software. 00039 */ 00040 00041 import java.io.Externalizable; 00042 import java.io.IOException; 00043 import java.io.ObjectInput; 00044 import java.io.ObjectOutput; 00045 00046 import java.util.Hashtable; 00047 import java.util.Vector; 00048 00049 import java.sql.SQLException; 00050 00051 import com.quadcap.sql.types.Value; 00052 import com.quadcap.sql.types.ValueBoolean; 00053 00054 import com.quadcap.util.Debug; 00055 00056 /** 00057 * Cursor implementation of cross-join (cartesion product) 00058 * 00059 * @author Stan Bailes 00060 */ 00061 public abstract class JoinCursor extends CursorImpl { 00062 Cursor ca; 00063 Cursor cb; 00064 JoinMapRow row; 00065 Expression where; 00066 boolean left; 00067 boolean inner; 00068 00069 Row ra; 00070 Row rb; 00071 Expression aWhere; 00072 00073 public JoinCursor(Session session, Cursor outer, Cursor ca, Cursor cb, 00074 Expression where, Tuple tuple, JoinMapRow row, 00075 boolean left, boolean inner) 00076 throws SQLException 00077 { 00078 super(session, null, outer); 00079 this.ca = ca; 00080 this.cb = cb; 00081 addColumns(session, tuple); 00082 // XXX This is the problem. It's not the fact that the rows 00083 // XXX are flipped, per se, it's just that the key fields 00084 // XXX must be in the outer, rather than the inner row. 00085 // XXX So flip() must know what the key fields are in each 00086 // XXX row. 00087 this.row = row; 00088 this.where = where; 00089 this.left = left; 00090 this.inner = inner; 00091 00092 if (!(ca instanceof JoinCursor)) { 00093 this.aWhere = new Analyze(session, where).factorTable(ca); 00094 } 00095 00096 //Debug.println("ca = " + ca.getClass().getName() + ": " + ca); 00097 //Debug.println("cb = " + cb.getClass().getName() + ": " + cb); 00098 } 00099 00100 public Row getRow() { 00101 return row; 00102 } 00103 00104 public void updateRow(Row row) throws SQLException { 00105 throw new SQLException("JOIN cursors not updateable", "42000"); 00106 } 00107 00108 public void deleteRow() throws SQLException { 00109 throw new SQLException("JOIN cursor: delete not supported", "42000"); 00110 } 00111 00112 public void afterLast() throws SQLException { 00113 throw new SQLException("JOIN cursor: afterLast not supported", 00114 "42000"); 00115 } 00116 00117 public boolean isWritable(int column) { return false; } 00118 00119 public void beforeFirst() throws SQLException { 00120 ca.beforeFirst(); 00121 cb.beforeFirst(); 00122 ra = null; 00123 row.setA(null); 00124 rb = null; 00125 row.setB(null); 00126 } 00127 00128 protected boolean anext() throws SQLException { 00129 boolean ret = ca.next(); 00130 while (ret && !passRow(ca, aWhere)) { 00131 ret = ca.next(); 00132 } 00133 if (ret) { 00134 ra = ca.getRow(); 00135 } else { 00136 ra = null; 00137 } 00138 row.setA(ra); 00139 //Debug.println("anext: ra = " + ra + ", row = " + row); 00140 return ret; 00141 } 00142 00143 protected void bfirst() throws SQLException { 00144 cb.beforeFirst(); 00145 } 00146 00147 protected boolean bnext() throws SQLException { 00148 boolean ret = cb.next(); 00149 if (ret) { 00150 rb = cb.getRow(); 00151 } else { 00152 rb = null; 00153 } 00154 row.setB(rb); 00155 //Debug.println("bnext: rb = " + rb + ", row = " + row); 00156 return ret; 00157 } 00158 00159 public boolean next() throws SQLException { 00160 boolean ret = false; 00161 while (ra != null && !ret && inner && bnext()) { 00162 ret = true; 00163 } 00164 if (!ret) { 00165 while (anext()) { 00166 boolean anyInner = false; 00167 bfirst(); 00168 while (bnext()) { 00169 anyInner = true; 00170 if (inner) { 00171 return true; // single exit is "inconvenient" 00172 } 00173 } 00174 if (left && !anyInner) { 00175 ret = true; 00176 break; 00177 } 00178 } 00179 } 00180 return ret; 00181 } 00182 00183 final boolean passRow(Cursor c, Expression w) 00184 throws SQLException 00185 { 00186 boolean ret = true; 00187 if (w != null) { 00188 Value val = w.getValue(session, c); 00189 if (val instanceof ValueBoolean) { 00190 ValueBoolean vb = (ValueBoolean)val; 00191 ret = vb.isTrue(); 00192 } else { 00193 ret = false; 00194 } 00195 } 00196 return ret; 00197 } 00198 00199 public void close() throws SQLException { 00200 SQLException ex = null; 00201 try { 00202 ca.close(); 00203 } catch (SQLException e) { 00204 ex = e; 00205 } finally { 00206 ca = null; 00207 try { 00208 cb.close(); 00209 } catch (SQLException e) { 00210 if (ex != null) ex = e; 00211 } finally { 00212 cb = null; 00213 } 00214 } 00215 if (ex != null) throw ex; 00216 } 00217 00218 public long size() throws SQLException { return -1; } 00219 }