Compare commits
10 Commits
3f4855eca1
...
9c7a1b135c
Author | SHA1 | Date |
---|---|---|
Heiko Mueller | 9c7a1b135c | |
Oliver Kennedy | cc6be2fbfb | |
Heiko Mueller | 336fe2c554 | |
Heiko Mueller | b477728974 | |
Heiko Mueller | e48e14db1c | |
Oliver Kennedy | 9a1116c376 | |
Oliver Kennedy | afdf9f7042 | |
Heiko Mueller | d04b767df4 | |
Heiko Mueller | bcacfcc245 | |
Jacob | 3cf01e15b7 |
|
@ -0,0 +1,6 @@
|
|||
#!/bin/bash
|
||||
|
||||
BASE=`dirname $0`/..
|
||||
CLASSPATH=`echo $BASE/target/vizier-db/WEB-INF/lib/* | tr ' ' ':'`
|
||||
|
||||
java -cp $CLASSPATH:$BASE/target/classes:$BASE/target/test-classes org.vizier.test.$1
|
24
pom.xml
24
pom.xml
|
@ -71,9 +71,33 @@
|
|||
<artifactId>gson</artifactId>
|
||||
<version>2.6.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.parboiled</groupId>
|
||||
<artifactId>parboiled-java</artifactId>
|
||||
<version>1.1.7</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>info.mimirdb</groupId>
|
||||
<artifactId>mimirdb-mimir</artifactId>
|
||||
<version>0.0.1</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<properties>
|
||||
<jersey.version>2.22.2</jersey.version>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>Mimir</id>
|
||||
<name>Mimir Snapshot</name>
|
||||
<releases>
|
||||
<enabled>true</enabled>
|
||||
<updatePolicy>always</updatePolicy>
|
||||
<checksumPolicy>warn</checksumPolicy>
|
||||
</releases>
|
||||
<url>http://maven.vizierdb.info/</url>
|
||||
<layout>default</layout>
|
||||
</repository>
|
||||
</repositories>
|
||||
</project>
|
||||
|
|
|
@ -13,68 +13,31 @@
|
|||
*/
|
||||
package org.vizierdb.database;
|
||||
|
||||
import org.vizierdb.util.SpreadsheetHelper;
|
||||
import org.vizierdb.database.value.Value;
|
||||
|
||||
/**
|
||||
* A cell in a notebook data snapshot. Each cell is identified by the unique
|
||||
* identifiers of the column and row that contain the cell. For a particular
|
||||
* snapshot the cell is mapped to a position defined by a mapping that is part
|
||||
* of the snapshot. Thus, column and row DO NOT identify the position of a cell
|
||||
* in a snapshot!
|
||||
* A cell in a notebook data snapshot. Extends a {@link CellCoordinates} with
|
||||
* a cell value.
|
||||
*
|
||||
* @author Heiko Mueller
|
||||
*/
|
||||
public class Cell {
|
||||
public class Cell extends CellCoordinates {
|
||||
|
||||
private final int _col;
|
||||
private final int _row;
|
||||
private final String _value;
|
||||
private final Value _value;
|
||||
|
||||
public Cell(int col, int row, String value) {
|
||||
public Cell(int columnId, int rowId, Value value) {
|
||||
|
||||
super(columnId, rowId);
|
||||
|
||||
_col = col;
|
||||
_row = row;
|
||||
_value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Identifier of the column that contains the cell.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public int getColumnId() {
|
||||
|
||||
return _col;
|
||||
}
|
||||
|
||||
/**
|
||||
* The column identifier is a concatenation of the column identifier
|
||||
* (transformed into spreadsheet column name notation) and row the
|
||||
* identifier.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getIdentifier() {
|
||||
|
||||
return SpreadsheetHelper.getColumnName(_col) + _row;
|
||||
}
|
||||
|
||||
/**
|
||||
* Identifier of the row that contains the cell.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public int getRowId() {
|
||||
|
||||
return _row;
|
||||
}
|
||||
|
||||
/**
|
||||
* The cell value.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getValue() {
|
||||
public Value getValue() {
|
||||
|
||||
return _value;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.vizierdb.database;
|
||||
|
||||
/**
|
||||
* Coordinates of a cell in a notebook data snapshot. Each cell is assigned to a
|
||||
* column and row, referenced by their respective unique identifiers.
|
||||
*
|
||||
* @author Heiko Mueller
|
||||
*/
|
||||
public class CellCoordinates {
|
||||
|
||||
public static final int UNKNOWN_COLUMN = -1;
|
||||
public static final int UNKNOWN_ROW = -1;
|
||||
|
||||
private final int _col;
|
||||
private final int _row;
|
||||
|
||||
public CellCoordinates(int col, int row) {
|
||||
|
||||
_col = col;
|
||||
_row = row;
|
||||
}
|
||||
|
||||
/**
|
||||
* Identifier of the column that contains the cell.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public int getColumnId() {
|
||||
|
||||
return _col;
|
||||
}
|
||||
|
||||
/**
|
||||
* The cell key is a concatenation of column and row identifier.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getKey() {
|
||||
|
||||
return _col + "#" + _row;
|
||||
}
|
||||
|
||||
/**
|
||||
* Identifier of the row that contains the cell.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public int getRowId() {
|
||||
|
||||
return _row;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.vizierdb.database;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import org.vizierdb.database.value.Value;
|
||||
|
||||
/**
|
||||
* Set of spreadsheet cells. Cells are indexed by the identifier of their value.
|
||||
*
|
||||
* @author Heiko Mueller
|
||||
*/
|
||||
public class CellSet implements Iterable<Cell> {
|
||||
|
||||
private final HashMap<String, Cell> _cellIndex = new HashMap<>();
|
||||
private final HashMap<Integer, Cell> _valueIndex = new HashMap<>();
|
||||
|
||||
public void add(Cell cell) {
|
||||
|
||||
_cellIndex.put(cell.getKey(), cell);
|
||||
_valueIndex.put(cell.getValue().getIdentifier(), cell);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cell with the given key.
|
||||
*
|
||||
* @param key
|
||||
* @return
|
||||
*/
|
||||
public Cell getCell(String key) {
|
||||
|
||||
return _cellIndex.get(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cell at given coordinate position.
|
||||
*
|
||||
* @param coordinates
|
||||
* @return
|
||||
*/
|
||||
public Cell getCell(CellCoordinates coordinates) {
|
||||
|
||||
return this.getCell(coordinates.getKey());
|
||||
}
|
||||
|
||||
/**
|
||||
* Cell that contains value with given identifier.
|
||||
*
|
||||
* @param valueId
|
||||
* @return
|
||||
*/
|
||||
public Cell getCellForValue(int valueId) {
|
||||
|
||||
return _valueIndex.get(valueId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Value with given identifier or null if no such value exists.
|
||||
*
|
||||
* @param valueId
|
||||
* @return
|
||||
*/
|
||||
public Value getValue(int valueId) {
|
||||
|
||||
Cell cell = _valueIndex.get(valueId);
|
||||
if (cell != null) {
|
||||
return cell.getValue();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Cell> iterator() {
|
||||
|
||||
return _valueIndex.values().iterator();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,137 @@
|
|||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.vizierdb.database;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import org.vizierdb.database.value.DependencyGraph;
|
||||
import org.vizierdb.database.value.ErrorValue;
|
||||
import org.vizierdb.database.value.Value;
|
||||
import org.vizierdb.database.value.formula.Formula;
|
||||
|
||||
/**
|
||||
* Class to build a cell set. Keeps a mapping from cell keys to cells and the
|
||||
* dependency graph. The latter two objects are not part of the materialized
|
||||
* snapshot. This is a helper to group various objects that are needed when
|
||||
* executing script operations.
|
||||
*
|
||||
* @author Heiko Mueller
|
||||
*/
|
||||
public class CellSetFactory {
|
||||
|
||||
private final CellSet _cells = new CellSet();
|
||||
private final DependencyGraph _graph = new DependencyGraph();
|
||||
|
||||
/**
|
||||
* Add a cell to the set and indexes. Also updates the dependency graph.
|
||||
*
|
||||
* @param cell
|
||||
*/
|
||||
public void add(Cell cell) {
|
||||
|
||||
_cells.add(cell);
|
||||
if (cell.getValue().isDerived()) {
|
||||
int valueId = cell.getValue().getIdentifier();
|
||||
for (int sourceValueId : cell.getValue().getDependencies()) {
|
||||
_graph.addEdge(valueId, sourceValueId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-evaluate all values that depend on an updated value.
|
||||
*
|
||||
* @param valueId
|
||||
*/
|
||||
public void evalForUpdatedValue(int valueId) {
|
||||
|
||||
for (int dependentValueId : _graph.getDependentValues(valueId)) {
|
||||
Cell cell = _cells.getCellForValue(dependentValueId);
|
||||
_cells.add(new Cell(cell.getColumnId(), cell.getRowId(), cell.getValue().eval(_cells)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-evaluate all values that depend on deleted values. The new values will
|
||||
* all be error values due to their dependency on a deleted value.
|
||||
*
|
||||
* @param snapshot
|
||||
* @param valueIds
|
||||
*/
|
||||
public void evalForDeletedValues(Snapshot snapshot, List<Integer> valueIds) {
|
||||
|
||||
HashSet<Integer> processedValues = new HashSet<>();
|
||||
for (int valueId : valueIds) {
|
||||
for (int dependentValueId : _graph.getDirectDependentValues(valueId)) {
|
||||
Cell cell = _cells.getCellForValue(dependentValueId);
|
||||
if (cell != null) {
|
||||
Value value = cell.getValue();
|
||||
_cells.add(new Cell(cell.getColumnId(), cell.getRowId(), new ErrorValue(value.getIdentifier(), Formula.ERROR_UNKNOWN_NAME, value.getFormula(snapshot))));
|
||||
}
|
||||
processedValues.add(dependentValueId);
|
||||
}
|
||||
}
|
||||
|
||||
LinkedList<Integer> indirectDependents = new LinkedList<>(processedValues);
|
||||
while (!indirectDependents.isEmpty()) {
|
||||
int valueId = indirectDependents.pop();
|
||||
for (int dependentValueId : _graph.getDirectDependentValues(valueId)) {
|
||||
if (!processedValues.contains(dependentValueId)) {
|
||||
Cell cell = _cells.getCellForValue(dependentValueId);
|
||||
if (cell != null) {
|
||||
Value value = cell.getValue();
|
||||
_cells.add(new Cell(cell.getColumnId(), cell.getRowId(), value.eval(_cells)));
|
||||
for (int cand : value.getDependencies()) {
|
||||
indirectDependents.push(cand);
|
||||
}
|
||||
}
|
||||
processedValues.add(dependentValueId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve cell using cell key.
|
||||
*
|
||||
* @param key
|
||||
* @return
|
||||
*/
|
||||
public Cell get(String key) {
|
||||
|
||||
return _cells.getCell(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dependency graph that has been constructed.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public DependencyGraph getDependencyGraph() {
|
||||
|
||||
return _graph;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generated cell set.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public CellSet getSet() {
|
||||
|
||||
return _cells;
|
||||
}
|
||||
}
|
|
@ -13,20 +13,24 @@
|
|||
*/
|
||||
package org.vizierdb.database;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
import org.vizierdb.util.SpreadsheetHelper;
|
||||
|
||||
/**
|
||||
* Column in a spreadsheet. Has a name and a unique identifier. The name can be
|
||||
* empty. The identifier is immutable.
|
||||
* Column in a spreadsheet. Has a unique identifier, unique label, and a user
|
||||
* provided name. The name may not be unique among all column names in a
|
||||
* spreadsheet.
|
||||
*
|
||||
* @author Heiko Mueller
|
||||
*/
|
||||
public class Column {
|
||||
|
||||
/**
|
||||
* Special string prefix to all references to columns by their identifier.
|
||||
*/
|
||||
public static final String COLUMN_ID_INDICATOR = "#";
|
||||
public static final String COLUMN_ID_INDICATOR = "$";
|
||||
public static final Pattern VALID_NAME_REGEX = Pattern.compile("[\\d\\w-_]+");
|
||||
|
||||
private final ColumnList _columns;
|
||||
private final int _identifier;
|
||||
private final String _label;
|
||||
private final String _name;
|
||||
|
||||
/**
|
||||
|
@ -34,24 +38,40 @@ public class Column {
|
|||
*
|
||||
* @param identifier
|
||||
* @param name
|
||||
* @param columnIndex
|
||||
* @param columns
|
||||
*/
|
||||
public Column(int identifier, String name) {
|
||||
public Column(int identifier, String name, int columnIndex, ColumnList columns) {
|
||||
|
||||
if (name.startsWith(COLUMN_ID_INDICATOR)) {
|
||||
if (name == null) {
|
||||
throw new java.lang.IllegalArgumentException("Invalid column name: null");
|
||||
} else if (!VALID_NAME_REGEX.matcher(name).matches()) {
|
||||
throw new java.lang.IllegalArgumentException("Invalid column name: " + name);
|
||||
} else if (columnIndex < 0) {
|
||||
throw new java.lang.IllegalArgumentException("Invalid column index: " + columnIndex);
|
||||
}
|
||||
|
||||
_identifier = identifier;
|
||||
_name = name;
|
||||
_label = SpreadsheetHelper.getColumnName(columnIndex);
|
||||
_columns = columns;
|
||||
}
|
||||
|
||||
/**
|
||||
* A column without a name.
|
||||
* Returns the most descriptive name. This is the user provided name if
|
||||
* unique or the label otherwise.
|
||||
*
|
||||
* @param identifier
|
||||
* @return
|
||||
*/
|
||||
private Column(int identifier) {
|
||||
public String getDescriptiveName() {
|
||||
|
||||
this(identifier, null);
|
||||
if (_columns.isUniqueName(_name)) {
|
||||
return _name;
|
||||
} else if (_columns.isUniqueName(_label)) {
|
||||
return _label;
|
||||
} else {
|
||||
return COLUMN_ID_INDICATOR + _identifier;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -65,7 +85,18 @@ public class Column {
|
|||
}
|
||||
|
||||
/**
|
||||
* Column name. The name may be null.
|
||||
* Unique column label based on columns position in the spreadsheet (i.e.,
|
||||
* A, B, C, ...).
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getLabel() {
|
||||
|
||||
return _label;
|
||||
}
|
||||
|
||||
/**
|
||||
* User provided column name.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
|
@ -73,4 +104,15 @@ public class Column {
|
|||
|
||||
return _name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether the column name is unique among all columns in a
|
||||
* spreadsheet.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean hasUniqueName() {
|
||||
|
||||
return _columns.isUniqueName(_name);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,6 @@ package org.vizierdb.database;
|
|||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import org.vizierdb.util.SpreadsheetHelper;
|
||||
|
||||
/**
|
||||
* Listing of columns in a spreadsheet. Columns appear in the spreadsheet in the
|
||||
|
@ -27,28 +26,26 @@ import org.vizierdb.util.SpreadsheetHelper;
|
|||
*/
|
||||
public class ColumnList implements Iterable<Column> {
|
||||
|
||||
/**
|
||||
* Default name for unknown columns. Unknown columns may arise during
|
||||
* reenactment of operations that reference columns which have not been
|
||||
* created or no longer exist.
|
||||
*/
|
||||
public static final String UNKNOWN_COLUMN = "???";
|
||||
|
||||
private final HashMap<Integer, Integer> _columnIndex = new HashMap<>();
|
||||
private final ArrayList<Column> _columnList = new ArrayList<>();
|
||||
private final HashMap<String, Integer> _nameCount = new HashMap<>();
|
||||
|
||||
public void add(Column column) {
|
||||
public void add(int columnId, String columnName) {
|
||||
|
||||
_columnList.add(column);
|
||||
_columnIndex.put(column.getIdentifier(), _columnIndex.size());
|
||||
if (_nameCount.containsKey(column.getName())) {
|
||||
_nameCount.put(column.getName(), _nameCount.get(column.getName()) + 1);
|
||||
if (columnName == null) {
|
||||
throw new java.lang.IllegalArgumentException("Invalid column name: null");
|
||||
}
|
||||
|
||||
Column column = new Column(columnId, columnName, _columnList.size(), this);
|
||||
if (_nameCount.containsKey(columnName)) {
|
||||
_nameCount.put(column.getName(), _nameCount.get(column.getName()) + 1);
|
||||
} else {
|
||||
_nameCount.put(column.getName(), 1);
|
||||
}
|
||||
_columnList.add(column);
|
||||
_columnIndex.put(column.getIdentifier(), _columnIndex.size());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check if the list contains a column with the given identifier.
|
||||
*
|
||||
|
@ -72,34 +69,56 @@ public class ColumnList implements Iterable<Column> {
|
|||
}
|
||||
|
||||
/**
|
||||
* The most descriptive column name. This is the given column name if it
|
||||
* is unique. Otherwise it will be the spreadsheet column name. Should that
|
||||
* name exist as well it will be the column identifier (prefixed by the
|
||||
* COLUMN_ID_INDICATOR). If the column does not exists the result is the
|
||||
* default UNKNOWN_COLUMN name.
|
||||
*
|
||||
* Column with the given identifier or null if no such column exists.
|
||||
*
|
||||
* @param columnId
|
||||
* @return
|
||||
*/
|
||||
public String getDescriptiveName(int columnId) {
|
||||
public Column getColumn(int columnId) {
|
||||
|
||||
int index = this.getIndexOf(columnId);
|
||||
if (index != -1) {
|
||||
Column column = _columnList.get(index);
|
||||
if (_nameCount.get(column.getName()) == 1) {
|
||||
return column.getName();
|
||||
} else {
|
||||
String name = SpreadsheetHelper.getColumnName(index);
|
||||
if (_nameCount.containsKey(name)) {
|
||||
return Column.COLUMN_ID_INDICATOR + column.getIdentifier();
|
||||
} else {
|
||||
return name;
|
||||
return _columnList.get(index);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
public void renameColumn(int columnId, String newName)
|
||||
{
|
||||
int index = this.getIndexOf(columnId);
|
||||
Column col = _columnList.get(index);
|
||||
String oldName = col.getName();
|
||||
_nameCount.put(oldName, _nameCount.get(oldName) - 1);
|
||||
if (_nameCount.containsKey(newName)) {
|
||||
_nameCount.put(newName, _nameCount.get(newName) + 1);
|
||||
} else {
|
||||
_nameCount.put(newName, 1);
|
||||
}
|
||||
_columnList.set(index, new Column(columnId, newName, index, this));
|
||||
}
|
||||
|
||||
/**
|
||||
* The column identifier of the column with given name. Is UNKNOWN if either
|
||||
* (i) no column with name exists, or (ii) multiple columns with name
|
||||
* exist.
|
||||
*
|
||||
* @param name
|
||||
* @return
|
||||
*/
|
||||
public int getIdentifierOf(String name) {
|
||||
|
||||
if (_nameCount.containsKey(name)) {
|
||||
if (_nameCount.get(name) != 1) {
|
||||
return CellCoordinates.UNKNOWN_COLUMN;
|
||||
}
|
||||
for (Column column : _columnList) {
|
||||
if (column.getName().equals(name)) {
|
||||
return column.getIdentifier();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return UNKNOWN_COLUMN;
|
||||
}
|
||||
|
||||
return CellCoordinates.UNKNOWN_COLUMN;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -117,6 +136,15 @@ public class ColumnList implements Iterable<Column> {
|
|||
}
|
||||
}
|
||||
|
||||
public boolean isUniqueName(String name) {
|
||||
|
||||
if (_nameCount.containsKey(name)) {
|
||||
return (_nameCount.get(name) <= 1);
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Column> iterator() {
|
||||
|
||||
|
|
|
@ -29,7 +29,8 @@ public class Notebook implements Comparable<Notebook> {
|
|||
private final VersionGraph _history;
|
||||
private final int _identifier;
|
||||
private String _name;
|
||||
private int _rowCount;
|
||||
private int _rowCount = 0;
|
||||
private int _valueCount = 0;
|
||||
|
||||
public Notebook(int identifier, String name, VizierDB db) {
|
||||
|
||||
|
@ -101,6 +102,17 @@ public class Notebook implements Comparable<Notebook> {
|
|||
return _rowCount++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Next unique value identifier. Called when adding a new cell to a
|
||||
* notebook.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public synchronized int nextValueId() {
|
||||
|
||||
return _valueCount++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the notebook name.
|
||||
*
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.vizierdb.database;
|
||||
|
||||
import org.vizierdb.database.value.Value;
|
||||
|
||||
/**
|
||||
* Row in a spreadsheet. Primarily used to group cells for evaluation in filter
|
||||
* conditions.
|
||||
*
|
||||
* @author Heiko Mueller
|
||||
*/
|
||||
public class Row {
|
||||
|
||||
private final CellSet _cells;
|
||||
private final int _rowId;
|
||||
|
||||
public Row(int rowId, CellSet cells) {
|
||||
|
||||
_rowId = rowId;
|
||||
_cells = cells;
|
||||
}
|
||||
|
||||
/**
|
||||
* Value for column with given identifier. The result is null if the row
|
||||
* does not have a value for the given column.
|
||||
*
|
||||
* @param columnId
|
||||
* @return
|
||||
*/
|
||||
public Value getColumnValue(int columnId) {
|
||||
|
||||
Cell cell = _cells.getCell(new CellCoordinates(columnId, _rowId));
|
||||
if (cell != null) {
|
||||
return cell.getValue();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -281,7 +281,7 @@ public class SimpleVizierDBM implements VizierDB {
|
|||
if (branch.getHead() != UNKNOWN_SNAPSHOT) {
|
||||
return this.getSnapshot(notebookIdentifier, branch.getHead());
|
||||
} else {
|
||||
return new Snapshot(UNKNOWN_SNAPSHOT, new ColumnList(), new RowList(), new ArrayList<Cell>());
|
||||
return new Snapshot(UNKNOWN_SNAPSHOT, new ColumnList(), new RowList(), new CellSet());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,8 +13,6 @@
|
|||
*/
|
||||
package org.vizierdb.database;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Snapshot of the data in a notebook. Each operation in the script that is
|
||||
* associated with a notebook will modify the current snapshot.
|
||||
|
@ -26,12 +24,12 @@ import java.util.List;
|
|||
*/
|
||||
public class Snapshot {
|
||||
|
||||
private final List<Cell> _cells;
|
||||
private final CellSet _cells;
|
||||
private final ColumnList _columns;
|
||||
private final int _identifier;
|
||||
private final RowList _rows;
|
||||
|
||||
public Snapshot(int identifier, ColumnList columns, RowList rows, List<Cell> cells) {
|
||||
public Snapshot(int identifier, ColumnList columns, RowList rows, CellSet cells) {
|
||||
|
||||
_identifier = identifier;
|
||||
_columns = columns;
|
||||
|
@ -44,7 +42,7 @@ public class Snapshot {
|
|||
*
|
||||
* @return
|
||||
*/
|
||||
public List<Cell> getCells() {
|
||||
public CellSet getCells() {
|
||||
|
||||
return _cells;
|
||||
}
|
||||
|
|
|
@ -14,11 +14,9 @@
|
|||
package org.vizierdb.database;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import org.vizierdb.database.history.Branch;
|
||||
import org.vizierdb.database.script.Operation;
|
||||
import org.vizierdb.database.script.OperationType;
|
||||
import org.vizierdb.database.script.VizUALScript;
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.vizierdb.database.filter;
|
||||
|
||||
import org.vizierdb.database.ColumnList;
|
||||
import org.vizierdb.database.Row;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author heiko
|
||||
*/
|
||||
public class ANDOp extends LogicOp {
|
||||
|
||||
public ANDOp(Condition left, Condition right) {
|
||||
|
||||
super(left, right);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean eval(Row row) {
|
||||
|
||||
if (this.left().eval(row)) {
|
||||
return this.right().eval(row);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.vizierdb.database.filter;
|
||||
|
||||
import org.vizierdb.database.ColumnList;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author heiko
|
||||
*/
|
||||
public abstract class BinaryOp implements Condition {
|
||||
|
||||
private final Term _left;
|
||||
private final Term _right;
|
||||
|
||||
public BinaryOp(Term left, Term right) {
|
||||
|
||||
_left = left;
|
||||
_right = right;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isApplicable(ColumnList columns) {
|
||||
|
||||
Integer col = _left.getReferencedColumn();
|
||||
if (col != null) {
|
||||
if (!columns.contains(col)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
col = _right.getReferencedColumn();
|
||||
if (col != null) {
|
||||
if (!columns.contains(col)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public Term left() {
|
||||
|
||||
return _left;
|
||||
}
|
||||
|
||||
public Term rigth() {
|
||||
|
||||
return _right;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.vizierdb.database.filter;
|
||||
|
||||
import org.vizierdb.database.Row;
|
||||
import org.vizierdb.database.value.Value;
|
||||
|
||||
/**
|
||||
* Term that returns value of column with specific identifier.
|
||||
*
|
||||
* @author Heiko Mueller
|
||||
*/
|
||||
public class ColumnTerm implements Term {
|
||||
|
||||
private final int _columnId;
|
||||
|
||||
public ColumnTerm(int columnId) {
|
||||
|
||||
_columnId = columnId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Value getValue(Row row) {
|
||||
|
||||
return row.getColumnValue(_columnId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getReferencedColumn() {
|
||||
|
||||
return _columnId;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.vizierdb.database.filter;
|
||||
|
||||
import org.vizierdb.database.ColumnList;
|
||||
import org.vizierdb.database.Row;
|
||||
|
||||
/**
|
||||
* Condition in a VizUAL filter. Conditions are evaluated over rows in a
|
||||
* spreadsheet.
|
||||
*
|
||||
* @author Heiko Mueller
|
||||
*/
|
||||
public interface Condition {
|
||||
|
||||
/**
|
||||
* Evaluate the condition on a spreadsheet row.
|
||||
*
|
||||
* @param row
|
||||
* @return
|
||||
*/
|
||||
public boolean eval(Row row);
|
||||
|
||||
/**
|
||||
* Test if all column terms can be evaluated over given list of columns.
|
||||
*
|
||||
* @param columns
|
||||
* @return
|
||||
*/
|
||||
public boolean isApplicable(ColumnList columns);
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.vizierdb.database.filter;
|
||||
|
||||
import org.vizierdb.database.Row;
|
||||
import org.vizierdb.database.value.Value;
|
||||
|
||||
/**
|
||||
* Constant value term.
|
||||
*
|
||||
* @author heiko
|
||||
*/
|
||||
public class ConstantTerm implements Term{
|
||||
|
||||
private final Value _value;
|
||||
|
||||
public ConstantTerm(Value value) {
|
||||
|
||||
_value = value;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Value getValue(Row row) {
|
||||
|
||||
return _value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getReferencedColumn() {
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.vizierdb.database.filter;
|
||||
|
||||
import org.vizierdb.database.Row;
|
||||
import org.vizierdb.database.value.Value;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author heiko
|
||||
*/
|
||||
public class EQOp extends BinaryOp {
|
||||
|
||||
public EQOp(Term left, Term right) {
|
||||
|
||||
super(left, right);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean eval(Row row) {
|
||||
|
||||
Value leftVal = this.left().getValue(row);
|
||||
Value rightVal = this.rigth().getValue(row);
|
||||
|
||||
if ((leftVal != null) && (rightVal != null)) {
|
||||
try {
|
||||
return (leftVal.getAsBigDecimal().compareTo(rightVal.getAsBigDecimal()) == 0);
|
||||
} catch (Exception exception) {
|
||||
return leftVal.getAsString().equals(rightVal.getAsString());
|
||||
}
|
||||
} else {
|
||||
return ((leftVal == null) && (rightVal == null));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.vizierdb.database.filter;
|
||||
|
||||
import org.vizierdb.database.Row;
|
||||
import org.vizierdb.database.value.Value;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author heiko
|
||||
*/
|
||||
public class GEQOp extends BinaryOp {
|
||||
|
||||
public GEQOp(Term left, Term right) {
|
||||
|
||||
super(left, right);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean eval(Row row) {
|
||||
|
||||
Value leftVal = this.left().getValue(row);
|
||||
Value rightVal = this.rigth().getValue(row);
|
||||
|
||||
if ((leftVal != null) && (rightVal != null)) {
|
||||
try {
|
||||
return (leftVal.getAsBigDecimal().compareTo(rightVal.getAsBigDecimal()) >= 0);
|
||||
} catch (Exception exception) {
|
||||
return (leftVal.getAsString().compareTo(rightVal.getAsString()) >= 0);
|
||||
}
|
||||
} else {
|
||||
return ((leftVal == null) && (rightVal == null));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.vizierdb.database.filter;
|
||||
|
||||
import org.vizierdb.database.Row;
|
||||
import org.vizierdb.database.value.Value;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author heiko
|
||||
*/
|
||||
public class GTOp extends BinaryOp {
|
||||
|
||||
public GTOp(Term left, Term right) {
|
||||
|
||||
super(left, right);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean eval(Row row) {
|
||||
|
||||
Value leftVal = this.left().getValue(row);
|
||||
Value rightVal = this.rigth().getValue(row);
|
||||
|
||||
if ((leftVal != null) && (rightVal != null)) {
|
||||
try {
|
||||
return (leftVal.getAsBigDecimal().compareTo(rightVal.getAsBigDecimal()) > 0);
|
||||
} catch (Exception exception) {
|
||||
return (leftVal.getAsString().compareTo(rightVal.getAsString()) > 0);
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.vizierdb.database.filter;
|
||||
|
||||
import org.vizierdb.database.Row;
|
||||
import org.vizierdb.database.value.Value;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author heiko
|
||||
*/
|
||||
public class LEQOp extends BinaryOp {
|
||||
|
||||
public LEQOp(Term left, Term right) {
|
||||
|
||||
super(left, right);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean eval(Row row) {
|
||||
|
||||
Value leftVal = this.left().getValue(row);
|
||||
Value rightVal = this.rigth().getValue(row);
|
||||
|
||||
if ((leftVal != null) && (rightVal != null)) {
|
||||
try {
|
||||
return (leftVal.getAsBigDecimal().compareTo(rightVal.getAsBigDecimal()) <= 0);
|
||||
} catch (Exception exception) {
|
||||
return (leftVal.getAsString().compareTo(rightVal.getAsString()) <= 0);
|
||||
}
|
||||
} else {
|
||||
return ((leftVal == null) && (rightVal == null));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.vizierdb.database.filter;
|
||||
|
||||
import org.vizierdb.database.Row;
|
||||
import org.vizierdb.database.value.Value;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author heiko
|
||||
*/
|
||||
public class LTOp extends BinaryOp {
|
||||
|
||||
public LTOp(Term left, Term right) {
|
||||
|
||||
super(left, right);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean eval(Row row) {
|
||||
|
||||
Value leftVal = this.left().getValue(row);
|
||||
Value rightVal = this.rigth().getValue(row);
|
||||
|
||||
if ((leftVal != null) && (rightVal != null)) {
|
||||
try {
|
||||
return (leftVal.getAsBigDecimal().compareTo(rightVal.getAsBigDecimal()) < 0);
|
||||
} catch (Exception exception) {
|
||||
return (leftVal.getAsString().compareTo(rightVal.getAsString()) < 0);
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.vizierdb.database.filter;
|
||||
|
||||
import org.vizierdb.database.ColumnList;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author heiko
|
||||
*/
|
||||
public abstract class LogicOp implements Condition {
|
||||
|
||||
private final Condition _left;
|
||||
private final Condition _right;
|
||||
|
||||
public LogicOp(Condition left, Condition right) {
|
||||
|
||||
_left = left;
|
||||
_right = right;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isApplicable(ColumnList columns) {
|
||||
|
||||
if (_left.isApplicable(columns)) {
|
||||
return _right.isApplicable(columns);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public Condition left() {
|
||||
|
||||
return _left;
|
||||
}
|
||||
|
||||
public Condition right() {
|
||||
|
||||
return _right;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.vizierdb.database.filter;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
import org.vizierdb.database.ColumnList;
|
||||
import org.vizierdb.database.Row;
|
||||
import org.vizierdb.database.value.Value;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author heiko
|
||||
*/
|
||||
public class MatchesOp implements Condition {
|
||||
|
||||
private final Pattern _pattern;
|
||||
private final Term _term;
|
||||
|
||||
public MatchesOp(Term term, Pattern pattern) {
|
||||
|
||||
_term = term;
|
||||
_pattern = pattern;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean eval(Row row) {
|
||||
|
||||
Value val = _term.getValue(row);
|
||||
|
||||
if (val != null) {
|
||||
try {
|
||||
return _pattern.matcher(val.getAsString()).matches();
|
||||
} catch (Exception exception) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isApplicable(ColumnList columns) {
|
||||
|
||||
Integer col = _term.getReferencedColumn();
|
||||
if (col != null) {
|
||||
return (columns.contains(col));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.vizierdb.database.filter;
|
||||
|
||||
import org.vizierdb.database.Row;
|
||||
import org.vizierdb.database.value.Value;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author heiko
|
||||
*/
|
||||
public class NEQOp extends BinaryOp {
|
||||
|
||||
public NEQOp(Term left, Term right) {
|
||||
|
||||
super(left, right);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean eval(Row row) {
|
||||
|
||||
Value leftVal = this.left().getValue(row);
|
||||
Value rightVal = this.rigth().getValue(row);
|
||||
|
||||
if ((leftVal != null) && (rightVal != null)) {
|
||||
try {
|
||||
return (leftVal.getAsBigDecimal().compareTo(rightVal.getAsBigDecimal()) != 0);
|
||||
} catch (Exception exception) {
|
||||
return !leftVal.getAsString().equals(rightVal.getAsString());
|
||||
}
|
||||
} else {
|
||||
return !((leftVal == null) && (rightVal == null));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.vizierdb.database.filter;
|
||||
|
||||
import org.vizierdb.database.Row;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author heiko
|
||||
*/
|
||||
public class OROp extends LogicOp {
|
||||
|
||||
public OROp(Condition left, Condition right) {
|
||||
|
||||
super(left, right);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean eval(Row row) {
|
||||
|
||||
if (this.left().eval(row)) {
|
||||
return true;
|
||||
} else {
|
||||
return this.right().eval(row);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.vizierdb.database.filter;
|
||||
|
||||
import org.vizierdb.database.Row;
|
||||
import org.vizierdb.database.value.Value;
|
||||
|
||||
/**
|
||||
* Value expression in a filter condition operator. Returns a value. Could
|
||||
* either be a constant value or the value of a cell in a spreadsheet row.
|
||||
*
|
||||
* @author Heiko Mueller
|
||||
*/
|
||||
public interface Term {
|
||||
|
||||
/**
|
||||
* The value that the term evaluates to for the given row.
|
||||
*
|
||||
* @param row
|
||||
* @return
|
||||
*/
|
||||
public Value getValue(Row row);
|
||||
|
||||
/**
|
||||
* The identifier of the column from which the value is extracted. The
|
||||
* result is null if the term represents a constant value.
|
||||
* @return
|
||||
*/
|
||||
public Integer getReferencedColumn();
|
||||
}
|
|
@ -30,6 +30,7 @@ import org.vizierdb.database.script.VizUALStatement;
|
|||
public class VGEdge {
|
||||
|
||||
private final Operation _operation;
|
||||
private final String _sqlStatement;
|
||||
private final VizUALStatement _stmt;
|
||||
private final VGNode _target;
|
||||
|
||||
|
@ -40,8 +41,9 @@ public class VGEdge {
|
|||
* @param target
|
||||
* @param operation
|
||||
* @param stmt
|
||||
* @param sqlStatement
|
||||
*/
|
||||
public VGEdge(VGNode target, Operation operation, VizUALStatement stmt) {
|
||||
public VGEdge(VGNode target, Operation operation, VizUALStatement stmt, String sqlStatement) {
|
||||
|
||||
if (operation == null) {
|
||||
throw new java.lang.IllegalArgumentException("Derivation operation: null");
|
||||
|
@ -50,6 +52,7 @@ public class VGEdge {
|
|||
_target = target;
|
||||
_operation = operation;
|
||||
_stmt = stmt;
|
||||
_sqlStatement = sqlStatement;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -57,10 +60,11 @@ public class VGEdge {
|
|||
*
|
||||
* @param operation
|
||||
* @param stmt
|
||||
* @param sqlStatement
|
||||
*/
|
||||
public VGEdge(Operation operation, VizUALStatement stmt) {
|
||||
public VGEdge(Operation operation, VizUALStatement stmt, String sqlStatement) {
|
||||
|
||||
this(null, operation, stmt);
|
||||
this(null, operation, stmt, sqlStatement);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -79,11 +83,16 @@ public class VGEdge {
|
|||
*
|
||||
* @return
|
||||
*/
|
||||
public VizUALStatement getStatement() {
|
||||
public VizUALStatement getVizUALStatement() {
|
||||
|
||||
return _stmt;
|
||||
}
|
||||
|
||||
public String getSQLStatement() {
|
||||
|
||||
return _sqlStatement;
|
||||
}
|
||||
|
||||
/**
|
||||
* Node representing the target snapshot.
|
||||
*
|
||||
|
|
|
@ -20,6 +20,7 @@ import org.vizierdb.database.Snapshot;
|
|||
import org.vizierdb.database.script.Operation;
|
||||
import org.vizierdb.database.script.VizUALScript;
|
||||
import org.vizierdb.database.VizierDB;
|
||||
import org.vizierdb.database.script.op.CSVFileLoad;
|
||||
|
||||
/**
|
||||
* The version graph maintains information how snapshots in a notebook's
|
||||
|
@ -38,6 +39,7 @@ public class VersionGraph {
|
|||
private Branch _currentBranch;
|
||||
private final HashMap<Integer, VGNode> _nodes;
|
||||
private VGNode _root;
|
||||
private String _tableName = null;
|
||||
|
||||
/**
|
||||
* Create an empty graph. HEAD and ROOT are undefined for an empty graph.
|
||||
|
@ -92,7 +94,16 @@ public class VersionGraph {
|
|||
if (_root != null) {
|
||||
throw new java.lang.IllegalStateException("Version graph root has been set");
|
||||
}
|
||||
_root = new VGNode(targetId, new VGEdge(operation, operation.getStatement(source)));
|
||||
/**
|
||||
* NOTE: This is a hack. requires the first operation to be a load
|
||||
* operation. Should be changed.
|
||||
*/
|
||||
_tableName = ((CSVFileLoad)operation).getFileName();
|
||||
int pos = _tableName.indexOf(".");
|
||||
if (pos != -1) {
|
||||
_tableName = _tableName.substring(0, pos);
|
||||
}
|
||||
_root = new VGNode(targetId, new VGEdge(operation, operation.getVizUALStatement(source), operation.getSQLStatement(source, _tableName)));
|
||||
_nodes.put(targetId, _root);
|
||||
_currentBranch.setHead(targetId);
|
||||
return _root;
|
||||
|
@ -104,7 +115,7 @@ public class VersionGraph {
|
|||
if (parent == null) {
|
||||
throw new java.lang.IllegalArgumentException("Unknown snapshot: " + sourceId);
|
||||
}
|
||||
VGNode node = new VGNode(targetId, new VGEdge(parent, operation, operation.getStatement(source)));
|
||||
VGNode node = new VGNode(targetId, new VGEdge(parent, operation, operation.getVizUALStatement(source), operation.getSQLStatement(source, _tableName)));
|
||||
_nodes.put(targetId, node);
|
||||
/**
|
||||
* If the source snapshot is head of a branch then we will extend that
|
||||
|
@ -225,11 +236,11 @@ public class VersionGraph {
|
|||
VGNode node = _nodes.get(branch.getHead());
|
||||
if (node != null) {
|
||||
VGEdge derivation = node.getParent();
|
||||
script.addAtBeginning(derivation.getOperation(), derivation.getStatement(), node.getSnapshotIdentifier());
|
||||
script.addAtBeginning(derivation.getOperation(), derivation.getVizUALStatement(), derivation.getSQLStatement(), node.getSnapshotIdentifier());
|
||||
while (derivation.hasTarget()) {
|
||||
node = derivation.getTarget();
|
||||
derivation = node.getParent();
|
||||
script.addAtBeginning(derivation.getOperation(), derivation.getStatement(), node.getSnapshotIdentifier());
|
||||
script.addAtBeginning(derivation.getOperation(), derivation.getVizUALStatement(), derivation.getSQLStatement(), node.getSnapshotIdentifier());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -50,7 +50,16 @@ public abstract class Operation {
|
|||
* @param snapshot
|
||||
* @return
|
||||
*/
|
||||
public abstract VizUALStatement getStatement(Snapshot snapshot);
|
||||
public abstract VizUALStatement getVizUALStatement(Snapshot snapshot);
|
||||
|
||||
/**
|
||||
* SQL statement representing the operation when applied to the given
|
||||
* snapshot.
|
||||
*
|
||||
* @param snapshot
|
||||
* @return
|
||||
*/
|
||||
public abstract String getSQLStatement(Snapshot snapshot, String tableName);
|
||||
|
||||
/**
|
||||
* Operation type.
|
||||
|
|
|
@ -62,6 +62,7 @@ public enum OperationType {
|
|||
|
||||
DeleteColumn,
|
||||
DeleteRow,
|
||||
Filter,
|
||||
InsertColumn,
|
||||
InsertRow,
|
||||
LoadFile,
|
||||
|
|
|
@ -28,12 +28,14 @@ public class VizUALScript {
|
|||
|
||||
public final Operation op;
|
||||
public final int snapshot;
|
||||
public final String sqlStmt;
|
||||
public final VizUALStatement stmt;
|
||||
|
||||
public ScriptOp(Operation op, VizUALStatement stmt, int snapshot) {
|
||||
public ScriptOp(Operation op, VizUALStatement stmt, String sqlStmt, int snapshot) {
|
||||
|
||||
this.op = op;
|
||||
this.stmt = stmt;
|
||||
this.sqlStmt = sqlStmt;
|
||||
this.snapshot = snapshot;
|
||||
}
|
||||
}
|
||||
|
@ -45,11 +47,25 @@ public class VizUALScript {
|
|||
*
|
||||
* @param operation
|
||||
* @param stmt
|
||||
* @param sqlStmt
|
||||
* @param snapshotIdentifier
|
||||
*/
|
||||
public void addAtBeginning(Operation operation, VizUALStatement stmt, int snapshotIdentifier) {
|
||||
public void addAtBeginning(Operation operation, VizUALStatement stmt, String sqlStmt, int snapshotIdentifier) {
|
||||
|
||||
_ops.addFirst(new ScriptOp(operation, stmt, snapshotIdentifier));
|
||||
_ops.addFirst(new ScriptOp(operation, stmt, sqlStmt, snapshotIdentifier));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an operation to the end of the script.
|
||||
*
|
||||
* @param operation
|
||||
* @param stmt
|
||||
* @param sqlStmt
|
||||
* @param snapshotIdentifier
|
||||
*/
|
||||
public void addAtEnd(Operation operation, VizUALStatement stmt, String sqlStmt, int snapshotIdentifier) {
|
||||
|
||||
_ops.add(new ScriptOp(operation, stmt, sqlStmt, snapshotIdentifier));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -99,11 +115,16 @@ public class VizUALScript {
|
|||
* @param index
|
||||
* @return
|
||||
*/
|
||||
public VizUALStatement getStatement(int index) {
|
||||
public VizUALStatement getVizUALStatement(int index) {
|
||||
|
||||
return _ops.get(index).stmt;
|
||||
}
|
||||
|
||||
public String getSQLStatement(int index) {
|
||||
|
||||
return _ops.get(index).sqlStmt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Number of operations in the script.
|
||||
*
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package org.vizierdb.database.script;
|
||||
|
||||
import org.vizierdb.VizirDBException;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
@ -19,7 +21,7 @@ public class VizualTranslator implements Serializable {
|
|||
|
||||
public static void main(String[] args) throws ParseException {
|
||||
ArrayList<String> script = new ArrayList<>();
|
||||
String test = "move row 2 to 3";
|
||||
String test = "sort rows asc";
|
||||
|
||||
script.add(test);
|
||||
VizualTranslator parser = new VizualTranslator(script);
|
||||
|
@ -54,11 +56,11 @@ public class VizualTranslator implements Serializable {
|
|||
return getVizQL(vizualLine);
|
||||
}
|
||||
|
||||
private void setTableName(String tableName) {
|
||||
public void setTableName(String tableName) {
|
||||
VizualTranslator.tableName = tableName;
|
||||
}
|
||||
|
||||
private String getVizQL(String line) throws ParseException {
|
||||
public String getVizQL(String line) throws ParseException {
|
||||
String firstWord;
|
||||
String constructedSQL;
|
||||
String[] tokens;
|
||||
|
@ -117,13 +119,27 @@ public class VizualTranslator implements Serializable {
|
|||
}
|
||||
break;
|
||||
|
||||
case "SORT": {
|
||||
String order;
|
||||
if (tokens.length == 2) order = "ASC";
|
||||
else if (tokens.length == 3) order = "DESC";
|
||||
else throw new VizualTranslator.ParseException("Unknown sort order.");
|
||||
|
||||
constructedSQL = "UPDATE " + tableName +
|
||||
" SET VIZIER_ROWID = (SELECT NEW_RID FROM" +
|
||||
" (SELECT VIZIER_ROWID AS OLDID, " +
|
||||
" ROW_NUMBER() AS NEW_RID FROM " + tableName +
|
||||
" ORDER BY " + order + ") sub " +
|
||||
" WHERE OLDID = VIZIER_ROWID);";
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new ParseException("Unhandled operation : " + firstWord.toUpperCase());
|
||||
}
|
||||
return constructedSQL;
|
||||
}
|
||||
|
||||
private class ParseException extends Exception implements Serializable {
|
||||
public class ParseException extends Exception implements Serializable {
|
||||
ParseException(String errorMessage) {
|
||||
super(errorMessage);
|
||||
}
|
||||
|
|
|
@ -15,17 +15,18 @@ package org.vizierdb.database.script.op;
|
|||
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import org.apache.commons.csv.CSVFormat;
|
||||
import org.apache.commons.csv.CSVFormat.Predefined;
|
||||
import org.apache.commons.csv.CSVParser;
|
||||
import org.apache.commons.csv.CSVRecord;
|
||||
import org.vizierdb.RequestParameterException;
|
||||
import org.vizierdb.VizirDBException;
|
||||
import org.vizierdb.database.Cell;
|
||||
import org.vizierdb.database.Column;
|
||||
import org.vizierdb.database.CellSet;
|
||||
import org.vizierdb.database.ColumnList;
|
||||
import org.vizierdb.database.value.ConstantValue;
|
||||
import org.vizierdb.database.Notebook;
|
||||
import org.vizierdb.database.RowList;
|
||||
import org.vizierdb.database.Snapshot;
|
||||
|
@ -80,12 +81,30 @@ public class CSVFileLoad extends Operation {
|
|||
_headline = headline;
|
||||
}
|
||||
|
||||
public CSVFileLoad(File file, CSVFormat format, boolean headline) {
|
||||
|
||||
super(OperationType.LoadFile);
|
||||
|
||||
_file = file;
|
||||
_fileName = file.getName();
|
||||
_format = format;
|
||||
_headline = headline;
|
||||
|
||||
String formatName = "UNDEFINED";
|
||||
for (Predefined predefined : CSVFormat.Predefined.values()) {
|
||||
if (predefined.getFormat().equals(format)) {
|
||||
formatName = predefined.name();
|
||||
}
|
||||
}
|
||||
_formatName = formatName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Snapshot exec(Notebook notebook, Snapshot snapshot, int resultIdentifier) throws org.vizierdb.VizirDBException {
|
||||
|
||||
ColumnList columns = new ColumnList();
|
||||
RowList rows = new RowList();
|
||||
ArrayList<Cell> cells = new ArrayList<>();
|
||||
CellSet cells = new CellSet();
|
||||
|
||||
try (CSVParser parser = new CSVParser(new FileReader(_file), _format)) {
|
||||
List<CSVRecord> records = parser.getRecords();
|
||||
|
@ -93,7 +112,11 @@ public class CSVFileLoad extends Operation {
|
|||
if (_headline) {
|
||||
CSVRecord record = records.get(0);
|
||||
for (int iColumn = 0; iColumn < record.size(); iColumn++) {
|
||||
columns.add(new Column(notebook.nextColumnId(), record.get(iColumn)));
|
||||
String columnName = record.get(iColumn).trim();
|
||||
if (columnName.equals("")) {
|
||||
columnName = SpreadsheetHelper.getColumnName(iColumn);
|
||||
}
|
||||
columns.add(notebook.nextColumnId(), columnName);
|
||||
}
|
||||
offset = 1;
|
||||
} else {
|
||||
|
@ -104,7 +127,7 @@ public class CSVFileLoad extends Operation {
|
|||
}
|
||||
}
|
||||
for (int iCol = 0; iCol < maxCols; iCol++) {
|
||||
columns.add(new Column(notebook.nextColumnId(), SpreadsheetHelper.getColumnName(iCol)));
|
||||
columns.add(notebook.nextColumnId(), SpreadsheetHelper.getColumnName(iCol));
|
||||
}
|
||||
}
|
||||
for (int iRecord = offset; iRecord < records.size(); iRecord++) {
|
||||
|
@ -112,7 +135,7 @@ public class CSVFileLoad extends Operation {
|
|||
rows.add(rowId);
|
||||
CSVRecord record = records.get(iRecord);
|
||||
for (int iValue = 0; iValue < Math.min(columns.size(), record.size()); iValue++) {
|
||||
cells.add(new Cell(columns.get(iValue).getIdentifier(), rowId, record.get(iValue)));
|
||||
cells.add(new Cell(columns.get(iValue).getIdentifier(), rowId, new ConstantValue(notebook.nextValueId(), record.get(iValue))));
|
||||
}
|
||||
}
|
||||
} catch (java.io.IOException ioException) {
|
||||
|
@ -173,7 +196,7 @@ public class CSVFileLoad extends Operation {
|
|||
}
|
||||
|
||||
@Override
|
||||
public VizUALStatement getStatement(Snapshot snapshot) {
|
||||
public VizUALStatement getVizUALStatement(Snapshot snapshot) {
|
||||
|
||||
String cmd = "LOAD FILE " + _fileName + " OF TYPE " + _formatName;
|
||||
String html = "<span class=\"cmd-txt\">LOAD FILE</span> <span class=\"cmd-para\">" + _fileName + "</span>";
|
||||
|
@ -191,6 +214,12 @@ public class CSVFileLoad extends Operation {
|
|||
return new VizUALStatement(cmd, html, "LOAD FILE " + _fileName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSQLStatement(Snapshot snapshot, String tableName) {
|
||||
|
||||
return "CREATE TABLE " + tableName + " AS SELECT *, ROWID AS VIZIER_ROWID " + "FROM " + _fileName + ";";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isApplicable(Snapshot snapshot) {
|
||||
|
||||
|
|
|
@ -15,13 +15,27 @@ package org.vizierdb.database.script.op;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import org.parboiled.Parboiled;
|
||||
import org.parboiled.parserunners.ReportingParseRunner;
|
||||
import org.parboiled.support.ParsingResult;
|
||||
import org.vizierdb.RequestParameterException;
|
||||
import org.vizierdb.database.Cell;
|
||||
import org.vizierdb.database.CellCoordinates;
|
||||
import org.vizierdb.database.CellSetFactory;
|
||||
import org.vizierdb.database.Column;
|
||||
import org.vizierdb.database.value.ConstantValue;
|
||||
import org.vizierdb.database.Notebook;
|
||||
import org.vizierdb.database.Snapshot;
|
||||
import org.vizierdb.database.value.Value;
|
||||
import org.vizierdb.database.value.formula.FormulaNode;
|
||||
import org.vizierdb.database.value.formula.FormulaParser;
|
||||
import org.vizierdb.database.script.Operation;
|
||||
import org.vizierdb.database.script.OperationType;
|
||||
import org.vizierdb.database.script.VizUALStatement;
|
||||
import org.vizierdb.database.value.ErrorValue;
|
||||
import org.vizierdb.database.value.FormulaValue;
|
||||
import org.vizierdb.database.value.formula.CellReference;
|
||||
import org.vizierdb.database.value.formula.Formula;
|
||||
|
||||
/**
|
||||
* Update a cell in a notebook snapshot. The cell is identified by the column
|
||||
|
@ -36,6 +50,7 @@ public class CellUpdate extends Operation {
|
|||
public static final String PARAMETER_VALUE = "value";
|
||||
|
||||
private final int _columnId;
|
||||
private String _printValue;
|
||||
private final int _rowId;
|
||||
private final String _value;
|
||||
|
||||
|
@ -77,31 +92,169 @@ public class CellUpdate extends Operation {
|
|||
value = parameters.get(PARAMETER_VALUE);
|
||||
}
|
||||
_value = value;
|
||||
_printValue = value;
|
||||
}
|
||||
|
||||
public CellUpdate(Snapshot snapshot, int column, int row, String value) throws org.vizierdb.RequestParameterException {
|
||||
|
||||
super(OperationType.UpdateCell);
|
||||
|
||||
if ((column < 0) || (column >= snapshot.getColumns().size())) {
|
||||
throw new RequestParameterException(PARAMETER_COLUMN, "Invalid column: " + column);
|
||||
}
|
||||
_columnId = snapshot.getColumns().get(column).getIdentifier();
|
||||
if ((row < 0) || (row >= snapshot.getRows().size())) {
|
||||
throw new RequestParameterException(PARAMETER_ROW, "Invalid row: " + row);
|
||||
}
|
||||
_rowId = snapshot.getRows().get(row);
|
||||
_value = value;
|
||||
_printValue = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Snapshot exec(Notebook notebook, Snapshot snapshot, int resultIdentifier) {
|
||||
|
||||
CellSetFactory cells = new CellSetFactory();
|
||||
|
||||
/*
|
||||
* For new columns or row no cell objects are initially created. Thus,
|
||||
* the cell that is updated may need to be added if it is not contained
|
||||
* in the current set of cells.
|
||||
* Start by finding the updated cell. For new columns or row no cell
|
||||
* objects are initially created. Thus, the cell that is updated may
|
||||
* need to be added if it is not contained in the current set of cells.
|
||||
*/
|
||||
boolean added = false;
|
||||
ArrayList<Cell> cells = new ArrayList<>();
|
||||
Cell updatedCell = null;
|
||||
for (Cell cell : snapshot.getCells()) {
|
||||
if ((cell.getColumnId() == _columnId) && (cell.getRowId() == _rowId)) {
|
||||
cells.add(new Cell(cell.getColumnId(), cell.getRowId(), _value));
|
||||
added = true;
|
||||
updatedCell = cell;
|
||||
} else {
|
||||
cells.add(cell);
|
||||
}
|
||||
}
|
||||
if (!added) {
|
||||
cells.add(new Cell(_columnId, _rowId, _value));
|
||||
|
||||
/*
|
||||
* Identifier of updated cell. If this cell has not been created yet,
|
||||
* assign a new value identifier.
|
||||
*/
|
||||
int valueIdentifier;
|
||||
if (updatedCell != null) {
|
||||
valueIdentifier = updatedCell.getValue().getIdentifier();
|
||||
} else {
|
||||
valueIdentifier = notebook.nextValueId();
|
||||
}
|
||||
|
||||
return new Snapshot(resultIdentifier, snapshot.getColumns(), snapshot.getRows(), cells);
|
||||
/*
|
||||
* Create the new updated value. THis can either be a formula or a
|
||||
* constant value.
|
||||
*/
|
||||
Value value = null;
|
||||
if (_value.trim().startsWith("=")) {
|
||||
/**
|
||||
* New value is a formula. There are four different error conditions
|
||||
* the need to be handled:
|
||||
*
|
||||
* #SYNTAX!: Formula does not match the parsers grammar
|
||||
* #NAME? : Formula contains references to unknown columns or rows
|
||||
* #REF! : Formula introduces circular references (or contains self-reference)
|
||||
* #VALUE! : At least one of the referenced values could not be converted to a number
|
||||
*/
|
||||
FormulaParser<FormulaNode> parser = Parboiled.createParser(FormulaParser.class);
|
||||
ParsingResult<?> result = new ReportingParseRunner(parser.Formula()).run(_value.trim());
|
||||
if (result.matched) {
|
||||
FormulaNode root = (FormulaNode)result.parseTreeRoot.getValue();
|
||||
/*
|
||||
* Get identifier of all values that are associated with cells
|
||||
* that are referenced in the formula.
|
||||
*/
|
||||
ArrayList<Integer> valueReferences = new ArrayList<>();
|
||||
for (CellReference ref : root.getCellReferences()) {
|
||||
CellCoordinates coord = ref.getCoordinates(snapshot);
|
||||
if ((coord.getColumnId() == CellCoordinates.UNKNOWN_COLUMN) || (coord.getRowId() == CellCoordinates.UNKNOWN_ROW)) {
|
||||
// #NAME: Reference to unknown column or row
|
||||
value = new ErrorValue(valueIdentifier, Formula.ERROR_UNKNOWN_NAME, _value);
|
||||
break;
|
||||
} else {
|
||||
Cell cell = cells.get(coord.getKey());
|
||||
if (cell == null) {
|
||||
if ((coord.getColumnId() == _columnId) && (coord.getRowId() == _rowId)) {
|
||||
// #REF: Self-reference
|
||||
value = new ErrorValue(valueIdentifier, Formula.ERROR_INVALID_REFERENCE, _value);
|
||||
break;
|
||||
} else {
|
||||
/*
|
||||
* Reference to empty cell. Create the cell with
|
||||
* an empty value
|
||||
*/
|
||||
cell = new Cell(coord.getColumnId(), coord.getRowId(), new ConstantValue(notebook.nextValueId(), ""));
|
||||
cells.add(cell);
|
||||
}
|
||||
}
|
||||
valueReferences.add(cell.getValue().getIdentifier());
|
||||
ref.setReferencedValue(cell.getValue().getIdentifier());
|
||||
}
|
||||
}
|
||||
/*
|
||||
* The value will still be null if no error condition occurred.
|
||||
*/
|
||||
if (value == null) {
|
||||
/*
|
||||
* Ensure that value references do not create circular
|
||||
* references. The value can only be referenced from
|
||||
* another formula if it previously existed (i.e.,
|
||||
* updatedCell != null);
|
||||
*/
|
||||
if (updatedCell != null) {
|
||||
for (int sourceId : valueReferences) {
|
||||
if (cells.getDependencyGraph().createsCycle(sourceId, valueIdentifier)) {
|
||||
// #REF: Cyclic references
|
||||
value = new ErrorValue(valueIdentifier, Formula.ERROR_INVALID_REFERENCE, _value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Compute the formula value if no cycle was detected.
|
||||
*/
|
||||
if (value == null) {
|
||||
value = new FormulaValue(valueIdentifier, root, valueReferences, cells.getSet());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// #SYNTAX: There was a parse error
|
||||
value = new ErrorValue(valueIdentifier, Formula.ERROR_SYNTAX, _value);
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* New value is a constant value.
|
||||
*/
|
||||
value = new ConstantValue(valueIdentifier, _value);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add the updated cell and create the new snapshot. At this point all
|
||||
* values that depend on the modified value have not been updated.
|
||||
*/
|
||||
cells.add(new Cell(_columnId, _rowId, value));
|
||||
Snapshot nextSnapshot = new Snapshot(resultIdentifier, snapshot.getColumns(), snapshot.getRows(), cells.getSet());
|
||||
|
||||
/*
|
||||
* Get the printable version of the value (requires the snapshot to be
|
||||
* instantiated first).
|
||||
*/
|
||||
if (value.isDerived()) {
|
||||
_printValue = value.getFormula(nextSnapshot);
|
||||
} else {
|
||||
_printValue = _value;
|
||||
}
|
||||
|
||||
/*
|
||||
* Re-evaluate all formulas that depend on the updated value. Use the
|
||||
* wasUpdated() method of the cell factory to ensure that the cell set
|
||||
* which was used to generate the new snapshot is modified.
|
||||
*/
|
||||
if (updatedCell != null) {
|
||||
cells.evalForUpdatedValue(valueIdentifier);
|
||||
}
|
||||
|
||||
return nextSnapshot;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -130,30 +283,51 @@ public class CellUpdate extends Operation {
|
|||
* @return
|
||||
*/
|
||||
public String getValue() {
|
||||
|
||||
return _value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VizUALStatement getStatement(Snapshot snapshot) {
|
||||
public VizUALStatement getVizUALStatement(Snapshot snapshot) {
|
||||
|
||||
String columnName = snapshot.getColumns().getDescriptiveName(_columnId);
|
||||
String rowName = snapshot.getRows().getDescriptiveName(_rowId);
|
||||
|
||||
String shortCmd = "UPDATE CELL [" + columnName + "," + rowName + "]";
|
||||
String cmd = shortCmd + " = ";
|
||||
String html = "<span class=\"cmd-txt\">UPDATE CELL</span> [<span class=\"cmd-para\">" + columnName + "</span>,<span class=\"cmd-para\">" + rowName + "</span>] = ";
|
||||
if (_value != null) {
|
||||
cmd += "'" + _value + "'";
|
||||
html += "\'" + _value + "\'";
|
||||
} else {
|
||||
cmd += "''";
|
||||
html += "\'\'";
|
||||
}
|
||||
String cellReference;
|
||||
String cellReferenceHtml;
|
||||
|
||||
String rowName = snapshot.getRows().getDescriptiveName(_rowId);
|
||||
Column column = snapshot.getColumns().getColumn(_columnId);
|
||||
if (column.hasUniqueName()) {
|
||||
cellReference = "[" + column.getName() + "," + rowName + "]";
|
||||
cellReferenceHtml = "[<span class=\"cmd-para\">" + column.getName() + "</span>,<span class=\"cmd-para\">" + rowName + "</span>]";
|
||||
} else {
|
||||
cellReference = column.getLabel() + rowName;
|
||||
cellReferenceHtml = "<span class=\"cmd-para\">" + cellReference + "</span>";
|
||||
}
|
||||
|
||||
String shortCmd = "UPDATE CELL " + cellReference;
|
||||
String cmd = shortCmd;
|
||||
String html = "<span class=\"cmd-txt\">UPDATE CELL</span> " + cellReferenceHtml;
|
||||
if (_printValue != null) {
|
||||
if (_printValue.trim().startsWith("=")) {
|
||||
cmd += " " + _printValue.trim();
|
||||
html += " " + _printValue.trim();
|
||||
} else {
|
||||
cmd += " = '" + _printValue + "'";
|
||||
html += " = \'" + _printValue + "\'";
|
||||
}
|
||||
} else {
|
||||
cmd += " = ''";
|
||||
html += " = \'\'";
|
||||
}
|
||||
|
||||
return new VizUALStatement(cmd, html, shortCmd);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSQLStatement(Snapshot snapshot, String tableName) {
|
||||
|
||||
return "UPDATE TABLE " + tableName + " SET " + snapshot.getColumns().getColumn(_columnId).getDescriptiveName() + " = '" + _value
|
||||
+ "' WHERE VIZIER_ROWID = " + _rowId + ";";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isApplicable(Snapshot snapshot) {
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@ import java.util.ArrayList;
|
|||
import java.util.HashMap;
|
||||
import org.vizierdb.RequestParameterException;
|
||||
import org.vizierdb.database.Cell;
|
||||
import org.vizierdb.database.CellSetFactory;
|
||||
import org.vizierdb.database.Column;
|
||||
import org.vizierdb.database.ColumnList;
|
||||
import org.vizierdb.database.Notebook;
|
||||
|
@ -58,24 +59,45 @@ public class ColumnDelete extends Operation {
|
|||
_columnId = snapshot.getColumns().get(column).getIdentifier();
|
||||
}
|
||||
|
||||
public ColumnDelete(Snapshot snapshot, int column) throws org.vizierdb.RequestParameterException {
|
||||
|
||||
super(OperationType.DeleteColumn);
|
||||
|
||||
if ((column < 0) || (column >= snapshot.getColumns().size())) {
|
||||
throw new RequestParameterException(PARAMETER_COLUMN, "Invalid column: " + column);
|
||||
}
|
||||
_columnId = snapshot.getColumns().get(column).getIdentifier();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Snapshot exec(Notebook notebook, Snapshot snapshot, int resultIdentifier) {
|
||||
|
||||
ColumnList columns = new ColumnList();
|
||||
for (Column column : snapshot.getColumns()) {
|
||||
if (column.getIdentifier() != _columnId) {
|
||||
columns.add(column);
|
||||
columns.add(column.getIdentifier(), column.getName());
|
||||
}
|
||||
}
|
||||
|
||||
ArrayList<Cell> cells = new ArrayList<>();
|
||||
CellSetFactory cells = new CellSetFactory();
|
||||
ArrayList<Integer> deletedValues = new ArrayList<>();
|
||||
for (Cell cell : snapshot.getCells()) {
|
||||
if (cell.getColumnId() != _columnId) {
|
||||
cells.add(cell);
|
||||
} else {
|
||||
deletedValues.add(cell.getValue().getIdentifier());
|
||||
}
|
||||
}
|
||||
|
||||
return new Snapshot(resultIdentifier, columns, snapshot.getRows(), cells);
|
||||
/*
|
||||
* Create new snapshot and updated values that are depending on values
|
||||
* in the deleted column.
|
||||
*/
|
||||
Snapshot nextSnapshot = new Snapshot(resultIdentifier, columns, snapshot.getRows(), cells.getSet());
|
||||
if (!deletedValues.isEmpty()) {
|
||||
cells.evalForDeletedValues(nextSnapshot, deletedValues);
|
||||
}
|
||||
return nextSnapshot;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -89,14 +111,20 @@ public class ColumnDelete extends Operation {
|
|||
}
|
||||
|
||||
@Override
|
||||
public VizUALStatement getStatement(Snapshot snapshot) {
|
||||
public VizUALStatement getVizUALStatement(Snapshot snapshot) {
|
||||
|
||||
String name = snapshot.getColumns().getDescriptiveName(_columnId);
|
||||
String name = snapshot.getColumns().getColumn(_columnId).getDescriptiveName();
|
||||
String cmd = "DELETE COLUMN " + name;
|
||||
String html = "<span class=\"cmd-txt\">DELETE COLUMN</span> <span class=\"cmd-para\">" + name + "</span>";
|
||||
return new VizUALStatement(cmd, html);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSQLStatement(Snapshot snapshot, String tableName) {
|
||||
|
||||
return "ALTER TABLE " + tableName + " DROP COLUMN " + snapshot.getColumns().getColumn(_columnId).getDescriptiveName() + ";";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isApplicable(Snapshot snapshot) {
|
||||
|
||||
|
|
|
@ -72,22 +72,37 @@ public class ColumnInsert extends Operation {
|
|||
}
|
||||
}
|
||||
|
||||
public ColumnInsert(Snapshot snapshot, int position, String name) throws org.vizierdb.RequestParameterException {
|
||||
|
||||
super(OperationType.InsertColumn);
|
||||
|
||||
_position = position;
|
||||
if ((_position < 0) || (_position > snapshot.getColumns().size())) {
|
||||
throw new RequestParameterException(PARAMETER_POSITION, "Invalid position: " + _position);
|
||||
}
|
||||
if (name.equals("")) {
|
||||
_name = SpreadsheetHelper.getColumnName(_position);
|
||||
} else {
|
||||
_name = name;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Snapshot exec(Notebook notebook, Snapshot snapshot, int resultIdentifier) {
|
||||
|
||||
ColumnList columns = new ColumnList();
|
||||
for (Column column : snapshot.getColumns()) {
|
||||
if (columns.size() == _position) {
|
||||
columns.add(new Column(notebook.nextColumnId(), _name));
|
||||
columns.add(notebook.nextColumnId(), _name);
|
||||
}
|
||||
columns.add(column);
|
||||
columns.add(column.getIdentifier(), column.getName());
|
||||
}
|
||||
/**
|
||||
* Column may not have been added if the position equals the size of the
|
||||
* column list.
|
||||
*/
|
||||
if (columns.size() == _position) {
|
||||
columns.add(new Column(notebook.nextColumnId(), _name));
|
||||
columns.add(notebook.nextColumnId(), _name);
|
||||
}
|
||||
|
||||
return new Snapshot(resultIdentifier, columns, snapshot.getRows(), snapshot.getCells());
|
||||
|
@ -114,7 +129,7 @@ public class ColumnInsert extends Operation {
|
|||
}
|
||||
|
||||
@Override
|
||||
public VizUALStatement getStatement(Snapshot snapshot) {
|
||||
public VizUALStatement getVizUALStatement(Snapshot snapshot) {
|
||||
|
||||
String cmd = "INSERT COLUMN " + _name + " AT POSITION " + _position;
|
||||
String html = "<span class=\"cmd-txt\">INSERT COLUMN <span class=\"cmd-para\">" + _name + "</span> AT POSITION <span class=\"cmd-para\">" + _position + "</span>";
|
||||
|
@ -122,6 +137,12 @@ public class ColumnInsert extends Operation {
|
|||
return new VizUALStatement(cmd, html, "INSERT COLUMN " + _name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSQLStatement(Snapshot snapshot, String tableName) {
|
||||
|
||||
return "ALTER TABLE " + tableName + " ADD COLUMN " + _name + " CHAR(100);";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isApplicable(Snapshot snapshot) {
|
||||
|
||||
|
|
|
@ -70,6 +70,21 @@ public class ColumnMove extends Operation {
|
|||
}
|
||||
}
|
||||
|
||||
public ColumnMove(Snapshot snapshot, int column, int position) throws org.vizierdb.RequestParameterException {
|
||||
|
||||
super(OperationType.MoveColumn);
|
||||
|
||||
if ((column < 0) || (column >= snapshot.getColumns().size())) {
|
||||
throw new RequestParameterException(PARAMETER_COLUMN, "Invalid column: " + column);
|
||||
}
|
||||
_columnId = snapshot.getColumns().get(column).getIdentifier();
|
||||
|
||||
_position = position;
|
||||
if ((_position < 0) || (_position > snapshot.getColumns().size())) {
|
||||
throw new RequestParameterException(PARAMETER_POSITION, "Invalid target column: " + _position);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Snapshot exec(Notebook notebook, Snapshot snapshot, int resultIdentifier) {
|
||||
|
||||
|
@ -81,22 +96,25 @@ public class ColumnMove extends Operation {
|
|||
for (int iColumn = 0; iColumn < currentColumns.size(); iColumn++) {
|
||||
if (iColumn == _position) {
|
||||
if (columnIndex < _position) {
|
||||
modifiedColumns.add(currentColumns.get(iColumn));
|
||||
modifiedColumns.add(column);
|
||||
Column mColumn = currentColumns.get(iColumn);
|
||||
modifiedColumns.add(mColumn.getIdentifier(), mColumn.getName());
|
||||
modifiedColumns.add(column.getIdentifier(), column.getName());
|
||||
} else {
|
||||
modifiedColumns.add(column);
|
||||
modifiedColumns.add(currentColumns.get(iColumn));
|
||||
modifiedColumns.add(column.getIdentifier(), column.getName());
|
||||
Column mColumn = currentColumns.get(iColumn);
|
||||
modifiedColumns.add(mColumn.getIdentifier(), mColumn.getName());
|
||||
}
|
||||
} else if (iColumn != columnIndex) {
|
||||
modifiedColumns.add(currentColumns.get(iColumn));
|
||||
Column mColumn = currentColumns.get(iColumn);
|
||||
modifiedColumns.add(mColumn.getIdentifier(), mColumn.getName());
|
||||
}
|
||||
}
|
||||
if (_position == currentColumns.size()) {
|
||||
modifiedColumns.add(column);
|
||||
modifiedColumns.add(column.getIdentifier(), column.getName());
|
||||
}
|
||||
} else {
|
||||
for (Column column : currentColumns) {
|
||||
modifiedColumns.add(column);
|
||||
modifiedColumns.add(column.getIdentifier(), column.getName());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -124,15 +142,20 @@ public class ColumnMove extends Operation {
|
|||
}
|
||||
|
||||
@Override
|
||||
public VizUALStatement getStatement(Snapshot snapshot) {
|
||||
public VizUALStatement getVizUALStatement(Snapshot snapshot) {
|
||||
|
||||
String columnName = snapshot.getColumns().getDescriptiveName(_columnId);
|
||||
String columnName = snapshot.getColumns().getColumn(_columnId).getDescriptiveName();
|
||||
String cmd = "MOVE COLUMN " + columnName + " TO POSITION " + _position;
|
||||
String html = "<span class=\"cmd-txt\">MOVE COLUMN</span> <span class=\"cmd-para\">" + columnName + "</span> TO POSITION <span class=\"cmd-para\">" + _position + "</span>";
|
||||
|
||||
return new VizUALStatement(cmd, html, "MOVE COLUMN " + columnName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSQLStatement(Snapshot snapshot, String tableName) {
|
||||
return "UNDEFINED: MOVE COLUMN";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isApplicable(Snapshot snapshot) {
|
||||
|
||||
|
|
|
@ -60,7 +60,19 @@ public class ColumnRename extends Operation {
|
|||
if (parameters.containsKey(PARAMETER_NAME)) {
|
||||
name = parameters.get(PARAMETER_NAME);
|
||||
}
|
||||
_name = name;
|
||||
_name = name.trim();
|
||||
}
|
||||
|
||||
public ColumnRename(Snapshot snapshot, int column, String name) throws org.vizierdb.RequestParameterException {
|
||||
|
||||
super(OperationType.RenameColumn);
|
||||
|
||||
if ((column < 0) || (column >= snapshot.getColumns().size())) {
|
||||
throw new RequestParameterException(PARAMETER_COLUMN, "Invalid column: " + column);
|
||||
}
|
||||
_columnId = snapshot.getColumns().get(column).getIdentifier();
|
||||
|
||||
_name = name.trim();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -69,9 +81,9 @@ public class ColumnRename extends Operation {
|
|||
ColumnList columns = new ColumnList();
|
||||
for (Column column : snapshot.getColumns()) {
|
||||
if (column.getIdentifier() == _columnId) {
|
||||
columns.add(new Column(column.getIdentifier(), _name));
|
||||
columns.add(column.getIdentifier(), _name);
|
||||
} else {
|
||||
columns.add(column);
|
||||
columns.add(column.getIdentifier(), column.getName());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -99,15 +111,21 @@ public class ColumnRename extends Operation {
|
|||
}
|
||||
|
||||
@Override
|
||||
public VizUALStatement getStatement(Snapshot snapshot) {
|
||||
public VizUALStatement getVizUALStatement(Snapshot snapshot) {
|
||||
|
||||
String columnName = snapshot.getColumns().getDescriptiveName(_columnId);
|
||||
String columnName = snapshot.getColumns().getColumn(_columnId).getDescriptiveName();
|
||||
String cmd = "RENAME COLUMN " + columnName + " AS " + _name;
|
||||
String html = "<span class=\"cmd-txt\">RENAME COLUMN </span> <span class=\"cmd-para\">" + columnName + "</span> AS <span class=\"cmd-para\">" + _name + "</span>";
|
||||
|
||||
return new VizUALStatement(cmd, html, "RENAME COLUMN " + columnName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSQLStatement(Snapshot snapshot, String tableName) {
|
||||
|
||||
return "ALTER TABLE " + tableName + " RENAME COLUMN " + snapshot.getColumns().getColumn(_columnId).getDescriptiveName() + " TO " + _name + ";";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isApplicable(Snapshot snapshot) {
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@ import java.util.ArrayList;
|
|||
import java.util.HashMap;
|
||||
import org.vizierdb.RequestParameterException;
|
||||
import org.vizierdb.database.Cell;
|
||||
import org.vizierdb.database.CellSetFactory;
|
||||
import org.vizierdb.database.Notebook;
|
||||
import org.vizierdb.database.RowList;
|
||||
import org.vizierdb.database.Snapshot;
|
||||
|
@ -57,6 +58,16 @@ public class RowDelete extends Operation {
|
|||
_rowId = snapshot.getRows().get(row);
|
||||
}
|
||||
|
||||
public RowDelete(Snapshot snapshot, int row) throws org.vizierdb.RequestParameterException {
|
||||
|
||||
super(OperationType.DeleteRow);
|
||||
|
||||
if ((row < 0) || (row >= snapshot.getRows().size())) {
|
||||
throw new RequestParameterException(PARAMETER_ROW, "Invalid row: " + row);
|
||||
}
|
||||
_rowId = snapshot.getRows().get(row);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Snapshot exec(Notebook notebook, Snapshot snapshot, int resultIdentifier) {
|
||||
|
||||
|
@ -68,13 +79,24 @@ public class RowDelete extends Operation {
|
|||
}
|
||||
|
||||
if (rows.size() != snapshot.getRows().size()) {
|
||||
ArrayList<Cell> cells = new ArrayList<>();
|
||||
CellSetFactory cells = new CellSetFactory();
|
||||
ArrayList<Integer> deletedValues = new ArrayList<>();
|
||||
for (Cell cell : snapshot.getCells()) {
|
||||
if (cell.getRowId() != _rowId) {
|
||||
cells.add(cell);
|
||||
} else {
|
||||
deletedValues.add(cell.getValue().getIdentifier());
|
||||
}
|
||||
}
|
||||
return new Snapshot(resultIdentifier, snapshot.getColumns(), rows, cells);
|
||||
/*
|
||||
* Create new snapshot and update values that depend on values in
|
||||
* the deleted row.
|
||||
*/
|
||||
Snapshot nextSnapshot = new Snapshot(resultIdentifier, snapshot.getColumns(), rows, cells.getSet());
|
||||
if (!deletedValues.isEmpty()) {
|
||||
cells.evalForDeletedValues(nextSnapshot, deletedValues);
|
||||
}
|
||||
return nextSnapshot;
|
||||
} else {
|
||||
return new Snapshot(resultIdentifier, snapshot.getColumns(), snapshot.getRows(), snapshot.getCells());
|
||||
}
|
||||
|
@ -91,7 +113,7 @@ public class RowDelete extends Operation {
|
|||
}
|
||||
|
||||
@Override
|
||||
public VizUALStatement getStatement(Snapshot snapshot) {
|
||||
public VizUALStatement getVizUALStatement(Snapshot snapshot) {
|
||||
|
||||
String rowName = snapshot.getRows().getDescriptiveName(_rowId);
|
||||
String cmd = "DELETE ROW " + rowName;
|
||||
|
@ -100,6 +122,12 @@ public class RowDelete extends Operation {
|
|||
return new VizUALStatement(cmd, html);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSQLStatement(Snapshot snapshot, String tableName) {
|
||||
|
||||
return "DELETE FROM " + tableName + " WHERE VIZIER_ROWID = " + _rowId + ";";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isApplicable(Snapshot snapshot) {
|
||||
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.vizierdb.database.script.op;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import org.vizierdb.database.Cell;
|
||||
import org.vizierdb.database.CellSetFactory;
|
||||
import org.vizierdb.database.Notebook;
|
||||
import org.vizierdb.database.Row;
|
||||
import org.vizierdb.database.RowList;
|
||||
import org.vizierdb.database.Snapshot;
|
||||
import org.vizierdb.database.filter.Condition;
|
||||
import org.vizierdb.database.script.Operation;
|
||||
import org.vizierdb.database.script.OperationType;
|
||||
import org.vizierdb.database.script.VizUALStatement;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author heiko
|
||||
*/
|
||||
public class RowFilter extends Operation {
|
||||
|
||||
private final Condition _filter;
|
||||
|
||||
public RowFilter(Condition filter) {
|
||||
|
||||
super(OperationType.Filter);
|
||||
|
||||
_filter = filter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Snapshot exec(Notebook notebook, Snapshot snapshot, int resultIdentifier) {
|
||||
|
||||
RowList rows = new RowList();
|
||||
for (int rowId : snapshot.getRows()) {
|
||||
Row row = new Row(rowId, snapshot.getCells());
|
||||
if (_filter.eval(row)) {
|
||||
rows.add(rowId);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
CellSetFactory cells = new CellSetFactory();
|
||||
ArrayList<Integer> deletedValues = new ArrayList<>();
|
||||
for (Cell cell : snapshot.getCells()) {
|
||||
if (rows.contains(cell.getRowId())) {
|
||||
cells.add(cell);
|
||||
} else {
|
||||
deletedValues.add(cell.getValue().getIdentifier());
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Create new snapshot and update values that depend on values in
|
||||
* the deleted row.
|
||||
*/
|
||||
Snapshot nextSnapshot = new Snapshot(resultIdentifier, snapshot.getColumns(), rows, cells.getSet());
|
||||
if (!deletedValues.isEmpty()) {
|
||||
cells.evalForDeletedValues(nextSnapshot, deletedValues);
|
||||
}
|
||||
return nextSnapshot;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VizUALStatement getVizUALStatement(Snapshot snapshot) {
|
||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSQLStatement(Snapshot snapshot, String tableName) {
|
||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isApplicable(Snapshot snapshot) {
|
||||
|
||||
return _filter.isApplicable(snapshot.getColumns());
|
||||
}
|
||||
}
|
|
@ -15,6 +15,7 @@ package org.vizierdb.database.script.op;
|
|||
|
||||
import java.util.HashMap;
|
||||
import org.vizierdb.RequestParameterException;
|
||||
import org.vizierdb.database.Column;
|
||||
import org.vizierdb.database.Notebook;
|
||||
import org.vizierdb.database.RowList;
|
||||
import org.vizierdb.database.Snapshot;
|
||||
|
@ -53,6 +54,16 @@ public class RowInsert extends Operation {
|
|||
}
|
||||
}
|
||||
|
||||
public RowInsert(Snapshot snapshot, int position) throws org.vizierdb.RequestParameterException {
|
||||
|
||||
super(OperationType.InsertRow);
|
||||
|
||||
_position = position;
|
||||
if ((_position < 0) || (_position > snapshot.getRows().size())) {
|
||||
throw new RequestParameterException(PARAMETER_POSITION, "Invalid position: " + _position);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Snapshot exec(Notebook notebook, Snapshot snapshot, int resultIdentifier) {
|
||||
|
||||
|
@ -85,7 +96,7 @@ public class RowInsert extends Operation {
|
|||
}
|
||||
|
||||
@Override
|
||||
public VizUALStatement getStatement(Snapshot snapshot) {
|
||||
public VizUALStatement getVizUALStatement(Snapshot snapshot) {
|
||||
|
||||
String cmd = "INSERT ROW AT POSITION " + _position;
|
||||
String html = "<span class=\"cmd-txt\">INSERT ROW</span> AT POSITION <span class=\"cmd-para\">" + _position + "</span>";
|
||||
|
@ -93,6 +104,18 @@ public class RowInsert extends Operation {
|
|||
return new VizUALStatement(cmd, html);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSQLStatement(Snapshot snapshot, String tableName) {
|
||||
|
||||
String columnList = "VIZIER_ROWID";
|
||||
String valueList = Integer.toString(snapshot.getRows().size());
|
||||
for (Column column : snapshot.getColumns()) {
|
||||
columnList = columnList + ", " + column.getDescriptiveName();
|
||||
valueList = valueList + ", ''";
|
||||
}
|
||||
return "INSERT INTO " + tableName + "(" + columnList + ") VALUES(" + valueList + ");";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isApplicable(Snapshot snapshot) {
|
||||
|
||||
|
|
|
@ -69,6 +69,21 @@ public class RowMove extends Operation {
|
|||
}
|
||||
}
|
||||
|
||||
public RowMove(Snapshot snapshot, int row, int position) throws org.vizierdb.RequestParameterException {
|
||||
|
||||
super(OperationType.MoveRow);
|
||||
|
||||
if ((row < 0) || (row >= snapshot.getRows().size())) {
|
||||
throw new RequestParameterException(PARAMETER_ROW, "Invalid row: " + row);
|
||||
}
|
||||
_rowId = snapshot.getRows().get(row);
|
||||
|
||||
_position = position;
|
||||
if ((_position < 0) || (_position > snapshot.getRows().size())) {
|
||||
throw new RequestParameterException(PARAMETER_POSITION, "Invalid target row: " + _position);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Snapshot exec(Notebook notebook, Snapshot snapshot, int resultIdentifier) {
|
||||
|
||||
|
@ -123,7 +138,7 @@ public class RowMove extends Operation {
|
|||
}
|
||||
|
||||
@Override
|
||||
public VizUALStatement getStatement(Snapshot snapshot) {
|
||||
public VizUALStatement getVizUALStatement(Snapshot snapshot) {
|
||||
|
||||
String rowName = snapshot.getRows().getDescriptiveName(_rowId);
|
||||
String cmd = "MOVE ROW " + rowName + " TO POSITION " + _position;
|
||||
|
@ -132,6 +147,11 @@ public class RowMove extends Operation {
|
|||
return new VizUALStatement(cmd, html, "MOVE ROW " + rowName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSQLStatement(Snapshot snapshot, String tableName) {
|
||||
return "UNDEFINED: MOVE ROW";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isApplicable(Snapshot snapshot) {
|
||||
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.vizierdb.database.value;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.vizierdb.database.CellSet;
|
||||
import org.vizierdb.database.Snapshot;
|
||||
|
||||
/**
|
||||
* Constant cell value. For constant values the formula is basically the value.
|
||||
* The formula flag is set to false although the formula value will not be null.
|
||||
*
|
||||
* @author Heiko Mueller
|
||||
*/
|
||||
public class ConstantValue extends Value {
|
||||
|
||||
private final String _value;
|
||||
|
||||
public ConstantValue(int identifier, String value) {
|
||||
|
||||
super(identifier);
|
||||
|
||||
_value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Value eval(CellSet cells) {
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BigDecimal getAsBigDecimal() {
|
||||
|
||||
return new BigDecimal(_value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAsString() {
|
||||
|
||||
return _value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Integer> getDependencies() {
|
||||
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFormula(Snapshot snapshot) {
|
||||
|
||||
return this.getAsString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDerived() {
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,153 @@
|
|||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.vizierdb.database.value;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Graph containing information about derivation dependencies for values as
|
||||
* defined by their formulas. An edge source -> target indicates that source
|
||||
* uses target (or depends on target).
|
||||
*
|
||||
* @author Heiko Mueller
|
||||
*/
|
||||
public class DependencyGraph {
|
||||
|
||||
private final HashMap<Integer, HashSet<Integer>> _incomingEdges = new HashMap<>();
|
||||
private final HashMap<Integer, HashSet<Integer>> _outgoingEdges = new HashMap<>();
|
||||
|
||||
public void addEdge(int source, int target) {
|
||||
|
||||
this.addEdge(source, target, _outgoingEdges);
|
||||
this.addEdge(target, source, _incomingEdges);
|
||||
}
|
||||
|
||||
private void addEdge(int node, int target, HashMap<Integer, HashSet<Integer>> edges) {
|
||||
|
||||
HashSet<Integer> references;
|
||||
if (edges.containsKey(node)) {
|
||||
references = edges.get(node);
|
||||
} else {
|
||||
references = new HashSet<>();
|
||||
edges.put(node, references);
|
||||
}
|
||||
references.add(target);
|
||||
}
|
||||
|
||||
/**
|
||||
* True, if inserting the given edge will create a cycle. Note, this assumes
|
||||
* that the graph is acyclic at the moment. Checks whether there exists a
|
||||
* path from the target to the source.
|
||||
*
|
||||
* @param source
|
||||
* @param target
|
||||
* @return
|
||||
*/
|
||||
public boolean createsCycle(int source, int target) {
|
||||
|
||||
HashSet<Integer> reachable = new HashSet<>();
|
||||
reachable.add(target);
|
||||
this.getReachableNodes(target, reachable, source);
|
||||
return reachable.contains(source);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a topologically sorted list of nodes that depend on the given
|
||||
* target. Note, that this operation will modify the graph by removing
|
||||
* edges!
|
||||
*
|
||||
* @param target
|
||||
* @return
|
||||
*/
|
||||
public List<Integer> getDependentValues(int target) {
|
||||
|
||||
/**
|
||||
* Find all start nodes reachable from the target
|
||||
*/
|
||||
HashSet<Integer> nodes = new HashSet<>();
|
||||
ArrayList<Integer> startNodes = new ArrayList<>();
|
||||
|
||||
if (_incomingEdges.containsKey(target)) {
|
||||
this.getIncomingNodes(target, nodes, startNodes);
|
||||
}
|
||||
|
||||
ArrayList<Integer> result = new ArrayList<>();
|
||||
while (!startNodes.isEmpty()) {
|
||||
int node = startNodes.remove(0);
|
||||
result.add(node);
|
||||
HashSet<Integer> outEdges = _outgoingEdges.get(node);
|
||||
if (outEdges != null) {
|
||||
for (int nextNode : outEdges) {
|
||||
HashSet<Integer> inEdges = _incomingEdges.get(nextNode);
|
||||
inEdges.remove(node);
|
||||
if ((inEdges.isEmpty()) && (nextNode != target)) {
|
||||
startNodes.add(nextNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Collections.reverse(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* List all values that depend directly on the value with the given
|
||||
* identifier.
|
||||
*
|
||||
* @param valueId
|
||||
* @return
|
||||
*/
|
||||
public List<Integer> getDirectDependentValues(int valueId) {
|
||||
|
||||
if (_incomingEdges.containsKey(valueId)) {
|
||||
return new ArrayList<>(_incomingEdges.get(valueId));
|
||||
} else {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
}
|
||||
|
||||
private void getIncomingNodes(int target, HashSet<Integer> nodes, ArrayList<Integer> startNodes) {
|
||||
|
||||
for (int source : _incomingEdges.get(target)) {
|
||||
nodes.add(source);
|
||||
if (_incomingEdges.containsKey(source)) {
|
||||
this.getIncomingNodes(source, nodes, startNodes);
|
||||
} else {
|
||||
startNodes.add(source);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void getReachableNodes(int source, HashSet<Integer> visited, int aimedTarget) {
|
||||
|
||||
if (_outgoingEdges.containsKey(source)) {
|
||||
for (int target : _outgoingEdges.get(source)) {
|
||||
if (!visited.contains(target)) {
|
||||
visited.add(target);
|
||||
if (target == aimedTarget) {
|
||||
return;
|
||||
}
|
||||
this.getReachableNodes(target, visited, aimedTarget);
|
||||
if (visited.contains(aimedTarget)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.vizierdb.database.value;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.vizierdb.database.CellSet;
|
||||
import org.vizierdb.database.Snapshot;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author heiko
|
||||
*/
|
||||
public class ErrorValue extends Value {
|
||||
|
||||
private final String _formula;
|
||||
private final String _message;
|
||||
|
||||
public ErrorValue(int identifier, String message, String formula) {
|
||||
|
||||
super(identifier);
|
||||
|
||||
_message = message;
|
||||
_formula = formula;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Value eval(CellSet cells) {
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BigDecimal getAsBigDecimal() {
|
||||
|
||||
throw new java.lang.NumberFormatException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAsString() {
|
||||
|
||||
return _message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Integer> getDependencies() {
|
||||
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFormula(Snapshot snapshot) {
|
||||
|
||||
return _formula;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDerived() {
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.vizierdb.database.value;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
import org.vizierdb.database.CellSet;
|
||||
import org.vizierdb.database.Snapshot;
|
||||
import org.vizierdb.database.value.formula.Formula;
|
||||
import org.vizierdb.database.value.formula.FormulaNode;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author heiko
|
||||
*/
|
||||
public class FormulaValue extends Value {
|
||||
|
||||
private final List<Integer> _dependencies;
|
||||
private final FormulaNode _formula;
|
||||
private final BigDecimal _value;
|
||||
private String _text;
|
||||
|
||||
public FormulaValue(int valueIdentifier, FormulaNode formula, List<Integer> dependencies, CellSet cells) {
|
||||
|
||||
super(valueIdentifier);
|
||||
|
||||
_formula = formula;
|
||||
_dependencies = dependencies;
|
||||
|
||||
BigDecimal value = null;
|
||||
try {
|
||||
value = _formula.eval(cells);
|
||||
if (value != null) {
|
||||
_text = value.toPlainString();
|
||||
}
|
||||
} catch (java.lang.NumberFormatException | java.lang.ArithmeticException ex) {
|
||||
_text = Formula.ERROR_NOT_A_NUMBER;
|
||||
}
|
||||
_value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Value eval(CellSet cells) {
|
||||
|
||||
return new FormulaValue(this.getIdentifier(), _formula, _dependencies, cells);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BigDecimal getAsBigDecimal() {
|
||||
|
||||
if ((_value == null) && (_text.equals(Formula.ERROR_NOT_A_NUMBER))) {
|
||||
throw new java.lang.NumberFormatException();
|
||||
} else {
|
||||
return _value;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAsString() {
|
||||
|
||||
return _text;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Integer> getDependencies() {
|
||||
|
||||
return _dependencies;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFormula(Snapshot snapshot) {
|
||||
|
||||
return "=" + _formula.toExternalForm(snapshot);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDerived() {
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.vizierdb.database.value;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
import org.vizierdb.database.CellSet;
|
||||
import org.vizierdb.database.Snapshot;
|
||||
|
||||
/**
|
||||
* A value in a spreadsheet cell. Each value has a unique identifier. THe value
|
||||
* is either a constant or a formula.
|
||||
*
|
||||
* @author Heiko Mueller
|
||||
*/
|
||||
public abstract class Value {
|
||||
|
||||
private final int _identifier;
|
||||
|
||||
public Value(int identifier) {
|
||||
|
||||
_identifier = identifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate a formula. Only in effect for formula values. Returns the
|
||||
* new value.
|
||||
*
|
||||
* @param cells
|
||||
* @return
|
||||
*/
|
||||
public abstract Value eval(CellSet cells);
|
||||
|
||||
/**
|
||||
* List of value identifier that this value is derived from.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public abstract List<Integer> getDependencies();
|
||||
|
||||
/**
|
||||
* The value as BigDecimal. May throw a NumberFormatException.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public abstract BigDecimal getAsBigDecimal();
|
||||
|
||||
/**
|
||||
* Text representation of the value.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public abstract String getAsString();
|
||||
|
||||
/**
|
||||
* Text representation of the values formula. The value is the same as the
|
||||
* text for constant values.
|
||||
*
|
||||
* @param snapshot
|
||||
* @return
|
||||
*/
|
||||
public abstract String getFormula(Snapshot snapshot);
|
||||
|
||||
/**
|
||||
* Unique value identifier.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public int getIdentifier() {
|
||||
|
||||
return _identifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* Flag indicating whether the value is constant (false) or derived using
|
||||
* a formula (true).
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public abstract boolean isDerived();
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.vizierdb.database.value.formula;
|
||||
|
||||
import org.vizierdb.database.CellCoordinates;
|
||||
import org.vizierdb.database.Snapshot;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author heiko
|
||||
*/
|
||||
public interface CellReference {
|
||||
|
||||
/**
|
||||
* The coordinates for the reference cell in the given snapshot. If either
|
||||
* the referenced column or row are invalid the respective coordinate is
|
||||
* UNKNOWN.
|
||||
*
|
||||
* @param snapshot
|
||||
* @return
|
||||
*/
|
||||
public CellCoordinates getCoordinates(Snapshot snapshot);
|
||||
|
||||
/**
|
||||
* Set the identifier of the value that is associated with the referenced
|
||||
* cell.
|
||||
*
|
||||
* @param valueIdentifier
|
||||
*/
|
||||
public void setReferencedValue(int valueIdentifier);
|
||||
}
|
|
@ -0,0 +1,108 @@
|
|||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.vizierdb.database.value.formula;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.vizierdb.database.CellCoordinates;
|
||||
import org.vizierdb.database.CellSet;
|
||||
import org.vizierdb.database.Column;
|
||||
import org.vizierdb.database.Snapshot;
|
||||
import org.vizierdb.database.value.Value;
|
||||
import org.vizierdb.util.SpreadsheetHelper;
|
||||
|
||||
/**
|
||||
* Cell reference in formula. The column may be a reference to the name of a
|
||||
* column in the spreadsheet or a spreadsheet column identifier.
|
||||
*
|
||||
* @author Heiko Mueller
|
||||
*/
|
||||
public class CellReferenceNode extends FormulaNode implements CellReference {
|
||||
|
||||
private final String _col;
|
||||
private final boolean _isColumnName;
|
||||
private int _referencedValueIdentifier = -1;
|
||||
private final int _row;
|
||||
|
||||
public CellReferenceNode(String col, int row, boolean isColumnName) {
|
||||
|
||||
super(null, null);
|
||||
|
||||
_col = col;
|
||||
_row = row;
|
||||
_isColumnName = isColumnName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BigDecimal eval(CellSet cells) {
|
||||
|
||||
Value ref = cells.getValue(_referencedValueIdentifier);
|
||||
if (ref != null) {
|
||||
return ref.getAsBigDecimal();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CellReference> getCellReferences() {
|
||||
|
||||
ArrayList<CellReference> references = new ArrayList<>();
|
||||
references.add(this);
|
||||
return references;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CellCoordinates getCoordinates(Snapshot snapshot) {
|
||||
|
||||
int columnId = CellCoordinates.UNKNOWN_COLUMN;
|
||||
int rowId = CellCoordinates.UNKNOWN_ROW;
|
||||
if ((_row >= 0) && (_row < snapshot.getRows().size())) {
|
||||
rowId = snapshot.getRows().get(_row);
|
||||
if (_isColumnName) {
|
||||
columnId = snapshot.getColumns().getIdentifierOf(_col);
|
||||
} else {
|
||||
int columnIndex = SpreadsheetHelper.getColumnIndex(_col);
|
||||
if ((columnIndex >= 0) && (columnIndex < snapshot.getColumns().size())) {
|
||||
columnId = snapshot.getColumns().get(columnIndex).getIdentifier();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new CellCoordinates(columnId, rowId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setReferencedValue(int valueIdentifier) {
|
||||
|
||||
_referencedValueIdentifier = valueIdentifier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toExternalForm(Snapshot snapshot) {
|
||||
|
||||
CellCoordinates cell = snapshot.getCells().getCellForValue(_referencedValueIdentifier);
|
||||
if (cell != null) {
|
||||
Column column = snapshot.getColumns().getColumn(cell.getColumnId());
|
||||
if (column.hasUniqueName()) {
|
||||
return "[" + column.getName() + "," + snapshot.getRows().getDescriptiveName(cell.getRowId()) + "]";
|
||||
} else {
|
||||
return column.getLabel() + snapshot.getRows().getDescriptiveName(cell.getRowId());
|
||||
}
|
||||
} else {
|
||||
return Formula.ERROR_UNKNOWN_NAME;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.vizierdb.database.value.formula;
|
||||
|
||||
/**
|
||||
* Collection of constants for formulas.
|
||||
*
|
||||
* @author Heiko Mueller
|
||||
*/
|
||||
public final class Formula {
|
||||
|
||||
public static final String ERROR_INVALID_REFERENCE = "#REF!";
|
||||
public static final String ERROR_NOT_A_NUMBER = "#VALUE!";
|
||||
public static final String ERROR_SYNTAX = "#SYNTAX!";
|
||||
public static final String ERROR_UNKNOWN_NAME = "#NAME?";
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.vizierdb.database.value.formula;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
import org.parboiled.trees.ImmutableBinaryTreeNode;
|
||||
import org.vizierdb.database.CellSet;
|
||||
import org.vizierdb.database.Snapshot;
|
||||
|
||||
/**
|
||||
* The AST node for spreadsheet cell formulas. Internal nodes are operators
|
||||
* while leave nodes represent scalars. These can either be constant values
|
||||
* or cell references.
|
||||
*/
|
||||
public abstract class FormulaNode extends ImmutableBinaryTreeNode<FormulaNode> {
|
||||
|
||||
public FormulaNode(FormulaNode left, FormulaNode right) {
|
||||
|
||||
super(left, right);
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluates the formula. Returns null if any of the referenced cells is
|
||||
* empty. Throws NuberFormatException if any of the referenced values is
|
||||
* not a number.
|
||||
*
|
||||
* @param cells
|
||||
* @return
|
||||
*/
|
||||
public abstract BigDecimal eval(CellSet cells);
|
||||
|
||||
/**
|
||||
* List of all cell references by this node and all of it's
|
||||
* children.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public abstract List<CellReference> getCellReferences();
|
||||
|
||||
/**
|
||||
* String representation of the formula for a given snapshot.
|
||||
*
|
||||
* @param snapshot
|
||||
* @return
|
||||
*/
|
||||
public abstract String toExternalForm(Snapshot snapshot);
|
||||
}
|
|
@ -0,0 +1,181 @@
|
|||
/*
|
||||
* Copyright (C) 2009-2011 Mathias Doenitz
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.vizierdb.database.value.formula;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import org.parboiled.BaseParser;
|
||||
import org.parboiled.Rule;
|
||||
import org.parboiled.annotations.BuildParseTree;
|
||||
import org.parboiled.support.Var;
|
||||
|
||||
/**
|
||||
* A calculator parser building an AST representing the expression structure before performing the actual calculation.
|
||||
* The value field of the parse tree nodes is used for AST nodes.
|
||||
* As opposed to the CalculatorParser2 this parser also supports floating point operations, negative numbers, a "power"
|
||||
* and a "SQRT" operation as well as optional whitespace between the various expressions components.
|
||||
* @param <V>
|
||||
*/
|
||||
@BuildParseTree
|
||||
public class FormulaParser<V> extends BaseParser<FormulaNode> {
|
||||
|
||||
public Rule Formula() {
|
||||
|
||||
return Sequence(
|
||||
'=',
|
||||
Optional(Whitespace()),
|
||||
Expression(),
|
||||
EOI
|
||||
);
|
||||
}
|
||||
|
||||
public Rule Expression() {
|
||||
|
||||
Var<Character> op = new Var<>();
|
||||
return Sequence(
|
||||
Term(),
|
||||
ZeroOrMore(
|
||||
Optional(Whitespace()),
|
||||
FirstOf('+', '-'),
|
||||
op.set(matchedChar()),
|
||||
Optional(Whitespace()),
|
||||
Term(),
|
||||
push(new OpNode(op.get(), pop(1), pop()))
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public Rule Term() {
|
||||
|
||||
Var<Character> op = new Var<>();
|
||||
return Sequence(
|
||||
Factor(),
|
||||
ZeroOrMore(
|
||||
Optional(Whitespace()),
|
||||
FirstOf('*', '/'),
|
||||
op.set(matchedChar()),
|
||||
Optional(Whitespace()),
|
||||
Factor(),
|
||||
push(new OpNode(op.get(), pop(1), pop()))
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public Rule Factor() {
|
||||
|
||||
return Sequence(
|
||||
Atom(),
|
||||
ZeroOrMore(
|
||||
Optional(Whitespace()),
|
||||
'^',
|
||||
Optional(Whitespace()),
|
||||
Atom(),
|
||||
push(new OpNode('^', pop(1), pop()))
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public Rule Atom() {
|
||||
|
||||
return FirstOf(Number(), CellReference(), SquareRoot(), Parens());
|
||||
}
|
||||
|
||||
public Rule CellReference() {
|
||||
|
||||
return FirstOf(SpreadsheetCell(), TableCell());
|
||||
}
|
||||
|
||||
public Rule SpreadsheetCell() {
|
||||
|
||||
Var<String> col = new Var<>();
|
||||
Var<String> row = new Var<>();
|
||||
return Sequence(
|
||||
OneOrMore(FirstOf(CharRange('a', 'z'), CharRange('A', 'Z'))),
|
||||
col.set(matchOrDefault("").toUpperCase()),
|
||||
OneOrMore(Digit()),
|
||||
row.set(matchOrDefault("")),
|
||||
push(new CellReferenceNode(col.get(), Integer.parseInt(row.get()), false))
|
||||
);
|
||||
}
|
||||
|
||||
public Rule TableCell() {
|
||||
|
||||
Var<String> col = new Var<>();
|
||||
Var<String> row = new Var<>();
|
||||
return Sequence(
|
||||
'[',
|
||||
Optional(Whitespace()),
|
||||
OneOrMore(FirstOf(CharRange('a', 'z'), CharRange('A', 'Z'), CharRange('0', '9'), '-', '_')),
|
||||
col.set(matchOrDefault("")),
|
||||
Optional(Whitespace()),
|
||||
',',
|
||||
Optional(Whitespace()),
|
||||
OneOrMore(Digit()),
|
||||
row.set(matchOrDefault("")),
|
||||
Optional(Whitespace()),
|
||||
']',
|
||||
push(new CellReferenceNode(col.get(), Integer.parseInt(row.get()), true))
|
||||
);
|
||||
}
|
||||
|
||||
public Rule SquareRoot() {
|
||||
|
||||
return Sequence(
|
||||
"SQRT",
|
||||
Optional(Whitespace()),
|
||||
Parens(),
|
||||
push(new OpNode('R', pop(), null))
|
||||
);
|
||||
}
|
||||
|
||||
public Rule Parens() {
|
||||
|
||||
return Sequence(
|
||||
'(',
|
||||
Optional(Whitespace()),
|
||||
Expression(),
|
||||
Optional(Whitespace()),
|
||||
')');
|
||||
}
|
||||
|
||||
public Rule Number() {
|
||||
|
||||
return Sequence(
|
||||
// we use another Sequence in the "Number" Sequence so we can easily access the input text matched
|
||||
// by the three enclosed rules with "match()" or "matchOrDefault()"
|
||||
Sequence(
|
||||
Optional('-'),
|
||||
OneOrMore(Digit()),
|
||||
Optional('.', OneOrMore(Digit()))
|
||||
),
|
||||
|
||||
// the matchOrDefault() call returns the matched input text of the immediately preceding rule
|
||||
// or a default string (in this case if it is run during error recovery (resynchronization))
|
||||
push(new ValueNode(new BigDecimal(matchOrDefault("0")))),
|
||||
Whitespace()
|
||||
);
|
||||
}
|
||||
|
||||
public Rule Digit() {
|
||||
|
||||
return CharRange('0', '9');
|
||||
}
|
||||
|
||||
public Rule Whitespace() {
|
||||
|
||||
return ZeroOrMore(AnyOf(" \t\f"));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,100 @@
|
|||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.vizierdb.database.value.formula;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.vizierdb.database.CellSet;
|
||||
import org.vizierdb.database.Snapshot;
|
||||
|
||||
/**
|
||||
* Internal operator node in the formula AST. Only node with a left and right
|
||||
* child.
|
||||
*
|
||||
* @author Heiko Mueller
|
||||
*/
|
||||
public class OpNode extends FormulaNode {
|
||||
|
||||
private final Character _operator;
|
||||
|
||||
public OpNode(Character operator, FormulaNode left, FormulaNode right) {
|
||||
|
||||
super(left, right);
|
||||
|
||||
_operator = operator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CellReference> getCellReferences() {
|
||||
|
||||
ArrayList<CellReference> references = new ArrayList<>();
|
||||
references.addAll(this.left().getCellReferences());
|
||||
references.addAll(this.right().getCellReferences());
|
||||
return references;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BigDecimal eval(CellSet cells) {
|
||||
|
||||
BigDecimal left = this.left().eval(cells);
|
||||
if (left == null) {
|
||||
return null;
|
||||
}
|
||||
if (_operator == 'R') {
|
||||
return new BigDecimal(Math.sqrt(left.doubleValue()));
|
||||
} else {
|
||||
BigDecimal right = this.right().eval(cells);
|
||||
if (right == null) {
|
||||
return null;
|
||||
}
|
||||
switch (_operator) {
|
||||
case '+':
|
||||
return left.add(right);
|
||||
case '-':
|
||||
return left.subtract(right);
|
||||
case '*':
|
||||
return left.multiply(right).setScale(Math.max(left.scale(), right.scale()), RoundingMode.CEILING);
|
||||
case '/':
|
||||
return left.divide(right, Math.max(left.scale(), right.scale()), RoundingMode.CEILING);
|
||||
case '^':
|
||||
return new BigDecimal(Math.pow(left.doubleValue(), right.doubleValue()));
|
||||
default:
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toExternalForm(Snapshot snapshot) {
|
||||
|
||||
switch (_operator) {
|
||||
case '+':
|
||||
return "(" + left().toExternalForm(snapshot) + " + " + right().toExternalForm(snapshot) + ")";
|
||||
case '-':
|
||||
return "(" + left().toExternalForm(snapshot) + " - " + right().toExternalForm(snapshot) + ")";
|
||||
case '*':
|
||||
return "(" + left().toExternalForm(snapshot) + " * " + right().toExternalForm(snapshot) + ")";
|
||||
case '/':
|
||||
return "(" + left().toExternalForm(snapshot) + " / " + right().toExternalForm(snapshot) + ")";
|
||||
case '^':
|
||||
return left().toExternalForm(snapshot) + "^" + right().toExternalForm(snapshot);
|
||||
case 'R':
|
||||
return "SQRT (" + left().toExternalForm(snapshot) + ")";
|
||||
default:
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.vizierdb.database.value.formula;
|
||||
|
||||
import org.parboiled.Parboiled;
|
||||
import org.parboiled.errors.ErrorUtils;
|
||||
import org.parboiled.parserunners.ReportingParseRunner;
|
||||
import org.parboiled.support.ParsingResult;
|
||||
import static org.parboiled.support.ParseTreeUtils.printNodeTree;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author heiko
|
||||
*/
|
||||
public class ParserTest {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
FormulaParser<FormulaNode> parser = Parboiled.createParser(FormulaParser.class);
|
||||
ParsingResult<?> result = new ReportingParseRunner(parser.Formula()).run("= 2 + ( A3 ^ ( 2 ) - 1) * C2");
|
||||
|
||||
if (!result.parseErrors.isEmpty()) {
|
||||
System.out.println(ErrorUtils.printParseError(result.parseErrors.get(0)));
|
||||
} else {
|
||||
System.out.println(printNodeTree(result) + '\n');
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.vizierdb.database.value.formula;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.vizierdb.database.CellSet;
|
||||
import org.vizierdb.database.Snapshot;
|
||||
|
||||
/**
|
||||
* Constant value node in formula AST.
|
||||
*
|
||||
* @author Heiko Mueller
|
||||
*/
|
||||
public class ValueNode extends FormulaNode {
|
||||
|
||||
private final BigDecimal _value;
|
||||
|
||||
public ValueNode(BigDecimal value) {
|
||||
|
||||
super(null, null);
|
||||
|
||||
_value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BigDecimal eval(CellSet cells) {
|
||||
|
||||
return _value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CellReference> getCellReferences() {
|
||||
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toExternalForm(Snapshot snapshot) {
|
||||
|
||||
return _value.toPlainString();
|
||||
}
|
||||
}
|
|
@ -48,6 +48,7 @@ import org.vizierdb.database.VizierDB;
|
|||
import org.vizierdb.database.script.Operation;
|
||||
import org.vizierdb.resources.ResourceManager;
|
||||
import org.vizierdb.server.io.FileListingStream;
|
||||
import org.vizierdb.server.io.ScriptSQLStatementStream;
|
||||
|
||||
/**
|
||||
* The Vizier Database Web API Server.
|
||||
|
@ -72,12 +73,12 @@ public class DatabaseServer {
|
|||
/*
|
||||
* Uncomment for local web server
|
||||
*/
|
||||
//_urls = new URLFactory("http://localhost:8080/vizier-db/api/v1");
|
||||
_urls = new URLFactory("http://localhost:8080/vizier-db/api/v1");
|
||||
|
||||
/*
|
||||
* Uncomment for current AWS deployment
|
||||
*/
|
||||
_urls = new URLFactory("http://vizirdb.7mi5uspdsy.us-west-2.elasticbeanstalk.com/api/v1");
|
||||
//_urls = new URLFactory("http://vizirdb.7mi5uspdsy.us-west-2.elasticbeanstalk.com/api/v1");
|
||||
|
||||
_resources = new ResourceManager(new File(context.getRealPath("/WEB-INF/resources")));
|
||||
_vdb = new SimpleVizierDBM(_resources);
|
||||
|
@ -295,6 +296,39 @@ public class DatabaseServer {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the VizUAL script associated with a given branch as an array of
|
||||
* SQL statements.
|
||||
*
|
||||
* @param notebookIdentifier Notebook identifier
|
||||
* @param branchIdentifier Branch identifier
|
||||
* @return
|
||||
* @throws java.io.IOException
|
||||
*/
|
||||
@Path("/notebooks/{notebookIdentifier}/branches/{branchIdentifier}/script/sql")
|
||||
@GET
|
||||
@Produces({MediaType.APPLICATION_JSON})
|
||||
public Response getBranchScriptSQLExport(@PathParam("notebookIdentifier") int notebookIdentifier, @PathParam("branchIdentifier") int branchIdentifier) throws java.io.IOException, javax.ws.rs.WebApplicationException {
|
||||
|
||||
VizUALScript script = null;
|
||||
try {
|
||||
script = _vdb.getScript(notebookIdentifier, branchIdentifier);
|
||||
} catch (org.vizierdb.VizirDBException vizierException ){
|
||||
Logger.getLogger(DatabaseServer.class.getName()).log(Level.SEVERE, null, vizierException);
|
||||
throw new WebApplicationException(500);
|
||||
}
|
||||
if (script != null) {
|
||||
try {
|
||||
return Response.ok().entity(new ScriptSQLStatementStream(_vdb.getNotebook(notebookIdentifier), script)).type(MediaType.APPLICATION_JSON).build();
|
||||
} catch (org.vizierdb.VizirDBException vizierException ){
|
||||
Logger.getLogger(DatabaseServer.class.getName()).log(Level.SEVERE, null, vizierException);
|
||||
throw new WebApplicationException(500);
|
||||
}
|
||||
} else {
|
||||
throw new WebApplicationException(404);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute an operation on the head of the given branch.
|
||||
*
|
||||
|
|
|
@ -44,6 +44,19 @@ public class URLFactory {
|
|||
return this.getNotebookBranchURL(notebookIdentifier, branchIdentifier) + "/script";
|
||||
}
|
||||
|
||||
/**
|
||||
* URL referencing SQL translation of the script resource for a branch in a
|
||||
* notebook.
|
||||
*
|
||||
* @param notebookIdentifier Notebook identifier
|
||||
* @param branchIdentifier Branch identifier
|
||||
* @return
|
||||
*/
|
||||
public String getBranchScriptSQLExportURL(int notebookIdentifier, int branchIdentifier) {
|
||||
|
||||
return this.getNotebookBranchURL(notebookIdentifier, branchIdentifier) + "/script/sql";
|
||||
}
|
||||
|
||||
/**
|
||||
* URL referencing script resource for a branch in a notebook.
|
||||
*
|
||||
|
|
|
@ -24,6 +24,7 @@ import org.vizierdb.database.Cell;
|
|||
import org.vizierdb.database.Column;
|
||||
import org.vizierdb.database.Notebook;
|
||||
import org.vizierdb.database.Snapshot;
|
||||
import org.vizierdb.database.value.Value;
|
||||
import org.vizierdb.database.history.Branch;
|
||||
import org.vizierdb.database.history.VGEdge;
|
||||
import org.vizierdb.database.history.VGNode;
|
||||
|
@ -200,7 +201,9 @@ public class ResourceStreamWriter implements AutoCloseable {
|
|||
for (Column column : snapshot.getColumns()) {
|
||||
_out.beginObject();
|
||||
_out.name("name").value(column.getName());
|
||||
_out.name("refName").value(snapshot.getColumns().getDescriptiveName(column.getIdentifier()));
|
||||
_out.name("label").value(column.getLabel());
|
||||
_out.name("isUniqueName").value(column.hasUniqueName());
|
||||
_out.name("uniqueName").value(column.getDescriptiveName());
|
||||
_out.endObject();
|
||||
columnMapping.put(column.getIdentifier(), columnMapping.size());
|
||||
}
|
||||
|
@ -217,7 +220,13 @@ public class ResourceStreamWriter implements AutoCloseable {
|
|||
_out.beginObject();
|
||||
_out.name("col").value(columnMapping.get(cell.getColumnId()));
|
||||
_out.name("row").value(rowMapping.get(cell.getRowId()));
|
||||
_out.name("value").value(cell.getValue());
|
||||
_out.name("value").beginObject();
|
||||
Value value = cell.getValue();
|
||||
_out.name("text").value(value.getAsString());
|
||||
if (value.isDerived()) {
|
||||
_out.name("formula").value(value.getFormula(snapshot));
|
||||
}
|
||||
_out.endObject();
|
||||
_out.endObject();
|
||||
}
|
||||
_out.endArray();
|
||||
|
@ -283,9 +292,9 @@ public class ResourceStreamWriter implements AutoCloseable {
|
|||
_out.endObject();
|
||||
VGEdge edge = node.getParent();
|
||||
if (edge.hasTarget()) {
|
||||
edges.add(new Edge(edge.getTarget().getSnapshotIdentifier(), edge.getStatement(), node.getSnapshotIdentifier()));
|
||||
edges.add(new Edge(edge.getTarget().getSnapshotIdentifier(), edge.getVizUALStatement(), node.getSnapshotIdentifier()));
|
||||
} else {
|
||||
edges.add(new Edge(VizierDB.UNKNOWN_SNAPSHOT, edge.getStatement(), node.getSnapshotIdentifier()));
|
||||
edges.add(new Edge(VizierDB.UNKNOWN_SNAPSHOT, edge.getVizUALStatement(), node.getSnapshotIdentifier()));
|
||||
}
|
||||
}
|
||||
_out.endArray();
|
||||
|
|
|
@ -16,6 +16,7 @@ package org.vizierdb.server.io;
|
|||
import java.io.OutputStream;
|
||||
import javax.ws.rs.core.StreamingOutput;
|
||||
import org.vizierdb.database.script.VizUALScript;
|
||||
import org.vizierdb.server.ReferenceObject;
|
||||
import org.vizierdb.server.URLFactory;
|
||||
|
||||
/**
|
||||
|
@ -45,9 +46,12 @@ public class ScriptObjectStream implements StreamingOutput {
|
|||
writer.getWriter().beginObject();
|
||||
writer.getWriter().name("operations").beginArray();
|
||||
for (int iOp = 0; iOp < _script.size(); iOp++) {
|
||||
writer.writeOperation(_script.getStatement(iOp), _notebookIdentifier, _branchIdentifier, _script.getSnapshotIdentifier(iOp), _urls);
|
||||
writer.writeOperation(_script.getVizUALStatement(iOp), _notebookIdentifier, _branchIdentifier, _script.getSnapshotIdentifier(iOp), _urls);
|
||||
}
|
||||
writer.getWriter().endArray();
|
||||
writer.getWriter().name("links").beginArray();
|
||||
writer.writeReference(new ReferenceObject("sql", _urls.getBranchScriptSQLExportURL(_notebookIdentifier, _branchIdentifier)));
|
||||
writer.getWriter().endArray();
|
||||
writer.getWriter().endObject();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.vizierdb.server.io;
|
||||
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.ws.rs.core.StreamingOutput;
|
||||
import org.vizierdb.database.Column;
|
||||
import org.vizierdb.database.ColumnList;
|
||||
import org.vizierdb.database.Notebook;
|
||||
import org.vizierdb.database.script.VizUALScript;
|
||||
import org.vizierdb.sql.MimirAdaptor;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author heiko
|
||||
*/
|
||||
public class ScriptSQLStatementStream implements StreamingOutput{
|
||||
|
||||
private final Notebook _notebook;
|
||||
private final VizUALScript _script;
|
||||
|
||||
public ScriptSQLStatementStream(Notebook notebook, VizUALScript script) {
|
||||
|
||||
_script = script;
|
||||
_notebook = notebook;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(OutputStream out) throws java.io.IOException, javax.ws.rs.WebApplicationException {
|
||||
|
||||
try (ResourceStreamWriter writer = new ResourceStreamWriter(out)) {
|
||||
writer.getWriter().beginObject();
|
||||
writer.getWriter().name("operations").beginArray();
|
||||
for (int iOp = 0; iOp < _script.size(); iOp++) {
|
||||
writer.getWriter().beginObject();
|
||||
writer.getWriter().name("sql").value(_script.getSQLStatement(iOp));
|
||||
writer.getWriter().endObject();
|
||||
}
|
||||
writer.getWriter().endArray();
|
||||
try {
|
||||
writer.getWriter().name("mimir").value(MimirAdaptor.compileToSQL(_notebook));
|
||||
} catch (org.vizierdb.VizirDBException ex) {
|
||||
writer.getWriter().name("mimir").value(ex.getMessage());
|
||||
}
|
||||
writer.getWriter().endObject();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,188 @@
|
|||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.vizierdb.sql;
|
||||
|
||||
import java.util.*;
|
||||
import scala.Enumeration;
|
||||
|
||||
import org.vizierdb.*;
|
||||
import org.vizierdb.database.*;
|
||||
import org.vizierdb.database.history.*;
|
||||
import org.vizierdb.database.script.*;
|
||||
import org.vizierdb.database.script.op.*;
|
||||
import mimir.algebra.Table;
|
||||
import mimir.algebra.Project;
|
||||
import mimir.algebra.ProjectArg;
|
||||
import mimir.algebra.Select;
|
||||
import mimir.algebra.Union;
|
||||
|
||||
/**
|
||||
* A script in VizUAL is a sequence of operations. Each operation generates a
|
||||
* new snapshot. Operations and generated snapshot identifiers are recorded as
|
||||
* part of the script.
|
||||
*
|
||||
* @author Oliver Kennedy
|
||||
*/
|
||||
public class MimirAdaptor {
|
||||
|
||||
public static <A, B> scala.collection.immutable.Map<A, B> toScalaMap(Map<A, B> m) {
|
||||
return scala.collection.JavaConverters.mapAsScalaMapConverter(m).asScala().toMap(
|
||||
scala.Predef.<scala.Tuple2<A, B>>conforms()
|
||||
);
|
||||
}
|
||||
|
||||
public static scala.collection.immutable.List<scala.Tuple2<String,scala.Enumeration.Value>> makeMimirSchema(Collection<String> cols)
|
||||
{
|
||||
return makeMimirSchema(cols, mimir.algebra.Type.withName("TString"));
|
||||
}
|
||||
public static scala.collection.immutable.List<scala.Tuple2<String,scala.Enumeration.Value>> makeMimirSchema(Collection<String> cols, scala.Enumeration.Value t)
|
||||
{
|
||||
scala.collection.immutable.List<scala.Tuple2<String,scala.Enumeration.Value>> ret =
|
||||
scala.collection.immutable.List$.MODULE$.empty();
|
||||
for(String col : cols){
|
||||
ret = new scala.collection.immutable.$colon$colon<scala.Tuple2<String,scala.Enumeration.Value>>(
|
||||
new scala.Tuple2<String,scala.Enumeration.Value>(col, t), ret
|
||||
);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static mimir.algebra.Operator compileToRA(VizUALScript script, Map<String, List<String>> schemas)
|
||||
{
|
||||
mimir.algebra.Operator raTree = null;
|
||||
ColumnList cols = new ColumnList();
|
||||
int colIdx = 0;
|
||||
BitSet deleted = new BitSet();
|
||||
|
||||
for(int x = 0; x < script.size(); x++){
|
||||
Operation step = script.getOperation(x);
|
||||
// System.out.println("CONVERT: "+step);
|
||||
if(step instanceof CellUpdate){
|
||||
CellUpdate update = (CellUpdate)step;
|
||||
String targetCol = cols.get(update.getColumnId()).getName();
|
||||
|
||||
raTree = mimir.algebra.OperatorUtils$.MODULE$.replaceColumn(
|
||||
targetCol,
|
||||
(mimir.algebra.Expression)(new mimir.algebra.Conditional(
|
||||
new mimir.algebra.Comparison(
|
||||
mimir.algebra.Cmp.withName("Eq"),
|
||||
new mimir.algebra.Var("ROWID_MIMIR"),
|
||||
new mimir.algebra.RowIdPrimitive(""+update.getRowId())
|
||||
),
|
||||
new mimir.algebra.StringPrimitive(update.getValue()),
|
||||
new mimir.algebra.Var(targetCol)
|
||||
)),
|
||||
raTree
|
||||
);
|
||||
} else if(step instanceof ColumnDelete){
|
||||
ColumnDelete delete = (ColumnDelete)step;
|
||||
String targetCol = cols.get(delete.getColumnId()).getName();
|
||||
// System.out.println("Deleting "+ targetCol);
|
||||
raTree = mimir.algebra.OperatorUtils$.MODULE$.projectAwayColumn(targetCol, raTree);
|
||||
deleted.set(delete.getColumnId());
|
||||
} else if(step instanceof ColumnInsert){
|
||||
ColumnInsert insert = (ColumnInsert)step;
|
||||
raTree = mimir.algebra.OperatorUtils$.MODULE$.projectInColumn(insert.getName(), new mimir.algebra.NullPrimitive(), raTree);
|
||||
cols.add(colIdx++, insert.getName());
|
||||
} else if(step instanceof ColumnMove){
|
||||
//ignore positions for now
|
||||
} else if(step instanceof ColumnRename){
|
||||
ColumnRename rename = (ColumnRename)step;
|
||||
String targetCol = cols.get(rename.getColumnId()).getName();
|
||||
raTree = mimir.algebra.OperatorUtils$.MODULE$.renameColumn(targetCol, rename.getName(), raTree);
|
||||
cols.renameColumn(rename.getColumnId(), rename.getName());
|
||||
} else if(step instanceof CSVFileLoad){
|
||||
String relName = ((CSVFileLoad)step).getFileName().replaceFirst("\\..*$", "");
|
||||
colIdx = 0;
|
||||
cols = new ColumnList();
|
||||
for(String col : schemas.get(relName)){
|
||||
cols.add(colIdx++, col);
|
||||
}
|
||||
raTree = new mimir.algebra.Table(relName,
|
||||
makeMimirSchema(schemas.get(relName)),
|
||||
makeMimirSchema(Arrays.asList("ROWID_MIMIR"), mimir.algebra.Type.withName("TRowId"))
|
||||
);
|
||||
} else if(step instanceof RowDelete){
|
||||
RowDelete delete = (RowDelete)step;
|
||||
raTree = new mimir.algebra.Select(
|
||||
(mimir.algebra.Expression)(new mimir.algebra.Comparison(
|
||||
mimir.algebra.Cmp.withName("Neq"),
|
||||
new mimir.algebra.Var("ROWID_MIMIR"),
|
||||
new mimir.algebra.RowIdPrimitive(""+delete.getRowId())
|
||||
)),
|
||||
raTree
|
||||
);
|
||||
} else if(step instanceof RowInsert){
|
||||
mimir.algebra.Operator dual = new mimir.algebra.Table("dual",
|
||||
makeMimirSchema(schemas.get("dual")),
|
||||
makeMimirSchema(Arrays.asList("ROWID_MIMIR"), mimir.algebra.Type.withName("TRowId"))
|
||||
);
|
||||
for(int i = 0; i < colIdx; i++){
|
||||
if(!deleted.get(i)){
|
||||
dual = mimir.algebra.OperatorUtils$.MODULE$.projectInColumn(cols.getColumn(i).getName(), new mimir.algebra.NullPrimitive(), dual);
|
||||
}
|
||||
}
|
||||
dual = mimir.optimizer.InlineProjections$.MODULE$.optimize(dual);
|
||||
raTree = new mimir.algebra.Union(dual, raTree);
|
||||
} else if(step instanceof RowMove){
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
}
|
||||
return mimir.algebra.OperatorUtils$.MODULE$.projectAwayColumn("ROWID_MIMIR", raTree);
|
||||
}
|
||||
|
||||
public static String compileToSQL(mimir.algebra.Operator raTree, Map<String, List<String>> schemas)
|
||||
{
|
||||
Map<String,
|
||||
scala.collection.immutable.List<
|
||||
scala.Tuple2<String,scala.Enumeration.Value>>> scalaSchemas = new HashMap<>();
|
||||
for(Map.Entry<String, List<String>> table : schemas.entrySet()){
|
||||
scalaSchemas.put(table.getKey(), makeMimirSchema(table.getValue()));
|
||||
}
|
||||
|
||||
mimir.Database db = new mimir.Database("Test DB",
|
||||
new mimir.sql.NullBackend(toScalaMap(scalaSchemas)));
|
||||
return db.convert(raTree).toString();
|
||||
}
|
||||
|
||||
public static String compileToSQL(VizUALScript script, Map<String, List<String>> schemas)
|
||||
{
|
||||
return compileToSQL(compileToRA(script, schemas), schemas);
|
||||
}
|
||||
|
||||
public static String compileToSQL(Notebook notebook)
|
||||
throws VizirDBException
|
||||
{
|
||||
VersionGraph history = notebook.getHistory();
|
||||
VizUALScript script = history.getScript(history.getCurrentBranch().getIdentifier());
|
||||
CSVFileLoad load = (CSVFileLoad)script.getOperation(0);
|
||||
ColumnList cols = load.exec(notebook, null, 0).getColumns();
|
||||
List<String> colNames = new ArrayList<String>();
|
||||
for(Column col : cols){ colNames.add(col.getName()); }
|
||||
|
||||
Map<String, List<String>> schemas = new HashMap<String, List<String>>();
|
||||
String tableName = load.getFileName().replaceFirst("\\..*$", "");
|
||||
schemas.put(tableName, colNames);
|
||||
schemas.put("dual", new ArrayList<String>());
|
||||
|
||||
return compileToSQL(script, schemas);
|
||||
}
|
||||
|
||||
public static class UnsupportedFeature extends Exception {
|
||||
public UnsupportedFeature(String msg) { super(msg); }
|
||||
}
|
||||
|
||||
}
|
|
@ -19,7 +19,38 @@ package org.vizierdb.util;
|
|||
* @author Heiko Mueller
|
||||
*/
|
||||
public final class SpreadsheetHelper {
|
||||
|
||||
|
||||
/**
|
||||
* The index position (starting at 1) derived from a given spreadsheet
|
||||
* column name.
|
||||
*
|
||||
* @param name
|
||||
* @return
|
||||
*/
|
||||
public static int getColumnIndex(String name) {
|
||||
|
||||
int columnIndex = 0;
|
||||
for (int iPos = 0; iPos < name.length(); iPos++) {
|
||||
char c = name.charAt((name.length() - 1) - iPos);
|
||||
int index = c - 'A';
|
||||
if ((index < 0) || (index > 26)) {
|
||||
throw new java.lang.IllegalArgumentException(name);
|
||||
}
|
||||
if (iPos > 0) {
|
||||
index++;
|
||||
}
|
||||
columnIndex += (Math.pow(26, iPos) * index);
|
||||
}
|
||||
return columnIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* The spreadsheet name of the column. Columns in spreadsheets are name
|
||||
* with strings starting at A, B, C, ... AA, AB, AC, ....
|
||||
*
|
||||
* @param columnIndex
|
||||
* @return
|
||||
*/
|
||||
public static String getColumnName(int columnIndex) {
|
||||
|
||||
if (columnIndex < 0) {
|
||||
|
|
|
@ -49,93 +49,3 @@ site oel_tthm_g_l_a lraa_haa5_g_l_b oel_haa5_g_l_b location result_haa5_g_l_b sa
|
|||
33450 36 32 34 "SS - IFO 135 N/S W 112th St, 2nd SS W/O St Nicholas Ave, 12\""" 40 2015-05-05T00:00:00 2015-05-08T00:00:00 44 37 2015-05-05T00:00:00
|
||||
33950 34 32 34 "SS - N/S E 104th Street, 2nd SS E/O 3rd Avenue, 12\""" 41 2015-05-05T00:00:00 2015-05-08T00:00:00 43 36 2015-05-05T00:00:00
|
||||
37950 27 30 32 "SS - IFO 325 N/S E 12th Street, 2nd SS E/O 2nd Ave, 12\""" 37 2015-05-05T00:00:00 2015-05-09T00:00:00 30 33 2015-05-05T00:00:00
|
||||
38250 29 32 33 "SS - IFO 309 N/S E 87th St, 2nd SS W/O 1st Ave, 12\""" 37 2015-05-05T00:00:00 2015-05-13T00:00:00 32 34 2015-05-05T00:00:00
|
||||
39650 27 31 31 "SS - IFO 229 N/S E 49th St, 2nd SS W/O 2nd Ave, 12\""" 36 2015-05-05T00:00:00 2015-05-09T00:00:00 27 32 2015-05-05T00:00:00
|
||||
44350 28 29 30 "SS - IFO 21-55 N/S 34th Ave, 1st SS W/O 24th St, 12\""" 33 2015-05-05T00:00:00 2015-05-09T00:00:00 29 31 2015-05-05T00:00:00
|
||||
45250 27 33 32 "SS - E/S Beach 58th St, 2nd SS N/O Beach Channel Drive, 12\""" 35 2015-05-05T00:00:00 2015-05-09T00:00:00 30 29 2015-05-05T00:00:00
|
||||
50250 26 39 34 "SS - IFO 937 N/S Victory Blvd, 2nd SS E/O Highland Ave, 20\""" 36 2015-05-05T00:00:00 2015-05-09T00:00:00 28 30 2015-05-05T00:00:00
|
||||
50750 35 37 34 "SS - E/S Woodhull Ave, 1st SS S/O Albourne Ave, 8\""" 33 2015-05-05T00:00:00 2015-05-09T00:00:00 39 38 2015-05-06T00:00:00
|
||||
50850 30 40 37 "SS - IFO 512 W/S Arlene St, 1st SS N/O Dawson Ct, 12\""" 38 2015-05-05T00:00:00 2015-05-09T00:00:00 32 33 2015-05-06T00:00:00
|
||||
52050 32 38 35 "SS - IFO 218 W/S Nicholas Ave, 1st SS S/O Charles Ave, 12\""" 38 2015-05-05T00:00:00 2015-05-09T00:00:00 33 35 2015-05-05T00:00:00
|
||||
58650 34 39 36 "SS - IFO 510 W/S Main St, 2nd SS S/O Hylan Blvd, 12\""" 35 2015-05-05T00:00:00 2015-05-09T00:00:00 36 37 2015-05-06T00:00:00
|
||||
77650 27 32 31 SS - OPP 110-52 E/S 207th St 34 2015-05-05T00:00:00 2015-05-09T00:00:00 28 30 2015-05-05T00:00:00
|
||||
15150 26 28 29 "SS - IFO 1420 E/S Grand Concourse, 1st SS S/O E 171st St, 20\""" 34 2015-05-05T00:00:00 2015-05-07T00:00:00 30 30 2015-05-06T00:00:00
|
||||
18650 22 29 29 "SS - N/S Dewey Ave, btw Quincy & Swinton Aves, 12\""" 34 2015-05-05T00:00:00 2015-05-07T00:00:00 25 24 2015-05-06T00:00:00
|
||||
23450 31 30 31 "SS - N/S Jefferson Avenue, 2nd SS W/O Lewis Avenue, 20\""" 36 2015-05-05T00:00:00 2015-05-08T00:00:00 39 31 2015-05-06T00:00:00
|
||||
24350 32 32 34 "SS - W/S Brighton 11th Street, 2nd SS S/O Cass Place, 12\""" 40 2015-05-05T00:00:00 2015-05-08T00:00:00 36 34 2015-05-05T00:00:00
|
||||
31750 36 31 33 "SS - IFO 427 N/S W 26th St, 2nd SS W/O 9th Ave, 12\""" 39 2015-05-05T00:00:00 2015-05-08T00:00:00 42 37 2015-05-05T00:00:00
|
||||
31850 34 30 32 "SS - IFO 82 S/S Warren St, 2nd SS E/O Greenwich St, 12\""" 38 2015-05-05T00:00:00 2015-05-08T00:00:00 41 36 2015-05-05T00:00:00
|
||||
32350 33 31 33 "SS - IFO 116 E/S Ave C, 2nd SS N/O E 7th St, 12\""" 40 2015-05-05T00:00:00 2015-05-08T00:00:00 39 36 2015-05-05T00:00:00
|
||||
33450 36 32 34 "SS - IFO 135 N/S W 112th St, 2nd SS W/O St Nicholas Ave, 12\""" 40 2015-05-05T00:00:00 2015-05-08T00:00:00 44 37 2015-05-05T00:00:00
|
||||
33950 34 32 34 "SS - N/S E 104th Street, 2nd SS E/O 3rd Avenue, 12\""" 41 2015-05-05T00:00:00 2015-05-08T00:00:00 43 36 2015-05-05T00:00:00
|
||||
37950 27 30 32 "SS - IFO 325 N/S E 12th Street, 2nd SS E/O 2nd Ave, 12\""" 37 2015-05-05T00:00:00 2015-05-09T00:00:00 30 33 2015-05-05T00:00:00
|
||||
38250 29 32 33 "SS - IFO 309 N/S E 87th St, 2nd SS W/O 1st Ave, 12\""" 37 2015-05-05T00:00:00 2015-05-13T00:00:00 32 34 2015-05-05T00:00:00
|
||||
39650 27 31 31 "SS - IFO 229 N/S E 49th St, 2nd SS W/O 2nd Ave, 12\""" 36 2015-05-05T00:00:00 2015-05-09T00:00:00 27 32 2015-05-05T00:00:00
|
||||
44350 28 29 30 "SS - IFO 21-55 N/S 34th Ave, 1st SS W/O 24th St, 12\""" 33 2015-05-05T00:00:00 2015-05-09T00:00:00 29 31 2015-05-05T00:00:00
|
||||
45250 27 33 32 "SS - E/S Beach 58th St, 2nd SS N/O Beach Channel Drive, 12\""" 35 2015-05-05T00:00:00 2015-05-09T00:00:00 30 29 2015-05-05T00:00:00
|
||||
50250 26 39 34 "SS - IFO 937 N/S Victory Blvd, 2nd SS E/O Highland Ave, 20\""" 36 2015-05-05T00:00:00 2015-05-09T00:00:00 28 30 2015-05-05T00:00:00
|
||||
50750 35 37 34 "SS - E/S Woodhull Ave, 1st SS S/O Albourne Ave, 8\""" 33 2015-05-05T00:00:00 2015-05-09T00:00:00 39 38 2015-05-06T00:00:00
|
||||
50850 30 40 37 "SS - IFO 512 W/S Arlene St, 1st SS N/O Dawson Ct, 12\""" 38 2015-05-05T00:00:00 2015-05-09T00:00:00 32 33 2015-05-06T00:00:00
|
||||
52050 32 38 35 "SS - IFO 218 W/S Nicholas Ave, 1st SS S/O Charles Ave, 12\""" 38 2015-05-05T00:00:00 2015-05-09T00:00:00 33 35 2015-05-05T00:00:00
|
||||
58650 34 39 36 "SS - IFO 510 W/S Main St, 2nd SS S/O Hylan Blvd, 12\""" 35 2015-05-05T00:00:00 2015-05-09T00:00:00 36 37 2015-05-06T00:00:00
|
||||
77650 27 32 31 SS - OPP 110-52 E/S 207th St 34 2015-05-05T00:00:00 2015-05-09T00:00:00 28 30 2015-05-05T00:00:00
|
||||
15150 40 28 29 "SS - IFO 1420 E/S Grand Concourse, 1st SS S/O E 171st St, 20\""" 30 2015-08-04T00:00:00 2015-08-08T00:00:00 58 33 2015-08-06T00:00:00
|
||||
18650 30 27 27 "SS - N/S Dewey Ave, btw Quincy & Swinton Aves, 12\""" 27 2015-08-04T00:00:00 2015-08-08T00:00:00 40 26 2015-08-06T00:00:00
|
||||
23450 41 29 30 "SS - N/S Jefferson Avenue, 2nd SS W/O Lewis Avenue, 20\""" 30 2015-08-04T00:00:00 2015-08-08T00:00:00 54 35 2015-08-06T00:00:00
|
||||
24350 44 32 32 "SS - W/S Brighton 11th Street, 2nd SS S/O Cass Place, 12\""" 32 2015-08-04T00:00:00 2015-08-08T00:00:00 61 38 2015-08-07T00:00:00
|
||||
31750 39 31 33 "SS - IFO 427 N/S W 26th St, 2nd SS W/O 9th Ave, 12\""" 32 2015-08-04T00:00:00 2015-08-08T00:00:00 46 37 2015-08-07T00:00:00
|
||||
31850 44 29 30 "SS - IFO 82 S/S Warren St, 2nd SS E/O Greenwich St, 12\""" 28 2015-08-04T00:00:00 2015-08-08T00:00:00 60 39 2015-08-07T00:00:00
|
||||
32350 42 30 30 "SS - IFO 116 E/S Ave C, 2nd SS N/O E 7th St, 12\""" 28 2015-08-04T00:00:00 2015-08-08T00:00:00 56 37 2015-08-07T00:00:00
|
||||
33450 33 30 29 "SS - IFO 135 N/S W 112th St, 2nd SS W/O St Nicholas Ave, 12\""" 25 2015-08-04T00:00:00 2015-08-08T00:00:00 36 34 2015-08-07T00:00:00
|
||||
33950 33 30 29 "SS - N/S E 104th Street, 2nd SS E/O 3rd Avenue, 12\""" 25 2015-08-04T00:00:00 2015-08-08T00:00:00 37 33 2015-08-07T00:00:00
|
||||
37950 36 30 31 "SS - IFO 325 N/S E 12th Street, 2nd SS E/O 2nd Ave, 12\""" 31 2015-08-04T00:00:00 2015-08-10T00:00:00 48 32 2015-08-07T00:00:00
|
||||
38250 41 32 33 "SS - IFO 309 N/S E 87th St, 2nd SS W/O 1st Ave, 12\""" 35 2015-08-19T00:00:00 2015-08-10T00:00:00 57 35 2015-08-21T00:00:00
|
||||
39650 35 31 32 "SS - IFO 229 N/S E 49th St, 2nd SS W/O 2nd Ave, 12\""" 34 2015-08-04T00:00:00 2015-08-11T00:00:00 49 32 2015-08-07T00:00:00
|
||||
44350 27 30 30 "SS - IFO 21-55 N/S 34th Ave, 1st SS W/O 24th St, 12\""" 32 2015-08-04T00:00:00 2015-08-11T00:00:00 31 28 2015-08-07T00:00:00
|
||||
45250 38 30 30 "SS - E/S Beach 58th St, 2nd SS N/O Beach Channel Drive, 12\""" 28 2015-08-04T00:00:00 2015-08-11T00:00:00 53 32 2015-08-07T00:00:00
|
||||
50250 33 36 37 "SS - IFO 937 N/S Victory Blvd, 2nd SS E/O Highland Ave, 20\""" 43 2015-08-19T00:00:00 2015-08-11T00:00:00 43 30 2015-08-21T00:00:00
|
||||
50750 46 33 31 "SS - E/S Woodhull Ave, 1st SS S/O Albourne Ave, 8\""" 30 2015-08-04T00:00:00 2015-08-11T00:00:00 62 40 2015-08-07T00:00:00
|
||||
50850 39 36 35 "SS - IFO 512 W/S Arlene St, 1st SS N/O Dawson Ct, 12\""" 35 2015-08-04T00:00:00 2015-08-11T00:00:00 53 35 2015-08-07T00:00:00
|
||||
52050 41 34 33 "SS - IFO 218 W/S Nicholas Ave, 1st SS S/O Charles Ave, 12\""" 31 2015-08-04T00:00:00 2015-08-11T00:00:00 56 38 2015-08-07T00:00:00
|
||||
58650 40 36 36 "SS - IFO 510 W/S Main St, 2nd SS S/O Hylan Blvd, 12\""" 38 2015-08-04T00:00:00 2015-08-10T00:00:00 50 37 2015-08-07T00:00:00
|
||||
77650 32 30 30 SS - OPP 110-52 E/S 207th St 31 2015-08-04T00:00:00 2015-08-10T00:00:00 42 30 2015-08-07T00:00:00
|
||||
15150 44 33 39 "SS - IFO 1420 E/S Grand Concourse, 1st SS S/O E 171st St, 20\""" 45 2015-11-04T00:00:00 2015-11-05T00:00:00 44 37 2015-11-06T00:00:00
|
||||
18650 34 30 34 "SS - N/S Dewey Ave, btw Quincy & Swinton Aves, 12\""" 37 2015-11-04T00:00:00 2015-11-20T00:00:00 35 28 2015-11-06T00:00:00
|
||||
23450 42 32 35 "SS - N/S Jefferson Avenue, 2nd SS W/O Lewis Avenue, 20\""" 37 2015-11-04T00:00:00 2015-11-05T00:00:00 38 37 2015-11-06T00:00:00
|
||||
24350 44 33 36 "SS - W/S Brighton 11th Street, 2nd SS S/O Cass Place, 12\""" 35 2015-11-04T00:00:00 2015-11-07T00:00:00 39 38 2015-11-05T00:00:00
|
||||
31750 46 31 30 "SS - IFO 427 N/S W 26th St, 2nd SS W/O 9th Ave, 12\""" 25 2015-11-04T00:00:00 2015-11-07T00:00:00 47 39 2015-11-05T00:00:00
|
||||
31850 50 31 34 "SS - IFO 82 S/S Warren St, 2nd SS E/O Greenwich St, 12\""" 35 2015-11-04T00:00:00 2015-11-09T00:00:00 50 42 2015-11-06T00:00:00
|
||||
32350 47 31 33 "SS - IFO 116 E/S Ave C, 2nd SS N/O E 7th St, 12\""" 31 2015-11-04T00:00:00 2015-11-07T00:00:00 47 40 2015-11-05T00:00:00
|
||||
33450 39 29 30 "SS - IFO 135 N/S W 112th St, 2nd SS W/O St Nicholas Ave, 12\""" 27 2015-11-04T00:00:00 2015-11-11T00:00:00 37 34 2015-11-06T00:00:00
|
||||
33950 39 29 31 "SS - N/S E 104th Street, 2nd SS E/O 3rd Avenue, 12\""" 28 2015-11-04T00:00:00 2015-11-11T00:00:00 37 33 2015-11-06T00:00:00
|
||||
37950 44 30 31 "SS - IFO 325 N/S E 12th Street, 2nd SS E/O 2nd Ave, 12\""" 28 2015-11-04T00:00:00 2015-11-07T00:00:00 48 36 2015-11-06T00:00:00
|
||||
38250 48 37 44 "SS - IFO 309 N/S E 87th St, 2nd SS W/O 1st Ave, 12\""" 51 2015-11-04T00:00:00 2015-11-11T00:00:00 51 39 2015-11-06T00:00:00
|
||||
39650 44 34 39 "SS - IFO 229 N/S E 49th St, 2nd SS W/O 2nd Ave, 12\""" 42 2015-11-04T00:00:00 2015-11-11T00:00:00 49 35 2015-11-06T00:00:00
|
||||
44350 33 31 34 "SS - IFO 21-55 N/S 34th Ave, 1st SS W/O 24th St, 12\""" 35 2015-11-04T00:00:00 2015-11-05T00:00:00 35 28 2015-11-05T00:00:00
|
||||
45250 38 31 32 "SS - E/S Beach 58th St, 2nd SS N/O Beach Channel Drive, 12\""" 33 2015-11-04T00:00:00 2015-11-07T00:00:00 34 34 2015-11-05T00:00:00
|
||||
50250 37 36 38 "SS - IFO 937 N/S Victory Blvd, 2nd SS E/O Highland Ave, 20\""" 36 2015-11-04T00:00:00 2015-11-07T00:00:00 38 31 2015-11-05T00:00:00
|
||||
50750 49 29 27 "SS - E/S Woodhull Ave, 1st SS S/O Albourne Ave, 8\""" 22 2015-11-04T00:00:00 2015-11-07T00:00:00 47 42 2015-11-06T00:00:00
|
||||
50850 42 34 35 "SS - IFO 512 W/S Arlene St, 1st SS N/O Dawson Ct, 12\""" 33 2015-11-04T00:00:00 2015-11-09T00:00:00 42 36 2015-11-05T00:00:00
|
||||
52050 45 31 30 "SS - IFO 218 W/S Nicholas Ave, 1st SS S/O Charles Ave, 12\""" 25 2015-11-04T00:00:00 2015-11-07T00:00:00 45 38 2015-11-05T00:00:00
|
||||
58650 45 34 34 "SS - IFO 510 W/S Main St, 2nd SS S/O Hylan Blvd, 12\""" 31 2015-11-04T00:00:00 2015-11-09T00:00:00 46 39 2015-11-05T00:00:00
|
||||
77650 36 31 33 SS - OPP 110-52 E/S 207th St 33 2015-11-04T00:00:00 2015-11-07T00:00:00 37 31 2015-11-05T00:00:00
|
||||
15150 43 36 36 "SS - IFO 1420 E/S Grand Concourse, 1st SS S/O E 171st St, 20\""" 35 2016-02-02T00:00:00 2016-02-04T00:00:00 34 42 2016-02-03T00:00:00
|
||||
18650 30 31 29 "SS - N/S Dewey Ave, btw Quincy & Swinton Aves, 12\""" 25 2016-02-02T00:00:00 2016-02-05T00:00:00 23 31 2016-02-02T00:00:00
|
||||
23450 37 33 31 "SS - N/S Jefferson Avenue, 2nd SS W/O Lewis Avenue, 20\""" 29 2016-02-02T00:00:00 2016-02-05T00:00:00 27 40 2016-02-02T00:00:00
|
||||
24350 44 36 35 "SS - W/S Brighton 11th Street, 2nd SS S/O Cass Place, 12\""" 36 2016-02-02T00:00:00 2016-02-05T00:00:00 38 44 2016-02-02T00:00:00
|
||||
31750 42 31 28 "SS - IFO 427 N/S W 26th St, 2nd SS W/O 9th Ave, 12\""" 27 2016-02-02T00:00:00 2016-02-06T00:00:00 38 43 2016-02-02T00:00:00
|
||||
31850 47 33 30 "SS - IFO 82 S/S Warren St, 2nd SS E/O Greenwich St, 12\""" 29 2016-02-02T00:00:00 2016-02-06T00:00:00 38 47 2016-02-02T00:00:00
|
||||
32350 44 34 32 "SS - IFO 116 E/S Ave C, 2nd SS N/O E 7th St, 12\""" 35 2016-02-02T00:00:00 2016-02-06T00:00:00 37 45 2016-02-03T00:00:00
|
||||
33450 31 29 24 "SS - IFO 135 N/S W 112th St, 2nd SS W/O St Nicholas Ave, 12\""" 22 2016-02-02T00:00:00 2016-02-06T00:00:00 25 36 2016-02-03T00:00:00
|
||||
33950 31 29 24 "SS - N/S E 104th Street, 2nd SS E/O 3rd Avenue, 12\""" 22 2016-02-02T00:00:00 2016-02-06T00:00:00 25 36 2016-02-03T00:00:00
|
||||
37950 45 33 33 "SS - IFO 325 N/S E 12th Street, 2nd SS E/O 2nd Ave, 12\""" 36 2016-02-02T00:00:00 2016-02-06T00:00:00 41 42 2016-02-03T00:00:00
|
||||
38250 47 41 42 "SS - IFO 309 N/S E 87th St, 2nd SS W/O 1st Ave, 12\""" 40 2016-02-02T00:00:00 2016-02-06T00:00:00 39 45 2016-02-03T00:00:00
|
||||
39650 43 37 37 "SS - IFO 229 N/S E 49th St, 2nd SS W/O 2nd Ave, 12\""" 36 2016-02-02T00:00:00 2016-02-08T00:00:00 37 41 2016-02-03T00:00:00
|
||||
44350 38 36 38 "SS - IFO 21-55 N/S 34th Ave, 1st SS W/O 24th St, 12\""" 42 2016-02-02T00:00:00 2016-02-08T00:00:00 42 34 2016-02-03T00:00:00
|
||||
45250 35 32 31 "SS - E/S Beach 58th St, 2nd SS N/O Beach Channel Drive, 12\""" 31 2016-02-02T00:00:00 2016-02-09T00:00:00 26 36 2016-02-03T00:00:00
|
||||
50250 33 37 36 "SS - IFO 937 N/S Victory Blvd, 2nd SS E/O Highland Ave, 20\""" 32 2016-02-02T00:00:00 2016-02-09T00:00:00 26 34 2016-02-03T00:00:00
|
||||
50750 42 30 31 "SS - E/S Woodhull Ave, 1st SS S/O Albourne Ave, 8\""" 35 2016-02-02T00:00:00 2016-02-09T00:00:00 29 44 2016-02-03T00:00:00
|
||||
50850 38 35 34 "SS - IFO 512 W/S Arlene St, 1st SS N/O Dawson Ct, 12\""" 33 2016-02-02T00:00:00 2016-02-09T00:00:00 28 39 2016-02-03T00:00:00
|
||||
52050 40 32 31 "SS - IFO 218 W/S Nicholas Ave, 1st SS S/O Charles Ave, 12\""" 34 2016-02-02T00:00:00 2016-02-09T00:00:00 30 41 2016-02-03T00:00:00
|
||||
58650 41 35 35 "SS - IFO 510 W/S Main St, 2nd SS S/O Hylan Blvd, 12\""" 35 2016-02-02T00:00:00 2016-02-09T00:00:00 34 42 2016-02-03T00:00:00
|
||||
77650 32 32 31 SS - OPP 110-52 E/S 207th St 29 2016-02-02T00:00:00 2016-02-09T00:00:00 24 33 2016-02-03T00:00:00
|
||||
|
|
|
|
@ -1,4 +1,4 @@
|
|||
buildingid consttype boro geo_dist name projdesc award location_1/needs_recoding location_1/longitude location_1/latitude location_1/human_address/address location_1/human_address/city location_1/human_address/state location_1/human_address/zip
|
||||
buildingid consttype boro geo_dist name projdesc award needs_recoding longitude latitude address city state zip
|
||||
M092 CIP M 5 ACADEMY OF COLLABORATIVE ED EXTERIOR MASONRY/REPAIR WINDOWS 4678000 false -73.94493618207292 40.8149219739981 222 134 STREET New York NY 10030
|
||||
K610 CIP K 14 AUTOMOTIVE TRADES VOC HS FIRE ALARM 402500 false -73.95311779468979 40.72215011764413 50 BEDFORD AVENUE Brooklyn NY 11222
|
||||
K554 CAP K 78 All City Leadership School Lease 29299000 false -73.91312770264774 40.69743439114146 321 Palmetto St Brooklyn NY 11237
|
||||
|
@ -48,392 +48,4 @@ M465 CIP M 6 GEORGE WASHINGTON H.S. FLOOD ELIMINATION/PARAPETS 12686000 false -7
|
|||
M460 CIP M 2 GRAMERCY ARTS HS - M SCIENCE DEMO ROOM UPGRADE 1059950 false -73.98760494227764 40.735537114027146 40 IRVING PLACE New York NY 10003
|
||||
M625 CIP M 2 GRAPHIC COMMUNICATION ARTS WINDOWS/EXTERIOR MASONRY/PLAZA DECK 12647000 false -73.9905041730044 40.76336102095483 439 49 STREET New York NY 10019
|
||||
M465 CIP M 6 HEALTH CAREERS & SCIENCE FY11 RESO A ELECTRICAL SYSTEM 516000 false -73.92672451121956 40.856389753646916 549 AUDOBON AVENUE New York NY 10040
|
||||
Q585 CAP Q 78 HS 585 New 70250000 false -73.87835115518163 40.73871040256307 54 40 74th St Elmhurst NY 11373
|
||||
X783 CAP X 78 HS 783 New 0 false -73.92662867570321 40.816146910599706 201 144th St Bronx NY 10451
|
||||
Q456 CIP Q 24 HS FOR ARTS & BUS (@ Q456) WINDOWS 837000 false -73.85304068857687 40.749678220373596 105 25 HORACE HARDING EXPRESSWAY QUEENS NY 11368
|
||||
K465 CIP K 17 HS FOR SERVICE & LEARNING FIRE ALARM SYSTEM 2625000 false -73.95845755993555 40.649532936565414 911 FLATBUSH AVENUE Brooklyn NY 11226
|
||||
Q490 CIP Q 29 HUMANITIES & ARTS FY08 RESO A TECHNOLOGY 17555.4 false -73.73568329125084 40.694293339066405 207 01 116TH AVENUE CAMBRIA HEIGHTS NY 11411
|
||||
M908 CAP M 5 Harlem Promise Academy New 60000000 false -73.94715683161196 40.81182512837363 245 129th St New York NY 10027
|
||||
M280 CAP M 5 Harlem Village Academy New 36336432.4 false -73.94391077367071 40.80627609017035 35 124th St New York NY 10027
|
||||
M010 CIP M 5 I.S. 10 FLOOD ELIMINATION 5393000 false -73.93690714053237 40.82438364705368 2581 7TH AVENUE NEW YORK NY 10039
|
||||
K111 CIP K 32 I.S. 111 LL 41/16 COMPLIANCE 370000 false -73.9274722005684 40.70073228077929 35 STARR STREET Brooklyn NY 11221
|
||||
X115 CIP X 10 I.S. 115 (@X115) EXT MASONRY/ROOFS/REINFORCING SUPPORT/PARAPETS 3833000 false -73.9001023348563 40.859718306516946 120 184 STREET Bronx NY 10468
|
||||
K117 CIP K 13 I.S. 117 ELECTRICAL SYSTEMS 990000 false -73.95894653911148 40.69261081871296 300 WILLOUGHBY AVENUE Brooklyn NY 11205
|
||||
Q125 CIP Q 24 I.S. 125 LOW-VOLT ELEC SYSTEMS 980000 false -73.9048471440804 40.74519376448069 46 02 47 AVENUE QUEENS NY 11377
|
||||
M131 CIP M 2 I.S. 131 LL 41/16 COMPLIANCE 139807.64 false -73.99286250634624 40.71645702482035 100 HESTER STREET New York NY 10002
|
||||
X131 CIP X 8 I.S. 131 ROOFS/SAFETY SYSTEM/EXT MASONRY/FLOOD ELIMINATION 6780000 false -73.85977399112697 40.82386302071817 885 BOLTON AVENUE Bronx NY 10473
|
||||
X135 CIP X 11 I.S. 135 EXT MASONRY/WINDOWS/ROOFS 6988000 false -73.86461178363403 40.86208256356063 2441 WALLACE AVENUE Bronx NY 10467
|
||||
X137 CIP X 10 I.S. 137 PLANYC BOILER CONVERSION/PLANYC CLIMATE CTRL 4680000 false -73.89664962860274 40.85466127151118 2225 WEBSTER AVENUE Bronx NY 10457
|
||||
X139 CIP X 7 I.S. 139 EXT MASONRY/PARAPETS/FLOOD ELMNTN/WINDOWS/ROOFS 13447000 false -73.91782345430987 40.81004862442692 345 BROOK AVENUE Bronx NY 10454
|
||||
K014 CIP K 22 I.S. 14 PAVED AREA - BLACKTOP 659572.05
|
||||
X142 CIP X 11 I.S. 142 FY09 RESO A SCIENCE LAB 735800 false -73.84075720750138 40.88554553526394 3750 BAYCHESTER AVENUE Bronx NY 10466
|
||||
M143 CIP M 6 I.S. 143 ROOFS/FLOOD ELMNTN/EXT MASONRY 4237000 false -73.9320770216135 40.84941102208005 511 182 STREET New York NY 10033
|
||||
X144 CIP X 11 I.S. 144 ROOFS/EXT MASONRY/PARAPETS/FLOOD ELIMINATION 4891000 false -73.83609949442072 40.863858665108886 2545 GUNTHER AVENUE BRONX NY 10464
|
||||
X151 CIP X 7 I.S. 151 WINDOWS/EXTERIOR MASONRY 3426000 false -73.9211309650046 40.82298359886116 250 156 STREET Bronx NY 10451
|
||||
X158 CIP X 12 I.S. 158 PLANYC BOILER CONVRSN/PLANYC CLIMATE CTRL 3918000 false -73.90004072543645 40.827686311428195 800 HOME STREET Bronx NY 10456
|
||||
X166 CIP X 9 I.S. 166 PA SYSTEM 798000 false -73.91779283496383 40.82872889992432 250 164 STREET Bronx NY 10456
|
||||
K171 CIP K 19 I.S. 171/P.S. 7 SWB-FACADE/PARAPETS/PAVED AREA-BLACKTOP/FENCING 4828290 false -73.86966791838911 40.6861530810444 528 RIDGEWOOD AVENUE BROOKLYN NY 11208
|
||||
X183 CIP X 7 I.S. 183 PLANYC BOILER/PLANYC CLIMATE CTRL 3492000 false -73.92553701094046 40.813386726364335 339 MORRIS AVENUE Bronx NY 10451
|
||||
X184 CIP X 7 I.S. 184 PLANYC BOILER/PLANYC CLIMATE CTRL 4910270 false -73.90589968772917 40.81888494686362 778 FOREST AVENUE BRONX NY 10456
|
||||
X129 CIP X 12 I.S. 191 @X129 NEW SCIENCE DEMONSTRATION ROOM 438000 false -73.8865507352739 40.84549455019818 2055 MAPES AVENUE Bronx NY 10460
|
||||
Q192 CIP Q 29 I.S. 192 CITY COUNCIL REQ - LIGHTING FIXTURES 1800000 false -73.75923519834566 40.69812711747255 109 89 204 STREET QUEENS NY 11412
|
||||
X193 CIP X 12 I.S. 193 PLANYC BOILER/PLANYC CLIMATE CTRL 3885000 false -73.88973979569231 40.84359404962676 1919 PROSPECT AVENUE Bronx NY 10457
|
||||
M195 CIP M 5 I.S. 195 (ECF) PAVED AREAS BLACKTOP 770000 false -73.95739030775974 40.81937508503853 625 133 STREET New York NY 10027
|
||||
M195 CIP M 5 I.S. 195 (ECF) PLANYC BOILER CONVRSN/PLANYC CLIMATE CTRL 3788000 false -73.95739030775974 40.81937508503853 625 133 STREET New York NY 10027
|
||||
M195 CIP M 5 I.S. 195 (ECF) SCIENCE DEMO ROOM UPGRADE 469000 false -73.95739030775974 40.81937508503853 625 133 STREET New York NY 10027
|
||||
K002 CIP K 17 I.S. 2 SCIENCE DEMO ROOM UPGRADE 345000 false -73.95158492978685 40.6561968174429 655 PARKSIDE AVE BROOKLYN NY 11226
|
||||
K211 CIP K 18 I.S. 211 WALK IN FREEZER REPLACEMENT 343200 false -73.89642371322941 40.64348164485336 1001 100 STREET BROOKLYN NY 11236
|
||||
X116 CIP X 12 I.S. 216 (@X116) PLANYC BOILER CONVERSION/PLANYC CLIMATE CONTROL 4468000 false -73.89392410102988 40.822428225918 977 FOX STREET Bronx NY 10459
|
||||
K218 CIP K 19 I.S. 218 WALK IN FREEZER REPLACEMENT 2120000 false -73.8742292684109 40.67070199017694 370 FOUNTAIN AVENUE Brooklyn NY 11208
|
||||
M218 CIP M 6 I.S. 218 FLOOD ELIMINATION/WINDOWS/ROOFS 1867000
|
||||
X148 CIP X 9 I.S. 219 (OLD I.S. 148) RETAINING WALL 583000 false -73.90440606498304 40.833636708483105 3630 THIRD AVENUE Bronx NY 10456
|
||||
X022 CIP X 9 I.S. 22 FLOOD ELIMINATION/EXT MASONRY/PARAPETS 3990000 false -73.91408537225458 40.83322765425807 270 167 STREET Bronx NY 10456
|
||||
X149 CIP X 7 I.S. 223 (@X149) FY10 RESO A LIBRARY 328000 false -73.92087771305378 40.814006958025736 360 145 STREET Bronx NY 10454
|
||||
Q226 CIP Q 27 I.S. 226 EXT MASONRY/ROOFS 6691000 false -73.81770717164864 40.67334524268887 121 10 ROCKAWAY BLVD SO OZONE PARK NY 11420
|
||||
Q227 CIP Q 30 I.S. 227 CLIMATE CONTROL/HEATING PLANT UPGRADE 5294240 false -73.8723788986672 40.76341327370369 32 02 JUNCTION BLVD QUEENS NY 11369
|
||||
X082 CIP X 9 I.S. 232 (OLD 82) @X082 ACCESSIBILITY/FIRE ALARM 8193000 false -73.91609317547116 40.84901889749711 1700 MACOMBS ROAD Bronx NY 10453
|
||||
R024 CIP R 31 I.S. 24 AUDITORIUM FLOORS 77000 false -74.14643932417457 40.54537484828736 225 CLEVELAND AVENUE Staten Island NY 10308
|
||||
K246 CIP K 17 I.S. 246 SWB EXT MASONRY/SWB FLOOD/SWB WINDOWS/ROOF/PARAPET 4877000 false -73.95284496748633 40.64867994929756 72 VERONICA PLACE Brooklyn NY 11226
|
||||
K252 CIP K 18 I.S. 252 LL 41/16 COMPLIANCE 29175.77 false -73.92001930874018 40.658327698451274 1084 LENOX ROAD Brooklyn NY 11212
|
||||
M118 CIP M 3 I.S. 256 (@M118) IP SURVEILLANCE CAMERAS 216300 false -73.97053578315399 40.79156776872092 154 93 STREET New York NY 10025
|
||||
M118 CIP M 3 I.S. 256 (@M118) STRUCTURAL BEAMS-REINFORCING 410160 false -73.97053578315399 40.79156776872092 154 93 STREET New York NY 10025
|
||||
K265 CIP K 13 I.S. 265 SCIENCE LAB 765000 false -73.97572262403403 40.6963585351778 101 PARK AVENUE Brooklyn NY 11205
|
||||
K278 CIP K 22 I.S. 278 ROOFS/EXT MASONRY/FLOOD ELMNTN 5700000 false -73.93925429415825 40.60673733465248 1925 STUART STREET Brooklyn NY 11229
|
||||
K285 CIP K 18 I.S. 285 HEATING PLANT UPG/CLIMATE CTRL 4342000 false -73.921125893014 40.64688182984673 5905 BEVERLY ROAD Brooklyn NY 11203
|
||||
K291 CIP K 32 I.S. 291 HEATING PLANT UPGRADE/LOW-VOLTAGE 15199800 false -73.91527095847802 40.695256718115104 231 PALMETTO STREET Brooklyn NY 11221
|
||||
K292 CIP K 19 I.S. 292 CONCRETE FACADE 3477000 false -73.89288114787357 40.67148750548741 300 WYONA STREET Brooklyn NY 11207
|
||||
K318 CIP K 14 I.S. 318 PARAPETS/EXT MASONRY/EAST ROOF & FAN ROOM ROOF 4340000 false -73.94902462531712 40.702422370537974 101 WALTON STREET Brooklyn NY 11206
|
||||
K320 CIP K 17 I.S. 320 FLOOD ELMNTN/PARAPETS/SAFETY SYSTEMS/EXT MASONRY 3000050 false -73.95904314893046 40.66501317051537 46 MCKEEVER PLACE Brooklyn NY 11225
|
||||
M125 CIP M 5 I.S. 362 @ M125 SCIENCE LAB 1354564 false -73.95506966627367 40.81015743904045 425 123 STREET New York NY 10027
|
||||
X067 CIP X 12 I.S. 372 - X NEW SCIENCE LAB SUITE 945000 false -73.88479553814723 40.84392182388185 2024 MOHEGAN AVENUE Bronx NY 10460
|
||||
K383 CIP K 32 I.S. 383 PLANYC BOILER CONVERSION/PLANYC CLIMATE CONTROL 4668000 false -73.91986972170302 40.69762704651303 1300 GREENE AVENUE Brooklyn NY 11237
|
||||
K390 CIP K 17 I.S. 390 STAIRS IN STAIRWELL/FLOOD ELIM/CEC REQ-WINDOWS 4980000 false -73.93695770187597 40.67268717852895 1224 PARK PLACE Brooklyn NY 11213
|
||||
K049 CIP K 14 I.S. 49 FIRE ALARM 468000
|
||||
X052 CIP X 8 I.S. 52 PARAPETS/MASONRY/ROOFS/FLOOD/PAVED AREAS/SAFETY 8893000 false -73.90236106648733 40.815402542289604 681 KELLY STREET Bronx NY 10455
|
||||
K055 CIP K 23 I.S. 55 SAFETY SYSTEM/EXT MASONRY/WINDOWS 4535000 false -73.91355073965249 40.67414724704465 2021 BERGEN STREET Brooklyn NY 11233
|
||||
Q059 CIP Q 29 I.S. 59 LIBRARY UPGRADE 408000 false -73.75087393328533 40.66971118122609 132 55 RIDGEDALE STREET SPRINGFIELD GARDENS NY 11413
|
||||
K061 CIP K 17 I.S. 61 BOILER REPLACEMENT/CONCRETE PAVER/CLIMATE CTRL 5462800 false -73.9494072266281 40.66397432612488 400 EMPIRE BLVD Brooklyn NY 11225
|
||||
R072 CIP R 31 I.S. 72 ELEVATORS & ESCALATORS 691000 false -74.15872479868553 40.59325258206939 33 FERNDALE AVENUE Staten Island NY 10314
|
||||
Q849 CIP Q 24 I.S. 77 AUDITORIUM UPGRADE 1588000 false -73.90222734682403 40.699542257956786 976 SENECA AVENUE RIDGEWOOD NY 11385
|
||||
Q849 CIP Q 24 I.S. 77 EXTERIOR MASONRY/WINDOWS/ROOFS/PARAPETS/AC 12189000 false -73.90222734682403 40.699542257956786 976 SENECA AVENUE RIDGEWOOD NY 11385
|
||||
K078 CIP K 22 I.S. 78 FLOOD ELMNTN/EXT MASONRY 1589500 false -73.91286070496677 40.62118169409423 1420 68 STREET Brooklyn NY 11234
|
||||
X084 CIP X 12 I.S. 84 (@X084) PLANYC BOILER CONVRSN/PLANYC CLIMATE CTRL 3997000 false -73.88752511974951 40.830644846579055 1434 LONGFELLOW AVENUE Bronx NY 10459
|
||||
K043 CIP K 21 I.S. 98 EXT MASONRY/ROOFS/SAFETY SYSTEMS/PARAPETS 4869000 false -73.95376310696645 40.58324060677732 1401 EMMONS AVENUE Brooklyn NY 11235
|
||||
X098 CIP X 12 I.S. 98 RETAINING WALL 229571 false -73.89054065425974 40.83591680891802 1619 BOSTON ROAD Bronx NY 10460
|
||||
X139 CIP X 7 INTERNATIONAL COMMUNITY NEW SCIENCE LAB SUITE 1182000 false -73.91782345430987 40.81004862442692 345 BROOK AVENUE Bronx NY 10454
|
||||
X113 CIP X 11 IS 113 FY07 RES0 A PLAYGROUND REDEVELOPMENT 555000.05 false -73.86088460706405 40.88086639044798 3710 BARNES AVE Bronx NY 10467
|
||||
X285 CAP X 9 IS 285 New 34111000 false -73.92787186717345 40.838131334426876 200 167th St Bronx NY 10452
|
||||
Q297 CIP Q 30 IS 297 DEMOLITION FOR IS 297 746444 false -73.88361254528269 40.75163073936716 74 03 34TH AVE JACKSON HEIGHTS NY 11372
|
||||
X147 CIP X 9 IS 339 (OLD IS 147X) PLANYC BOILER/PLANYC CLIMATE CTRL 7116000 false -73.90441220971972 40.84131870954352 1600 WEBSTER AVENUE Bronx NY 10457
|
||||
Q404 CAP Q 78 IS/HS 404 New 61098000 false -73.93866902925225 40.74570244980828 1 50 51st Ave Long Island City NY 11101
|
||||
K422 CAP K 78 IS/HS @ Spring Creek New 72847565 false -73.87479320757765 40.65755969070249 1065 Elton St Brooklyn NY 11208
|
||||
X475 CIP X 10 J F KENNEDY HS FY09 FINAL C OF O FOR MULTI-CAMPUS 8387000 false -73.91213621128965 40.877210772673564 99 TERRACE VIEW AVENUE Bronx NY 10463
|
||||
Q141 CIP Q 30 J.H.S. 141 ROOFS/SAFETY/EXT MASONRY/PARAPETS 7459000 false -73.90960650023976 40.780092072491186 37 11 21 AVENUE QUEENS NY 11105
|
||||
X141 CIP X 10 J.H.S. 141 HEATING PLANT UPGRADE/CLIMATE CONTROL 3967000 false -73.9131873185513 40.88826732332943 660 237 STREET Bronx NY 10463
|
||||
Q157 CIP Q 28 J.H.S. 157 ROOFS/WDWS/HEATING UPG/FLOOD/MASON/PARAPET/CLIMATE 14279000 false -73.86148084756303 40.72646491702238 63 55 102ND ST QUEENS NY 11374
|
||||
Q168 CIP Q 25 J.H.S. 168 ACCESSIBILITY/FIRE ALARM/CLIM CTRL/HEAT PL UPG 8877000 false -73.79226817393703 40.72816440726166 158 40 76 ROAD QUEENS NY 11366
|
||||
Q168 CIP Q 25 J.H.S. 168 SCIENCE LAB UPGRADE 972000 false -73.79226817393703 40.72816440726166 158 40 76 ROAD QUEENS NY 11366
|
||||
Q180 CIP Q 27 J.H.S. 180 WINDOW/AC RETROFIT/AC SPLIT/MASONRY/PARAPET/ROOFS 22000000 false -73.85077700055808 40.57657830564432 3 20 BEACH 104 STREET ROCKAWAY NY 11694
|
||||
Q237 CIP Q 25 J.H.S. 237 CEC REQUEST - SCIENCE LAB UPG 1176000 false -73.82147854789662 40.7512997969481 46 21 COLDEN STREET QUEENS NY 11355
|
||||
Q025 CIP Q 25 J.H.S. 25 SWB-EXT MASONRY/ROOFS/PARAPETS 5618000 false -73.82147854789662 40.7512997969481 34 65 192 STREET QUEENS NY 11355
|
||||
K303 CIP K 21 J.H.S. 303 FY11 RESO A ELECTRICAL SYSTEM 196000 false -73.9727279509789 40.582102240554626 501 WEST AVENUE Brooklyn NY 11224
|
||||
K324 CIP K 16 J.H.S. 324 PLANYC BOILER CONVRSN/PLANYC CLIMATE CTRL 3819000 false -73.93217356292678 40.68830858053017 800 GATES AVENUE Brooklyn NY 11221
|
||||
M045 CIP M 4 J.H.S. 45 EXT MASONRY/ROOFS/PARAPETS 6670000 false -73.93335561512028 40.798869844574995 2351 1ST AVENUE New York NY 10035
|
||||
K057 CIP K 16 J.H.S. 57 GYM ROOF/SEWAGE FLOODING/PARAPETS/EXT MASONRY 8625000 false -73.93365273330902 40.691184878420714 125 STUYVESANT AVENUE Brooklyn NY 11221
|
||||
M070 CIP M 2 J.H.S. 70 EXTERIOR MASONRY/PARAPETS/ROOFS/WINDOWS 10489000 false -74.00204411405305 40.742083302451746 333 17 STREET NEW YORK NY 10011
|
||||
Q072 CIP Q 28 J.H.S. 72 EXT MASONRY/ROOFS/FLOOD ELMNTN/PARAPETS 6176000 false -73.77530690169215 40.6769452621142 133 25 ROCHDALE VILLAG NY 11434
|
||||
X080 CIP X 10 J.H.S. 80/P.S. 280 FLOOD ELIMINATION 1091773 false -73.88147439492262 40.87619978760749 149 MOSHOLU PKWY BRONX NY 10467
|
||||
Q470 CIP Q 28 JAMAICA HS CLIMATE CONTROL/HEATING PLANT UPGRADE 8100000 false -73.79282099978928 40.71311535449007 167 01 GOTHIC DRIVE QUEENS NY 11432
|
||||
M440 CIP M 2 JAMES BALDWIN HS LIBRARY UPGRADE 1132000 false -74.00211145861485 40.74287308397775 351 18 STREET New York NY 10011
|
||||
K425 CIP K 22 JAMES MADISON HS FIRE ALARM 485500 false -73.94845748858913 40.609742865286414 3787 BEDFORD AVENUE Brooklyn NY 11229
|
||||
K425 CIP K 22 JAMES MADISON HS SCIENCE LAB UPGRADE 985000 false -73.94845748858913 40.609742865286414 3787 BEDFORD AVENUE Brooklyn NY 11229
|
||||
Q008 CIP Q 28 JHS 8 SCIENCE LAB UPGRADE 1081000 false -73.7875740339145 40.698104881734935 108 35 167 STREET JAMAICA NY 11433
|
||||
Q425 CIP Q 25 JOHN BOWNE H.S. WIND REPLACE/AC RETROFIT/WIND BOE PORTION/UPG F.A. 27239000 false -73.82610630716033 40.730323085042414 63 25 MAIN STREET FLUSHING NY 11367
|
||||
K460 CIP K 15 JOHN JAY HS CEC REQUEST-HEAT'G PLANT UPG/ELEC SYS/CLIMATE CTRL 8168000 false -73.97924096910276 40.669623280409056 237 7TH AVENUE Brooklyn NY 11215
|
||||
K400 CIP K 21 LAFAYETTE HS UPGRADE BOILER PLANT/CLIMATE CONTROL 12400000 false -73.98615807328032 40.59448014682783 2630 BENSON AVENUE Brooklyn NY 11214
|
||||
Q490 CIP Q 29 LAW, GOVERNMENT & COMMUNITY HS CAMPUS RESTRUCTURING 435000 false -73.73568329125084 40.694293339066405 207 01 116TH AVENUE CAMBRIA HEIGHTS NY 11411
|
||||
X406 CIP X 8 LEHMAN AF ATHLETIC FIELDS 3748000 false -73.83830582037355 40.840618266233676 3000 TREMONT AVENUE BRONX NY 10461
|
||||
X405 CIP X 8 LEHMAN HS FY07 RESO A COMPUTER EQUIPMENT UPGR 75757.5758 false -73.83830582037355 40.840618266233676 3000 TREMONT AVENUE Bronx NY 10461
|
||||
X405 CIP X 8 LEHMAN HS STAIR WINDOWS 1087000 false -73.83830582037355 40.840618266233676 3000 TREMONT AVENUE Bronx NY 10461
|
||||
M645 CIP M 2 LIFE SCIENCE SECONDARY (@M645) FLOOD ELMNTN/EXT MASONRY/PARAPETS/ROOFS 7819500 false -74.03340357628376 40.616237105936534 320 96 STREET New York NY 10028
|
||||
M490 CIP M 3 MARTIN LUTHER KING HS AUD/ALARM REPLACEMENT/FINAL C OF O/VENTILATION 4647000 false -73.98485156692796 40.77425845083081 122 AMSTERDAM AVENUE New York NY 10023
|
||||
X099 CIP X 12 METROPOLITAN HS @ FORMER PS99X CODE COMPLIANCE/PA SYSTEM/PARAPET/MASONRY/ROOFS 5186000 false -73.89313106784448 40.82552621616202 1180 REVEREND JAMES POLITE AVE BRONX NY 10459
|
||||
M081 CIP M 3 MID-MAN ADULT TRAINING CENTER VENTILATION/ELEC SYSTEM 3711000 false -73.95128826417978 40.80602392163958 212 120TH ST NEW YORK NY 10027
|
||||
Q520 CIP Q 30 MIDDLE COLLEGE HS @LAGUARDIA DEMOLITION FOR MIDDLE COLLEGE HS 13112000 false -73.93866902925225 40.74570244980828 45 35 VAN DAM ST LONG ISLAND CITY NY 11101
|
||||
K406 CIP K 21 MIDWOOD AF (MAIN) FY11 RESO A ATHLETIC FIELDS 2146000 false -73.95905922151692 40.62291467677543 1124 17TH STREET BROOKLYN NY 11230
|
||||
M435 CIP M 4 MNHT CENTER FOR MATH & SCIENCE INTERIOR SPACES MARBLE PANELS ONLY 843000 false -73.9336482061862 40.794391919064594 260 PLEASANT AVENUE New York NY 10029
|
||||
X400 CIP X 9 MORRIS HS CERTIFICATE OF OCCUPANCY 5229000 false -73.90448079300582 40.8276109731601 1110 BOSTON RD BRONX NY 10456
|
||||
K390 CIP K 17 MS 334 SCIENCE DEMO ROOM UPGRADE 808000 false -73.93695770187597 40.67268717852895 1224 PARK PLACE Brooklyn NY 11213
|
||||
Q520 CAP Q 78 Middle College HS @ LaGuardia New 27927000 false -73.93866902925225 40.74570244980828 45 35 Van Dam St Long Island City NY 11101
|
||||
Q520 CAP Q 78 Middle College HS @ LaGuardia Room Conversion 13112000 false -73.93866902925225 40.74570244980828 45 35 Van Dam St Long Island City NY 11101
|
||||
R435 CIP R 31 NEW DORP HS LL 41/16 COMPLIANCE 10621.99 false -74.10726241466374 40.56922370455037 465 NEW DORP LANE Staten Island NY 10306
|
||||
K032 CIP K 15 NEW HORIZONS SCHOOL FY11 RESO A AUDITORIUM UPDATE 228000 false -73.99193273420018 40.680429275762485 317 HOYT STREET Brooklyn NY 11231
|
||||
M868 CIP M 2 NEW HS DEMOLITION FOR IS/HS 868 2182222 false -73.99224802961538 40.73631370241236 10 15TH ST NEW YORK NY 10003
|
||||
K445 CIP K 20 NEW UTRECHT HS EXT MASONRY/FLOOD ELMNTN/PARAPETS/ROOFS 10570000 false -74.00368977353216 40.61345273159829 1601 80TH ST Brooklyn NY 11214
|
||||
K445 CIP K 20 NEW UTRECHT HS FY09 RESO A LIBRARY UPGRADE 353250 false -74.00368977353216 40.61345273159829 1601 80TH ST Brooklyn NY 11214
|
||||
Q450 CIP Q 30 NEWCOMERS HS EXT MASONRY/PARAPETS/FLOOD ELMNTN 8395000 false -73.93866902925225 40.74570244980828 28 01 41ST AVENUE LONG ISLAND CITY NY 11101
|
||||
Q455 CIP Q 24 NEWTOWN HS FLOORS 2662000 false -73.87475600018911 40.74125600016447 48 01 90 STREET QUEENS NY 11373-4099
|
||||
M001 CIP M 2 P.S. 1 EXTERIOR MASONRY/PARAPETS/PAVED AREAS-CONCRETE 5139000 false -73.99734184420807 40.712756780441026 8 HENRY STREET New York NY 10038
|
||||
X001 CIP X 7 P.S. 1 IP SURVEILLANCE CAMERAS 1056000 false -73.91874134609046 40.818762661509254 335 152 STREET Bronx NY 10451
|
||||
Q100 CIP Q 27 P.S. 100 FLOOD ELMNTN/EXT MASONRY/PARAPETS 3199900 false -73.81770717164864 40.67334524268887 111 11 118 STREET JAMAICA NY 11420
|
||||
K101 CIP K 21 P.S. 101 RESO A - RESO A SCIENCE LAB 268800 false -73.99175987597347 40.59787681678778 2360 BENSON AVENUE Brooklyn NY 11214
|
||||
M101 CIP M 4 P.S. 101 ACCESSIBILITY 3689000 false -73.94443112132485 40.79566898981534 141 111 STREET NEW YORK NY 10029
|
||||
M101 CIP M 4 P.S. 101 ELEC UPGRADE 287950 false -73.94443112132485 40.79566898981534 141 111 STREET NEW YORK NY 10029
|
||||
X103 CIP X 11 P.S. 103 FY11 RESO A AUDITORIUM UPGRADE 419000 false -73.8614419003563 40.89224585042134 4125 CARPENTER AVENUE Bronx NY 10466
|
||||
Q105 CIP Q 27 P.S. 105 SWB EXT MASONRY/PARAPETS 1050000 false -73.78189411037111 40.59623844790385 420 BEACH 51 STREET FAR ROCKAWAY NY 11691
|
||||
K108 CIP K 19 P.S. 108 FY11 RESO A ELECTRICAL SYSTEM 345900 false -73.88403250144414 40.681012991519715 200 LINWOOD STREET Brooklyn NY 11208
|
||||
Q108 CIP Q 27 P.S. 108 CAFE MULTIPURPOSE ROOM UPG 233000 false -73.81770717164864 40.67334524268887 108 10 109 AVENUE SO OZONE PARK NY 11420
|
||||
X011 CIP X 9 P.S. 11 FLOOD ELMNTN/ROOFS/MASONRY/PARAPETS 6116000 false -73.92578827979769 40.83927054580515 1257 OGDEN AVENUE Bronx NY 10456
|
||||
X011 CIP X 9 P.S. 11 SIDEWALK BRIDGE 19442.75 false -73.92578827979769 40.83927054580515 1257 OGDEN AVENUE Bronx NY 10456
|
||||
K110 CIP K 14 P.S. 110 ROOFS/WINDOWS 3778000 false -73.94223625609604 40.723642548516075 124 MONITOR STREET Brooklyn NY 11222
|
||||
M110 CIP M 1 P.S. 110 FLOOD ELIMINATION 547000 false -73.97981939917048 40.715620302518175 285 DELANCY STREET New York NY 10002
|
||||
M111 CIP M 2 P.S. 111 CLIMATE CONTROL/HEATING PLANT UPGRADE 4305729 false -73.98953901918651 40.76616371249781 440 53 STREET New York NY 10019
|
||||
Q111 CIP Q 30 P.S. 111 HEATING PLANT UPG/CLIMATE CTRL 3811000 false -73.93866902925225 40.74570244980828 37 15 13 STREET QUEENS NY 11101
|
||||
K112 CIP K 20 P.S. 112 PARAPETS/EXT MASONRY/FLOOD ELMNTN 1420000 false -74.00071660633716 40.619828663672465 7115 15 AVENUE Brooklyn NY 11228
|
||||
K115 CIP K 18 P.S. 115 EXT MASONRY/ROOFS/PARAPETS 5747000 false -73.89697682968284 40.63477746307819 1500 92ND ST Brooklyn NY 11236
|
||||
M115 CIP M 6 P.S. 115 EXTERIOR MASONRY/HAZARDOUS-PARAPETS/ROOFS 2979000 false -73.93487128414608 40.84641769845956 586 177 STREET New York NY 10033
|
||||
K116 CIP K 32 P.S. 116 FY11 RESO A SCIENCE 388000 false -73.91643018838859 40.69774977550555 515 KNICKERBOCKER AVENUE Brooklyn NY 11237
|
||||
M116 CIP M 2 P.S. 116 FY11 RESO A PLAYGROUND REDEVELOPMENT 300000 false -73.97834193335258 40.74491153710013 210 33 STREET New York NY 10016
|
||||
X012 CIP X 11 P.S. 12 HEATING PLT UPG/CLIMATE CNTRL/LOW-VOLT ELECTRICAL 5722850 false -73.84450496658253 40.84010546581863 2555 TRATMAN AVENUE Bronx NY 10461
|
||||
K121 CIP K 21 P.S. 121 SWB-EXT MASONRY 1295000 false -73.97875690985585 40.62330608676003 5301 20TH AVENUE Brooklyn NY 11204
|
||||
Q121 CIP Q 28 P.S. 121 CLIMATE CONTROL/HEATING PLANT UPGRADE 3305000 false -73.81770717164864 40.67334524268887 126 10 109 AVENUE SO OZONE PARK NY 11420
|
||||
M123 CIP M 5 P.S. 123 FY10 RESO A SCIENCE LAB UPGRADE 444000 false -73.94425698262674 40.81972211192899 301 140 STREET New York NY 10030
|
||||
Q124 CIP Q 27 P.S. 124 EXT MASONRY/PARAPETS 3342000 false -73.81770717164864 40.67334524268887 129 15 150 AVENUE SO OZONE PARK NY 11420
|
||||
M124 CIP M 2 P.S. 124 (ECF) PARAPETS/EXTERIOR MASONRY 1367000 false -73.99579682364542 40.71420254465372 40 DIVISION STREET New York NY 10002
|
||||
M126 CIP M 2 P.S. 126 FY10 RESO A LIBRARY 415000 false -73.9966721705172 40.710854298398544 80 CATHERINE STREET New York NY 10038
|
||||
X126 CIP X 9 P.S. 126 (ECF) MASONRY/ROOFS/FLOOD ELMNTN/PARAPETS 5194000 false -73.9283372125368 40.83581122271332 175 166 STREET Bronx NY 10452
|
||||
K127 CIP K 20 P.S. 127 EXT MASONRY 2149000 false -74.01885662493696 40.62406545959219 7805 7 AVENUE Brooklyn NY 11209
|
||||
Q127 CIP Q 30 P.S. 127 AUD UPG/CAFETERIA MULTIPURPOSE RM UPG 985000 false -73.8723788986672 40.76341327370369 98 01 25 AVENUE EAST ELMHURST NY 11369
|
||||
X129 CIP X 12 P.S. 129 (PAIRED W X234) EXTERIOR MASONRY 2598000 false -73.8865507352739 40.84549455019818 2055 MAPES AVENUE Bronx NY 10460
|
||||
X129 CIP X 12 P.S. 129 (PAIRED W X234) SIDEWALK BRIDGE (EXT. MASONRY) 32157.31 false -73.8865507352739 40.84549455019818 2055 MAPES AVENUE Bronx NY 10460
|
||||
K132 CIP K 14 P.S. 132 FLOOD ELMNTN/WINDOWS/PARAPETS 6597000 false -73.9456777023208 40.71219332880771 320 MANHATTAN AVENUE Brooklyn NY 11206
|
||||
K132 CIP K 14 P.S. 132 FY10 RESO A GYM RENOVATION 70000 false -73.9456777023208 40.71219332880771 320 MANHATTAN AVENUE Brooklyn NY 11206
|
||||
K132 CIP K 14 P.S. 132 WORK REQUIRED TO OBTAIN C OF O 932000 false -73.9456777023208 40.71219332880771 320 MANHATTAN AVENUE Brooklyn NY 11206
|
||||
M132 CIP M 6 P.S. 132 FY11 RESO A SCIENCE LAB 243500 false -73.93432269770818 40.85071645775963 185 WADSWORTH AVENUE New York NY 10033
|
||||
X132 CIP X 9 P.S. 132 INTERIOR STRUCTURAL INVESTMENT - TEST 5005000 false -73.90656891847989 40.83194251909681 1245 WASHINGTON AVENUE Bronx NY 10456
|
||||
K135 CIP K 18 P.S. 135 PARAPETS/FLOOD ELMNTN/ROOFS 1784000 false -73.93311810571299 40.65357812334444 684 LINDEN BLVD Brooklyn NY 11203
|
||||
K138 CIP K 17 P.S. 138 ROOFS/PARAPETS/EXT MASONRY 2793000 false -73.95141196170016 40.674353675202426 760 PROSPECT PLACE Brooklyn NY 11216
|
||||
K138 CIP K 17 P.S. 138 SCIENCE DEMO ROOM UPGRADE 762000 false -73.95141196170016 40.674353675202426 760 PROSPECT PLACE Brooklyn NY 11216
|
||||
M844 CIP M 2 P.S. 138 (@M844) SWB - FACADE/PARAPETS/ROOFS 8833000 false -73.97802974198606 40.73757796345728 400 1ST AVENUE New York NY 10010
|
||||
K849 CIP K 22 P.S. 139 AX (OLD 134) LL 41/16 COMPLIANCE 100000 false -73.97391982714538 40.632244467750226 4001 18 AVENUE Brooklyn NY 11208
|
||||
R014 CIP R 31 P.S. 14 ROOFS/EXT MASONRY/WINDOWS/FLOORS/SAFETY SYSTEMS 3315000 false -74.07837687526822 40.622148795415534 100 TOMPKINS AVENUE Staten Island NY 10304
|
||||
Q140 CIP Q 28 P.S. 140 PARAPETS 3269000 false -73.77530690169215 40.6769452621142 116 00 166 ST JAMAICA NY 11434
|
||||
M142 CIP M 1 P.S. 142 ELEVATORS & ESCALATORS/TOILETS-STUDENTS 2995000 false -73.98376386528082 40.71945606619147 100 ATTORNEY STREET New York NY 10002
|
||||
K145 CIP K 32 P.S. 145 PARAPETS/FLOOD ELMNTN/EXT MASONRY/EXT LIGHTING 4737575 false -73.93232374110994 40.7016598916867 100 NOLL STREET Brooklyn NY 11206
|
||||
K142 CIP K 15 P.S. 146 (@K142) PARAPETS/EXTERIOR MASONRY/ROOFS/WINDOWS/FLOOD 13106731 false -74.00136121297172 40.68011121449034 610 HENRY STREET Brooklyn NY 11231
|
||||
Q147 CIP Q 29 P.S. 147 FLOORS 537000
|
||||
K015 CIP K 15 P.S. 15 LIBRARY UPGRADE 411054
|
||||
M153 CIP M 6 P.S. 153 DEFECTIVE MASONRY/ROOFS/DOORS/PARAPETS 4134000 false -73.94689450753023 40.8262600138953 1750 AMSTERDAM AVENUE New York NY 10031
|
||||
Q154 CIP Q 25 P.S. 154 ACCESSIBILITY/ELEC SYS/MASONRY/ROOFS/FLOOD/PARAPET 6127000 false -73.79226817393703 40.72816440726166 75 02 162 STREET FLUSHING NY 11366
|
||||
M155 CIP M 4 P.S. 155 FLOOD ELMNTN/PARAPETS/EXT MASONRY 2350000 false -73.93679763009355 40.797501313680264 319 117 STREET New York NY 10035
|
||||
Q156 CIP Q 29 P.S. 156 SWB - EXT MASONRY/FLOOD ELMNTN/WINDOWS/PARAPETS 7354000 false -73.75087393328533 40.66971118122609 229 02 137 AVENUE SPRINGFIELD GAR NY 11413
|
||||
X156 CIP X 7 P.S. 156 CINDER BLOCK WALLS & CEILING BEAMS/FLOOD ELIMN 9780000 false -73.92024166597307 40.82226334901861 750 CONCOURSE VILLAGE Bronx NY 10451
|
||||
K157 CIP K 14 P.S. 157 SWB-MASONRY 1843000 false -73.95959701353979 40.69546110023352 850 KENT AVENUE Brooklyn NY 11205
|
||||
X157 CIP X 7 P.S. 157 FY11 RESO A LIBRARY UPGRADE 178000 false -73.90861019557366 40.81920242494304 757 CAULDWELL AVENUE Bronx NY 10456
|
||||
K158 CIP K 19 P.S. 158 EXT MASONRY/FLOOD ELIMINATION 4244000 false -73.88480467674624 40.672471173748015 400 ASHFORD STREET Brooklyn NY 11207
|
||||
K016 CIP K 14 P.S. 16 CEC REQUEST - STUDENT CAFETERIA UPG 1139000 false -73.96144993294666 40.706051659903764 157 WILSON STREET Brooklyn NY 11211
|
||||
X160 CIP X 11 P.S. 160 FY11 RESO A LIBRARY 345300 false -73.8242748469253 40.86466106194175 4140 HUTCHINSON RIVER PARKWAY Bronx NY 10475
|
||||
K161 CIP K 17 P.S. 161 LIBRARY UPGRADE 89500 false -73.94885261044026 40.66615564566118 330 CROWN STREET Brooklyn NY 11225
|
||||
X163 CIP X 9 P.S. 163 INTERIOR MODERNIZATIONS/ROOFS 3143000 false -73.89841328719618 40.85190466527893 2075 WEBSTER AVENUE Bronx NY 10457
|
||||
M165 CIP M 3 P.S. 165 ROOF TILES & SNOW GUARD/EXT MASONRY/FLOOD/PARAPETS 2118994.65 false -73.96526411800443 40.80275180384162 234 109 STREET New York NY 10025
|
||||
K017 CIP K 14 P.S. 17 WINDOWS/EXT MASONRY/FLOOD ELMNTN/ROOFS/PARAPETS 7842000 false -73.95663645640386 40.715277522913524 208 5 STREET Brooklyn NY 11211
|
||||
M173 CIP M 6 P.S. 173 FIRE ALARM 359900 false -73.94042010106682 40.84561730185351 306 FORT WASHINGTON AVE New York NY 10033
|
||||
Q174 CIP Q 28 P.S. 174 FY11 RESO A LIBRARY UPGRADE 104000 false -73.86148084756303 40.72646491702238 65 10 DIETERLE CRESCENT REGO PARK NY 11374
|
||||
Q175 CIP Q 28 P.S. 175 FY11 RESO A FENCING 319571 false -73.86148084756303 40.72646491702238 64 35 102 STREET REGO PARK NY 11374
|
||||
X175 CIP X 11 P.S. 175 INTERIOR MODERNIZATIONS/WINDOWS 5296000 false -73.78516944174876 40.84381012246547 200 CITY ISLAND AVENUE Bronx NY 10464
|
||||
K178 CIP K 23 P.S. 178 FLOORS 695000 false -73.9159181765978 40.675074588842676 2163 DEAN STREET Brooklyn NY 11212
|
||||
Q178 CIP Q 26 P.S. 178 HEATING PLANT UPGRADE/CLIMATE CONTROL/MASONRY 7100000 false -73.7671414999802 40.71722229567246 189 10 RADNOR RD JAMAICA NY 11423
|
||||
R018 CIP R 31 P.S. 18 BOILER REPLACEMENT 3171000 false -74.11747369098056 40.63603930909672 221 BROADWAY Staten Island NY 10310
|
||||
X182 CIP X 8 P.S. 182 BRICK MASONRY WATER PENETRATION/WINDOWS 3464027 false -73.85625766017206 40.817936957362555 601 STICKBALL BLVD BRONX NY 10473
|
||||
Q183 CIP Q 27 P.S. 183 MSNRY/SFTY/WINDOW/LIBRARY UPG/HVAC/ROOF/FIRE ALARM 8248000 false -73.82495531523557 40.6183036047276 2 45 BEACH 79 STREET ROCKAWAY BEACH NY 11693
|
||||
M137 CIP M 1 P.S. 184 (SHUANG WEN @M137) FY11 RESO A PLAYGROUND REDEVELOPMENT 230000 false -73.98042410080346 40.71217484702834 327 CHERRY ST New York NY 10002
|
||||
M137 CIP M 1 P.S. 184 (SHUANG WEN @M137) SWB-HAZARDOUS VIOLATION/ROOFS 979000 false -73.98042410080346 40.71217484702834 327 CHERRY ST New York NY 10002
|
||||
Q186 CIP Q 26 P.S. 186 ACCESSIBILITY/FIRE ALARM SYSTEM/ELECTRICAL SYSTEMS 4577000 false -73.72415699894628 40.73704138495202 252 12 72 AVENUE BELLEROSE NY 11426
|
||||
Q186 CIP Q 26 P.S. 186 FLOOD ELIMINATION 968000 false -73.72415699894628 40.73704138495202 252 12 72 AVENUE BELLEROSE NY 11426
|
||||
K188 CIP K 21 P.S. 188 RESO A GYM ADDITION/FY10 RESO A PLAYGROUND 7879007 false -74.00012292790208 40.57720405091032 3314 NEPTUNE AVENUE Brooklyn NY 11224
|
||||
M188 CIP M 1 P.S. 188 ACCESSIBILITY 6422000 false -73.97792876586212 40.719709960041634 442 HOUSTON STREET New York NY 10002
|
||||
M188 CIP M 1 P.S. 188 EXTERIOR MASONRY/ROOFS/PARAPETS/WINDOWS 13457000 false -73.97792876586212 40.719709960041634 442 HOUSTON STREET New York NY 10002
|
||||
K189 CIP K 17 P.S. 189 LOW-VOLT SYSTEM 840000 false -73.92626797722787 40.66553683638519 1100 NEW YORK AVE Brooklyn NY 11212
|
||||
Q019 CIP Q 24 P.S. 19 SWB - EXT MASONRY/ROOFS/FLOOD ELIMINATION/PARAPETS 16175000 false -73.85304068857687 40.749678220373596 98 02 ROOSEVELT AVE CORONA NY 11368
|
||||
R019 CIP R 31 P.S. 19 IP SURVEILLANCE CAMERAS 1270000 false -74.127115288525 40.631189624083056 780 POST AVENUE Staten Island NY 10310
|
||||
K190 CIP K 19 P.S. 190 PARAPETS/ROOFS/EXT MASONRY 6720000 false -73.89448660618348 40.66233878188243 590 SHEFFIELD AVENUE Brooklyn NY 11207
|
||||
K191 CIP K 17 P.S. 191 SAFETY SYSTEMS 345900 false -73.92433266937152 40.671984269991356 1600 PARK PLACE Brooklyn NY 11233
|
||||
X198 CIP X 12 P.S. 198 PLANYC BOILER CONVRSN/PLANYC CLIMATE CTRL 3794000 false -73.90058806585479 40.82868626889099 1180 TINTON AVENUE Bronx NY 10456
|
||||
K199 CIP K 21 P.S. 199 FY11 RESO A LIBRARY 369000 false -73.96308897272426 40.61673348809886 1100 ELM AVENUE Brooklyn NY 11230
|
||||
R020 CIP R 31 P.S. 20 EXT MASONRY/ROOFS/WINDOWS 3285000 false -74.13295576709373 40.63651173103697 161 PARK AVENUE Staten Island NY 10302
|
||||
X020 CIP X 10 P.S. 20 ROOFS 1470000 false -73.87958395897564 40.869529034465444 3020 WEBSTER AVENUE BRONX NY 10467
|
||||
K203 CIP K 22 P.S. 203 EXT MASONRY/ROOFS/PARAPETS/FLOOD ELMNTN 5668000 false -73.92773224974349 40.61636866748006 5101 AVENUE Brooklyn NY 11234
|
||||
Q206 CIP Q 28 P.S. 206 FLOOD ELIMINATION 283000 false -73.86148084756303 40.72646491702238 61 02 98TH STREET REGO PARK NY 11374
|
||||
M206 CIP M 4 P.S. 206 (TANDEM PS 112) EXT MASONRY/PARAPETS/FLD ELIMINATION/ROOFS/WALKWAY 5822870 false -73.93112623193574 40.79754733338499 508 120TH STREET New York NY 10035
|
||||
R021 CIP R 31 P.S. 21 FLOORS 418000 false -74.14676832354822 40.63194814504947 168 HOOKER PLACE Staten Island NY 10303
|
||||
X021 CIP X 11 P.S. 21 PARAPETS/EXT MASONRY/FLOOD ELIMINATION/ROOFS 5259000 false -73.86044891659131 40.88782430615607 715 225 STREET Bronx NY 10466
|
||||
K214 CIP K 19 P.S. 214 EXT MASONRY/PARAPETS/FLOOD/WINDOWS/ROOFS 7654000 false -73.8631601400929 40.67649228343164 2944 PITKIN AVENUE Brooklyn NY 11208
|
||||
Q215 CIP Q 27 P.S. 215 FY11 RESO A SCIENCE LAB UPGRADES 260000 false -73.75832418340367 40.59915376512268 535 BRIAR PLACE FAR ROCKAWAY NY 11691
|
||||
K219 CIP K 18 P.S. 219 EXT MASONRY/PARAPETS/ROOFS 3079000 false -73.92291949545782 40.65925656671725 1060 CLARKSON AVENUE Brooklyn NY 11212
|
||||
Q022 CIP Q 25 P.S. 22 FY10 RESO A NEW PLAYGROUND 180000 false -73.82147854789662 40.7512997969481 153 01 SANFORD AVENUE FLUSHING NY 11355
|
||||
R022 CIP R 31 P.S. 22 LIBRARY UPGRADE 340000 false -74.15109445915424 40.62530363633885 1860 FOREST AVENUE Staten Island NY 10303
|
||||
K225 CIP K 21 P.S. 225 ACCESSIBILITY/FIRE ALARM/ELECTRICAL SYSTEMS 4105450 false -73.95643350547934 40.5797910944251 1075 OCEAN VIEW AVENUE Brooklyn NY 11235
|
||||
Q229 CIP Q 24 P.S. 229 SWB - MASONRY/ROOFS 3633000 false -73.9048471440804 40.74519376448069 67 25 51 ROAD WOODSIDE NY 11377
|
||||
X229 CIP X 9 P.S. 229 ELEVATORS & ESCALATORS 1327150 false -73.92150462714196 40.85261854069672 275 HARLEM RIVER PARK BR Bronx NY 10453
|
||||
X229 CIP X 9 P.S. 229 PLANYC BOILER/PLANYC CLIMATE CTRL 2910000 false -73.92150462714196 40.85261854069672 275 HARLEM RIVER PARK BR Bronx NY 10453
|
||||
K230 CIP K 15 P.S. 230 ACCESSIBILITY 4392000 false -73.98088211473515 40.64501828504539 1 ALBEMARLE ROAD Brooklyn NY 11210
|
||||
Q232 CIP Q 27 P.S. 232 FY11 RESO A SCIENCE LAB UPGRADES 384000 false -73.84496263981396 40.65817022817356 153 23 83 STREET HOWARD BEACH NY 11414
|
||||
K236 CIP K 22 P.S. 236 EXT MASONRY/FLOOD ELIMINATION 1054000 false -73.92773224974349 40.61636866748006 6302 AVENUE Brooklyn NY 11234
|
||||
K249 CIP K 17 P.S. 249 EXT MASONRY/ROOFS/PARAPETS 4474000 false -73.96609617601914 40.649842155595174 18 MARLBOROUGH ROAD Brooklyn NY 11226
|
||||
K249 CIP K 17 P.S. 249 FY11 RESO A AUDITORIUM UPGRADE 198000 false -73.96609617601914 40.649842155595174 18 MARLBOROUGH ROAD Brooklyn NY 11226
|
||||
K253 CIP K 21 P.S. 253 BOILER PLANT/CLIMATE CONTROL 4282800 false -73.96219337408164 40.579594157400855 601 OCEAN VIEW AVENUE Brooklyn NY 11235
|
||||
Q816 CIP Q 27 P.S. 256 ANNEX WINDOWS/EXT MASONRY 5282000 false -73.85454217391299 40.576996863641924 445 BEACH 135 STREET QUEENS NY 11694
|
||||
K026 CIP K 16 P.S. 26 PLANYC BOILER/PLANYC CLIMATE CTRL 3960000 false -73.93167037460694 40.69211086975316 1010 LAFAYETTE AVENUE Brooklyn NY 11221
|
||||
Q026 CIP Q 26 P.S. 26 ELECTRICAL SYSTEM 594999 false -73.79462153515567 40.73987184371066 195 02 69 AVENUE FLUSHING NY 11365
|
||||
K262 CIP K 16 P.S. 262 NEW SCIENCE DEMONSTRATION ROOM 534000 false -73.93085733477353 40.68321860795158 500 MACON STREET Brooklyn NY 11233
|
||||
K273 CIP K 19 P.S. 273 EXT MASONRY/ROOFS/PARAPETS 5335000 false -73.87935692616207 40.65796581134507 923 JEROME STREET Brooklyn NY 11207
|
||||
X027 CIP X 7 P.S. 277 (@ X027) SWB-ROOF/SWB-EXT MASONRY/WINDOWS/PARAPETS/ HEATING 15843000 false -73.91337206062776 40.813641430845045 519 ST ANNS AVENUE Bronx NY 10451
|
||||
X279 CIP X 10 P.S. 279 FIRE ALARM UPGRADE 2998000 false -73.90550751626725 40.85444390420279 2100 WALTON AVE BRONX NY 10453
|
||||
X028 CIP X 9 P.S. 28 EXTERIOR MASONRY/PARAPETS/FLOOD ELIMINATION 5016000 false -73.90357863607737 40.84796917302349 1861 ANTHONY AVENUE Bronx NY 10456
|
||||
K284 CIP K 23 P.S. 284 SWB-PARAPET-MASONRY/EXTERIOR MASONRY 5680000 false -73.90818838446248 40.66735004908563 213 OSBORN STREET Brooklyn NY 11212
|
||||
K289 CIP K 17 P.S. 289 WINDOW/CAFE MULTIPURPOSE RM UPG/MASONRY/PARAPET/PA 4440000 false -73.94240595654854 40.67477355898667 900 ST MARKS AVENUE Brooklyn NY 11213
|
||||
R029 CIP R 31 P.S. 29 PARAPETS/EXT MASONRY/ROOFS 3826000 false -74.11613224214713 40.61361168930647 1581 VICTORY BLVD Staten Island NY 10314
|
||||
K003 CIP K 13 P.S. 3 PARAPETS/EXT MASONRY/ROOF/PLAYGROUND REDEVELOPMENT 4820800 false -73.9554933572393 40.68262499957862 50 JEFFERSON AVENUE Brooklyn NY 11216
|
||||
M003 CIP M 2 P.S. 3 FLOORS/INTERIOR SPACES 3824000 false -74.00641883360943 40.73261607852907 490 HUDSON STREET New York NY 10014
|
||||
R003 CIP R 31 P.S. 3 LIGHTING FIXTURES 934104 false -74.21279962614892 40.52665926345466 80 GOFF AVENUE Staten Island NY 10309
|
||||
K306 CIP K 19 P.S. 306 PLAYGROUND REDEVELOPMENT 1071501 false -73.88669548652338 40.65614802525013 970 VERMONT STREET Brooklyn NY 11207
|
||||
K308 CIP K 16 P.S. 308 PAVED AREA-BLACKTOP & TCU 437000 false -73.93578222590314 40.6886393472372 616 QUINCY STREET Brooklyn NY 11221
|
||||
X122 CIP X 10 P.S. 310 (@ X122) FY10 RESO A AUDITORIUM UPG 205000 false -73.90565533914132 40.873019134707036 260 KINGSBRIDGE RD Bronx NY 10463
|
||||
K316 CIP K 17 P.S. 316 HOT WATER HEATER 375000 false -73.96025809844292 40.67448517044413 750 CLASSON AVENUE Brooklyn NY 11238
|
||||
K032 CIP K 15 P.S. 32 FY11 RESO A LIBRARY UPGRADE 357960 false -73.99193273420018 40.680429275762485 317 HOYT STREET Brooklyn NY 11231
|
||||
X032 CIP X 10 P.S. 32 VINYL FLR/BOILER RM/CLIMATE CTRL/HEAT PLANT 15839000 false -73.88593877891165 40.85208555646217 690 183 STREET Bronx NY 10458
|
||||
K329 CIP K 21 P.S. 329 WINDOWS/ROOFS 4659000 false -73.99625853857127 40.5746069203897 2929 30 STREET Brooklyn NY 11212
|
||||
X033 CIP X 10 P.S. 33 GUTTERS, DOWNSPOUTS & DRAINGAGE/FLOOD/EXT MASONRY 2965000 false -73.90165549892143 40.86194912850306 2424 JEROME AVENUE Bronx NY 10468
|
||||
K034 CIP K 14 P.S. 34 ROOFS 1297000 false -73.94966946764082 40.72614326106391 131 NORMAN AVENUE Brooklyn NY 11222
|
||||
Q034 CIP Q 29 P.S. 34 PLAYGROUND & TCU REMOVAL 1375500 false -73.74193729726841 40.721396964798146 104 12 SPRINGFIELD BLVD QUEENS VILLAGE NY 11428
|
||||
M036 CIP M 5 P.S. 36 REINFORCE SUPPRT ELEMT/MASONRY/FLOOD/PARAPET/ ROOF 7179000 false -73.95760614504678 40.81034589186436 123 MORNINGSIDE DRIVE New York NY 10027
|
||||
R036 CIP R 31 P.S. 36 PARAPETS 617000 false -74.18245006610681 40.54294395216458 255 IONIA AVENUE Staten Island NY 10312
|
||||
Q037 CIP Q 29 P.S. 37 FLOOD ELMNTN 4627000 false -73.77530690169215 40.6769452621142 179 37 137 AVENUE JAMAICA NY 11434
|
||||
K370 CIP K 21 P.S. 370 PLAYGROUND REDEVELOPMENT 2587000 false -73.96958337858405 40.577497294548174 3000 1 STREET Brooklyn NY 11224
|
||||
K370 CIP K 21 P.S. 370 WINDOWS/FLOOD ELIMNTN/MASONRY/ROOFS/PARAPETS 6920000 false -73.96958337858405 40.577497294548174 3000 1 STREET Brooklyn NY 11224
|
||||
R040 CIP R 31 P.S. 373 (SP ED) @R040 ROOFS/PARAPETS 824000 false -74.09531252948968 40.64071111953775 91 HENDERSON AVENUE Staten Island NY 10301
|
||||
K384 CIP K 32 P.S. 384 LL 41/16 COMPLIANCE 275000 false -73.90500308262318 40.69009686200851 242 COOPER STREET Brooklyn NY 11221
|
||||
R004 CIP R 31 P.S. 4 FY09 RESO A TECHNOLOGY 90290.18
|
||||
Q040 CIP Q 28 P.S. 40 CEC REQUEST-TOILETS STUDENTS 889000
|
||||
Q040 CIP Q 28 P.S. 40 EXTERIOR MASONRY/PARAPETS 2520000
|
||||
Q040 CIP Q 28 P.S. 40 PLAYGROUND REDEVELOPMENT 1424537
|
||||
M041 CIP M 2 P.S. 41 SWB-EXTERIOR MASONRY/WINDOWS/AUD. CEILING/PARAPETS 3447868 false -73.99904466974961 40.735686525332646 116 11 STREET New York NY 10011
|
||||
Q041 CIP Q 26 P.S. 41 MASONRY SUPPORT REPAIR/PARAPETS 2564500 false -73.77481079967868 40.773606900238235 214 43 35 AVENUE BAYSIDE NY 11261
|
||||
R041 CIP R 31 P.S. 41 FY10 RESO A PA SYSTEMS 448000 false -74.10928336025026 40.574024158045525 216 CLAWSON STREET Staten Island NY 10306
|
||||
R045 CIP R 31 P.S. 45 TOILETS STUDENTS 999999 false -74.10718417740732 40.62863428073003 58 LAWRENCE AVENUE Staten Island NY 10310
|
||||
R045 CIP R 31 P.S. 45 WATER PENETRATION 579900 false -74.10718417740732 40.62863428073003 58 LAWRENCE AVENUE Staten Island NY 10310
|
||||
K046 CIP K 13 P.S. 46 SCIENCE DEMO ROOM 376999 false -73.9711875089949 40.694634881525445 100 CLERMONT AVENUE Brooklyn NY 11205
|
||||
M046 CIP M 5 P.S. 46 SCIENCE DEMO LAB 512000
|
||||
Q046 CIP Q 26 P.S. 46 CORRIDOR SPACES 290000 false -73.75790275560763 40.745924680379744 64 45 218TH STREET QUEENS NY 11364
|
||||
K048 CIP K 20 P.S. 48 EXT MASONRY/PARAPETS/ROOFS 5315000
|
||||
Q050 CIP Q 28 P.S. 50 SWB EXT MASONRY/PARAPETS/ROOFS 1900000 false -73.80979665579099 40.70119264912154 143 26 101 AVENUE JAMAICA NY 11435
|
||||
R050 CIP R 31 P.S. 50 BOILER REPLACEMENT/CLIMATE CONTROL 3330000 false -74.12474473444865 40.561729222740695 200 ADELAIDE AVENUE Staten Island NY 10306
|
||||
X050 CIP X 12 P.S. 50 FLOOD ELIMINATION 818000 false -73.88769223705626 40.83380386816254 1550 VYSE AVENUE Bronx NY 10460
|
||||
M050 CIP M 4 P.S. 50 (UDC & ECF) PLANYC BOILER CONVERSION/PLANYC CLIMATE CONTROL 3174000 false -73.94222449721103 40.78556522081211 433 100 STREET New York NY 10029
|
||||
Q051 CIP Q 27 P.S. 51 (ECC) EXTERIOR MASONRY 1023000 false -73.84031024991805 40.69637041236467 87 45 117TH STREET QUEENS NY 11418
|
||||
Q052 CIP Q 29 P.S. 52 SWB EXT MASONRY 2700000 false -73.77530690169215 40.6769452621142 178 37 146 TERRACE SPRINGFIELD GARDENS NY 11434
|
||||
R053 CIP R 31 P.S. 53 FENCING/PAVED AREAS-CONCRETE 675000 false -74.13710643405284 40.55253899268856 330 DURANT AVENUE Staten Island NY 10308
|
||||
R054 CIP R 31 P.S. 54 PARAPETS/ROOFS/WINDOWS/EXT MASONRY 5847000 false -74.13792964309168 40.60321556338597 1060 WILLOWBROOK RD Staten Island NY 10314
|
||||
Q055 CIP Q 28 P.S. 55 SWB-BULGING MASONRY/PARAPETS 4795000 false -73.82288833053201 40.68871379040917 131 10 97 AVENUE RICHMOND HILL NY 11419
|
||||
R055 CIP R 31 P.S. 55 ROOFS/CEC REQUEST-MASONRY/FLOOD ELMNTN/PARAPETS 1890000 false -74.16332659953605 40.53686781464157 54 OSBORNE STREET Staten Island NY 10312
|
||||
X055 CIP X 9 P.S. 55 EXTERIOR MASONRY/PARAPETS 1285000 false -73.90461113077222 40.836276563944345 450 SAINT PAUL'S PLACE Bronx NY 10456
|
||||
K056 CIP K 13 P.S. 56 PLANYC CLIMATE/BOILER CONTROL 5240000 false -73.960643681102 40.68503684353989 170 GATES AVENUE Brooklyn NY 11238
|
||||
R057 CIP R 31 P.S. 57 PLANYC PLAYGROUND 613715.9 false -74.08283106498078 40.61136129612238 140 PALMA DRIVE Staten Island NY 10304
|
||||
K006 CIP K 17 P.S. 6 (PS 600B) BLDG MANAGEMENT SYSTEM 2269000
|
||||
K006 CIP K 17 P.S. 6 (PS 600B) EXT MASONRY/ROOFS 773000
|
||||
X060 CIP X 8 P.S. 60 FLOOD/EXT MASONRY/CEC REQUEST-PARAPET/ROOFS/WINDOW 14619000 false -73.89313106784448 40.82552621616202 888 REV J A POLITE AVE Bronx NY 10459
|
||||
X061 CIP X 12 P.S. 61 FIRE ALARM 349119 false -73.89295310872916 40.836569959473785 1550 CROTONA PARK Bronx NY 10460
|
||||
X061 CIP X 12 P.S. 61 IP SURVEILLANCE CAMERAS 1528000 false -73.89295310872916 40.836569959473785 1550 CROTONA PARK Bronx NY 10460
|
||||
X064 CIP X 9 P.S. 64 BATHROOMS 4TH & 5TH FLR 508499 false -73.91558081775857 40.8401115358764 1425 WALTON AVENUE Bronx NY 10452
|
||||
Q066 CIP Q 27 P.S. 66 FLOOD ELIMINATION/EXT MASONRY/PARAPETS 1110000 false -73.84031024991805 40.69637041236467 85 11 102 STREET RICHMOND HILL NY 11418
|
||||
M066 CIP M 2 P.S. 66 (RICHARD R GREEN) CAFE MULTIPURPOSE ROOM 482000 false -74.02858656018857 40.62102637693336 421 88 STREET New York NY 10028
|
||||
X068 CIP X 11 P.S. 68 ELEVATORS & ESCALATORS 688000 false -73.83837769297637 40.89141479468151 4011 MONTICELLO AVENUE Bronx NY 10466
|
||||
R069 CIP R 31 P.S. 69 FENCING 234000 false -74.15650379993006 40.59169714382341 144 KEATING PLACE Staten Island NY 10314
|
||||
X007 CIP X 10 P.S. 7 ROOFS/EXT MASONRY/PARAPETS 4700000 false -73.90547390792568 40.881013909978904 3201 KINGSBRIDGE AVENUE Bronx NY 10463
|
||||
Q071 CIP Q 24 P.S. 71 FLOOD ELIMINATION 408990 false -73.88334858436963 40.70122489161548 62 85 FOREST AVENUE RIDGEWOOD NY 11385
|
||||
X072 CIP X 8 P.S. 72 BATHROOM 668000 false -73.81850425419442 40.822539080023574 2951 DEWEY AVENUE Bronx NY 10465
|
||||
K722 CIP K 21 P.S. 721 OTC TILTED FIELD LIGHTING 1396800 false -73.97331147204676 40.596939623165156 64 AVENUE Brooklyn NY 11223
|
||||
M641 CIP M 2 P.S. 721 OTC SP ED FLOOD ELIMINATION 1897000 false -74.00542114697957 40.72862785368122 250 HOUSTON ST MANHATTAN NY 10014
|
||||
K073 CIP K 23 P.S. 73 SWB EXT MSNRY/SWB PARAPETS/SWB FLOOD/ROOFS 3084000 false -73.91089377023927 40.68032732647815 251 MCDOUGAL STREET Brooklyn NY 11233
|
||||
X075 CIP X 8 P.S. 75 ROOFS/EXT MASONRY 2549000 false -73.88942113898915 40.822818392634325 984 FAILE STREET Bronx NY 10459
|
||||
X155 CIP X 7 P.S. 754 (@X155) CAFE/MULTIPURPOSE RM UPGRADE/FLOOD ELIMINATION 1230000 false -73.90975689502312 40.81117582303449 470 JACKSON AVENUE BRONX NY 10455
|
||||
X155 CIP X 7 P.S. 754 (@X155) FY11 REOS A LIBRARY UPGRADE 299155 false -73.90975689502312 40.81117582303449 470 JACKSON AVENUE BRONX NY 10455
|
||||
Q076 CIP Q 30 P.S. 76 EXTERIOR MASONRY/PARAPETS 2284875 false -73.91327185810974 40.76286893025696 36 36 10 STREET QUEENS NY 11103
|
||||
X076 CIP X 11 P.S. 76 MASONRY/PARAPETS/FLOOD ELMNTN/ROOFS 4042000 false -73.8614028579785 40.86957454109854 900 ADEE AVENUE Bronx NY 10469
|
||||
X078 CIP X 11 P.S. 78 AUDITORIUM UPGRADE/STUDENT TOILETS 715000 false -73.8513380848076 40.87847023359842 1400 NEEDHAM AVENUE Bronx NY 10469
|
||||
Q079 CIP Q 25 P.S. 79 ELEC SYSTEMS 258100 false -73.81123206101074 40.78628404147537 147 27 15 DRIVE WHITESTONE NY 11357
|
||||
R008 CIP R 31 P.S. 8 ELEC SYSTEM 790000 false -74.1517569152093 40.54764073027023 112 LINDENWOOD ROAD Staten Island NY 10308
|
||||
R880 CIP R 31 P.S. 80 (PETRIDES BLDG B) WINDOWS/EXT MASONRY 3228000
|
||||
Q081 CIP Q 24 P.S. 81 FLOOD ELIM/STRUCTURAL:FLOOR SYS/EXT MASONRY 1274800 false -73.91225035614077 40.70373293561221 559 CYPRESS AVENUE RIDGEWOOD NY 11237
|
||||
X081 CIP X 10 P.S. 81 FLOOD ELIMINATION 474000 false -73.90520839316682 40.903559546831026 5550 RIVERDALE AVENUE Bronx NY 10471
|
||||
Q848 CIP Q 24 P.S. 81 ANNEX (@Q848) FLOOD ELIMINATION/EXT MASONRY 2390270
|
||||
Q811 CIP Q 26 P.S. 811 (OL 187 - CMCH) LL 41/16 COMPLIANCE 954000 false -73.73430017711144 40.759074216601846 61 25 MARATHON PKWY QUEENS NY 11362
|
||||
Q811 CIP Q 26 P.S. 811 (OL 187 - CMCH) LOW VOLTAGE 560000 false -73.73430017711144 40.759074216601846 61 25 MARATHON PKWY QUEENS NY 11362
|
||||
M841 CIP M 3 P.S. 811(@ M841) WORK REQUIRED TO OBTAIN C OF O 1880750 false -73.96653900057436 40.78362556816552 466 END AVENUE NEW YORK NY 10024
|
||||
Q082 CIP Q 28 P.S. 82 WATER PENETRATION 1120000 false -73.80979665579099 40.70119264912154 88 02 144 STREET QUEENS NY 11435
|
||||
X083 CIP X 11 P.S. 83 ACCESSIBILITY 3377000 false -73.85933122663833 40.849332468676785 950 RHINELANDER AVENUE Bronx NY 10462
|
||||
Q085 CIP Q 30 P.S. 85 FLOOD ELMNTN/ROOFS/EXT MASONRY/PARAPETS 3111000 false -73.90960650023976 40.780092072491186 23 70 31 STREET QUEENS NY 11105
|
||||
X085 CIP X 10 P.S. 85 RETAINING WALL 1596000 false -73.89472052099663 40.859331900138066 2400 MARION AVENUE Bronx NY 10458
|
||||
K086 CIP K 32 P.S. 86 FLOOD ELMNTN/EXT MASONRY 4269000 false -73.91749723727719 40.7007452458598 220 IRVING AVENUE Brooklyn NY 11237
|
||||
X086 CIP X 10 P.S. 86 ELEVATORS & ESCALATORS 747400 false -73.89880422371779 40.869715575827065 2756 RESERVOIR AVENUE Bronx NY 10468
|
||||
K009 CIP K 13 P.S. 9 PAVED AREA - BLACKTOP 974000
|
||||
X009 CIP X 10 P.S. 9 (OLD 115) ACCESSIBILITY 6177000 false -73.89936166242526 40.8571875830873 230 183 STREET Bronx NY 10458
|
||||
Q090 CIP Q 27 P.S. 90 ELEC SYSTEMS 778000 false -73.84031024991805 40.69637041236467 86 50 109 STREET RICHMOND HILL NY 11418
|
||||
Q090 CIP Q 27 P.S. 90 SWB - EMERGENCY MASONRY REPAIRS/PARAPETS 3769000 false -73.84031024991805 40.69637041236467 86 50 109 STREET RICHMOND HILL NY 11418
|
||||
X090 CIP X 9 P.S. 90 EXTERIOR MASONRY/RETAINING WALLS 1857000 false -73.91794566527413 40.83197402670032 1116 SHERIDAN AVENUE Bronx NY 10456
|
||||
K093 CIP K 13 P.S. 93 FLOORS 1748375 false -73.94682098403624 40.679147761017056 31 NEW YORK AVENUE Brooklyn NY 11216
|
||||
K094 CIP K 15 P.S. 94 PLANYC PLAYGROUND 264500 false -74.0082060957207 40.64372817395559 5010 6TH AVENUE Brooklyn NY 11220
|
||||
K095 CIP K 21 P.S. 95 EXT MASONRY/WINDOWS 3373000 false -73.97512954825021 40.595683557953876 345 VAN SICKLEN STREET Brooklyn NY 11223
|
||||
M271 CIP M 2 P.S./I.S. 217 ROOSEVELT ISLAND ROOFS/EXT MASONRY/WINDOWS/PARAPETS 8444000 false -73.94703392787746 40.76494453865442 645 MAIN STREET New York NY 10044
|
||||
M495 CIP M 4 PARK EAST ALT HS FY10 RESO A SCIENCE LAB 759354 false -73.94403228106489 40.79161072055837 230 34 EAST 105 STREET New York NY 10029
|
||||
M495 CIP M 4 PARK EAST ALT HS WATER DAMAGE & MASONRY/ROOF/PARAPETS/WINDOWS 2887000 false -73.94403228106489 40.79161072055837 230 34 EAST 105 STREET New York NY 10029
|
||||
Q102 CAP Q 24 PS 102 Addition Addition 56222000 false -73.87835115518163 40.73871040256307 55 24 Van Horn St Elmhurst NY 11373
|
||||
Q013 CAP Q 24 PS 13 Addition Addition 41250000 false -73.87835115518163 40.73871040256307 55 01 94th St Elmhurst NY 11373
|
||||
M130 CIP M 2 PS 130 SWB-WINDOWS 1327000 false -73.99859121725036 40.7186139475248 143 BAXTER STREET New York NY 10013
|
||||
K317 CAP K 13 PS 133 New 66224000 false -73.98070466529857 40.68047819552629 610 Baltic St Brooklyn NY 11217
|
||||
Q143 CIP Q 24 PS 143 FY10 RESO A PA SYSTEM 189000 false -73.85304068857687 40.749678220373596 34 74 113 STREET CORONA NY 11368
|
||||
K160 CAP K 20 PS 160 Annex Addition 38772000 false -73.99911127943953 40.637367859169615 5105 Fort Hamilton Pkwy Brooklyn NY 11219
|
||||
X136 CIP X 12 PS 186 COMPUTER LAB FLOOD ELIMINATION/EXTERIOR RAMPS & CANOPIES 968700 false -73.89748338090764 40.8318681052202 750 JENNINGS STREET Bronx NY 10459
|
||||
Q196 CAP Q 28 PS 196 Addition Addition 29800000 false -73.84628429608335 40.720707263029794 71 25 113th St Forest Hills NY 11375
|
||||
K264 CAP K 20 PS 264 New 39814903 false -74.02907223284222 40.62112765715576 8818 4th Ave Brooklyn NY 11209
|
||||
Q280 CAP Q 30 PS 280 Lease 6230000 false -73.88361254528269 40.75163073936716 34 20 94th St Jackson Heights NY 11372
|
||||
Q280 CAP Q 30 PS 280 Lease 7250000 false -73.88361254528269 40.75163073936716 34 20 94th St Jackson Heights NY 11372
|
||||
Q029 CAP Q 25 PS 29 Addition Addition 20180000 false -73.84181070040347 40.7849280967543 125 10 23rd Ave College Point NY 11356
|
||||
Q290 CIP Q 24 PS 290 DEMOLITION FOR PS 290 3370000 false -73.88334858436963 40.70122489161548 55 20 METROPOLITAN AVE RIDGEWOOD NY 11385
|
||||
X292 CAP X 11 PS 292 New 31927000 false -73.86385184249058 40.85441144971648 800 Lydig Ave Bronx NY 10462
|
||||
K310 CAP K 20 PS 310 New 26400000 false -74.00762713591367 40.632432204151364 942 62nd St Brooklyn NY 11219
|
||||
K331 CAP K 20 PS 331 New 51133300 false -74.02392108137985 40.633713521609366 7002 4th Ave Brooklyn NY 11209
|
||||
Q198 CIP Q 27 PS 333 @ 198 SCIENCE DEMO ROOM UPGRADE 670000 false -73.79540208463845 40.593133885620375 3 65 BEACH 56 STREET QUEENS NY 11692
|
||||
Q042 CAP Q 27 PS 42 Addition Addition 43065000 false -73.79529882397365 40.59475372321819 488 Beach 66th St Arverne NY 11692
|
||||
Q043 CIP Q 27 PS 43 FIRE ALARM SYSTEM 1982000 false -73.76182654029463 40.594515128003 160 BEACH 29TH STREET ROCKAWAY NY 11691
|
||||
M338 CAP M 2 PS 51 New 54730000 false -73.99547864190042 40.761366217679694 525 44th St New York NY 10036
|
||||
R071 CAP R 31 PS 71 New 53450000 false -74.09118595249046 40.60412964758937 1050 Targee St Staten Island NY 10304
|
||||
K008 CAP K 13 PS 8 Addition Addition 21230000 false -73.9932378538064 40.700668802148385 37 Hicks St Brooklyn NY 11201
|
||||
M916 CAP M 5 PS 916 Lease 0 false -73.95327141286555 40.81245030541294 168 Morningside Ave New York NY 10027
|
||||
X177 CAP X 10 PS/IS 177 New 48888000 false -73.8752514350975 40.87277450072955 3177 Webster Ave Bronx NY 10467
|
||||
Q277 CAP Q 28 PS/IS 277 New 47135000 false -73.79282099978928 40.71311535449007 153 27 88th Ave Jamaica NY 11432
|
||||
M281 CAP M 2 PS/IS 281 New 47580000 false -73.97273509303172 40.74436150165521 425 35th St New York NY 10016
|
||||
Q312 CAP Q 30 PS/IS 312 New 47820000 false -73.93866902925225 40.74570244980828 46 08 5th St Long Island City NY 11101
|
||||
X784 CAP X 11 PS/IS 784 New 0 false -73.84367515955307 40.85710649548991 1500 Pelham Pkwy Bronx NY 10461
|
||||
K990 CAP K 15 Pave Charter School New 25933333 false -74.00338737261256 40.67592711246962 732 Henry St Brooklyn NY 11231
|
||||
Q475 CIP Q 27 RICHMOND HILL HS SWB - EXT MASONRY/WINDOWS/ROOFS 9333000 false -73.84031024991805 40.69637041236467 89 30 114 STREET QUEENS NY 11418
|
||||
K655 CIP K 15 SARAH J HALE VOCATIONAL HS ACCESSIBILITY/SAFETY 2450000 false -73.98061564042008 40.68371105568558 345 DEAN STREET Brooklyn NY 11217
|
||||
K218 CIP K 19 SCH FOR CLASSICS:ACAD OF THINK NEW SCIENCE LAB SUITE 845000 false -73.8742292684109 40.67070199017694 370 FOUNTAIN AVENUE Brooklyn NY 11208
|
||||
M660 CIP M 2 SCHOOL OF THE FUTURE @MD BACON FLOOD ELIMINATION 618000 false -73.98552809234425 40.73900208799275 127 22 STREET NEW YORK NY 10010
|
||||
Q751 CIP Q 30 SCHOOL SAFETY PARKING LOT SCHOOL SAFETY PARKING LOT 2648000 false -73.93866902925225 40.74570244980828 43 30 DUTCH KILLS STREET LONG ISLAND CITY NY 11101
|
||||
M445 CIP M 2 SEWARD PARK HS CAFETERIA MULTIPURPOSE RM UPG 929000 false -73.98959502962896 40.716852373698316 350 GRAND STREET New York NY 10002
|
||||
K515 CIP K 18 SOUTH SHORE HS ROOFS/EXT MASONRY/PARAPETS 18887000 false -73.91781691770764 40.63268510415105 6565 FLATLANDS AVENUE BROOKLYN NY 11236
|
||||
M477 CIP M 2 STUYVESANT HS (NEW) EXT MASONRY/ROOFS 7752000
|
||||
X240 CAP X 78 Settlement Housing PS/IS/HS New 83300000 false -73.91619367568833 40.84236125885491 1501 Jerome Ave Bronx NY 10452
|
||||
X988 CAP X 78 Suspension Center - Bronx Lease 7335500 false -73.89020247936504 40.81655388322442 1231 Lafayette Ave Bronx NY 10474
|
||||
X410 CIP X 9 TAFT HS PLANYC BOILER CONVERSION/PLANYC CLIMATE CTRL 10174000 false -73.9108816444482 40.84038797720987 240 172 STREET BRONX NY 10457
|
||||
K485 CIP K 20 TELECOM ARTS & TECHNOLOGY H.S. EXT MASONRY 4138000 false -74.02385245520922 40.63726462862678 350 67TH ST Brooklyn NY 11220
|
||||
X435 CIP X 10 THEODORE ROOSEVELT H.S. FLOORS 1593000 false -73.88817875264016 40.85990614640288 500 FORDHAM ROAD Bronx NY 10458
|
||||
X435 CIP X 10 THEODORE ROOSEVELT H.S. SWB - COPPER SIDING 1500000 false -73.88817875264016 40.85990614640288 500 FORDHAM ROAD Bronx NY 10458
|
||||
R455 CIP R 31 TOTTENVILLE H.S. FY10 RESO A AF REPLACEMENT 1452882 false -74.19217697672369 40.52826198723337 100 LUTEN AVENUE Staten Island NY 10312
|
||||
R455 CIP R 31 TOTTENVILLE HS WINDOWS 7960000 false -74.19217697672369 40.52826198723337 100 LUTEN AVENUE Staten Island NY 10312
|
||||
M971 CAP M 2 The Spruce Street Educational New 34146385.86 false -74.00596371272646 40.71174136432668 12 Spruce St New York NY 10038
|
||||
M445 CIP M 2 URBAN ASSEMBLY ACADEMY GIRLS SHOWER ROOM 1014300 false -73.98959502962896 40.716852373698316 350 GRAND STREET New York NY 10002
|
||||
R460 CIP R 31 WAGNER HS FY06 RESO A ATHLETIC FIELD 5799000 false -74.12366587081469 40.59771088831585 1200 MANOR ROAD Staten Island NY 10314
|
||||
K805 CIP K 13 WATER'S EDGE EDUCATIONAL COMPL ELEVATOR UPGRADE 764398 false -73.98496543482732 40.69721149151847 49 FLATBUSH AVE EXTENSION BROOKLYN NY 11201
|
||||
Q680 CIP Q 28 YOUNG WOMENS' LEADERSHIP SCHOO IP SURVEILLANCE CAMERAS 1047000 false -73.7875740339145 40.698104881734935 150 91 87TH ROAD JAMAICA NY 11433
|
||||
Q585 CAP Q 78 HS 585 New 70250000 false -73.87835115518163 40.73871040256307 54 40 74th St Elmhurst NY 11373
|
|
|
@ -1,4 +1,4 @@
|
|||
candname officeboro canclass generalpay election totalpay primarypay officedist officecd runoffpay candid
|
||||
candname officeboro canclass generalpay election totalpay primarypay officedist officecd runoffpay candid
|
||||
Addabbo, Joseph P P 0 2005 0 0 32 5 0
|
||||
Akbar, Celestina P 0 2005 0 0 23 5 0 884
|
||||
Antoine, Royston P 0 2005 59900.00 59900.00 41 5 0 864
|
||||
|
@ -34,4 +34,4 @@ de Blasio, Bill P 0 2005 0 0 39 5 0 326
|
|||
Denis, Nelson A P 0 2005 78562.00 78562.00 8 5 0
|
||||
Dickens, Inez E P 0 2005 82500.00 82500.00 9 5 0 867
|
||||
Dilan, Erik M P 0 2005 0 0 37 5 0 444
|
||||
Doty, Cynthia L P 0 2005 65044.00 65044.00 9 5 0 860
|
||||
Doty, Cynthia L P 0 2005 65044.00 65044.00 9 5 0 860
|
||||
|
|
Can't render this file because it has a wrong number of fields in line 2.
|
File diff suppressed because it is too large
Load Diff
|
@ -47,6 +47,25 @@ p.panel-subheadline {
|
|||
color: #333;
|
||||
}
|
||||
|
||||
p.sql-statement {
|
||||
font-size: 1.05em;
|
||||
color: #004b87;
|
||||
padding-left: 10px;
|
||||
padding-top: 10px;
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
|
||||
p.mimir-statement {
|
||||
font-size: 1.05em;
|
||||
color: #004b87;
|
||||
padding-left: 10px;
|
||||
padding-top: 10px;
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
|
||||
h4.modal-subheadline {
|
||||
}
|
||||
|
||||
/*
|
||||
* Panels
|
||||
*/
|
||||
|
|
|
@ -38,8 +38,8 @@
|
|||
if (url && url.length > 1) {
|
||||
url = decodeURIComponent(url[1]);
|
||||
} else {
|
||||
//url = "http://localhost:8080/vizier-db/doc/vizier-db.yaml";
|
||||
url = "http://vizirdb.7mi5uspdsy.us-west-2.elasticbeanstalk.com/doc/vizier-db.yaml";
|
||||
url = "http://localhost:8080/vizier-db/doc/vizier-db.yaml";
|
||||
//url = "http://vizirdb.7mi5uspdsy.us-west-2.elasticbeanstalk.com/doc/vizier-db.yaml";
|
||||
}
|
||||
|
||||
hljs.configure({
|
||||
|
|
|
@ -11,8 +11,8 @@ info:
|
|||
|
||||
schemes:
|
||||
- http
|
||||
host: vizirdb.7mi5uspdsy.us-west-2.elasticbeanstalk.com
|
||||
#host: localhost:8080/vizier-db
|
||||
#host: vizirdb.7mi5uspdsy.us-west-2.elasticbeanstalk.com
|
||||
host: localhost:8080/vizier-db
|
||||
basePath: /api/v1
|
||||
|
||||
paths:
|
||||
|
@ -239,7 +239,10 @@ paths:
|
|||
type: array
|
||||
items:
|
||||
$ref: "#/definitions/VizUALOperation"
|
||||
|
||||
links:
|
||||
type: array
|
||||
items:
|
||||
$ref: "#/definitions/Reference"
|
||||
404:
|
||||
description: Notebook not found
|
||||
post:
|
||||
|
@ -282,6 +285,45 @@ paths:
|
|||
description: Invalid parameters
|
||||
404:
|
||||
description: Notebook or branch not found
|
||||
/notebooks/{notebookIdentifier}/branches/{branchIdentifier}/script/sql:
|
||||
get:
|
||||
summary: Get VizUAL script as SQL
|
||||
description: List the sequence of operations in the VizUAL script
|
||||
representing the curation workflow that represented by the
|
||||
branch as SQL statements
|
||||
operationId: getBranchScriptSQLExport
|
||||
tags:
|
||||
- branch
|
||||
- script
|
||||
parameters:
|
||||
- name: notebookIdentifier
|
||||
in: path
|
||||
required: true
|
||||
description: The unique notbook identifier
|
||||
type: integer
|
||||
format: int32
|
||||
- name: branchIdentifier
|
||||
in: path
|
||||
required: true
|
||||
description: The brnach identifier
|
||||
type: integer
|
||||
format: int32
|
||||
responses:
|
||||
200:
|
||||
description: List of operations in curation workflow as SQL
|
||||
statements
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
operations:
|
||||
type: array
|
||||
items:
|
||||
properties:
|
||||
sql:
|
||||
type: string
|
||||
|
||||
404:
|
||||
description: Notebook not found
|
||||
/notebooks/{notebookIdentifier}/branches/{branchIdentifier}/script/snapshots/{snapshotIdentifier}:
|
||||
delete:
|
||||
summary: Delete snapshot from branch
|
||||
|
@ -417,7 +459,11 @@ paths:
|
|||
properties:
|
||||
name:
|
||||
type: string
|
||||
refName:
|
||||
label:
|
||||
type: string
|
||||
isUniqueName:
|
||||
type: boolean
|
||||
uniqueName:
|
||||
type: string
|
||||
rows:
|
||||
type: integer
|
||||
|
@ -487,7 +533,14 @@ definitions:
|
|||
type: integer
|
||||
format: int32
|
||||
value:
|
||||
type: string
|
||||
type: object
|
||||
required:
|
||||
- text
|
||||
properties:
|
||||
text:
|
||||
type: string
|
||||
formula:
|
||||
type: string
|
||||
NotebookObject:
|
||||
type: object
|
||||
required:
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
<script src="./js/ie-emulation-modes-warning.js"></script>
|
||||
|
||||
<!-- D3.js -->
|
||||
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
|
||||
<script src="./js/d3.v3.min.js" charset="utf-8"></script>
|
||||
<script src="./js/dagre-d3.min.js"></script>
|
||||
|
||||
<!-- Bootstrap core JavaScript
|
||||
|
@ -291,5 +291,22 @@
|
|||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- SHOW SQL -->
|
||||
<div class="modal fade" id="modal-show-sql" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
<h4 class="modal-title">VizUAL Script - SQL Translation</h4>
|
||||
</div>
|
||||
<div class="modal-body" id="modal-show-sql-body">
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
|
||||
</div>
|
||||
</div><!-- /.modal-content -->
|
||||
</div><!-- /.modal-dialog -->
|
||||
</div><!-- /.modal -->
|
||||
|
||||
</body></html>
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -17,8 +17,8 @@
|
|||
*
|
||||
* @type String
|
||||
*/
|
||||
var apiUrl = 'http://vizirdb.7mi5uspdsy.us-west-2.elasticbeanstalk.com//api/v1';
|
||||
//var apiUrl = 'http://localhost:8080/vizier-db/api/v1';
|
||||
//var apiUrl = 'http://vizirdb.7mi5uspdsy.us-west-2.elasticbeanstalk.com//api/v1';
|
||||
var apiUrl = 'http://localhost:8080/vizier-db/api/v1';
|
||||
|
||||
/**
|
||||
* Maintains global variables for the current notebook
|
||||
|
@ -27,7 +27,8 @@ var apiUrl = 'http://vizirdb.7mi5uspdsy.us-west-2.elasticbeanstalk.com//api/v1';
|
|||
* name: '',
|
||||
* snapshot: {
|
||||
* links[],
|
||||
* columns: []
|
||||
* columns: [],
|
||||
* cells: []
|
||||
* },
|
||||
* script: {
|
||||
* operations: []
|
||||
|
@ -43,7 +44,58 @@ var scriptOp = -1;
|
|||
* Keep track of cells being edited
|
||||
*/
|
||||
var editedCell = null;
|
||||
var cellValue = null;
|
||||
|
||||
var SpreadsheetCell = function(cell, notebook) {
|
||||
// Reference to the current notebook
|
||||
this.notebook = notebook;
|
||||
// Table cell that is being edits
|
||||
this.cell = cell;
|
||||
// Cell column index
|
||||
this.column = cell.cellIndex - 1;
|
||||
// Cell row index
|
||||
this.row = cell.parentNode.rowIndex - 1;
|
||||
// Set .text, .formula, and .operationType based on whether the updated
|
||||
// cell is a column header or not
|
||||
if (this.row === -1) {
|
||||
this.text = notebook.snapshot.columns[this.column].name;
|
||||
this.formula = this.text;
|
||||
this.operationType = 'RENAME_COLUMN';
|
||||
} else {
|
||||
var value = notebook.snapshot.cells[this.column + '#' + this.row];
|
||||
if (value) {
|
||||
this.text = value.text;
|
||||
if (value.formula) {
|
||||
this.formula = value.formula;
|
||||
} else {
|
||||
this.formula = this.text;
|
||||
}
|
||||
} else {
|
||||
this.text = '';
|
||||
this.formula = this.text;
|
||||
}
|
||||
this.operationType = 'UPDATE_CELL';
|
||||
}
|
||||
// VizUAL statement for update operation with current user input
|
||||
this.currentScript = function(text) {
|
||||
switch(this.operationType){
|
||||
case 'UPDATE_CELL':
|
||||
var col = this.notebook.snapshot.columns[this.column];
|
||||
var cellRef;
|
||||
if (col.isUniqueName) {
|
||||
cellRef = '[' + col.name + ', ' + this.row + ']';
|
||||
} else {
|
||||
cellRef = col.label + this.row;
|
||||
}
|
||||
if (text.trim().startsWith('=')) {
|
||||
return 'UPDATE CELL ' + cellRef + ' ' + text.trim();
|
||||
} else {
|
||||
return 'UPDATE CELL ' + cellRef + ' = \'' + text + '\'';
|
||||
}
|
||||
case 'RENAME_COLUMN':
|
||||
return 'RENAME COLUMN ' + this.notebook.snapshot.columns[this.column].uniqueName + ' AS ' + '\'' + text + '\'';
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* List of all uploaded files.
|
||||
|
@ -95,10 +147,10 @@ $(function(){
|
|||
$('#column-header').contextMenu({
|
||||
selector: 'th',
|
||||
callback: function(key, options) {
|
||||
var columnIndex = $('body').data($(this).text());
|
||||
var tableData = this[0];
|
||||
var columnIndex = tableData.cellIndex - 1;
|
||||
if (key === 'delete_column') {
|
||||
var headerTitle = $(this).text();
|
||||
deleteColumn(headerTitle);
|
||||
deleteColumn(columnIndex);
|
||||
} else if (key === 'insert_column_left') {
|
||||
insertColumn(columnIndex);
|
||||
} else if (key === 'insert_column_right') {
|
||||
|
@ -147,21 +199,6 @@ $(function(){
|
|||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Get the command text for UPDATE cell command.
|
||||
*
|
||||
* @param {type} cell
|
||||
* @param {type} text
|
||||
* @returns {String}
|
||||
*/
|
||||
function getUpdateCellCmd(cell, text) {
|
||||
return 'UPDATE CELL [' + notebook.snapshot.columns[cell.cellIndex - 1].refName +','+ (cell.parentNode.rowIndex - 1) + '] = \'' + text + '\'';
|
||||
}
|
||||
|
||||
function getUpdateColumnText(column, text){
|
||||
return 'RENAME COLUMN ' + notebook.snapshot.columns[column].refName + ' AS ' + '\'' + text + '\'';
|
||||
}
|
||||
|
||||
function deleteRow(index){
|
||||
var requestBody = {};
|
||||
requestBody.type = 'DeleteRow';
|
||||
|
@ -169,10 +206,10 @@ function deleteRow(index){
|
|||
postRequest(requestBody);
|
||||
}
|
||||
|
||||
function deleteColumn(header){
|
||||
function deleteColumn(index){
|
||||
var requestBody = {};
|
||||
requestBody.type = 'DeleteColumn';
|
||||
requestBody.parameters = [{ name: 'column', value: $('body').data(header)}];
|
||||
requestBody.parameters = [{ name: 'column', value: index}];
|
||||
postRequest(requestBody);
|
||||
}
|
||||
|
||||
|
@ -267,19 +304,17 @@ function deleteSnapshot() {
|
|||
if (op.index > 0) {
|
||||
var url = getReference('script', op.links);
|
||||
if (url) {
|
||||
if (confirm('Do you really want to delete ' + op.text + '?')) {
|
||||
$.ajax({
|
||||
url: url,
|
||||
type: "DELETE",
|
||||
contentType: "application/json",
|
||||
success: function(data) {
|
||||
showNotebook(getReference('notebook', data.links));
|
||||
},
|
||||
error: function() {
|
||||
alert('There was an error');
|
||||
}
|
||||
});
|
||||
}
|
||||
$.ajax({
|
||||
url: url,
|
||||
type: "DELETE",
|
||||
contentType: "application/json",
|
||||
success: function(data) {
|
||||
showNotebook(getReference('notebook', data.links));
|
||||
},
|
||||
error: function() {
|
||||
alert('There was an error');
|
||||
}
|
||||
});
|
||||
}
|
||||
} else {
|
||||
alert('Cannot delete ' + op.text);
|
||||
|
@ -349,19 +384,20 @@ function showNotebook(href) {
|
|||
notebook.links = data.links;
|
||||
// Edit notebook dropdown menu
|
||||
var notebookDropdown = '<div class="btn-group" id="notebook-dropdown">' +
|
||||
'<button class="btn btn-white toggle-dropdown" data-toggle="dropdown" aria-expanded="false" aria-haspopup="true"><span class="glyphicon glyphicon-pencil"></span></button>' +
|
||||
'<button class="btn btn-white toggle-dropdown" data-toggle="dropdown" aria-expanded="false" aria-haspopup="true"><span class="glyphicon glyphicon-cog"></span></button>' +
|
||||
'<ul class="dropdown-menu">' +
|
||||
'<li><a href="#" onclick="showEditModal();">Edit Notebook</a></li>' +
|
||||
'<li><a href="#" onclick="deleteNotebook();">Delete Notebook</a></li>' +
|
||||
'<li><a href="#" onclick="showEditModal();"><span class="glyphicon glyphicon-pencil"></span> Edit Notebook</a></li>' +
|
||||
'<li><a href="#" onclick="deleteNotebook();"><span class="glyphicon glyphicon-trash"></span> Delete Notebook</a></li>' +
|
||||
'</ul>' +
|
||||
'</div>';
|
||||
// Textbox for users command input
|
||||
var cmdInputField = '<div><div class="input-group"><span class="input-group-addon" id="basic-addon1">></span><input id="script-next-cmd" type="text" class="form-control" aria-describedby="basic-addon1"></div></div>';
|
||||
// Manipulate script dorpdown menu
|
||||
var scriptDropdown = '<div class="btn-group" id="script-dropdown">' +
|
||||
'<button class="btn btn-invert btn-sm toggle-dropdown disabled" id="script-dropdown-btn" data-toggle="dropdown" aria-expanded="false" aria-haspopup="true"> <span class="glyphicon glyphicon-trash"></span></button>' +
|
||||
'<button class="btn btn-invert btn-sm toggle-dropdown disabled" id="script-dropdown-btn" data-toggle="dropdown" aria-expanded="false" aria-haspopup="true"> <span class="glyphicon glyphicon-cog"></span></button>' +
|
||||
'<ul class="dropdown-menu dropdown-menu-right">' +
|
||||
'<li><a href="#" onclick="deleteSnapshot();">Delete Operation</a></li>' +
|
||||
'<li><a href="#" onclick="deleteSnapshot();"><span class="glyphicon glyphicon-trash"></span> Delete Operation</a></li>' +
|
||||
'<li><a href="#" onclick="showSQL();"><span class="glyphicon glyphicon-export"></span> Export as SQL</a></li>' +
|
||||
'</ul>' +
|
||||
'</div>';
|
||||
// Put it all together
|
||||
|
@ -424,6 +460,7 @@ function showSpreadsheet(url, op, opSize) {
|
|||
if (status === 'success') {
|
||||
notebook.snapshot.columns = data.columns;
|
||||
notebook.snapshot.links = data.links;
|
||||
notebook.snapshot.cells = {};
|
||||
// Keep track of the operation in the script that is currently
|
||||
// being displayed
|
||||
scriptOp = op;
|
||||
|
@ -436,21 +473,19 @@ function showSpreadsheet(url, op, opSize) {
|
|||
var columns = data.columns;
|
||||
for (var i_col = 0; i_col < columns.length; i_col++) {
|
||||
tableHtml = tableHtml + '<th class="spreadsheet-cell">' + columns[i_col].name + '</th>';
|
||||
$('body').data(columns[i_col].name, i_col);
|
||||
}
|
||||
tableHtml = tableHtml + '</thead></tr><tbody>';
|
||||
var cells = {};
|
||||
for (var i_cell = 0; i_cell < data.cells.length; i_cell++) {
|
||||
var cell = data.cells[i_cell];
|
||||
cells[cell.col + '#' + cell.row] = cell.value;
|
||||
notebook.snapshot.cells[cell.col + '#' + cell.row] = cell.value;
|
||||
}
|
||||
for (var i_row = 0; i_row < data.rows; i_row++) {
|
||||
tableHtml = tableHtml + '<tr><td class="row-header">' + i_row + '</td>';
|
||||
for (var i_col = 0; i_col < columns.length; i_col++) {
|
||||
var key = i_col + '#' + i_row;
|
||||
tableHtml = tableHtml + '<td class="spreadsheet-cell">';
|
||||
if (cells[key]) {
|
||||
tableHtml = tableHtml + cells[key];
|
||||
if (notebook.snapshot.cells[key]) {
|
||||
tableHtml = tableHtml + notebook.snapshot.cells[key].text;
|
||||
}
|
||||
tableHtml = tableHtml + '</td>';
|
||||
}
|
||||
|
@ -461,7 +496,6 @@ function showSpreadsheet(url, op, opSize) {
|
|||
$("td.spreadsheet-cell, th.spreadsheet-cell").click(function(){editSpreadsheetCell(this);});
|
||||
if (op >= 0) {
|
||||
for (var i_op = 0; i_op < opSize; i_op++) {
|
||||
var opLink = document.getElementById('script-op-' + i_op);
|
||||
if (i_op === op) {
|
||||
$('#script-op-' + i_op).addClass('list-group-item-info');
|
||||
} else {
|
||||
|
@ -572,6 +606,36 @@ function showVersionGraph(url, head) {
|
|||
});
|
||||
}
|
||||
|
||||
function showSQL() {
|
||||
|
||||
var url = getReference('sql', notebook.script.links);
|
||||
if (url) {
|
||||
$.get(url, function(data, status) {
|
||||
if (status === 'success') {
|
||||
//var innerHtml = '<div class="sql-statement"><h4 class="modal-subheadline">SQL Statements</h4>';
|
||||
var sql = '';
|
||||
for (var iOp = 0; iOp < data.operations.length; iOp++) {
|
||||
sql += '<p class="sql-statement">' + data.operations[iOp].sql + '</p>';
|
||||
}
|
||||
//innerHtml += '<h4 class="modal-subheadline">Table Statement</h4><p class="mimir-statement">' + data.mimir + '</p>';
|
||||
//innerHtml += '</div>';
|
||||
var innerHtml = '<div class="sql-statement"><ul class="nav nav-tabs" role="tablist">';
|
||||
innerHtml += '<li role="presentation" class="active"><a href="#sql-script" aria-controls="sql-script" role="tab" data-toggle="tab">SQL Statements</a></li>';
|
||||
innerHtml += '<li role="presentation"><a href="#sql-table" aria-controls="sql-table" role="tab" data-toggle="tab">Table statement</a></li>';
|
||||
innerHtml += '</ul>';
|
||||
innerHtml += '<div class="tab-content">';
|
||||
innerHtml += '<div role="tabpanel" class="tab-pane active" id="sql-script">' + sql + '</div>';
|
||||
innerHtml += '<div role="tabpanel" class="tab-pane" id="sql-table"><p class="mimir-statement">' + data.mimir + '</p></div>';
|
||||
innerHtml += '</div>';
|
||||
|
||||
innerHtml += '</div>';
|
||||
$("#modal-show-sql-body").html(innerHtml);
|
||||
$('#modal-show-sql').modal('show');
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* Modify Spreadsheety (UPDATE CELL)
|
||||
|
@ -588,10 +652,6 @@ function showVersionGraph(url, head) {
|
|||
|
||||
|
||||
function editSpreadsheetCell(cell) {
|
||||
//console.log(cell);
|
||||
var operationType = 'UPDATE_CELL';
|
||||
var currentScript = '';
|
||||
|
||||
|
||||
/*
|
||||
* Reset any cell that previously has been edited.
|
||||
|
@ -600,65 +660,43 @@ function editSpreadsheetCell(cell) {
|
|||
undoCellUpdate();
|
||||
}
|
||||
|
||||
editedCell = cell;
|
||||
cellValue = $(cell).html();
|
||||
editedCell = new SpreadsheetCell(cell, notebook);
|
||||
|
||||
$(cell).off('click')
|
||||
.addClass('cell')
|
||||
.html('<input id="cell-textbox" class="cell form-control" type="text"/>');
|
||||
|
||||
$("#cell-textbox").focus().val(cellValue);
|
||||
$("#cell-textbox").focus().val(editedCell.formula);
|
||||
$("#cell-textbox").focusout(function() {
|
||||
if ($("#cell-textbox").val() === cellValue) {
|
||||
if ($("#cell-textbox").val() === editedCell.formula) {
|
||||
undoCellUpdate();
|
||||
} else {
|
||||
submitCellUpdate(operationType);
|
||||
submitCellUpdate();
|
||||
}
|
||||
});
|
||||
|
||||
$("#cell-textbox").bind('keydown', function(e) {
|
||||
if(editedCell.parentNode.rowIndex === 0){
|
||||
operationType = 'RENAME_COLUMN';
|
||||
}
|
||||
/* UNDO changes if ESC is pressed */
|
||||
if (e.keyCode === 27) {
|
||||
undoCellUpdate();
|
||||
} else if (e.keyCode === 13) {
|
||||
if ($("#cell-textbox").val() === cellValue) {
|
||||
if ($("#cell-textbox").val() === editedCell.formula) {
|
||||
undoCellUpdate();
|
||||
} else {
|
||||
submitCellUpdate(operationType);
|
||||
submitCellUpdate();
|
||||
}
|
||||
} else {
|
||||
switch(operationType){
|
||||
case 'UPDATE_CELL':
|
||||
currentScript = getUpdateCellCmd(editedCell, $(this).val());
|
||||
break;
|
||||
case 'RENAME_COLUMN':
|
||||
currentScript = getUpdateColumnText($('body').data(cellValue), $(this).val());
|
||||
break;
|
||||
}
|
||||
$('#script-next-cmd').val(currentScript);
|
||||
$('#script-next-cmd').val(editedCell.currentScript($(this).val()));
|
||||
}
|
||||
});
|
||||
$("#cell-textbox").bind('keyup', function(e) {
|
||||
if (editedCell) {
|
||||
switch(operationType){
|
||||
case 'UPDATE_CELL':
|
||||
currentScript = getUpdateCellCmd(editedCell, $(this).val());
|
||||
break;
|
||||
case 'RENAME_COLUMN':
|
||||
currentScript = getUpdateColumnText($('body').data(cellValue), $(this).val());
|
||||
break;
|
||||
}
|
||||
$('#script-next-cmd').val(currentScript);
|
||||
$('#script-next-cmd').val(editedCell.currentScript($(this).val()));
|
||||
}
|
||||
});
|
||||
|
||||
$('#script-next-cmd').val(currentScript);
|
||||
}
|
||||
|
||||
function submitCellUpdate(type) {
|
||||
function submitCellUpdate() {
|
||||
|
||||
if (!editedCell) {
|
||||
return;
|
||||
|
@ -667,20 +705,16 @@ function submitCellUpdate(type) {
|
|||
var requestBody = {};
|
||||
requestBody.parameters = [];
|
||||
|
||||
if(type === 'UPDATE_CELL') {
|
||||
if(editedCell.operationType === 'UPDATE_CELL') {
|
||||
requestBody.type = 'UpdateCell';
|
||||
requestBody.parameters[0] = {'name': 'column', 'value': (editedCell.cellIndex - 1)};
|
||||
requestBody.parameters[1] = {'name': 'row', 'value': (editedCell.parentNode.rowIndex - 1)};
|
||||
requestBody.parameters[0] = {'name': 'column', 'value': (editedCell.column)};
|
||||
requestBody.parameters[1] = {'name': 'row', 'value': (editedCell.row)};
|
||||
requestBody.parameters[2] = {'name': 'value', 'value': $("#cell-textbox").val()};
|
||||
}
|
||||
else if(type === 'RENAME_COLUMN'){
|
||||
} else if(editedCell.operationType === 'RENAME_COLUMN'){
|
||||
requestBody.type = 'RenameColumn';
|
||||
var columnID = $('body').data(cellValue);
|
||||
var updatedValue = $('#cell-textbox').val();
|
||||
requestBody.parameters[0] = {name: 'column', value: columnID};
|
||||
requestBody.parameters[1] = {name: 'name', value: updatedValue};
|
||||
requestBody.parameters[0] = {name: 'column', value: editedCell.column};
|
||||
requestBody.parameters[1] = {name: 'name', value: $('#cell-textbox').val()};
|
||||
}
|
||||
//console.log(requestBody);
|
||||
undoCellUpdate();
|
||||
|
||||
$('body').removeData();
|
||||
|
@ -693,12 +727,11 @@ function undoCellUpdate() {
|
|||
return;
|
||||
}
|
||||
|
||||
$(editedCell).click(function(){editSpreadsheetCell(this);})
|
||||
$(editedCell.cell).click(function(){editSpreadsheetCell(this);})
|
||||
.removeClass('cell')
|
||||
.html(cellValue);
|
||||
.html(editedCell.text);
|
||||
$('#script-next-cmd').val('');
|
||||
editedCell = null;
|
||||
cellValue = null;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.vizier.test.database;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import com.google.gson.JsonPrimitive;
|
||||
import java.io.File;
|
||||
import java.util.Map;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import org.vizierdb.database.Notebook;
|
||||
import org.vizierdb.database.SimpleVizierDBM;
|
||||
import org.vizierdb.database.VizierDB;
|
||||
import org.vizierdb.database.history.VersionGraph;
|
||||
import org.vizierdb.database.script.VizUALScript;
|
||||
import org.vizierdb.database.script.op.*;
|
||||
import org.vizierdb.resources.ResourceManager;
|
||||
import org.vizierdb.sql.MimirAdaptor;
|
||||
|
||||
import mimir.sql.SqlToRA;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author oliver
|
||||
*/
|
||||
public class ConstructSQL {
|
||||
|
||||
public static final Map<String, List<String>> schemas = new HashMap<>();
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
JsonObject op;
|
||||
// JsonObject opMoveRow = new JsonParser().parse("{\"type\":\"MoveRow\", \"parameters\": [{\"name\" : \"position\", \"value\" : \"0\"}, {\"name\" : \"row\", \"value\" : \"2\"}]}").getAsJsonObject();;
|
||||
|
||||
schemas.put("dual", new ArrayList<String>());
|
||||
schemas.put("simple", Arrays.asList("Name","Age","Department"));
|
||||
|
||||
try {
|
||||
SimpleVizierDBM vdb = new SimpleVizierDBM(new ResourceManager(new File("/home/heiko/work/src/curation/vizir/vizier-db/src/main/webapp/WEB-INF/resources")));
|
||||
Notebook nb = vdb.createNotebook("My Notebook");
|
||||
// 0 - LoadFile
|
||||
op = new JsonParser().parse("{\"type\":\"LoadFile\", \"parameters\": [{\"name\" : \"file\", \"value\" : \"simple.csv\"}, {\"name\" : \"format\", \"value\" : \"RFC4180\"}, {\"name\" : \"headline\", \"value\" : \"true\"}]}").getAsJsonObject();
|
||||
vdb.executeOperation(nb.getIdentifier(), nb.getHistory().getCurrentBranch().getIdentifier(), vdb.createOperation(nb.getIdentifier(), nb.getHistory().getCurrentBranch().getIdentifier(), VizierDB.UNKNOWN_SNAPSHOT, op));
|
||||
printSQL(nb);
|
||||
// 1 - UpdateCell
|
||||
op = new JsonParser().parse("{\"type\":\"UpdateCell\", \"parameters\": [{\"name\" : \"row\", \"value\" : \"0\"}, {\"name\" : \"column\", \"value\" : \"0\"}, {\"name\" : \"value\", \"value\" : \"99\" }]}").getAsJsonObject();
|
||||
vdb.executeOperation(nb.getIdentifier(), nb.getHistory().getCurrentBranch().getIdentifier(), vdb.createOperation(nb.getIdentifier(), nb.getHistory().getCurrentBranch().getIdentifier(), VizierDB.UNKNOWN_SNAPSHOT, op));
|
||||
printSQL(nb);
|
||||
// 2 - DeleteColumn
|
||||
op = new JsonParser().parse("{\"type\":\"DeleteColumn\", \"parameters\": [{\"name\" : \"column\", \"value\" : \"1\"}]}").getAsJsonObject();
|
||||
vdb.executeOperation(nb.getIdentifier(), nb.getHistory().getCurrentBranch().getIdentifier(), vdb.createOperation(nb.getIdentifier(), nb.getHistory().getCurrentBranch().getIdentifier(), VizierDB.UNKNOWN_SNAPSHOT, op));
|
||||
printSQL(nb);
|
||||
// 3 - InsertColumn
|
||||
op = new JsonParser().parse("{\"type\":\"InsertColumn\", \"parameters\": [{\"name\" : \"name\", \"value\" : \"Derived\"},{\"name\" : \"position\", \"value\" : 2}]}").getAsJsonObject();
|
||||
vdb.executeOperation(nb.getIdentifier(), nb.getHistory().getCurrentBranch().getIdentifier(), vdb.createOperation(nb.getIdentifier(), nb.getHistory().getCurrentBranch().getIdentifier(), VizierDB.UNKNOWN_SNAPSHOT, op));
|
||||
printSQL(nb);
|
||||
// 4 - ColumnRename
|
||||
op = new JsonParser().parse("{\"type\":\"RenameColumn\", \"parameters\": [{\"name\" : \"column\", \"value\" : \"1\"},{\"name\" : \"name\", \"value\" : \"Steve\"}]}").getAsJsonObject();
|
||||
vdb.executeOperation(nb.getIdentifier(), nb.getHistory().getCurrentBranch().getIdentifier(), vdb.createOperation(nb.getIdentifier(), nb.getHistory().getCurrentBranch().getIdentifier(), VizierDB.UNKNOWN_SNAPSHOT, op));
|
||||
printSQL(nb);
|
||||
// 5 - RowDelete
|
||||
op = new JsonParser().parse("{\"type\":\"DeleteRow\", \"parameters\": [{\"name\" : \"row\", \"value\" : \"2\"}]}").getAsJsonObject();
|
||||
vdb.executeOperation(nb.getIdentifier(), nb.getHistory().getCurrentBranch().getIdentifier(), vdb.createOperation(nb.getIdentifier(), nb.getHistory().getCurrentBranch().getIdentifier(), VizierDB.UNKNOWN_SNAPSHOT, op));
|
||||
printSQL(nb);
|
||||
// 6 - RowInsert
|
||||
op = new JsonParser().parse("{\"type\":\"InsertRow\", \"parameters\": [{\"name\" : \"position\", \"value\" : \"1\"}]}").getAsJsonObject();
|
||||
vdb.executeOperation(nb.getIdentifier(), nb.getHistory().getCurrentBranch().getIdentifier(), vdb.createOperation(nb.getIdentifier(), nb.getHistory().getCurrentBranch().getIdentifier(), VizierDB.UNKNOWN_SNAPSHOT, op));
|
||||
printSQL(nb);
|
||||
|
||||
|
||||
|
||||
} catch (Exception exception) {
|
||||
exception.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private static void printSQL(Notebook notebook) {
|
||||
VersionGraph history = notebook.getHistory();
|
||||
VizUALScript script = notebook.getHistory().getScript(history.getCurrentBranch().getIdentifier());
|
||||
|
||||
System.out.println("------------");
|
||||
mimir.algebra.Operator raTree = MimirAdaptor.compileToRA(script, schemas);
|
||||
System.out.println(raTree.toString());
|
||||
String sql = MimirAdaptor.compileToSQL(raTree, schemas);
|
||||
System.out.println(sql);
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.vizier.test.database;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import org.apache.commons.csv.CSVFormat;
|
||||
import org.vizierdb.RequestParameterException;
|
||||
import org.vizierdb.VizirDBException;
|
||||
import org.vizierdb.database.Notebook;
|
||||
import org.vizierdb.database.SimpleVizierDBM;
|
||||
import org.vizierdb.database.script.op.CSVFileLoad;
|
||||
import org.vizierdb.database.script.op.CellUpdate;
|
||||
import org.vizierdb.database.script.op.ColumnDelete;
|
||||
import org.vizierdb.database.script.op.ColumnInsert;
|
||||
import org.vizierdb.resources.ResourceManager;
|
||||
import org.vizierdb.server.URLFactory;
|
||||
import org.vizierdb.server.io.ResourceStreamWriter;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author heiko
|
||||
*/
|
||||
public class DivideByZero {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
try {
|
||||
SimpleVizierDBM vdb = new SimpleVizierDBM(new ResourceManager(new File("/home/heiko/work/src/curation/vizir/vizier-db/src/main/webapp/WEB-INF/resources")));
|
||||
Notebook nb = vdb.createNotebook("My Notebook");
|
||||
int snapshotId = vdb.executeOperation(nb.getIdentifier(), 0, new CSVFileLoad(new File("/home/heiko/work/src/curation/vizir/vizier-db/src/main/webapp/WEB-INF/resources/files/simple.csv"), CSVFormat.RFC4180, true)).getHead();
|
||||
snapshotId = vdb.executeOperation(nb.getIdentifier(), 0, new ColumnInsert(vdb.getSnapshot(nb.getIdentifier(), snapshotId), 2, "Salary")).getHead();
|
||||
snapshotId = vdb.executeOperation(nb.getIdentifier(), 0, new CellUpdate(vdb.getSnapshot(nb.getIdentifier(), snapshotId), 2, 0, "=1000/[Age,0]")).getHead();
|
||||
snapshotId = vdb.executeOperation(nb.getIdentifier(), 0, new CellUpdate(vdb.getSnapshot(nb.getIdentifier(), snapshotId), 1, 0, "0")).getHead();
|
||||
StringWriter buf = new StringWriter();
|
||||
try (ResourceStreamWriter writer = new ResourceStreamWriter(new OutputStreamWriter(System.out, "UTF-8"), " ")) {
|
||||
writer.writeSnapshot(vdb.getSnapshot(nb.getIdentifier(), snapshotId), nb.getIdentifier(), new URLFactory("localhost"));
|
||||
}
|
||||
} catch (IOException | VizirDBException | RequestParameterException ex) {
|
||||
Logger.getLogger(DivideByZero.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.vizier.test.database;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import org.apache.commons.csv.CSVFormat;
|
||||
import org.vizierdb.RequestParameterException;
|
||||
import org.vizierdb.VizirDBException;
|
||||
import org.vizierdb.database.Notebook;
|
||||
import org.vizierdb.database.SimpleVizierDBM;
|
||||
import org.vizierdb.database.script.op.CSVFileLoad;
|
||||
import org.vizierdb.database.script.op.CellUpdate;
|
||||
import org.vizierdb.database.script.op.ColumnDelete;
|
||||
import org.vizierdb.database.script.op.ColumnInsert;
|
||||
import org.vizierdb.resources.ResourceManager;
|
||||
import org.vizierdb.server.URLFactory;
|
||||
import org.vizierdb.server.io.ResourceStreamWriter;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author heiko
|
||||
*/
|
||||
public class FormulaDependencies {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
try {
|
||||
SimpleVizierDBM vdb = new SimpleVizierDBM(new ResourceManager(new File("/home/heiko/work/src/curation/vizir/vizier-db/src/main/webapp/WEB-INF/resources")));
|
||||
Notebook nb = vdb.createNotebook("My Notebook");
|
||||
int snapshotId = vdb.executeOperation(nb.getIdentifier(), 0, new CSVFileLoad(new File("/home/heiko/work/src/curation/vizir/vizier-db/src/main/webapp/WEB-INF/resources/files/simple.csv"), CSVFormat.RFC4180, true)).getHead();
|
||||
snapshotId = vdb.executeOperation(nb.getIdentifier(), 0, new ColumnInsert(vdb.getSnapshot(nb.getIdentifier(), snapshotId), 2, "Salary")).getHead();
|
||||
snapshotId = vdb.executeOperation(nb.getIdentifier(), 0, new CellUpdate(vdb.getSnapshot(nb.getIdentifier(), snapshotId), 2, 0, "=[Age,0]*1000")).getHead();
|
||||
snapshotId = vdb.executeOperation(nb.getIdentifier(), 0, new ColumnInsert(vdb.getSnapshot(nb.getIdentifier(), snapshotId), 3, "Tax")).getHead();
|
||||
snapshotId = vdb.executeOperation(nb.getIdentifier(), 0, new CellUpdate(vdb.getSnapshot(nb.getIdentifier(), snapshotId), 3, 0, "=[Salary,0]*0.001")).getHead();
|
||||
snapshotId = vdb.executeOperation(nb.getIdentifier(), 0, new ColumnDelete(vdb.getSnapshot(nb.getIdentifier(), snapshotId), 1)).getHead();
|
||||
/*StringWriter buf = new StringWriter();
|
||||
try (ResourceStreamWriter writer = new ResourceStreamWriter(new OutputStreamWriter(System.out, "UTF-8"), " ")) {
|
||||
writer.writeSnapshot(vdb.getSnapshot(nb.getIdentifier(), snapshotId), nb.getIdentifier(), new URLFactory("localhost"));
|
||||
}*/
|
||||
} catch (IOException | VizirDBException | RequestParameterException ex) {
|
||||
Logger.getLogger(FormulaDependencies.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.vizier.test.database;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import java.io.File;
|
||||
import org.vizierdb.database.Notebook;
|
||||
import org.vizierdb.database.SimpleVizierDBM;
|
||||
import org.vizierdb.database.VizierDB;
|
||||
import org.vizierdb.resources.ResourceManager;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author heiko
|
||||
*/
|
||||
public class LoadCampaignPayments {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
JsonObject opLoadFile = new JsonParser().parse("{\"type\":\"LoadFile\", \"parameters\": [{\"name\" : \"file\", \"value\" : \"9mjx-v8ip.tsv\"}, {\"name\" : \"format\", \"value\" : \"TDF\"}, {\"name\" : \"headline\", \"value\" : \"true\"}]}").getAsJsonObject();
|
||||
|
||||
try {
|
||||
SimpleVizierDBM vdb = new SimpleVizierDBM(new ResourceManager(new File("/home/heiko/work/src/curation/vizir/vizier-db/src/main/webapp/WEB-INF/resources")));
|
||||
Notebook nb = vdb.createNotebook("My Notebook");
|
||||
// 0
|
||||
vdb.executeOperation(nb.getIdentifier(), nb.getHistory().getCurrentBranch().getIdentifier(), vdb.createOperation(nb.getIdentifier(), nb.getHistory().getCurrentBranch().getIdentifier(), VizierDB.UNKNOWN_SNAPSHOT, opLoadFile));
|
||||
} catch (Exception exception) {
|
||||
exception.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.vizier.test.database;
|
||||
|
||||
import org.vizierdb.database.Column;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author heiko
|
||||
*/
|
||||
public class ValidColumnName {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
System.out.println(Column.VALID_NAME_REGEX.matcher("candname").matches());
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue