/** * Copyright (C) 2009-2013 FoundationDB, LLC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package com.foundationdb.qp.operator; import com.foundationdb.qp.row.HKey; import com.foundationdb.qp.row.Row; import com.foundationdb.server.types.value.Value; import com.foundationdb.server.types.value.ValueSource; import com.foundationdb.server.types.value.ValueTargets; import com.foundationdb.util.BloomFilter; import com.foundationdb.qp.util.HashTable; import com.foundationdb.util.SparseArray; public class SparseArrayQueryBindings implements QueryBindings { private final SparseArray<Object> bindings = new SparseArray<>(); private final QueryBindings parent; private final int depth; public SparseArrayQueryBindings() { this.parent = null; this.depth = 0; } public SparseArrayQueryBindings(QueryBindings parent) { this.parent = parent; this.depth = parent.getDepth() + 1; } @Override public String toString() { StringBuilder str = new StringBuilder(getClass().getSimpleName()); str.append('('); bindings.describeElements(str); if (parent != null) { str.append(", "); str.append(parent); } str.append(')'); return str.toString(); } /* QueryBindings interface */ @Override public ValueSource getValue(int index) { if (bindings.isDefined(index)) { return (ValueSource)bindings.get(index); } else if (parent != null) { return parent.getValue(index); } else { throw new BindingNotSetException(index); } } /* * (non-Javadoc) * @see com.foundationdb.qp.operator.QueryContext#setValue(int, com.foundationdb.server.types.value.ValueSource) * This makes a copy of the ValueSource value, rather than simply * storing the reference. The assumption is the ValueSource parameter * will be reused by the caller as rows are processed, so the QueryContext * needs to keep a copy of the underlying value. * */ @Override public void setValue(int index, ValueSource value) { Value holder = null; if (bindings.isDefined(index)) { holder = (Value)bindings.get(index); if (holder.getType() != value.getType()) holder = null; } if (holder == null) { holder = new Value(value.getType()); bindings.set(index, holder); } ValueTargets.copyFrom(value, holder); } @Override public Row getRow(int index) { if (bindings.isDefined(index)) { return (Row)bindings.get(index); } else if (parent != null) { return parent.getRow(index); } else { throw new BindingNotSetException(index); } } @Override public void setRow(int index, Row row) { bindings.set(index, row); } @Override public HKey getHKey(int index) { if (bindings.isDefined(index)) { return (HKey)bindings.get(index); } else if (parent != null) { return parent.getHKey(index); } else { throw new BindingNotSetException(index); } } @Override public void setHKey(int index, HKey hKey) { bindings.set(index, hKey); } @Override public BloomFilter getBloomFilter(int index) { if (bindings.isDefined(index)) { return (BloomFilter)bindings.get(index); } else if (parent != null) { return parent.getBloomFilter(index); } else { throw new BindingNotSetException(index); } } @Override public void setBloomFilter(int index, BloomFilter filter) { bindings.set(index, filter); } @Override public HashTable getHashTable(int index){ if (bindings.isDefined(index)) { return (HashTable)bindings.get(index); } else if (parent != null) { return parent.getHashTable(index); } else { throw new BindingNotSetException(index); } } @Override public void setHashTable(int index, HashTable hashTable) { bindings.set(index, hashTable); } @Override public void clear() { bindings.clear(); } @Override public QueryBindings getParent() { return parent; } @Override public boolean isAncestor(QueryBindings ancestor) { for (QueryBindings descendant = this; descendant != null; descendant = descendant.getParent()) { if (descendant == ancestor) { return true; } } return false; } @Override public int getDepth() { return depth; } @Override public QueryBindings createBindings() { return new SparseArrayQueryBindings(this); } }