1 29 30 package com.caucho.db.table; 31 32 import com.caucho.db.index.BTree; 33 import com.caucho.db.index.KeyCompare; 34 import com.caucho.db.index.StringKeyCompare; 35 import com.caucho.db.sql.Expr; 36 import com.caucho.db.sql.QueryContext; 37 import com.caucho.db.sql.SelectResult; 38 import com.caucho.db.store.Transaction; 39 import com.caucho.util.L10N; 40 41 import java.sql.SQLException ; 42 import java.util.logging.Level ; 43 import java.util.logging.Logger ; 44 45 class StringColumn extends Column { 46 private static final Logger log 47 = Logger.getLogger(StringColumn.class.getName()); 48 private static final L10N L = new L10N(StringColumn.class); 49 50 private final int _maxLength; 51 52 58 StringColumn(Row row, String name, int maxLength) 59 { 60 super(row, name); 61 62 if (maxLength < 0) 63 throw new IllegalArgumentException ("length must be non-negative"); 64 else if (255 < maxLength) 65 throw new IllegalArgumentException ("length too big"); 66 67 _maxLength = maxLength; 68 } 69 70 73 public int getTypeCode() 74 { 75 return VARCHAR; 76 } 77 78 81 public Class getJavaType() 82 { 83 return String .class; 84 } 85 86 89 public int getDeclarationSize() 90 { 91 return _maxLength; 92 } 93 94 97 public int getLength() 98 { 99 return 2 * _maxLength + 1; 100 } 101 102 105 public KeyCompare getIndexKeyCompare() 106 { 107 return new StringKeyCompare(); 108 } 109 110 117 void setString(Transaction xa, byte []block, int rowOffset, String str) 118 { 119 int startOffset = rowOffset + _columnOffset; 120 121 if (str == null) { 122 setNull(block, rowOffset); 123 return; 124 } 125 126 int len = str.length(); 127 int offset = startOffset + 1; 128 int maxOffset = offset + 2 * _maxLength; 129 130 for (int i = 0; i < len && offset < maxOffset; i++) { 131 int ch = str.charAt(i); 132 133 block[offset++] = (byte) (ch >> 8); 134 block[offset++] = (byte) (ch); 135 } 136 137 block[startOffset] = (byte) (len); 138 setNonNull(block, rowOffset); 139 } 140 141 public String getString(byte []block, int rowOffset) 142 { 143 if (isNull(block, rowOffset)) 144 return null; 145 146 int startOffset = rowOffset + _columnOffset; 147 int len = block[startOffset] & 0xff; 148 149 char []cBuf = new char[len]; 150 StringBuffer cb = new StringBuffer (); 151 152 int offset = startOffset + 1; 153 int endOffset = offset + 2 * len; 154 int i = 0; 155 while (offset < endOffset) { 156 int ch1 = block[offset++] & 0xff; 157 int ch2 = block[offset++] & 0xff; 158 159 cBuf[i++] = (char) ((ch1 << 8) + ch2); 160 } 161 162 return new String (cBuf, 0, cBuf.length); 163 } 164 165 172 void setExpr(Transaction xa, 173 byte []block, int rowOffset, 174 Expr expr, QueryContext context) 175 throws SQLException 176 { 177 if (expr.isNull(null)) 178 setNull(block, rowOffset); 179 else 180 setString(xa, block, rowOffset, expr.evalString(context)); 181 } 182 183 186 public boolean isEqual(byte []block1, int rowOffset1, 187 byte []block2, int rowOffset2) 188 { 189 if (isNull(block1, rowOffset1) != isNull(block2, rowOffset2)) 190 return false; 191 192 int startOffset1 = rowOffset1 + _columnOffset; 193 int len1 = block1[startOffset1] & 0xff; 194 195 int startOffset2 = rowOffset2 + _columnOffset; 196 int len2 = block2[startOffset2] & 0xff; 197 198 if (len1 != len2) 199 return false; 200 201 for (int i = 2 * len1; i > 0; i--) { 202 if (block1[startOffset1 + i] != block2[startOffset2 + i]) 203 return false; 204 } 205 206 return true; 207 } 208 209 212 public boolean isEqual(byte []block, int rowOffset, 213 byte []buffer, int offset, int length) 214 { 215 if (isNull(block, rowOffset)) 216 return false; 217 218 int startOffset = rowOffset + _columnOffset; 219 int len = block[startOffset] & 0xff; 220 221 if (len != length) 222 return false; 223 224 int blockOffset = startOffset + 1; 225 int endOffset = blockOffset + 2 * len; 226 while (blockOffset < endOffset) { 227 if (block[blockOffset++] != buffer[offset++]) 228 return false; 229 } 230 231 return true; 232 } 233 234 public boolean isEqual(byte []block, int rowOffset, String value) 235 { 236 if (value == null) 237 return isNull(block, rowOffset); 238 else if (isNull(block, rowOffset)) 239 return false; 240 241 int startOffset = rowOffset + _columnOffset; 242 int len = block[startOffset] & 0xff; 243 244 int strLength = value.length(); 245 int strOffset = 0; 246 247 int offset = startOffset + 1; 248 int endOffset = offset + 2 * len; 249 while (offset < endOffset && strOffset < strLength) { 250 int ch1 = ((block[offset++] & 0xff) << 8) + (block[offset++] & 0xff); 251 char ch = value.charAt(strOffset++); 252 253 if (ch1 != ch) 254 return false; 255 } 256 257 return offset == endOffset && strOffset == strLength; 258 } 259 260 263 public void evalToResult(byte []block, int rowOffset, SelectResult result) 264 { 265 if (isNull(block, rowOffset)) { 266 result.writeNull(); 267 return; 268 } 269 270 int startOffset = rowOffset + _columnOffset; 271 int len = block[startOffset] & 0xff; 272 273 result.writeString(block, startOffset + 1, len); 274 282 } 283 284 294 int evalToBuffer(byte []block, int rowOffset, 295 byte []buffer, int bufferOffset) 296 throws SQLException 297 { 298 if (isNull(block, rowOffset)) 299 return 0; 300 301 int startOffset = rowOffset + _columnOffset; 302 int len = getLength(); 304 305 System.arraycopy(block, startOffset, buffer, bufferOffset, len); 306 307 return len; 308 } 309 310 317 void setIndex(Transaction xa, 318 byte []block, int rowOffset, 319 long rowAddr, QueryContext context) 320 throws SQLException 321 { 322 BTree index = getIndex(); 323 324 if (index != null) { 325 try { 326 index.insert(block, 327 rowOffset + _columnOffset, getLength(), 328 rowAddr, 329 xa, 330 false); 331 } catch (SQLException e) { 332 log.log(Level.FINER, e.toString(), e); 333 334 throw new SQLException (L.l("StringColumn '{0}.{1}' unique index set failed for {2}", 335 getTable().getName(), 336 getName(), 337 getString(block, rowOffset))); 338 } 339 } 340 } 341 342 349 void delete(Transaction xa, byte []block, int rowOffset) 350 throws SQLException 351 { 352 BTree index = getIndex(); 353 354 if (index != null) 355 index.remove(block, rowOffset + _columnOffset, getLength(), xa); 356 } 357 358 public String toString() 359 { 360 if (getIndex() != null) 361 return "StringColumn[" + getName() + ",index]"; 362 else 363 return "StringColumn[" + getName() + "]"; 364 } 365 } 366 | Popular Tags |