Beispiel #1
0
  /**
   * Converts nested ColumnFilter.f values from a column ID to the corresponding SQL field name.
   *
   * @param filters
   * @param entities
   * @return A copy of filters with field names in place of the column IDs.
   * @see ColumnFilter#f
   */
  private static NestedColumnFilters convertColumnIdsToFieldNames(
      NestedColumnFilters filters, Map<Integer, DataEntity> entities) {
    if (filters == null) return null;

    NestedColumnFilters result = new NestedColumnFilters();
    if (filters.cond != null) {
      result.cond = new ColumnFilter();
      result.cond.v = filters.cond.v;
      result.cond.r = filters.cond.r;
      result.cond.f =
          entities
              .get(((Number) filters.cond.f).intValue())
              .privateMetadata
              .get(PrivateMetadata.SQLCOLUMN);
    } else {
      NestedColumnFilters[] in = (filters.and != null ? filters.and : filters.or);
      NestedColumnFilters[] out = new NestedColumnFilters[in.length];
      for (int i = 0; i < in.length; i++) out[i] = convertColumnIdsToFieldNames(in[i], entities);
      if (filters.and == in) result.and = out;
      else result.or = out;
    }
    return result;
  }
Beispiel #2
0
  @SuppressWarnings("unchecked")
  public static WeaveRecordList getFilteredRows(
      int[] columns, NestedColumnFilters filters, String[] keysArray) throws RemoteException {
    if (columns == null || columns.length == 0)
      throw new RemoteException("At least one column must be specified.");

    if (filters != null) filters.assertValid();

    DataConfig dataConfig = getDataConfig();
    WeaveRecordList result = new WeaveRecordList();
    Map<Integer, DataEntity> entityLookup = new HashMap<Integer, DataEntity>();

    {
      // get all column IDs whether or not they are to be selected.
      Set<Integer> allColumnIds = new HashSet<Integer>();
      if (filters != null) allColumnIds.addAll(getReferencedColumnIds(filters));
      for (int id : columns) allColumnIds.add(id);
      // get all corresponding entities
      for (DataEntity entity : dataConfig.getEntities(allColumnIds, true))
        entityLookup.put(entity.id, entity);
      // check for missing columns
      for (int id : allColumnIds)
        if (entityLookup.get(id) == null) throw new RemoteException("No column with ID=" + id);

      // provide public metadata in the same order as the selected columns
      result.attributeColumnMetadata = new Map[columns.length];
      for (int i = 0; i < columns.length; i++)
        result.attributeColumnMetadata[i] = entityLookup.get(columns[i]).publicMetadata;
    }

    String keyType = result.attributeColumnMetadata[0].get(PublicMetadata.KEYTYPE);
    // make sure all columns have same keyType
    for (int i = 1; i < columns.length; i++)
      if (!Strings.equal(keyType, result.attributeColumnMetadata[i].get(PublicMetadata.KEYTYPE)))
        throw new RemoteException("Specified columns must all have same keyType.");

    if (keysArray == null) {
      boolean canGenerateSQL = true;
      // check to see if all the columns are from the same SQL table.
      String connection = null;
      String sqlSchema = null;
      String sqlTable = null;
      for (DataEntity entity : entityLookup.values()) {
        String c = entity.privateMetadata.get(PrivateMetadata.CONNECTION);
        String s = entity.privateMetadata.get(PrivateMetadata.SQLSCHEMA);
        String t = entity.privateMetadata.get(PrivateMetadata.SQLTABLE);
        if (connection == null) connection = c;
        if (sqlSchema == null) sqlSchema = s;
        if (sqlTable == null) sqlTable = t;

        if (!Strings.equal(connection, c)
            || !Strings.equal(sqlSchema, s)
            || !Strings.equal(sqlTable, t)) {
          canGenerateSQL = false;
          break;
        }
      }
      if (canGenerateSQL) {
        Connection conn =
            getColumnConnectionInfo(entityLookup.get(columns[0])).getStaticReadOnlyConnection();
        try {
          result.recordData =
              getFilteredRowsFromSQL(conn, sqlSchema, sqlTable, columns, filters, entityLookup)
                  .rows;
        } catch (SQLException e) {
          throw new RemoteException("getFilteredRows() failed.", e);
        }
      }
    }

    if (result.recordData == null) {
      throw new Error("Selecting across tables is not supported yet.");
      /*
      			HashMap<String,Object[]> data = new HashMap<String,Object[]>();
      			if (keysArray != null)
      				for (String key : keysArray)
      					data.put(key, new Object[entities.length]);

      			for (int colIndex = 0; colIndex < entities.length; colIndex++)
      			{
      				Object[] filters = fcrs[colIndex].filters;
      				DataEntity info = entities[colIndex];
      				String sqlQuery = info.privateMetadata.get(PrivateMetadata.SQLQUERY);
      				String sqlParams = info.privateMetadata.get(PrivateMetadata.SQLPARAMS);

      				//if (dataWithKeysQuery.length() == 0)
      				//	throw new RemoteException(String.format("No SQL query is associated with column \"%s\" in dataTable \"%s\"", attributeColumnName, dataTableName));

      				String dataType = info.publicMetadata.get(PublicMetadata.DATATYPE);

      				// use config min,max or param min,max to filter the data
      				String infoMinStr = info.publicMetadata.get(PublicMetadata.MIN);
      				String infoMaxStr = info.publicMetadata.get(PublicMetadata.MAX);
      				double minValue = Double.NEGATIVE_INFINITY;
      				double maxValue = Double.POSITIVE_INFINITY;
      				// first try parsing config min,max values
      				try { minValue = Double.parseDouble(infoMinStr); } catch (Exception e) { }
      				try { maxValue = Double.parseDouble(infoMaxStr); } catch (Exception e) { }
      				// override config min,max with param values if given

      //				 * columnInfoArray = config.getDataEntity(params);
      //				 * for each info in columnInfoArray
      //				 *      get sql data
      //				 *      for each row in sql data
      //				 *            if key is in keys array,
      //				 *                  add this value to the result
      //				 * return result

      				try
      				{
      					//timer.start();
      					boolean errorReported = false;

      					Connection conn = getColumnConnectionInfo(info).getStaticReadOnlyConnection();
      					String[] sqlParamsArray = null;
      					if (sqlParams != null && sqlParams.length() > 0)
      						sqlParamsArray = CSVParser.defaultParser.parseCSV(sqlParams, true)[0];

      					SQLResult sqlResult = SQLUtils.getResultFromQuery(conn, sqlQuery, sqlParamsArray, false);

      					//timer.lap("get row set");
      					// if dataType is defined in the config file, use that value.
      					// otherwise, derive it from the sql result.
      					if (Strings.isEmpty(dataType))
      						dataType = DataType.fromSQLType(sqlResult.columnTypes[1]);
      					boolean isNumeric = dataType != null && dataType.equalsIgnoreCase(DataType.NUMBER);

      					Object keyObj, dataObj;
      					for (int iRow = 0; iRow < sqlResult.rows.length; iRow++)
      					{
      						keyObj = sqlResult.rows[iRow][0];
      						dataObj = sqlResult.rows[iRow][1];

      						if (keyObj == null || dataObj == null)
      							continue;
      						keyObj = keyObj.toString();

      						if (data.containsKey(keyObj))
      						{
      							// if row has been set to null, skip
      							if (data.get(keyObj) == null)
      								continue;
      						}
      						else
      						{
      							// if keys are specified and row is not present, skip
      							if (keysArray != null)
      								continue;
      						}

      						try
      						{
      							boolean passedFilters = true;

      							// convert the data to the appropriate type, then filter by value
      							if (isNumeric)
      							{
      								if (dataObj instanceof Number) // TEMPORARY SOLUTION - FIX ME
      								{
      									double doubleValue = ((Number)dataObj).doubleValue();
      									// filter the data based on the min,max values
      									if (minValue <= doubleValue && doubleValue <= maxValue)
      									{
      										// filter the value
      										if (filters != null)
      										{
      											passedFilters = false;
      											for (Object range : filters)
      											{
      												Number min = (Number)((Object[])range)[0];
      												Number max = (Number)((Object[])range)[1];
      												if (min.doubleValue() <= doubleValue && doubleValue <= max.doubleValue())
      												{
      													passedFilters = true;
      													break;
      												}
      											}
      										}
      									}
      									else
      										passedFilters = false;
      								}
      								else
      									passedFilters = false;
      							}
      							else
      							{
      								String stringValue = dataObj.toString();
      								dataObj = stringValue;
      								// filter the value
      								if (filters != null)
      								{
      									passedFilters = false;
      									for (Object filter : filters)
      									{
      										if (filter.equals(stringValue))
      										{
      											passedFilters = true;
      											break;
      										}
      									}
      								}
      							}

      							Object[] row = data.get(keyObj);

      							if (passedFilters)
      							{
      								// add existing row if it has not been added yet
      								if (!data.containsKey(keyObj))
      								{
      									for (int i = 0; i < colIndex; i++)
      									{
      										Object[] prevFilters = fcrs[i].filters;
      										if (prevFilters != null)
      										{
      											passedFilters = false;
      											break;
      										}
      									}
      									if (passedFilters)
      										row = new Object[entities.length];

      									data.put((String)keyObj, row);
      								}

      								if (row != null)
      									row[colIndex] = dataObj;
      							}
      							else
      							{
      								// remove existing row if value did not pass filters
      								if (row != null || !data.containsKey(keyObj))
      									data.put((String)keyObj, null);
      							}
      						}
      						catch (Exception e)
      						{
      							if (!errorReported)
      							{
      								errorReported = true;
      								e.printStackTrace();
      							}
      						}
      					}
      				}
      				catch (SQLException e)
      				{
      					e.printStackTrace();
      				}
      				catch (NullPointerException e)
      				{
      					e.printStackTrace();
      					throw new RemoteException(e.getMessage());
      				}
      			}

      			if (keysArray == null)
      			{
      				List<String> keys = new LinkedList<String>();
      				for (Entry<String,Object[]> entry : data.entrySet())
      					if (entry.getValue() != null)
      						keys.add(entry.getKey());
      				keysArray = keys.toArray(new String[keys.size()]);
      			}

      			Object[][] rows = new Object[keysArray.length][];
      			for (int iKey = 0; iKey < keysArray.length; iKey++)
      				rows[iKey] = data.get(keysArray[iKey]);

      			result.recordData = rows;
      			*/
    }

    result.keyType = keyType;
    result.recordKeys = keysArray;

    return result;
  }