1 package com.quadcap.sql.types; 2 3 40 41 import java.io.Externalizable ; 42 import java.io.IOException ; 43 import java.io.ObjectInput ; 44 import java.io.ObjectOutput ; 45 46 import java.util.Calendar ; 47 48 import antlr.RecognitionException; 49 50 import com.quadcap.util.Debug; 51 52 57 public class ValueInterval extends Value implements Externalizable { 58 long val; 59 boolean ym; 60 TypeInterval type; 61 62 public ValueInterval() {} 63 64 public ValueInterval(TypeInterval type, long val, boolean ym) { 65 this.type = type; 66 this.val = val; 67 this.ym = ym; 68 } 69 70 public ValueInterval(String sval, int sign, TypeInterval type) 71 throws RecognitionException 72 { 73 this.type = type; 74 long v = 0; 75 int start = type.getStart(); 76 ym = start == TypeInterval.YEAR || start == TypeInterval.MONTH; 77 long accum = 0; 78 int len = 0; 79 char c = 0; 80 for (int i = 0; i < sval.length(); i++) { 81 c = sval.charAt(i); 82 if (i == 0 && c == '-') sign = sign * -1; 83 else if (Character.isDigit(c)) { 84 accum *= 10; 85 accum += Character.digit(c, 10); 86 len++; 87 } else if (c == ' ' || c == ':' || c == '-' || c == '.') { 88 v += sign * accum * type.units(start++, ym); 89 accum = 0; 90 len = 0; 91 } 92 } 93 94 long xtra = 1; 95 if (c == '.') { 96 while (len < type.getSecPrecision()) { 98 xtra *= 10; 99 len++; 100 } 101 } else { 102 xtra = type.units(start, ym); 103 } 104 v += (sign * accum * xtra); 105 this.val = v; 106 } 107 108 public long getValue() { return val; } 109 110 public Calendar getCalendar() { 111 Calendar c = Calendar.getInstance(); 112 for (int i = 0; i < Calendar.FIELD_COUNT - 1; i++) c.set(i, 0); 113 if (ym) { 114 c.add(Calendar.MONTH, (int)val); 115 } else { 116 long mult = type.getMult(); 117 long v = val; 118 if (mult > 1000000) { 119 v *= (mult / 1000000); 120 } else { 121 v = (v * mult) / 1000000; 122 } 123 c.add(Calendar.MILLISECOND, (int)(v)); 124 } 125 return c; 126 } 127 128 public Value getTimeComponent(int field) throws ValueException { 129 final int NANO = TypeInterval.NANO; 130 131 Value ret = null; 132 int f = TypeInterval.convertCalendarField(field); 133 if (f < type.getStart() || f > type.getEnd()) { 134 ret = new ValueLong(0); 135 } else { 136 int e = type.getEnd(); 137 int s = type.getStart(); 138 if (e == s) { 139 ret = new ValueLong(val); 140 } else if (f == e) { 141 ret = new ValueLong(val % type.units(f-1, ym)); 142 } else if (f == s) { 143 ret = new ValueLong(val / type.units(s, ym)); 144 } else { 145 if (e != NANO) { 146 ret = new ValueLong((val / type.units(f, ym)) % 147 type.units(f-1, ym)); 148 } else { 149 ret = new ValueLong((val / type.units(f, ym)) % 150 type.units(f-1, ym)); 151 } 152 } 153 } 154 return ret; 155 } 156 157 public Value unop(int op) throws ValueException { 158 switch (op) { 159 case Op.NULL: 160 return ValueBoolean.falseBoolean; 161 case Op.PLUS: 162 return this; 163 case Op.MINUS: 164 return new ValueInterval(type, 0 - val, ym); 165 default: 166 throw new ValueException("Unary op: " + Op.toString(op) + 167 " not implemented for this type"); 168 } 169 } 170 171 public Value binop(int op, Value l) throws ValueException { 172 return l.binop(op, this); 173 } 174 175 public Value binop(int op, ValueNull r) throws ValueException { 176 switch (op) { 177 case Op.EQ: 178 case Op.NE: 179 case Op.LT: 180 case Op.LE: 181 case Op.GT: 182 case Op.GE: 183 case Op.PLUS: 184 case Op.MINUS: 185 return ValueUnknown.valueUnknown; 186 case Op.COMPARE: 187 return r.valCmpNull(); 188 default: 189 throw badBinop(op, r); 190 } 191 } 192 193 public Value binop(int op, ValueDouble r) throws ValueException { 194 switch (op) { 195 case Op.TIMES: 196 return new ValueInterval(type, (long)(val * r.doubleValue()), ym); 197 case Op.DIVIDE: 198 return new ValueInterval(type, (long)(val / r.doubleValue()), ym); 199 default: 200 throw badBinop(op, r); 201 } 202 } 203 204 public Value binop(int op, ValueFloat r) throws ValueException { 205 switch (op) { 206 case Op.TIMES: 207 return new ValueInterval(type, (long)(val * r.floatValue()), ym); 208 case Op.DIVIDE: 209 return new ValueInterval(type, (long)(val / r.floatValue()), ym); 210 default: 211 throw badBinop(op, r); 212 } 213 } 214 215 public Value binop(int op, ValueScaledInteger r) throws ValueException { 216 switch (op) { 217 case Op.TIMES: 218 return new ValueInterval(type, (long)(val * r.doubleValue()), ym); 219 case Op.DIVIDE: 220 return new ValueInterval(type, (long)(val / r.doubleValue()), ym); 221 default: 222 throw badBinop(op, r); 223 } 224 } 225 226 public Value binop(int op, ValueLong r) throws ValueException { 227 switch (op) { 228 case Op.TIMES: 229 return new ValueInterval(type, (long)(val * r.longValue()), ym); 230 case Op.DIVIDE: 231 return new ValueInterval(type, (long)(val / r.longValue()), ym); 232 default: 233 throw badBinop(op, r); 234 } 235 } 236 237 public Value binop(int op, ValueInteger r) throws ValueException { 238 switch (op) { 239 case Op.TIMES: 240 return new ValueInterval(type, (long)(val * r.intValue()), ym); 241 case Op.DIVIDE: 242 return new ValueInterval(type, (long)(val / r.intValue()), ym); 243 default: 244 throw badBinop(op, r); 245 } 246 } 247 248 public Value binop(int op, ValueShort r) throws ValueException { 249 switch (op) { 250 case Op.TIMES: 251 return new ValueInterval(type, (long)(val * r.shortValue()), ym); 252 case Op.DIVIDE: 253 return new ValueInterval(type, (long)(val / r.shortValue()), ym); 254 default: 255 throw badBinop(op, r); 256 } 257 } 258 259 public Value binop(int op, ValueByte r) throws ValueException { 260 switch (op) { 261 case Op.TIMES: 262 return new ValueInterval(type, (long)(val * r.byteValue()), ym); 263 case Op.DIVIDE: 264 return new ValueInterval(type, (long)(val / r.byteValue()), ym); 265 default: 266 throw badBinop(op, r); 267 } 268 } 269 270 public Value binop(int op, ValueInterval r) throws ValueException { 271 return ValueInterval.binop(op, this, r); 272 } 273 274 public static final Value binop(int op, ValueInterval e, ValueInterval f) 275 throws ValueException 276 { 277 if (e.ym != f.ym) { 278 throw new ValueException("Incompatible interval types: " + 279 e.toString() + " vs " + f.toString()); 280 } 281 switch (op) { 282 case Op.EQ: 283 return new ValueBoolean(e.val == f.val); 284 case Op.GE: 285 return new ValueBoolean(e.val >= f.val); 286 case Op.GT: 287 return new ValueBoolean(e.val > f.val); 288 case Op.LE: 289 return new ValueBoolean(e.val <= f.val); 290 case Op.LT: 291 return new ValueBoolean(e.val < f.val); 292 case Op.MINUS: 293 return new ValueInterval(e.type, e.val - f.val, e.ym); 294 case Op.NE: 295 return new ValueBoolean(e.val != f.val); 296 case Op.PLUS: 297 return new ValueInterval(e.type, e.val + f.val, e.ym); 298 case Op.COMPARE: 299 if (e.ym == f.ym) { 300 if (e.val < f.val) return ValueInteger.MINUS_ONE; 301 if (e.val > f.val) return ValueInteger.PLUS_ONE; 302 return ValueInteger.ZERO; 303 } else { 304 throw new ValueException("Can't compare year/month interval " + 305 "to day-time interval"); 306 } 307 default: 308 throw badBinop(op, e, f); 309 } 310 } 311 312 public void readExternal(ObjectInput in) 313 throws IOException , ClassNotFoundException 314 { 315 val = in.readLong(); 316 type = (TypeInterval)in.readObject(); 317 int start = type.getStart(); 318 ym = start == TypeInterval.YEAR || start == TypeInterval.MONTH; 319 } 320 321 public void writeExternal(ObjectOutput out) 322 throws IOException 323 { 324 out.writeLong(val); 325 out.writeObject(type); 326 } 327 328 public Object asJavaObject() { 329 return toString(); 330 } 331 332 public void fromJavaObject(Object obj) throws ValueException { 333 throw new ValueException("bad type: " + obj); 334 } 335 336 public String toString() { 337 StringBuffer sb = new StringBuffer ("INTERVAL "); 338 sb.append('\''); 339 if (type.getStart() == type.getEnd()) { 340 sb.append(String.valueOf(val / type.units(type.getStart(), ym))); 341 } else { 342 String delim = ""; 343 for (int i = type.getStart(); i <= type.getEnd(); i++) { 344 long t1 = (i == type.getStart()) ? 345 val : val % type.units(i-1, ym); 346 long t2 = t1 / type.units(i, ym); 347 sb.append(delim); 348 sb.append(Long.toString(t2)); 349 switch (i) { 350 case TypeInterval.YEAR: 351 case TypeInterval.MONTH: 352 delim = "-"; break; 353 case TypeInterval.DAY: 354 delim = " "; break; 355 case TypeInterval.HOUR: 356 case TypeInterval.MINUTE: 357 delim = ":"; break; 358 case TypeInterval.SECOND: 359 delim = "."; break; 360 default: 361 } 362 } 363 } 364 sb.append("' "); 365 sb.append(type.toString().substring(9)); 366 return sb.toString(); 367 } 368 369 public Value convert(TypeInterval newType) throws ValueException { 370 long m1 = type.getMult(); 371 long m2 = newType.getMult(); 372 long v = val; 373 374 if (m1 > m2) { 375 v *= (m1 / m2); 376 } else if (m1 < m2) { 377 v /= (m2 / m1); 378 } 379 Value ret = new ValueInterval(newType, v, ym); 380 return ret; 381 } 382 383 public Value convert(TypeDecimal t) { 384 int f = type.getStart(); 385 return new ValueScaledInteger(val / type.units(f, ym)); 386 } 387 388 public Type getType() { 389 return type; 390 } 391 392 public void serializeKey(KeyStream out) throws IOException { 393 out.writeBoolean(ym); 394 out.writeLong(val); 395 } 396 397 } 398 | Popular Tags |