Quadcap Embeddable Database

com/quadcap/sql/View.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.ResultSetMetaData; 00050 import java.sql.SQLException; 00051 00052 import com.quadcap.sql.index.Btree; 00053 00054 import com.quadcap.sql.types.Value; 00055 import com.quadcap.sql.types.ValueBoolean; 00056 00057 import com.quadcap.util.Debug; 00058 00059 /** 00060 * A SQL <b>VIEW</b>. 00061 * 00062 * @author Stan Bailes 00063 */ 00064 public class View extends TupleImpl implements Relation, Externalizable { 00065 Vector viewColumns; 00066 TableExpression select; 00067 00068 static final int NOCHECK = -1; 00069 static final int CASCADED = 0; 00070 static final int LOCAL = 1; 00071 00072 int check; 00073 00074 /** 00075 * Default constructor 00076 */ 00077 public View() {} 00078 00079 /** 00080 * Explicit constructor from name, columns, select expression, 00081 * VIEW CHECK state 00082 */ 00083 public View(String name, Vector columns, TableExpression select, 00084 int check) 00085 { 00086 super(name); 00087 this.viewColumns = columns; 00088 this.select = select; 00089 this.check = check; 00090 } 00091 00092 /** 00093 * Lazy build the view's columns list 00094 */ 00095 public void addColumns(Session session) throws SQLException { 00096 if (columns.size() == 0) { 00097 Cursor c = getCursor(session, null, null, null); 00098 try { 00099 addColumns(session, c); 00100 } finally { 00101 c.close(); 00102 } 00103 } 00104 } 00105 00106 /** 00107 * Check a base row to see if it's contained in the view 00108 */ 00109 public void checkRow(Session session, Cursor cursor, Row row) throws SQLException { 00110 if ((check != NOCHECK || session.getViewCheck()) 00111 && select.isUpdatable()) { 00112 session.setViewCheck(); 00113 StaticCursor s = new StaticCursor(session, this, row); 00114 s.next(); 00115 Expression w = select.getWhere(); 00116 if (w != null) { 00117 Value v = w.getValue(session, s); 00118 if (v instanceof ValueBoolean && ((ValueBoolean)v).isTrue()) { 00119 // ok 00120 } else { 00121 throw new SQLException("View check option violation", "44000"); 00122 } 00123 } 00124 } 00125 } 00126 00127 /** 00128 * Externalizable.readExternal(): Read me from a stream. 00129 */ 00130 public void readExternal(ObjectInput in) 00131 throws IOException, ClassNotFoundException 00132 { 00133 super.readExternal(in); 00134 this.viewColumns = (Vector)in.readObject(); 00135 this.select = (TableExpression)in.readObject(); 00136 this.check = in.readInt(); 00137 } 00138 00139 /** 00140 * Externalizable.writeExternal(): Write me to a stream. 00141 */ 00142 public void writeExternal(ObjectOutput out) throws IOException { 00143 super.writeExternal(out); 00144 out.writeObject(viewColumns); 00145 out.writeObject(select); 00146 out.writeInt(check); 00147 } 00148 00149 /** 00150 * Get the view's cursor 00151 */ 00152 public Cursor getCursor(Session session, Expression where, 00153 String asName, Cursor cursor) 00154 throws SQLException 00155 { 00156 Cursor c = select.getCursor(session, cursor); 00157 00158 String qualName = asName; 00159 if (qualName == null) qualName = getName(); 00160 String qPrefix = qualName; 00161 if (qPrefix.length() > 0) qPrefix = qPrefix + "."; 00162 00163 Vector cols = viewColumns; 00164 if (cols == null) { 00165 cols = new Vector(); 00166 Hashtable t = new Hashtable(); 00167 for (int i = 1; i <= c.getColumnCount(); i++) { 00168 String name = c.getColumn(i).getName(); 00169 int idx = name.lastIndexOf('.'); 00170 if (idx >= 0) name = name.substring(idx+1); 00171 name = qPrefix + name; 00172 if (t.get(name) != null) { 00173 throw new SQLException( 00174 "A view column list must be specified if multiple " + 00175 "columns have the same name: " + name, "42000"); 00176 } 00177 cols.addElement(name); 00178 t.put(name, name); 00179 } 00180 } else { 00181 cols = new Vector(); 00182 for (int i = 0; i < viewColumns.size(); i++) { 00183 cols.addElement(qPrefix + viewColumns.elementAt(i).toString()); 00184 } 00185 } 00186 c = new ViewCursor(session, this, c, cols); 00187 return c; 00188 } 00189 00190 public void insertRow(Session session, Row row) 00191 throws SQLException, IOException 00192 { 00193 Cursor c = getCursor(session, null, null, null); 00194 try { 00195 session.clearViewCheck(); 00196 c.insertRow(row); 00197 } finally { 00198 c.close(); 00199 } 00200 } 00201 00202 public boolean isUpdatable() { 00203 return select.isUpdatable(); 00204 } 00205 00206 public boolean hasBlobs() { 00207 return false; // XXX test insert into view with blobs. 00208 } 00209 00210 public Vector getBaseTables() { 00211 Vector v = new Vector(); 00212 select.getBaseTables(v); 00213 return v; 00214 } 00215 00216 public Expression getViewExpression() { 00217 return select; 00218 } 00219 00220 public String getType() { return "VIEW"; } 00221 00222 public void delete(Session session) {} 00223 00224 public String toString() { 00225 StringBuffer sb = new StringBuffer("VIEW "); 00226 sb.append(getName()); 00227 if (columns != null) { 00228 sb.append('('); 00229 for (int i = 0; i < columns.size(); i++) { 00230 if (i > 0) sb.append(','); 00231 Column col = (Column)columns.get(i); 00232 sb.append(col.getShortName()); 00233 } 00234 sb.append(')'); 00235 } 00236 sb.append(" AS "); 00237 sb.append(select.toString()); 00238 return sb.toString(); 00239 } 00240 00241 }