1 5 package org.h2.index; 6 7 import java.sql.SQLException ; 8 9 import org.h2.engine.Constants; 10 import org.h2.engine.DbObject; 11 import org.h2.engine.Session; 12 import org.h2.message.Message; 13 import org.h2.message.Trace; 14 import org.h2.result.Row; 15 import org.h2.result.SearchRow; 16 import org.h2.schema.SchemaObject; 17 import org.h2.table.Column; 18 import org.h2.table.Table; 19 import org.h2.util.StringUtils; 20 import org.h2.value.Value; 21 import org.h2.value.ValueNull; 22 23 26 public abstract class Index extends SchemaObject { 27 28 protected Column[] columns; 29 protected int[] columnIndex; 30 protected Table table; 31 public IndexType indexType; 32 public static final int EMPTY_HEAD = -1; 33 protected int rowCount; 34 35 public Index(Table table, int id, String name, Column[] columns, IndexType indexType) { 36 super(table.getSchema(), id, name, Trace.INDEX); 37 this.indexType = indexType; 38 this.table = table; 39 if(columns != null) { 40 this.columns = columns; 41 columnIndex = new int[columns.length]; 42 for(int i=0; i<columns.length; i++) { 43 columnIndex[i] = columns[i].getColumnId(); 44 } 45 } 46 } 47 48 public SQLException getDuplicateKeyException() { 49 StringBuffer buff = new StringBuffer (); 50 buff.append(getName()); 51 buff.append(" "); 52 buff.append(" ON "); 53 buff.append(table.getSQL()); 54 buff.append("("); 55 buff.append(getColumnListSQL()); 56 buff.append(")"); 57 return Message.getSQLException(Message.DUPLICATE_KEY_1, buff.toString()); 58 } 59 60 public String getPlanSQL() { 61 return getSQL(); 62 } 63 64 public void removeChildrenAndResources(Session session) throws SQLException { 65 table.removeIndex(this); 66 remove(session); 67 } 68 69 public abstract void close(Session session) throws SQLException ; 70 public abstract void add(Session session, Row row) throws SQLException ; 71 public abstract void remove(Session session, Row row) throws SQLException ; 72 public abstract Cursor find(Session session, SearchRow first, SearchRow last) throws SQLException ; 73 public abstract int getCost(int[] masks) throws SQLException ; 74 public abstract void remove(Session session) throws SQLException ; 75 public abstract void truncate(Session session) throws SQLException ; 76 public abstract boolean canGetFirstOrLast(boolean first); 77 public abstract Value findFirstOrLast(Session session, boolean first) throws SQLException ; 78 public abstract boolean needRebuild(); 79 80 public int getRowCount() { 81 return rowCount; 82 } 83 84 public int getLookupCost(int rowCount) { 85 return 2; 86 } 87 88 public int getCostRangeIndex(int[] masks, int rowCount) throws SQLException { 89 rowCount += Constants.COST_ROW_OFFSET; 90 int cost = rowCount; 91 int totalSelectivity = 0; 92 for (int i = 0; masks != null && i < columns.length; i++) { 93 Column column = columns[i]; 94 int index = column.getColumnId(); 95 int mask = masks[index]; 96 if ((mask & IndexCondition.EQUALITY) == IndexCondition.EQUALITY) { 97 if(i == columns.length-1 && getIndexType().isUnique()) { 98 cost = getLookupCost(rowCount) + 1; 99 break; 100 } 101 totalSelectivity = 100 - ((100-totalSelectivity) * (100-column.getSelectivity()) / 100); 102 int distinctRows = rowCount * totalSelectivity / 100; 103 if(distinctRows <= 0) { 104 distinctRows = 1; 105 } 106 int rowsSelected = rowCount / distinctRows; 107 if(rowsSelected < 1) { 108 rowsSelected = 1; 109 } 110 cost = getLookupCost(rowCount) + rowsSelected; 111 } else if ((mask & IndexCondition.RANGE) == IndexCondition.RANGE) { 112 cost = getLookupCost(rowCount) + rowCount / 4; 113 break; 114 } else if ((mask & IndexCondition.START) == IndexCondition.START) { 115 cost = getLookupCost(rowCount) + rowCount / 3; 116 break; 117 } else if ((mask & IndexCondition.END) == IndexCondition.END) { 118 cost = rowCount / 3; 119 break; 120 } else { 121 break; 122 } 123 } 124 return cost; 125 } 126 127 public int compareRows(SearchRow rowData, SearchRow compare) throws SQLException { 128 for (int i = 0; i < columns.length; i++) { 129 int index = columnIndex[i]; 130 Value v = compare.getValue(index); 131 if(v==null) { 132 return 0; 134 } 135 int c = compareValues(rowData.getValue(index), v); 136 if (c != 0) { 137 return c; 138 } 139 } 140 return 0; 141 } 142 143 public boolean isNull(Row newRow) { 144 for (int i = 0; i < columns.length; i++) { 145 int index = columnIndex[i]; 146 Value v = newRow.getValue(index); 147 if(v == ValueNull.INSTANCE) { 148 return true; 149 } 150 } 151 return false; 152 } 153 154 public int compareKeys(SearchRow rowData, SearchRow compare) { 155 int k1 = rowData.getPos(); 156 int k2 = compare.getPos(); 157 if (k1 == k2) { 158 return 0; 159 } 160 return k1 > k2 ? 1 : -1; 161 } 162 163 private int compareValues(Value v1, Value v2) throws SQLException { 164 if (v1 == null) { 165 if (v2 == null) { 166 return 0; 167 } 168 return 1; 169 } 170 if (v2 == null) { 171 return -1; 172 } 173 return database.compareTypeSave(v1, v2); 174 } 175 176 public int getColumnIndex(Column col) { 177 for (int i = 0; i < columns.length; i++) { 178 if (columns[i] == col) { 179 return i; 180 } 181 } 182 return -1; 183 } 184 185 public String getColumnListSQL() { 186 StringBuffer buff = new StringBuffer (); 187 for (int i = 0; i < columns.length; i++) { 188 if (i > 0) { 189 buff.append(", "); 190 } 191 buff.append(columns[i].getSQL()); 192 } 193 return buff.toString(); 194 } 195 196 public String getCreateSQLForCopy(Table table, String quotedName) { 197 StringBuffer buff = new StringBuffer (); 198 buff.append("CREATE "); 199 buff.append(indexType.getSQL()); 200 if(!indexType.isPrimaryKey()) { 201 buff.append(' '); 202 buff.append(quotedName); 203 } 204 buff.append(" ON "); 205 buff.append(table.getSQL()); 206 if(comment != null) { 207 buff.append(" COMMENT "); 208 buff.append(StringUtils.quoteStringSQL(comment)); 209 } 210 buff.append("("); 211 buff.append(getColumnListSQL()); 212 buff.append(")"); 213 return buff.toString(); 214 } 215 216 public String getCreateSQL() { 217 return getCreateSQLForCopy(table, getSQL()); 218 } 219 220 public Column[] getColumns() { 221 return columns; 222 } 223 224 public IndexType getIndexType() { 225 return indexType; 226 } 227 228 public int getType() { 229 return DbObject.INDEX; 230 } 231 232 public Table getTable() { 233 return table; 234 } 235 236 } 237 | Popular Tags |