olap4j-1.0.1.500/ 0000755 0001750 0001750 00000000000 11772422544 013111 5 ustar drazzib drazzib olap4j-1.0.1.500/testsrc/ 0000755 0001750 0001750 00000000000 11542502232 014564 5 ustar drazzib drazzib olap4j-1.0.1.500/testsrc/jndi.properties 0000644 0001750 0001750 00000000232 11421322444 017624 0 ustar drazzib drazzib java.naming.factory.initial=org.osjava.sj.SimpleContextFactory
org.osjava.sj.root=simple-jndi/
org.osjava.sj.jndi.shared=true
org.osjava.sj.delimiter=/ olap4j-1.0.1.500/testsrc/org/ 0000755 0001750 0001750 00000000000 11421322442 015352 5 ustar drazzib drazzib olap4j-1.0.1.500/testsrc/org/olap4j/ 0000755 0001750 0001750 00000000000 11711470530 016547 5 ustar drazzib drazzib olap4j-1.0.1.500/testsrc/org/olap4j/ConnectionTest.java 0000644 0001750 0001750 00000367253 11711466636 022405 0 ustar drazzib drazzib /*
// $Id: ConnectionTest.java 497 2012-01-30 16:14:48Z lucboudreau $
//
// Licensed to Julian Hyde under one or more contributor license
// agreements. See the NOTICE file distributed with this work for
// additional information regarding copyright ownership.
//
// Julian Hyde licenses this file to you 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.olap4j;
import org.olap4j.driver.xmla.XmlaOlap4jDriver;
import org.olap4j.impl.Bug;
import org.olap4j.impl.Olap4jUtil;
import org.olap4j.mdx.*;
import org.olap4j.mdx.parser.*;
import org.olap4j.metadata.*;
import org.olap4j.test.TestContext;
import org.olap4j.test.TestContext.Tester;
import org.olap4j.test.TestContext.Tester.Flavor;
import org.olap4j.type.*;
import junit.framework.AssertionFailedError;
import junit.framework.TestCase;
import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.sql.*;
import java.util.*;
import static org.olap4j.test.TestContext.nameList;
/**
* Unit test for olap4j Driver and Connection classes.
*
*
The system property "org.olap4j.test.helperClassName" determines the
* name of the helper class. By default, uses {@link org.olap4j.XmlaTester},
* use the XMLA driver.
*
* @author jhyde
* @version $Id: ConnectionTest.java 497 2012-01-30 16:14:48Z lucboudreau $
*/
public class ConnectionTest extends TestCase {
private TestContext testContext = TestContext.instance();
private TestContext.Tester tester = testContext.getTester();
private static final boolean IS_JDK_16 =
System.getProperty("java.version").startsWith("1.6.");
/**
* Simple strategy to prevent connection leaks: each test that needs a
* connection assigns it to this field, and {@link #tearDown()} closes it
* if it is not already closed.
*/
private Connection connection;
protected void tearDown() throws Exception {
// Simple strategy to prevent connection leaks
if (connection != null
&& !connection.isClosed())
{
connection.close();
connection = null;
}
testContext = null;
tester = null;
}
/**
* Driver basics.
*/
public void testDriver() throws ClassNotFoundException, SQLException {
Class> clazz = Class.forName(tester.getDriverClassName());
assertNotNull(clazz);
assertTrue(Driver.class.isAssignableFrom(clazz));
// driver should have automatically registered itself
Driver driver = DriverManager.getDriver(tester.getDriverUrlPrefix());
assertNotNull(driver);
// deregister driver
DriverManager.deregisterDriver(driver);
try {
Driver driver2 =
DriverManager.getDriver(tester.getDriverUrlPrefix());
fail("expected error, got " + driver2);
} catch (SQLException e) {
assertEquals("No suitable driver", e.getMessage());
}
// register explicitly
DriverManager.registerDriver(driver);
Driver driver3 = DriverManager.getDriver(tester.getDriverUrlPrefix());
assertNotNull(driver3);
// test properties
int majorVersion = driver.getMajorVersion();
int minorVersion = driver.getMinorVersion();
assertTrue(majorVersion >= 0);
assertTrue(minorVersion >= 0);
assertTrue(majorVersion > 0 || minorVersion > 0);
// check that the getPropertyInfo method returns something sensible.
// We can't test individual properties in this non-driver-specific test.
DriverPropertyInfo[] driverPropertyInfos =
driver.getPropertyInfo(
tester.getDriverUrlPrefix(),
new Properties());
switch (tester.getFlavor()) {
case XMLA:
case REMOTE_XMLA:
break;
default:
assertTrue(driverPropertyInfos.length > 0);
}
}
void assertIsValid(Connection connection, int timeout) {
if (!IS_JDK_16) {
return;
}
// We would like to evaluate
// assertTrue(connection.isValid(0));
// but this code would not compile on JDK 1.5 or lower. So, we invoke
// the same code by reflection.
try {
java.lang.reflect.Method method =
Connection.class.getMethod("isValid", int.class);
Boolean b = (Boolean) method.invoke(connection, timeout);
assertTrue(b);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
if (e.getTargetException() instanceof AbstractMethodError) {
// This happens in commons-dbcp. Somehow the method exists in
// the connection class, but it fails later. Not the fault of
// olap4j or the olapj driver, so ignore the error.
Olap4jUtil.discard(e);
} else {
throw new RuntimeException(e);
}
} catch (AbstractMethodError e) {
// This happens in commons-dbcp. Somehow the method exists in
// the connection class, but it fails later. Not the fault of
// olap4j or the olapj driver, so ignore the error.
Olap4jUtil.discard(e);
}
}
/**
* Checks that the isClosed
method of a Statement, ResultSet or
* Connection object returns the expected result. Uses reflection because
* the isClosed
method only exists from JDBC 4.0 (JDK 1.6)
* onwrds.
*
* @param o Connection, Statement or ResultSet object
* @param b Expected result
*/
void assertIsClosed(Object o, boolean b) {
if (!IS_JDK_16) {
return;
}
if (tester.getWrapper() == TestContext.Wrapper.DBCP) {
// commons-dbcp 1.1 doesn't support isClosed
return;
}
// assertTrue(statment.isClosed());
try {
Class> clazz;
if (o instanceof Statement) {
clazz = Statement.class;
} else if (o instanceof ResultSet) {
clazz = ResultSet.class;
} else if (o instanceof Connection) {
clazz = Connection.class;
} else {
throw new AssertionFailedError(
"not a statement, resultSet or connection");
}
java.lang.reflect.Method method =
clazz.getMethod("isClosed");
Boolean closed = (Boolean) method.invoke(o);
if (b) {
assertTrue(closed);
} else {
assertFalse(closed);
}
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
}
}
public void testConnection() throws ClassNotFoundException, SQLException {
Class.forName(tester.getDriverClassName());
// connect using properties and no username/password
connection = tester.createConnection();
assertNotNull(connection);
// check isClosed, isValid
assertFalse(connection.isClosed());
// check valid with no time limit
assertIsValid(connection, 0);
// check valid with one minute time limit; should be enough
assertIsValid(connection, 60);
connection.close();
assertTrue(connection.isClosed());
// it's ok to close twice
switch (tester.getWrapper()) {
case DBCP:
// DBCP complains if you close a connection twice. Even though the
// JDBC spec is clear that it is OK.
break;
default:
connection.close();
break;
}
switch (tester.getFlavor()) {
case MONDRIAN:
// connect using username/password
connection = tester.createConnectionWithUserPassword();
assertNotNull(connection);
connection.close();
assertTrue(connection.isClosed());
// connect with URL only
connection = DriverManager.getConnection(tester.getURL());
assertNotNull(connection);
connection.close();
break;
case XMLA:
// in-process XMLA test does not support username/password
break;
case REMOTE_XMLA:
// connect using username/password
connection = tester.createConnectionWithUserPassword();
assertNotNull(connection);
// connect with URL only
connection = DriverManager.getConnection(tester.getURL());
assertNotNull(connection);
connection.close();
break;
}
assertTrue(connection.isClosed());
}
public void testConnectionUnwrap() throws SQLException {
// commons-dbcp 1.1 doesn't do wrapping very well
switch (tester.getWrapper()) {
case DBCP:
return;
}
connection = tester.createConnection();
// Trivial unwrap
assertTrue(((OlapWrapper) connection).isWrapperFor(Connection.class));
Connection connection2 =
((OlapWrapper) connection).unwrap(Connection.class);
assertEquals(connection2, connection);
// Silly unwrap
assertTrue(((OlapWrapper) connection).isWrapperFor(Object.class));
Object object = ((OlapWrapper) connection).unwrap(Object.class);
assertEquals(object, connection);
// Invalid unwrap
assertFalse(((OlapWrapper) connection).isWrapperFor(Writer.class));
try {
Writer writer = ((OlapWrapper) connection).unwrap(Writer.class);
fail("expected exception, got writer" + writer);
} catch (SQLException e) {
assertTrue(e.getMessage().contains("does not implement"));
}
// Unwrap and get locale
OlapConnection olapConnection =
tester.getWrapper().unwrap(connection, OlapConnection.class);
final Locale locale = olapConnection.getLocale();
assertEquals(locale, Locale.getDefault());
// Set locale to something else.
olapConnection.setLocale(Locale.CANADA_FRENCH);
assertEquals(olapConnection.getLocale(), Locale.CANADA_FRENCH);
// Against mondrian, Sales cube is localized.
final OlapDatabaseMetaData metaData = olapConnection.getMetaData();
final String databaseName = metaData.getDatabaseProductName();
final String databaseVersion = metaData.getDatabaseProductVersion();
if (databaseName.equals("Mondrian XML for Analysis Provider")
&& databaseVersion.compareTo("3.3") > 0)
{
olapConnection.setLocale(Locale.US);
final Cube salesCubeUs =
olapConnection.getOlapSchema().getCubes().get("Sales");
assertEquals("Sales", salesCubeUs.getCaption());
// Switch locales. Note that we have to re-read metadata from the
// root (getOlapSchema()).
olapConnection.setLocale(Locale.GERMANY);
final Cube salesCubeGerman =
olapConnection.getOlapSchema().getCubes().get("Sales");
assertEquals("Verkaufen", salesCubeGerman.getCaption());
assertEquals("Cube Verkaufen", salesCubeGerman.getDescription());
olapConnection.setLocale(Locale.FRANCE);
final Cube salesCubeFrance =
olapConnection.getOlapSchema().getCubes().get("Sales");
assertEquals("Ventes", salesCubeFrance.getCaption());
assertEquals("Cube des ventes", salesCubeFrance.getDescription());
// The sales cube queried when the connection had a different
// locale has not been updated. According to the olap4j spec,
// behavior is undefined (e.g. the US sales cube might be invalid).
// In the xmla-olap4j driver, it stays valid but still shows the
// caption under the US locale.
assertEquals("Sales", salesCubeUs.getCaption());
// Reset locale.
olapConnection.setLocale(Locale.US);
}
// Try to set locale to null, should get error.
try {
olapConnection.setLocale(null);
fail("expected exception");
} catch (IllegalArgumentException e) {
// Set if back
olapConnection.setLocale(Locale.getDefault());
}
// Get, set role, get available role names.
final String s = olapConnection.getRoleName(); // ok if s is null
olapConnection.setRoleName(null);
assertNull(olapConnection.getRoleName());
olapConnection.setRoleName(s);
// ok if role names list is null
final List roleNames = olapConnection.getAvailableRoleNames();
if (roleNames != null && s != null) {
assertTrue(
"role name " + s + " should be in available role names "
+ roleNames,
roleNames.contains(s));
}
// Unwrap the mondrian connection.
switch (tester.getFlavor()) {
case MONDRIAN:
// mondrian.olap.Connection does not extend java.sql.Connection
// but we should be able to unwrap it regardless
final Class> mondrianConnectionClass;
try {
mondrianConnectionClass =
Class.forName("mondrian.olap.Connection");
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
final Object mondrianConnection =
((OlapWrapper) connection).unwrap(
mondrianConnectionClass);
assertNotNull(mondrianConnection);
assert mondrianConnectionClass.isInstance(mondrianConnection);
}
}
public void testXmlaCatalogParameter() throws Exception {
if (tester.getFlavor() == TestContext.Tester.Flavor.XMLA
|| tester.getFlavor() == Tester.Flavor.REMOTE_XMLA)
{
// We won't use the tester itself since we want to test
// creating a connection with and without a Catalog parameter.
Properties info = new Properties();
connection =
DriverManager.getConnection(
tester.getURL().replaceFirst("\\;Catalog=FoodMart", ""),
info);
assertEquals("FoodMart", connection.getCatalog());
final NamedList catalogs =
((OlapConnection) connection).getOlapCatalogs();
assertNotNull(catalogs);
Statement statement = connection.createStatement();
OlapStatement olapStatement =
TestContext.Wrapper.NONE.unwrap(statement, OlapStatement.class);
assertSame(connection, olapStatement.getConnection());
CellSet cellSet =
olapStatement.executeOlapQuery(
"SELECT FROM [Sales]");
assertSame(statement, cellSet.getStatement());
List axesList = cellSet.getAxes();
assertNotNull(axesList);
assertEquals(0, axesList.size());
info.setProperty(
XmlaOlap4jDriver.Property.CATALOG.name(), "FoodMart");
connection =
DriverManager.getConnection(
tester.getURL().replaceFirst("\\;Catalog=FoodMart", ""),
info);
assertEquals("FoodMart", connection.getCatalog());
info.setProperty(
XmlaOlap4jDriver.Property.CATALOG.name(), "FoodMartError");
try {
connection = DriverManager.getConnection(
tester.getURL().replaceFirst("\\;Catalog=FoodMart", ""),
info);
Statement statement2 = connection.createStatement();
OlapStatement olapStatement2 =
TestContext.Wrapper.NONE.unwrap(
statement2,
OlapStatement.class);
olapStatement2.executeOlapQuery(
"SELECT FROM [Sales]");
fail();
} catch (OlapException e) {
// no op.
}
}
}
public void testDatabaseMetaData() throws SQLException {
connection = tester.createConnection();
final OlapConnection olapConnection =
tester.getWrapper().unwrap(connection, OlapConnection.class);
final OlapDatabaseMetaData databaseMetaData =
olapConnection.getMetaData();
// as per testDriver
Driver driver = DriverManager.getDriver(tester.getDriverUrlPrefix());
assertNotNull(driver);
assertEquals(
databaseMetaData.getDriverMajorVersion(),
driver.getMajorVersion());
assertEquals(
databaseMetaData.getDriverMinorVersion(),
driver.getMinorVersion());
final String driverName = databaseMetaData.getDriverName();
// typically a string like "Mondrian olap4j driver"
assertTrue(
driverName != null
&& driverName.length() > 10);
final String driverVersion = databaseMetaData.getDriverVersion();
// typically a string like "0.9" or "3.1.2"
assertTrue(
driverVersion != null
&& driverName.length() > 2);
}
public void testStatement() throws SQLException {
connection = tester.createConnection();
Statement statement = connection.createStatement();
// Closing a statement is idempotent.
assertIsClosed(statement, false);
statement.close();
assertIsClosed(statement, true);
statement.close();
assertIsClosed(statement, true);
// Unwrap the statement to get the olap statement. Depending on the
// driver, this may or may not be the same object.
statement = connection.createStatement();
OlapStatement olapStatement =
tester.getWrapper().unwrap(statement, OlapStatement.class);
assertNotNull(olapStatement);
// Execute a simple query.
CellSet cellSet =
olapStatement.executeOlapQuery(
"SELECT FROM [Sales]");
List axesList = cellSet.getAxes();
assertNotNull(axesList);
assertEquals(0, axesList.size());
// Executing another query implicitly closes the previous result set.
assertIsClosed(statement, false);
assertIsClosed(cellSet, false);
CellSet cellSet2 =
olapStatement.executeOlapQuery(
"SELECT FROM [Sales]");
assertIsClosed(statement, false);
assertIsClosed(cellSet, true);
// Close the statement; this closes the result set.
assertIsClosed(cellSet2, false);
statement.close();
assertIsClosed(statement, true);
assertIsClosed(cellSet2, true);
cellSet.close();
assertIsClosed(statement, true);
assertIsClosed(cellSet2, true);
assertIsClosed(cellSet, true);
// Close the connection.
connection.close();
}
public void testAxes() throws SQLException {
connection = tester.createConnection();
Statement statement = connection.createStatement();
OlapStatement olapStatement =
tester.getWrapper().unwrap(statement, OlapStatement.class);
CellSet cellSet =
olapStatement.executeOlapQuery(
"SELECT {[Measures].[Unit Sales]} on 0,\n"
+ "{[Store].Children} on 1\n"
+ "FROM [Sales]\n"
+ "WHERE ([Time].[1997].[Q1], [Gender].[F])");
List axesList = cellSet.getAxes();
assertEquals(2, axesList.size());
final Member rowsMember =
axesList.get(0).getPositions().get(0).getMembers().get(0);
assertTrue(
rowsMember.getUniqueName(),
rowsMember instanceof Measure);
final Member columnsMember =
axesList.get(1).getPositions().get(0).getMembers().get(0);
assertTrue(
columnsMember.getUniqueName(),
!(columnsMember instanceof Measure));
// filter axis
final CellSetAxis filterAxis = cellSet.getFilterAxis();
assertEquals(1, filterAxis.getPositionCount());
final List positions = filterAxis.getPositions();
assertEquals(1, positions.size());
final Position pos0 = positions.get(0);
assertEquals(0, pos0.getOrdinal());
// The filter contains members explicitly returned. It does not contain
// the members of hierarchies not mentioned on any axis (e.g.
// [Marital Status]).
assertEquals(2, pos0.getMembers().size());
assertEquals("Q1", pos0.getMembers().get(0).getName());
assertEquals("F", pos0.getMembers().get(1).getName());
// If the query has no WHERE clause, the CellSet has a filter axis, but
// it has one position and zero members (i.e. equivalent to "WHERE ()".)
CellSet cellSetNoSlicer =
olapStatement.executeOlapQuery(
"SELECT {[Measures].[Unit Sales]} on 0,\n"
+ "{[Store].Children} on 1\n"
+ "FROM [Sales]");
assertEquals(2, cellSetNoSlicer.getAxes().size());
final CellSetAxis filterAxisNoSlicer = cellSetNoSlicer.getFilterAxis();
assertNotNull(filterAxisNoSlicer);
assertEquals(1, filterAxisNoSlicer.getPositionCount());
final Position position = filterAxisNoSlicer.getPositions().get(0);
assertEquals(0, position.getMembers().size());
}
/**
* Tests a filter with more than one position.
*
* @throws SQLException on error
*/
public void testCompoundFilter() throws SQLException {
connection = tester.createConnection();
OlapConnection olapConnection =
tester.getWrapper().unwrap(connection, OlapConnection.class);
OlapStatement statement = olapConnection.createStatement();
CellSet cellSet =
statement.executeOlapQuery(
"SELECT {[Measures].[Unit Sales]} on 0,\n"
+ "{[Product].Children} on 1\n"
+ "FROM [Sales]\n"
+ "WHERE [Time].[1997].[Q1] * [Gender].Members");
List axesList = cellSet.getAxes();
assertEquals(2, axesList.size());
final CellSetAxis filterAxis = cellSet.getFilterAxis();
assertEquals(3, filterAxis.getPositionCount());
final List filterPositions = filterAxis.getPositions();
assertEquals(3, filterPositions.size());
final Position filterPosition = filterPositions.get(2);
assertEquals(2, filterPosition.getMembers().size());
assertEquals("M", filterPosition.getMembers().get(1).getName());
}
/**
* Tests a filter with zero positions.
*
* @throws SQLException on error
*/
public void testEmptyFilter() throws SQLException {
connection = tester.createConnection();
OlapConnection olapConnection =
tester.getWrapper().unwrap(connection, OlapConnection.class);
OlapStatement statement = olapConnection.createStatement();
CellSet cellSet =
statement.executeOlapQuery(
"SELECT {[Measures].[Unit Sales]} on 0,\n"
+ "{[Product].Children} on 1\n"
+ "FROM [Sales]\n"
+ "WHERE [Time].[1997].[Q1] * [Gender].Parent");
List axesList = cellSet.getAxes();
assertEquals(2, axesList.size());
final CellSetAxis filterAxis = cellSet.getFilterAxis();
assertEquals(0, filterAxis.getPositionCount());
final List filterPositions = filterAxis.getPositions();
assertEquals(0, filterPositions.size());
assertEquals(2, filterAxis.getAxisMetaData().getHierarchies().size());
final Cell cell = cellSet.getCell(Arrays.asList(0, 0));
assertTrue(cell.isNull());
}
/**
* Tests a query with no filter (no WHERE clause).
*
* @throws SQLException on error
*/
public void testMissingFilter() throws SQLException {
connection = tester.createConnection();
OlapConnection olapConnection =
tester.getWrapper().unwrap(connection, OlapConnection.class);
OlapStatement statement = olapConnection.createStatement();
CellSet cellSet =
statement.executeOlapQuery(
"SELECT {[Measures].[Unit Sales]} on 0,\n"
+ "{[Product].Children} on 1\n"
+ "FROM [Sales]\n");
List axesList = cellSet.getAxes();
assertEquals(2, axesList.size());
final CellSetAxis filterAxis = cellSet.getFilterAxis();
assertEquals(1, filterAxis.getPositionCount());
final List filterPositions = filterAxis.getPositions();
assertEquals(1, filterPositions.size());
final Position position = filterPositions.get(0);
assertEquals(0, position.getMembers().size());
assertEquals(
0, filterAxis.getAxisMetaData().getHierarchies().size());
assertTrue(filterAxis.getAxisMetaData().getHierarchies().isEmpty());
final Cell cell = cellSet.getCell(Arrays.asList(0, 0));
assertEquals("24,597", cell.getFormattedValue());
}
public void testMeasureVersusMemberCasting() throws Exception {
connection = tester.createConnection();
Statement statement = connection.createStatement();
OlapStatement olapStatement =
tester.getWrapper().unwrap(statement, OlapStatement.class);
CellSet cellSet =
olapStatement.executeOlapQuery(
"SELECT {[Measures].[Unit Sales]} on 0,\n"
+ "{[Store].Children} on 1\n"
+ "FROM [Sales]\n"
+ "WHERE ([Time].[1997].[Q1], [Gender].[F])");
List axesList = cellSet.getAxes();
assertEquals(2, axesList.size());
final Member rowsMember =
axesList.get(0).getPositions().get(0).getMembers().get(0);
assertTrue(
rowsMember.getUniqueName(),
rowsMember instanceof Measure);
final Member columnsMember =
axesList.get(1).getPositions().get(0).getMembers().get(0);
assertTrue(
columnsMember.getUniqueName(),
!(columnsMember instanceof Measure));
}
public void testInvalidStatement() throws SQLException {
connection = tester.createConnection();
Statement statement = connection.createStatement();
OlapStatement olapStatement =
tester.getWrapper().unwrap(statement, OlapStatement.class);
// Execute a query with a syntax error.
try {
CellSet cellSet =
olapStatement.executeOlapQuery(
"SELECT an error FROM [Sales]");
fail("expected error, got " + cellSet);
} catch (OlapException e) {
switch (tester.getFlavor()) {
case XMLA:
case REMOTE_XMLA:
assertTrue(
e.getMessage(),
e.getMessage().indexOf("XMLA MDX parse failed") >= 0);
break;
default:
assertTrue(
TestContext.getStackTrace(e).indexOf(
"Failed to parse query") >= 0);
break;
}
}
// Error does not cause statement to become closed.
assertIsClosed(olapStatement, false);
olapStatement.close();
connection.close();
}
private enum Method {
ClassName,
Mode,
Type,
TypeName,
OlapType
}
public void testPreparedStatement() throws SQLException {
connection = tester.createConnection();
OlapConnection olapConnection =
tester.getWrapper().unwrap(connection, OlapConnection.class);
PreparedOlapStatement pstmt =
olapConnection.prepareOlapStatement(
"SELECT {\n"
+ " Parameter(\"P1\", [Store], [Store].[USA].[CA]).Parent,\n"
+ " ParamRef(\"P1\").Children} ON 0\n"
+ "FROM [Sales]\n"
+ "WHERE [Gender].[M]");
OlapParameterMetaData parameterMetaData =
pstmt.getParameterMetaData();
int paramCount = parameterMetaData.getParameterCount();
// XMLA driver does not support parameters yet.
switch (tester.getFlavor()) {
case XMLA:
case REMOTE_XMLA:
assertEquals(0, paramCount);
return;
}
// Mondrian driver supports parameters.
assertEquals(1, paramCount);
int[] paramIndexes = {0, 1, 2};
for (int paramIndex : paramIndexes) {
for (Method method : Method.values()) {
try {
switch (method) {
case ClassName:
String className =
parameterMetaData.getParameterClassName(paramIndex);
assertEquals("org.olap4j.metadata.Member", className);
break;
case Mode:
int mode =
parameterMetaData.getParameterMode(paramIndex);
assertEquals(ParameterMetaData.parameterModeIn, mode);
break;
case Type:
int type =
parameterMetaData.getParameterType(paramIndex);
assertEquals(Types.OTHER, type);
break;
case TypeName:
String typeName =
parameterMetaData.getParameterTypeName(paramIndex);
assertEquals("MemberType", typeName);
break;
case OlapType:
Type olapType =
parameterMetaData.getParameterOlapType(paramIndex);
assertEquals(
"MemberType",
olapType.toString());
break;
default:
throw Olap4jUtil.unexpected(method);
}
if (paramIndex != 1) {
fail("expected exception");
}
} catch (SQLException e) {
if (paramIndex == 1) {
throw e;
} else {
// ok - expecting exception
}
}
}
}
if (tester.getFlavor() == Tester.Flavor.XMLA) // TODO: upgrade mondrian
assertEquals("Sales", pstmt.getCube().getName());
// Check metadata exists. (Support for this method is optional.)
final CellSetMetaData metaData = pstmt.getMetaData();
assertEquals("Sales", metaData.getCube().getName());
CellSet cellSet = pstmt.executeQuery();
assertEquals(metaData, cellSet.getMetaData());
assertEquals("Sales", metaData.getCube().getName());
String s = TestContext.toString(cellSet);
final String expected =
"Axis #0:\n"
+ "{[Gender].[M]}\n"
+ "Axis #1:\n"
+ "{[Store].[USA]}\n"
+ "{[Store].[USA].[CA].[Alameda]}\n"
+ "{[Store].[USA].[CA].[Beverly Hills]}\n"
+ "{[Store].[USA].[CA].[Los Angeles]}\n"
+ "{[Store].[USA].[CA].[San Diego]}\n"
+ "{[Store].[USA].[CA].[San Francisco]}\n"
+ "Row #0: 135,215\n"
+ "Row #0: \n"
+ "Row #0: 10,562\n"
+ "Row #0: 13,574\n"
+ "Row #0: 12,800\n"
+ "Row #0: 1,053\n";
TestContext.assertEqualsVerbose(expected, s);
// Bind parameter and re-execute.
final List positions =
cellSet.getAxes().get(0).getPositions();
final Member member =
positions.get(positions.size() - 1).getMembers().get(0);
assertFalse(pstmt.isSet(1));
// parameter is 'set' even if value is null
pstmt.setObject(1, null);
assertTrue(pstmt.isSet(1));
pstmt.unset(1);
assertFalse(pstmt.isSet(1));
pstmt.setObject(1, member);
assertTrue(pstmt.isSet(1));
CellSet cellSet2 = pstmt.executeQuery();
assertIsClosed(cellSet, true);
assertIsClosed(cellSet2, false);
s = TestContext.toString(cellSet2);
final String expected2 =
"Axis #0:\n"
+ "{[Gender].[M]}\n"
+ "Axis #1:\n"
+ "{[Store].[USA].[CA]}\n"
+ "{[Store].[USA].[CA].[San Francisco].[Store 14]}\n"
+ "Row #0: 37,989\n"
+ "Row #0: 1,053\n";
TestContext.assertEqualsVerbose(expected2, s);
// Unset parameter and re-execute.
pstmt.unset(1);
cellSet = pstmt.executeQuery();
s = TestContext.toString(cellSet);
TestContext.assertEqualsVerbose(expected, s);
// Re-execute with a new MDX string.
CellSet cellSet3 = pstmt.executeOlapQuery(
"SELECT FROM [Sales] WHERE [Time.Weekly].[1997].[3]");
TestContext.assertEqualsVerbose(
"Axis #0:\n"
+ "{[Time.Weekly].[1997].[3]}\n"
+ "9,518",
TestContext.toString(cellSet3));
// Number of parameters has changed.
OlapParameterMetaData parameterMetaData1 = pstmt.getParameterMetaData();
assertEquals(0, parameterMetaData1.getParameterCount());
// Try to bind non-existent parameter.
try {
pstmt.setInt(1, 100);
fail("expected exception");
} catch (SQLException e) {
// ok
}
// Execute again.
CellSet cellSet4 = pstmt.executeQuery();
assertIsClosed(cellSet4, false);
assertIsClosed(cellSet3, true);
assertEquals(0, cellSet4.getAxes().size());
assertEquals(9518.0, cellSet4.getCell(0).getValue());
// Re-execute with a parse tree.
MdxParser mdxParser =
olapConnection.getParserFactory().createMdxParser(olapConnection);
SelectNode select =
mdxParser.parseSelect(
"select {[Gender]} on columns from [sales]\n"
+ "where [Time].[1997].[Q4]");
CellSet cellSet5 = pstmt.executeOlapQuery(select);
TestContext.assertEqualsVerbose(
"Axis #0:\n"
+ "{[Time].[1997].[Q4]}\n"
+ "Axis #1:\n"
+ "{[Gender].[All Gender]}\n"
+ "Row #0: 72,024\n",
TestContext.toString(cellSet5));
// Execute.
CellSet cellSet6 = pstmt.executeQuery();
assertIsClosed(cellSet6, false);
assertIsClosed(cellSet5, true);
assertEquals(1, cellSet6.getAxes().size());
assertEquals(72024.0, cellSet6.getCell(0).getDoubleValue());
// Close prepared statement.
assertIsClosed(pstmt, false);
pstmt.close();
assertIsClosed(pstmt, true);
assertIsClosed(cellSet, true);
assertIsClosed(cellSet2, true);
assertIsClosed(cellSet6, true);
// todo: test all of the PreparedOlapStatement.setXxx methods
if (false) {
pstmt.getCube();
}
}
public void testCellSetMetaData() throws SQLException {
// Metadata of prepared statement
connection = tester.createConnection();
OlapConnection olapConnection =
tester.getWrapper().unwrap(connection, OlapConnection.class);
checkCellSetMetaData1(
olapConnection,
"select {[Gender]} on columns from [sales]\n"
+ "where [Time].[1997].[Q4]");
// now a query with no explicit slicer
checkCellSetMetaData1(
olapConnection,
"select {[Gender]} on columns from [sales]");
}
private void checkCellSetMetaData1(
OlapConnection olapConnection, String mdx) throws SQLException
{
PreparedOlapStatement pstmt =
olapConnection.prepareOlapStatement(mdx);
final CellSetMetaData cellSetMetaData = pstmt.getMetaData();
checkCellSetMetaData(cellSetMetaData, 1, null);
// Metadata of its cellset
final CellSet cellSet = pstmt.executeQuery();
checkCellSetMetaData(cellSet.getMetaData(), 1, cellSet);
// Metadata of regular statement executing string.
final OlapStatement stmt = olapConnection.createStatement();
final CellSet cellSet1 = stmt.executeOlapQuery(mdx);
checkCellSetMetaData(cellSet1.getMetaData(), 1, cellSet1);
// Metadata of regular statement executing parse tree.
MdxParser mdxParser =
olapConnection.getParserFactory().createMdxParser(olapConnection);
SelectNode select = mdxParser.parseSelect(mdx);
final OlapStatement stmt2 = olapConnection.createStatement();
CellSet cellSet2 = stmt2.executeOlapQuery(select);
checkCellSetMetaData(cellSet2.getMetaData(), 1, cellSet2);
}
private void checkCellSetMetaData(
CellSetMetaData cellSetMetaData,
int axesCount,
CellSet cellSet) throws OlapException
{
assertNotNull(cellSetMetaData);
assertEquals(axesCount, cellSetMetaData.getAxesMetaData().size());
assertEquals("Sales", cellSetMetaData.getCube().getName());
int k = -1;
final Set unseenHierarchies =
new HashSet(cellSetMetaData.getCube().getHierarchies());
for (CellSetAxisMetaData axisMetaData
: cellSetMetaData.getAxesMetaData())
{
++k;
assertEquals(
Axis.Factory.forOrdinal(k),
axisMetaData.getAxisOrdinal());
assertEquals(k, axisMetaData.getAxisOrdinal().axisOrdinal());
assertTrue(axisMetaData.getHierarchies().size() > 0);
unseenHierarchies.removeAll(axisMetaData.getHierarchies());
assertTrue(axisMetaData.getProperties().size() == 0);
if (cellSet != null) {
final CellSetAxisMetaData cellSetAxisMetaData =
cellSet.getAxes().get(k).getAxisMetaData();
assertEquals(cellSetAxisMetaData, axisMetaData);
}
}
CellSetAxisMetaData axisMetaData =
cellSetMetaData.getFilterAxisMetaData();
assertNotNull(axisMetaData);
assertEquals(Axis.FILTER, axisMetaData.getAxisOrdinal());
assertTrue(axisMetaData.getHierarchies().size() >= 0);
if (false) {
// The slicer used to contain all hierarchies not seen on other
// axes. No longer true.
assertEquals(
new HashSet(axisMetaData.getHierarchies()),
unseenHierarchies);
} else {
for (Hierarchy hierarchy : axisMetaData.getHierarchies()) {
assertTrue(unseenHierarchies.contains(hierarchy));
}
}
assertTrue(axisMetaData.getProperties().size() == 0);
if (cellSet != null) {
assertEquals(
cellSet.getFilterAxis().getAxisMetaData(), axisMetaData);
assertEquals(
1, cellSet.getFilterAxis().getPositionCount());
assertEquals(
1, cellSet.getFilterAxis().getPositions().size());
}
}
/**
* Tests the {@link CellSetAxisMetaData} class, based on an example
* in the javadoc of same class.
*
* @throws Exception on error
*/
public void testCellSetAxisMetaData() throws Exception {
connection = tester.createConnection();
OlapConnection olapConnection =
tester.getWrapper().unwrap(connection, OlapConnection.class);
final String mdx = "SELECT\n"
+ " {[Measures].Members} ON COLUMNS,\n"
+ " CrossJoin([Store].Members, [Gender].Children)\n"
+ " DIMENSION PROPERTIES\n"
+ " MEMBER_ORDINAL,\n"
+ " MEMBER_UNIQUE_NAME,\n"
+ " DISPLAY_INFO ON ROWS\n"
+ " FROM [Sales]";
// first via prepared statement
final PreparedOlapStatement preparedStmt =
olapConnection.prepareOlapStatement(mdx);
final CellSetMetaData cellSetMetaData = preparedStmt.getMetaData();
checkAxisMetaData(cellSetMetaData.getAxesMetaData().get(1));
// second via directly executed statement
OlapStatement olapStatement = olapConnection.createStatement();
final CellSet cellSet =
olapStatement.executeOlapQuery(mdx);
checkAxisMetaData(cellSet.getAxes().get(1).getAxisMetaData());
// third via metadata of direct statement
checkAxisMetaData(cellSet.getMetaData().getAxesMetaData().get(1));
}
private void checkAxisMetaData(CellSetAxisMetaData cellSetAxisMetaData) {
final List hierarchies =
cellSetAxisMetaData.getHierarchies();
assertEquals(2, hierarchies.size());
assertEquals("Store", hierarchies.get(0).getName());
assertEquals("Gender", hierarchies.get(1).getName());
final List properties = cellSetAxisMetaData.getProperties();
switch (tester.getFlavor()) {
case MONDRIAN:
// todo: fix mondrian driver. If there are 3 properties and 2
// hierarchies, that's 6 properties total
assertEquals(3, properties.size());
break;
default:
assertEquals(6, properties.size());
break;
}
assertEquals("MEMBER_ORDINAL", properties.get(0).getName());
assertEquals("MEMBER_UNIQUE_NAME", properties.get(1).getName());
assertEquals("DISPLAY_INFO", properties.get(2).getName());
}
public void testCellSet() throws SQLException {
connection = tester.createConnection();
Statement statement = connection.createStatement();
final OlapStatement olapStatement =
tester.getWrapper().unwrap(statement, OlapStatement.class);
final CellSet cellSet =
olapStatement.executeOlapQuery(
"SELECT\n"
+ " {[Measures].[Unit Sales],\n"
+ " [Measures].[Store Sales]} ON COLUMNS\n,"
+ " Crossjoin({[Gender].[M]}, [Product].Children) ON ROWS\n"
+ "FROM [Sales]\n"
+ "WHERE [Time].[1997].[Q2]");
String s = TestContext.toString(cellSet);
TestContext.assertEqualsVerbose(
"Axis #0:\n"
+ "{[Time].[1997].[Q2]}\n"
+ "Axis #1:\n"
+ "{[Measures].[Unit Sales]}\n"
+ "{[Measures].[Store Sales]}\n"
+ "Axis #2:\n"
+ "{[Gender].[M], [Product].[Drink]}\n"
+ "{[Gender].[M], [Product].[Food]}\n"
+ "{[Gender].[M], [Product].[Non-Consumable]}\n"
+ "Row #0: 3,023\n"
+ "Row #0: 6,004.80\n"
+ "Row #1: 22,558\n"
+ "Row #1: 47,869.17\n"
+ "Row #2: 6,037\n"
+ "Row #2: 12,935.16\n",
s);
}
public void testCell() throws Exception {
connection = tester.createConnection();
Statement statement = connection.createStatement();
final OlapStatement olapStatement =
tester.getWrapper().unwrap(statement, OlapStatement.class);
CellSet cellSet =
olapStatement.executeOlapQuery(
"SELECT\n"
+ " {[Measures].[Unit Sales],\n"
+ " [Measures].[Store Sales]} ON COLUMNS\n,"
+ " Crossjoin({[Gender].[M]}, [Product].Children) ON ROWS\n"
+ "FROM [Sales]\n"
+ "WHERE [Time].[1997].[Q2]");
// cell column#1, row#2
// cellOrdinal = colOrdinal + rowOrdinal * columnCount
// = 1 + 2 * 2
// = 5
// access method 1
Cell cell = cellSet.getCell(5);
assertEquals(5, cell.getOrdinal());
if (tester.getFlavor() != TestContext.Tester.Flavor.XMLA // FIXME
|| tester.getFlavor() != TestContext.Tester.Flavor.REMOTE_XMLA)
{
assertEquals(12935.16, cell.getValue());
}
assertEquals(12935.16, cell.getDoubleValue());
assertEquals("12,935.16", cell.getFormattedValue());
assertEquals(cellSet, cell.getCellSet());
// access method 2
cell = cellSet.getCell(Arrays.asList(1, 2));
assertEquals(5, cell.getOrdinal());
// access method 3
cell = cellSet.getCell(
cellSet.getAxes().get(0).getPositions().get(1),
cellSet.getAxes().get(1).getPositions().get(2));
assertEquals(5, cell.getOrdinal());
assertEquals(Arrays.asList(1, 2), cell.getCoordinateList());
assertEquals(
"#,###.00",
cell.getPropertyValue(Property.StandardCellProperty.FORMAT_STRING));
assertFalse(cell.isEmpty());
assertFalse(cell.isError());
assertFalse(cell.isNull());
assertNull(cell.getErrorText());
switch (tester.getFlavor()) {
case XMLA:
case REMOTE_XMLA:
// TODO: implement drill-through in XMLA driver
break;
default:
final ResultSet resultSet = cell.drillThrough();
final ResultSetMetaData metaData = resultSet.getMetaData();
// Most databases return 5 columns. Derby returns 9 because of
// 4 columns in the ORDER BY clause.
assertTrue(metaData.getColumnCount() >= 5);
assertEquals("Year", metaData.getColumnLabel(1));
assertEquals("Store Sales", metaData.getColumnLabel(5));
resultSet.close();
break;
}
// cell out of range using getCell(int)
try {
Cell cell2 = cellSet.getCell(-5);
fail("expected exception, got " + cell2);
} catch (IndexOutOfBoundsException e) {
// ok
}
// cell out of range using getCell(int)
try {
Cell cell2 = cellSet.getCell(105);
fail("expected exception, got " + cell2);
} catch (IndexOutOfBoundsException e) {
// ok
}
// cell out of range using getCell(List)
try {
Cell cell2 = cellSet.getCell(Arrays.asList(2, 1));
fail("expected exception, got " + cell2);
} catch (IndexOutOfBoundsException e) {
// ok
}
// cell out of range using getCell(Position...) is not possible; but
// number of positions might be wrong
try {
// too few dimensions
Cell cell2 =
cellSet.getCell(cellSet.getAxes().get(0).getPositions().get(0));
fail("expected exception, got " + cell2);
} catch (IllegalArgumentException e) {
// ok
}
try {
// too many dimensions
Cell cell2 =
cellSet.getCell(
cellSet.getAxes().get(0).getPositions().get(0),
cellSet.getAxes().get(1).getPositions().get(0),
cellSet.getAxes().get(0).getPositions().get(0));
fail("expected exception, got " + cell2);
} catch (IllegalArgumentException e) {
// ok
}
// We provide positions from the wrong axes, but the provider doesn't
// notice that they're wrong. That's OK.
cell =
cellSet.getCell(
cellSet.getAxes().get(1).getPositions().get(1),
cellSet.getAxes().get(0).getPositions().get(1));
assertEquals(3, cell.getOrdinal());
// Null cell
cellSet =
olapStatement.executeOlapQuery(
"with member [Measures].[X] as 'IIF([Measures].[Store Sales]>10000,[Measures].[Store Sales],Null)'\n"
+ "select\n"
+ "{[Measures].[X]} on columns,\n"
+ "{[Product].[Product Department].members} on rows\n"
+ "from Sales");
cell = cellSet.getCell(0);
assertFalse(cell.isNull());
cell = cellSet.getCell(2);
assertTrue(cell.isNull());
// Empty cell
cellSet =
olapStatement.executeOlapQuery(
"select from [Sales]\n"
+ "where ([Time].[1997].[Q4].[12],\n"
+ " [Product].[All Products].[Drink].[Alcoholic Beverages].[Beer and Wine].[Beer].[Portsmouth].[Portsmouth Imported Beer],\n"
+ " [Store].[All Stores].[USA].[WA].[Bellingham])");
cell = cellSet.getCell(0);
assertTrue(cell.isEmpty());
// Error cell
cellSet =
olapStatement.executeOlapQuery(
"with member [Measures].[Foo] as ' Dimensions(-1).Name '\n"
+ "select {[Measures].[Foo]} on columns from [Sales]");
cell = cellSet.getCell(0);
switch (tester.getFlavor()) {
case XMLA:
case REMOTE_XMLA:
// FIXME: mondrian's XMLA provider doesn't indicate that a cell is
// an error
break;
default:
assertTrue(cell.isError());
assertEquals("Index '-1' out of bounds", cell.getErrorText());
break;
}
// todo: test CellSetAxis methods
/*
public int getAxisOrdinal()
public CellSet getCellSet()
public CellSetAxisMetaData getAxisMetaData()
public List getPositions()
public int getPositionCount()
public ListIterator iterate()
todo: test OlapResultAxisMetaData methods
public org.olap4j.Axis getAxisOrdinal()
public List getHierarchies()
public List getProperties()
*/
}
/**
* Tests different scrolling characteristics.
*
* In one mode, you request that you get all of the positions on an axis.
* You can call {@link CellSetAxis#getPositions()} and
* {@link CellSetAxis#getPositions()}.
*
*
In another mode, you can iterate over the positions, calling
* {@link org.olap4j.CellSetAxis#iterator()}. Note that this method returns
* a {@link java.util.ListIterator}, which has
* {@link java.util.ListIterator#nextIndex()}. We could maybe extend this
* interface further, to allow to jump forwards/backwards by N.
*
*
This test should check that queries work correctly when you ask
* for axes as lists and iterators. If you open the query as a list,
* you can get it as an iterator, but if you open it as an iterator, you
* cannot get it as a list. (Or maybe you can, but it is expensive.)
*
*
The existing JDBC method {@link Connection#createStatement(int, int)},
* where the 2nd parameter has values such as
* {@link ResultSet#TYPE_FORWARD_ONLY} and
* {@link ResultSet#TYPE_SCROLL_INSENSITIVE}, might be the way to invoke
* those two modes.
*
*
Note that cell ordinals are not well-defined until axis lengths are
* known. Test that cell ordinal property is not available if the statement
* is opened in this mode.
*
*
It was proposed that there would be an API to get blocks of cell
* values. Not in the spec yet.
*/
public void testScrolling() {
// todo: submit a query where you ask for different scrolling
// characteristics. maybe the values
int x = ResultSet.TYPE_SCROLL_INSENSITIVE;
int y = ResultSet.TYPE_FORWARD_ONLY;
// are how to ask for these characteristics. also need to document this
// behavior in the API and the spec. in one mode,
}
/**
* Tests creation of an MDX parser, and converting an MDX statement into
* a parse tree.
*
*
Also create a set of negative tests. Do we give sensible errors if
* the MDX is misformed.
*
*
Also have a set of validator tests, which check that the functions
* used exist, are applied to arguments of the correct type, and members
* exist.
*/
public void testParsing() throws SQLException {
// parse
connection = tester.createConnection();
OlapConnection olapConnection =
tester.getWrapper().unwrap(connection, OlapConnection.class);
MdxParser mdxParser =
olapConnection.getParserFactory().createMdxParser(olapConnection);
SelectNode select =
mdxParser.parseSelect(
"with member [Measures].[Foo] as ' [Measures].[Bar] ', FORMAT_STRING='xxx'\n"
+ " select {[Gender]} on columns, {[Store].Children} on rows\n"
+ "from [sales]\n"
+ "where [Time].[1997].[Q4]");
// unparse
checkUnparsedMdx(select);
// test that get error if axes do not have unique names
select =
mdxParser.parseSelect(
"select {[Gender]} on columns, {[Store].Children} on columns\n"
+ "from [sales]");
if (tester.getFlavor() == TestContext.Tester.Flavor.XMLA
|| tester.getFlavor() != Tester.Flavor.XMLA)
{
// This test requires validator support.
return;
}
MdxValidator validator =
olapConnection.getParserFactory().createMdxValidator(
olapConnection);
try {
select = validator.validateSelect(select);
fail("expected exception, got " + select);
} catch (Exception e) {
assertTrue(
TestContext.getStackTrace(e)
.indexOf("Duplicate axis name 'COLUMNS'.") >= 0);
}
}
private void checkUnparsedMdx(SelectNode select) {
checkUnparsedMdx(
select,
"WITH\n"
+ "MEMBER [Measures].[Foo] AS\n"
+ " [Measures].[Bar], FORMAT_STRING = \"xxx\"\n"
+ "SELECT\n"
+ "{[Gender]} ON COLUMNS,\n"
+ "{[Store].Children} ON ROWS\n"
+ "FROM [sales]\n"
+ "WHERE [Time].[1997].[Q4]");
}
private void checkUnparsedMdx(
SelectNode select,
String expectedMdx)
{
StringWriter sw = new StringWriter();
ParseTreeWriter parseTreeWriter = new ParseTreeWriter(sw);
select.unparse(parseTreeWriter);
String mdx = sw.toString();
TestContext.assertEqualsVerbose(
expectedMdx, mdx);
}
/**
* Tests creation of an MDX query from a parse tree. Build the parse tree
* programmatically.
*/
public void testUnparsing() {
// Note that the select statement constructed here is equivalent
// to the one in testParsing.
final IdentifierNode cubeName =
new IdentifierNode(new NameSegment("sales"));
SelectNode select = new SelectNode(
null,
new ArrayList(),
new ArrayList(),
cubeName,
new AxisNode(
null,
false,
Axis.FILTER,
new ArrayList(),
null),
new ArrayList());
select.getWithList().add(
new WithMemberNode(
null,
new IdentifierNode(
new NameSegment("Measures"),
new NameSegment("Foo")),
new IdentifierNode(
new NameSegment("Measures"),
new NameSegment("Bar")),
Arrays.asList(
new PropertyValueNode(
null,
"FORMAT_STRING",
LiteralNode.createString(
null,
"xxx")))));
select.getAxisList().add(
new AxisNode(
null,
false,
Axis.COLUMNS,
new ArrayList(),
new CallNode(
null,
"{}",
Syntax.Braces,
Arrays.asList(
(ParseTreeNode)
new IdentifierNode(
new NameSegment("Gender"))))));
select.getAxisList().add(
new AxisNode(
null,
false,
Axis.ROWS,
new ArrayList(),
new CallNode(
null,
"{}",
Syntax.Braces,
new CallNode(
null,
"Children",
Syntax.Property,
new IdentifierNode(
new NameSegment("Store"))))));
select.getFilterAxis().setExpression(
new IdentifierNode(
new NameSegment("Time"),
new NameSegment("1997"),
new NameSegment("Q4")));
assertEquals(select.getFrom(), cubeName);
checkUnparsedMdx(select);
// Now with a subquery in the FROM clause.
SelectNode subSelect = new SelectNode(
null,
new ArrayList(),
new ArrayList(),
new IdentifierNode(new NameSegment("warehouse")),
new AxisNode(
null,
false,
Axis.FILTER,
new ArrayList(),
null),
new ArrayList());
select.setFrom(subSelect);
assertEquals(select.getFrom(), subSelect);
checkUnparsedMdx(
select,
"WITH\n"
+ "MEMBER [Measures].[Foo] AS\n"
+ " [Measures].[Bar], FORMAT_STRING = \"xxx\"\n"
+ "SELECT\n"
+ "{[Gender]} ON COLUMNS,\n"
+ "{[Store].Children} ON ROWS\n"
+ "FROM (\n"
+ " SELECT\n"
+ " FROM [warehouse])\n"
+ "WHERE [Time].[1997].[Q4]");
}
public void testBuildParseTree() {
// It is an error to create a select node with a filter axis whose type
// is not filter
try {
SelectNode select = new SelectNode(
null,
new ArrayList(),
new ArrayList(),
new IdentifierNode(new NameSegment("sales")),
new AxisNode(
null,
false,
Axis.COLUMNS,
new ArrayList(),
null),
new ArrayList());
fail("expected error, got " + select);
} catch (IllegalArgumentException e) {
TestContext.checkThrowable(e, "Filter axis must have type FILTER");
}
// Create a select node with empty filter axis. It is populated with
// a filter axis whose expression is null.
SelectNode select = new SelectNode(
null,
new ArrayList(),
new ArrayList(),
new IdentifierNode(new NameSegment("sales")),
new AxisNode(
null,
false,
Axis.FILTER,
new ArrayList(),
null),
new ArrayList());
final AxisNode filterAxis = select.getFilterAxis();
assertNotNull(filterAxis);
assertNull(filterAxis.getExpression());
assertEquals(Axis.FILTER, filterAxis.getAxis());
// Parses to an expression with no WHERE clause
checkUnparsedMdx(
select,
"SELECT\n"
+ "FROM [sales]");
// Set the filter, see if it takes.
select.getFilterAxis().setExpression(
new CallNode(
null,
"()",
Syntax.Parentheses,
new IdentifierNode(
new NameSegment("Measures"),
new NameSegment("Store Sales")),
new IdentifierNode(
new NameSegment("Gender"),
new NameSegment("M"))));
checkUnparsedMdx(
select,
"SELECT\n"
+ "FROM [sales]\n"
+ "WHERE ([Measures].[Store Sales], [Gender].[M])");
// Set it back to null
select.getFilterAxis().setExpression(null);
checkUnparsedMdx(
select,
"SELECT\n"
+ "FROM [sales]");
}
/**
* Tests the {@link Cube#lookupMember(java.util.List)} method.
*/
public void testCubeLookupMember() throws Exception {
Class.forName(tester.getDriverClassName());
connection = tester.createConnection();
OlapConnection olapConnection =
tester.getWrapper().unwrap(connection, OlapConnection.class);
Cube cube =
olapConnection
.getOlapCatalogs()
.get("FoodMart")
.getSchemas()
.get("FoodMart")
.getCubes()
.get("Sales Ragged");
Member member =
cube.lookupMember(nameList("Time", "1997", "Q2"));
assertEquals("[Time].[1997].[Q2]", member.getUniqueName());
// Member.getChildMemberCount
assertEquals(3, member.getChildMemberCount());
// Member.getChildMembers
final NamedList extends Member> childMembers =
member.getChildMembers();
assertEquals(3, childMembers.size());
assertEquals(
"[Time].[1997].[Q2].[4]", childMembers.get(0).getUniqueName());
assertEquals(0, childMembers.get(0).getChildMemberCount());
assertEquals(
"[Time].[1997].[Q2].[6]", childMembers.get("6").getUniqueName());
assertNull(childMembers.get("1"));
member =
cube.lookupMember(nameList("Time", "1997", "Q5"));
assertNull(member);
// arguably this should return [Customers].[All Customers]; but it
// makes a bit more sense for it to return null
member =
cube.lookupMember(nameList("Customers"));
assertNull(member);
member =
cube.lookupMember(nameList("Customers", "All Customers"));
assertTrue(member.isAll());
}
/**
* Tests the {@link Cube#lookupMembers(java.util.Set, java.util.List)}
* method.
*/
public void testCubeLookupMembers() throws Exception {
Class.forName(tester.getDriverClassName());
connection = tester.createConnection();
OlapConnection olapConnection =
tester.getWrapper().unwrap(connection, OlapConnection.class);
Cube cube =
olapConnection
.getOlapCatalogs()
.get("FoodMart")
.getSchemas()
.get("FoodMart")
.getCubes()
.get("Sales");
List memberList =
cube.lookupMembers(
Olap4jUtil.enumSetOf(
Member.TreeOp.ANCESTORS, Member.TreeOp.CHILDREN),
nameList("Time", "1997", "Q2"));
String expected;
switch (tester.getFlavor()) {
case XMLA:
case REMOTE_XMLA:
// TODO: Fix mondrian's XMLA driver to return members ordered by
// level then by ordinal as per XMLA spec
expected =
"[Time].[1997].[Q2].[4]\n"
+ "[Time].[1997].[Q2].[5]\n"
+ "[Time].[1997].[Q2].[6]\n"
+ "[Time].[1997]\n";
break;
default:
expected =
"[Time].[1997]\n"
+ "[Time].[1997].[Q2].[4]\n"
+ "[Time].[1997].[Q2].[5]\n"
+ "[Time].[1997].[Q2].[6]\n";
}
TestContext.assertEqualsVerbose(
expected,
memberListToString(memberList));
// ask for non-existent member; list should be empty
memberList =
cube.lookupMembers(
Olap4jUtil.enumSetOf(
Member.TreeOp.ANCESTORS, Member.TreeOp.CHILDREN),
nameList("Time", "1997", "Q5"));
assertTrue(memberList.isEmpty());
// ask for parent & ancestors; should not get duplicates
memberList =
cube.lookupMembers(
Olap4jUtil.enumSetOf(
Member.TreeOp.ANCESTORS, Member.TreeOp.PARENT),
nameList("Time", "1997", "Q2"));
TestContext.assertEqualsVerbose(
"[Time].[1997]\n",
memberListToString(memberList));
// ask for parent of root member, should not get null member in list
memberList =
cube.lookupMembers(
Olap4jUtil.enumSetOf(
Member.TreeOp.ANCESTORS, Member.TreeOp.PARENT),
nameList("Product"));
assertTrue(memberList.isEmpty());
// ask for siblings and children, and the results should be
// hierarchically ordered (as always)
memberList =
cube.lookupMembers(
Olap4jUtil.enumSetOf(
Member.TreeOp.SIBLINGS, Member.TreeOp.CHILDREN),
nameList("Time", "1997", "Q2"));
switch (tester.getFlavor()) {
case XMLA:
case REMOTE_XMLA:
// TODO: fix mondrian's XMLA driver to return members ordered by
// level then ordinal
expected =
"[Time].[1997].[Q2].[4]\n"
+ "[Time].[1997].[Q2].[5]\n"
+ "[Time].[1997].[Q2].[6]\n"
+ "[Time].[1997].[Q1]\n"
+ "[Time].[1997].[Q3]\n"
+ "[Time].[1997].[Q4]\n";
break;
default:
expected =
"[Time].[1997].[Q1]\n"
+ "[Time].[1997].[Q2].[4]\n"
+ "[Time].[1997].[Q2].[5]\n"
+ "[Time].[1997].[Q2].[6]\n"
+ "[Time].[1997].[Q3]\n"
+ "[Time].[1997].[Q4]\n";
break;
}
TestContext.assertEqualsVerbose(
expected,
memberListToString(memberList));
// siblings of the root member - potentially tricky
memberList =
cube.lookupMembers(
Olap4jUtil.enumSetOf(Member.TreeOp.SIBLINGS),
nameList("Time", "1997"));
TestContext.assertEqualsVerbose(
"[Time].[1998]\n",
memberListToString(memberList));
memberList =
cube.lookupMembers(
Olap4jUtil.enumSetOf(
Member.TreeOp.SIBLINGS, Member.TreeOp.SELF),
nameList("Customers", "USA", "OR"));
TestContext.assertEqualsVerbose(
"[Customers].[USA].[CA]\n"
+ "[Customers].[USA].[OR]\n"
+ "[Customers].[USA].[WA]\n",
memberListToString(memberList));
}
/**
* Tests metadata browsing.
*/
public void testMetadata() throws Exception {
Class.forName(tester.getDriverClassName());
connection = tester.createConnection();
OlapConnection olapConnection =
tester.getWrapper().unwrap(connection, OlapConnection.class);
OlapDatabaseMetaData metadata = olapConnection.getMetaData();
// We engineered the XMLA test environment to have two catalogs.
switch (tester.getFlavor()) {
case REMOTE_XMLA:
assertEquals(1, olapConnection.getOlapCatalogs().size());
break;
case XMLA:
assertEquals(2, olapConnection.getOlapCatalogs().size());
break;
case MONDRIAN:
assertEquals(1, olapConnection.getOlapCatalogs().size());
break;
}
Cube cube =
olapConnection
.getOlapCatalogs()
.get("FoodMart")
.getSchemas()
.get("FoodMart")
.getCubes()
.get("Sales");
int z = 0;
int hierarchyCount = 0;
for (Dimension dimension : cube.getDimensions()) {
// Call every method of Dimension
assertNotNull(dimension.getCaption());
dimension.getDescription();
assertNotNull(dimension.getDefaultHierarchy());
assertEquals(
dimension.getName().equals("Time")
? Dimension.Type.TIME
: dimension.getName().equals("Measures")
? Dimension.Type.MEASURE
: Dimension.Type.OTHER,
dimension.getDimensionType());
assertNotNull(dimension.getName());
assertNotNull(dimension.getUniqueName());
for (Hierarchy hierarchy : dimension.getHierarchies()) {
++hierarchyCount;
// Call every method of Hierarchy
final NamedList rootMemberList =
hierarchy.getRootMembers();
if (hierarchy.hasAll()) {
assertEquals(1, rootMemberList.size());
}
for (Member rootMember : rootMemberList) {
assertNull(rootMember.getParentMember());
}
assertEquals(
rootMemberList,
hierarchy.getLevels().get(0).getMembers());
assertNotNull(hierarchy.getDefaultMember());
assertNotNull(hierarchy.getName());
assertNotNull(hierarchy.getUniqueName());
hierarchy.getDescription();
assertNotNull(hierarchy.getCaption());
assertEquals(dimension, hierarchy.getDimension());
for (Level level : hierarchy.getLevels()) {
if (level.getCardinality() >= 100) {
continue;
}
if (level.getName().equals("Year")) {
assertEquals(
Level.Type.TIME_YEARS, level.getLevelType());
assertFalse(level.isCalculated());
++z;
}
if (level.getName().equals("Gender")) {
assertEquals(Level.Type.REGULAR, level.getLevelType());
assertFalse(level.isCalculated());
++z;
}
if (level.getName().equals("Measures")) {
assertEquals(Level.Type.REGULAR, level.getLevelType());
assertFalse(level.isCalculated());
++z;
}
// for (Member member : level.getMembers()) {
// assertNotNull(member.getName());
// assertEquals(level, member.getLevel());
// if (dimension.getDimensionType()
// == Dimension.Type.MEASURE)
// {
// assertTrue(member instanceof Measure);
// }
// if (++k > 3) {
// break;
// }
// }
}
}
}
// Make sure every hierarchy which came out through
// cube.getDimensions().getHierarchies() also comes out through
// cube.getHierarchies().
for (Hierarchy hierarchy : cube.getHierarchies()) {
--hierarchyCount;
assertNotNull(hierarchy.getName());
}
assertEquals(0, hierarchyCount);
assertEquals("found Year, Measures, Gender levels", 3, z);
// Look for the Time.Weekly hierarchy, the 2nd hierarchy in the Time
// dimension.
final Hierarchy timeWeeklyHierarchy =
cube.getHierarchies().get("Time.Weekly");
assertNotNull(timeWeeklyHierarchy);
assertEquals("Time", timeWeeklyHierarchy.getDimension().getName());
assertEquals(
2, timeWeeklyHierarchy.getDimension().getHierarchies().size());
Cube warehouseCube =
olapConnection
.getOlapCatalogs()
.get("FoodMart")
.getSchemas()
.get("FoodMart")
.getCubes()
.get("Warehouse");
int count = 0;
for (NamedSet namedSet : warehouseCube.getSets()) {
++count;
assertNotNull(namedSet.getName());
assertNotNull(namedSet.getUniqueName());
assertNotNull(namedSet.getCaption());
namedSet.getDescription();
switch (tester.getFlavor()) {
case XMLA:
case REMOTE_XMLA:
// FIXME: implement getExpression in XMLA driver
break;
default:
assertTrue(
namedSet.getExpression().getType() instanceof SetType);
}
}
assertTrue(count > 0);
// ~ Member
Member member =
cube.lookupMember(
nameList("Product", "Food", "Marshmallows"));
assertNull(member); // we don't sell marshmallows!
member =
cube.lookupMember(
nameList("Product", "Food"));
assertNotNull(member);
Member member2 =
cube.lookupMember(
nameList("Product", "All Products", "Food"));
assertEquals(member, member2);
final Member bread =
cube.lookupMember(
nameList("Product", "Food", "Baked Goods", "Bread"));
assertEquals("[Product].[Food]", member.getUniqueName());
assertEquals("Food", member.getName());
assertEquals(
"[Product].[Product Family]",
member.getLevel().getUniqueName());
assertEquals(Member.Type.REGULAR, member.getMemberType());
assertEquals(
"[Product].[Food].[Baked Goods]",
bread.getParentMember().getUniqueName());
final List list = bread.getAncestorMembers();
assertEquals(3, list.size());
assertEquals(
"[Product].[Food].[Baked Goods]", list.get(0).getUniqueName());
assertEquals("[Product].[Food]", list.get(1).getUniqueName());
assertEquals("[Product].[All Products]", list.get(2).getUniqueName());
assertEquals("Food", member.getCaption());
switch (tester.getFlavor()) {
case XMLA:
case REMOTE_XMLA:
assertEquals("", member.getDescription());
assertEquals(204, member.getOrdinal());
break;
default:
assertNull(member.getDescription());
// mondrian does not set ordinals correctly
assertEquals(-1, member.getOrdinal());
assertEquals(1, member.getDepth());
assertEquals(-1, member.getSolveOrder());
assertFalse(member.isHidden());
assertNull(member.getDataMember());
assertFalse(member.isCalculatedInQuery());
}
final NamedList propertyList = member.getProperties();
final Property property = propertyList.get("MEMBER_CAPTION");
assertEquals("Food", member.getPropertyFormattedValue(property));
assertEquals("Food", member.getPropertyValue(property));
assertFalse(member.isAll());
// All member
final Member allProductsMember = member.getParentMember();
assertEquals(
"[Product].[All Products]",
allProductsMember.getUniqueName());
assertEquals("(All)", allProductsMember.getLevel().getName());
assertEquals(
"[Product].[(All)]", allProductsMember.getLevel().getUniqueName());
assertEquals(1, allProductsMember.getLevel().getMembers().size());
assertTrue(allProductsMember.isAll());
assertNull(allProductsMember.getParentMember());
// ~ Property
assertEquals("MEMBER_CAPTION", property.getName());
assertEquals("MEMBER_CAPTION", property.getUniqueName());
assertEquals(
Olap4jUtil.enumSetOf(Property.TypeFlag.MEMBER), property.getType());
assertEquals(Datatype.STRING, property.getDatatype());
// PARENT_LEVEL property
final Property parentLevelProperty = propertyList.get("PARENT_LEVEL");
assertNotNull(parentLevelProperty);
assertEquals(
0, allProductsMember.getPropertyValue(parentLevelProperty));
assertEquals(0, member.getPropertyValue(parentLevelProperty));
assertEquals(2, bread.getPropertyValue(parentLevelProperty));
// PARENT_UNIQUE_NAME property
final Property parentUniqueNameProperty =
propertyList.get("PARENT_UNIQUE_NAME");
assertNotNull(parentUniqueNameProperty);
assertNull(
allProductsMember.getPropertyValue(parentUniqueNameProperty));
assertEquals(
"[Product].[All Products]",
member.getPropertyValue(parentUniqueNameProperty));
assertEquals(
"[Product].[Food].[Baked Goods]",
bread.getPropertyValue(parentUniqueNameProperty));
// Measures
int k = -1;
Set measureNameSet = new HashSet();
for (Measure measure : cube.getMeasures()) {
++k;
// The first measure is [Unit Sales], because the list must be
// sorted by ordinal.
if (k == 0) {
assertEquals("Unit Sales", measure.getName());
}
if (measure.getName().equals("Profit Growth")
|| measure.getName().equals("Profit last Period")
|| measure.getName().equals("Profit"))
{
assertEquals(Member.Type.FORMULA, measure.getMemberType());
assertTrue(measure.isCalculated());
} else {
assertEquals(Member.Type.MEASURE, measure.getMemberType());
assertFalse(measure.isCalculated());
}
assertNotNull(measure.getName());
assertNotNull(measure.getAggregator());
assertTrue(measure.getDatatype() != null);
// mondrian's olap4j driver returns the invisible member
// [Measures].[Profit last Period]; the xmla driver does not,
// because XMLA by default does not return invisible measures.
if (measure.getName().equals("Profit last Period")) {
assertFalse(measure.isVisible());
} else {
measureNameSet.add(measure.getName());
}
}
assertEquals(
new HashSet(
Arrays.asList(
"Unit Sales",
"Customer Count",
"Profit",
"Profit Growth",
"Promotion Sales",
"Sales Count",
"Store Sales",
"Store Cost")),
measureNameSet);
}
/**
* Test case for {@link org.olap4j.metadata.Schema#getSharedDimensions()}.
* Bug 3375355, "getSharedDimensions returns empty result".
*/
public void testSchemaGetSharedDimensions() throws Exception {
Class.forName(tester.getDriverClassName());
connection = tester.createConnection();
OlapConnection olapConnection =
tester.getWrapper().unwrap(connection, OlapConnection.class);
final List list = new ArrayList();
final NamedList sharedDimensions =
olapConnection.getOlapSchema().getSharedDimensions();
for (Dimension dimension : sharedDimensions) {
list.add(dimension.getName());
}
// note that, per specification, list is sorted
assertEquals(
Arrays.asList(
"Product",
"Store",
"Store Size in SQFT",
"Store Type",
"Time",
"Warehouse"),
list);
int hierarchyCount = 0, levelCount = 0;
for (Dimension sharedDimension : sharedDimensions) {
for (Hierarchy hierarchy : sharedDimension.getHierarchies()) {
++hierarchyCount;
for (Level level : hierarchy.getLevels()) {
++levelCount;
}
}
}
assertTrue(hierarchyCount > 0);
assertTrue(levelCount > 0);
}
/**
* Testcase for bug 3312701, "VirtualCube doesn't show
* Calculated Members"
*/
public void testVirtualCubeCmBug() throws Exception {
Class.forName(tester.getDriverClassName());
connection = tester.createConnection();
OlapConnection olapConnection =
tester.getWrapper().unwrap(connection, OlapConnection.class);
Cube warehouseSalesCube =
olapConnection
.getOlapCatalogs()
.get("FoodMart")
.getSchemas()
.get("FoodMart")
.getCubes()
.get("Warehouse and Sales");
Set measureVcNameSet = new HashSet();
for (Measure measure : warehouseSalesCube.getMeasures()) {
measureVcNameSet.add(measure.getName());
}
assertEquals(
new HashSet(
Arrays.asList(
"Sales Count",
"Store Cost",
"Store Sales",
"Unit Sales",
"Profit",
"Profit Growth",
"Profit Per Unit Shipped",
"Store Invoice",
"Supply Time",
"Units Ordered",
"Units Shipped",
"Warehouse Cost",
"Warehouse Profit",
"Warehouse Sales",
"Average Warehouse Sale")),
measureVcNameSet);
}
/**
* Testcase for bug 1868075, "Query on ragged hierarchy gives only empty
* cells".
*/
public void testRagged() throws SQLException {
connection = tester.createConnection();
Statement statement = connection.createStatement();
final OlapStatement olapStatement =
tester.getWrapper().unwrap(statement, OlapStatement.class);
final CellSet cellSet =
olapStatement.executeOlapQuery(
"SELECT\n"
+ "{[Product].[All Products].[Drink].[Alcoholic Beverages].Children,\n"
+ "[Product].[All Products].[Food].[Baked Goods].Children} ON COLUMNS,\n"
+ "CrossJoin([Store].[All Stores].[USA].[CA].Children,\n"
+ "[Time].[1997].[Q1].Children) ON ROWS\n"
+ "FROM [Sales Ragged]");
String s = TestContext.toString(cellSet);
TestContext.assertEqualsVerbose(
"Axis #0:\n"
+ "{}\n"
+ "Axis #1:\n"
+ "{[Product].[Drink].[Alcoholic Beverages].[Beer and Wine]}\n"
+ "{[Product].[Food].[Baked Goods].[Bread]}\n"
+ "Axis #2:\n"
+ "{[Store].[USA].[CA].[Alameda], [Time].[1997].[Q1].[1]}\n"
+ "{[Store].[USA].[CA].[Alameda], [Time].[1997].[Q1].[2]}\n"
+ "{[Store].[USA].[CA].[Alameda], [Time].[1997].[Q1].[3]}\n"
+ "{[Store].[USA].[CA].[Beverly Hills], [Time].[1997].[Q1].[1]}\n"
+ "{[Store].[USA].[CA].[Beverly Hills], [Time].[1997].[Q1].[2]}\n"
+ "{[Store].[USA].[CA].[Beverly Hills], [Time].[1997].[Q1].[3]}\n"
+ "{[Store].[USA].[CA].[Los Angeles], [Time].[1997].[Q1].[1]}\n"
+ "{[Store].[USA].[CA].[Los Angeles], [Time].[1997].[Q1].[2]}\n"
+ "{[Store].[USA].[CA].[Los Angeles], [Time].[1997].[Q1].[3]}\n"
+ "{[Store].[USA].[CA].[San Francisco], [Time].[1997].[Q1].[1]}\n"
+ "{[Store].[USA].[CA].[San Francisco], [Time].[1997].[Q1].[2]}\n"
+ "{[Store].[USA].[CA].[San Francisco], [Time].[1997].[Q1].[3]}\n"
+ "Row #0: \n"
+ "Row #0: \n"
+ "Row #1: \n"
+ "Row #1: \n"
+ "Row #2: \n"
+ "Row #2: \n"
+ "Row #3: 22\n"
+ "Row #3: 63\n"
+ "Row #4: 28\n"
+ "Row #4: 59\n"
+ "Row #5: 28\n"
+ "Row #5: 39\n"
+ "Row #6: 70\n"
+ "Row #6: 51\n"
+ "Row #7: 89\n"
+ "Row #7: 51\n"
+ "Row #8: 27\n"
+ "Row #8: 54\n"
+ "Row #9: 6\n"
+ "Row #9: 2\n"
+ "Row #10: 3\n"
+ "Row #10: 7\n"
+ "Row #11: 2\n"
+ "Row #11: 10\n",
s);
}
/**
* Tests members from a parent-child hierarchy.
*
* @throws ClassNotFoundException
* @throws SQLException
*/
public void testParentChild() throws ClassNotFoundException, SQLException {
Class.forName(tester.getDriverClassName());
connection = tester.createConnection();
OlapConnection olapConnection =
tester.getWrapper().unwrap(connection, OlapConnection.class);
final CellSet cellSet =
olapConnection.createStatement().executeOlapQuery(
"select {[Measures].[Org Salary]} on 0,\n"
+ " Head([Employees].Members, 10) DIMENSION PROPERTIES DEPTH ON 1\n"
+ "from [HR]");
final CellSetAxis rowsAxis = cellSet.getAxes().get(1);
assertEquals(10, rowsAxis.getPositionCount());
Member member0 = rowsAxis.getPositions().get(0).getMembers().get(0);
assertEquals("All Employees", member0.getName());
assertEquals(0, member0.getDepth());
Member member1 = rowsAxis.getPositions().get(1).getMembers().get(0);
assertEquals("[Employees].[Sheri Nowmer]", member1.getUniqueName());
assertEquals(1, member1.getDepth());
assertEquals(1, member1.getLevel().getDepth());
assertEquals(
member0.getUniqueName(),
member1.getParentMember().getUniqueName());
assertEquals(member0, member1.getParentMember());
Member member2 = rowsAxis.getPositions().get(2).getMembers().get(0);
assertTrue(
member2.getUniqueName().equals(
"[Employees].[Derrick Whelply]")
|| member2.getUniqueName().equals(
"[Employees].[Sheri Nowmer].[Derrick Whelply]"));
assertEquals(2, member2.getDepth());
assertEquals(1, member2.getLevel().getDepth());
final Member parent = member2.getParentMember();
assertNotNull(parent);
assertEquals("[Employees].[Sheri Nowmer]", parent.getUniqueName());
assertEquals(1, parent.getDepth());
assertEquals(member2.getLevel(), parent.getLevel());
assertEquals(member1, parent);
final CellSetAxis filterAxis = cellSet.getFilterAxis();
assertEquals(1, filterAxis.getPositionCount());
final List positions = filterAxis.getPositions();
assertEquals(1, positions.size());
assertEquals(0, positions.get(0).getOrdinal());
// No WHERE clause, therefore slicer is empty (but not null).
assertEquals(0, positions.get(0).getMembers().size());
}
/**
* Tests the type-derivation for
* {@link org.olap4j.mdx.SelectNode#getFrom()} and the {@link CubeType}
* class.
*
* @throws Throwable on error
*/
public void testCubeType() throws Throwable {
if (tester.getFlavor() == TestContext.Tester.Flavor.XMLA
|| tester.getFlavor() == TestContext.Tester.Flavor.REMOTE_XMLA)
{
// This test requires validator support.
return;
}
Class.forName(tester.getDriverClassName());
connection = tester.createConnection();
OlapConnection olapConnection =
tester.getWrapper().unwrap(connection, OlapConnection.class);
final MdxParserFactory parserFactory =
olapConnection.getParserFactory();
MdxParser mdxParser =
parserFactory.createMdxParser(olapConnection);
MdxValidator mdxValidator =
parserFactory.createMdxValidator(olapConnection);
SelectNode select =
mdxParser.parseSelect(
"select {[Gender]} on columns from [sales]\n"
+ "where [Time].[1997].[Q4]");
// CubeType
// Before validation, we cannot ask for type
try {
final ParseTreeNode from = select.getFrom();
assertTrue(from instanceof IdentifierNode);
Type type = from.getType();
fail("expected error, got " + type);
} catch (UnsupportedOperationException e) {
// ignore
}
select = mdxValidator.validateSelect(select);
CubeType cubeType = (CubeType) select.getFrom().getType();
assertEquals("Sales", cubeType.getCube().getName());
assertNull(cubeType.getDimension());
assertNull(cubeType.getHierarchy());
assertNull(cubeType.getLevel());
// Different query based on same cube should have equal CubeType
select =
mdxParser.parseSelect(
"select from [sales]");
select = mdxValidator.validateSelect(select);
assertEquals(cubeType, select.getFrom().getType());
// Different query based on different cube should have different
// CubeType
select =
mdxParser.parseSelect(
"select from [warehouse and sales]");
select = mdxValidator.validateSelect(select);
assertNotSame(cubeType, select.getFrom().getType());
}
/**
* Tests the type-derivation for query axes
* ({@link org.olap4j.mdx.SelectNode#getAxisList()} and
* {@link org.olap4j.mdx.SelectNode#getFilterAxis()}), and the
* {@link org.olap4j.type.SetType},
* {@link org.olap4j.type.TupleType},
* {@link org.olap4j.type.MemberType} type subclasses.
*
* @throws Throwable on error
*/
public void testAxisType() throws Throwable {
if (tester.getFlavor() == TestContext.Tester.Flavor.XMLA
|| tester.getFlavor() == TestContext.Tester.Flavor.REMOTE_XMLA)
{
// This test requires validator support.
return;
}
Class.forName(tester.getDriverClassName());
// connect using properties and no username/password
connection = tester.createConnection();
OlapConnection olapConnection =
tester.getWrapper().unwrap(connection, OlapConnection.class);
final MdxParserFactory parserFactory =
olapConnection.getParserFactory();
MdxParser mdxParser =
parserFactory.createMdxParser(olapConnection);
MdxValidator mdxValidator =
parserFactory.createMdxValidator(olapConnection);
SelectNode select =
mdxParser.parseSelect(
"select ([Gender], [Store]) on columns\n,"
+ "{[Customers].[City].Members} on rows\n"
+ "from [sales]\n"
+ "where ([Time].[1997].[Q4], [Marital Status].[S])");
select = mdxValidator.validateSelect(select);
// a query is not an expression, so does not have a type
assertNull(select.getType());
final AxisNode columnsAxis = select.getAxisList().get(0);
// an axis is not an expression, so does not have a type
assertNull(columnsAxis.getType());
// ~ SetType
final SetType setType = (SetType) columnsAxis.getExpression().getType();
assertNull(setType.getDimension());
assertNull(setType.getHierarchy());
assertNull(setType.getLevel());
assertNotNull(setType.toString());
final Type elementType = setType.getElementType();
// ~ TupleType
assertTrue(elementType instanceof TupleType);
TupleType tupleType = (TupleType) elementType;
assertNotNull(tupleType.toString());
assertNull(tupleType.getDimension());
assertNull(tupleType.getHierarchy());
assertNull(tupleType.getLevel());
final Cube cube = ((CubeType) select.getFrom().getType()).getCube();
final Dimension storeDimension = cube.getDimensions().get("Store");
final Dimension genderDimension = cube.getDimensions().get("Gender");
final Dimension measuresDimension =
cube.getDimensions().get("Measures");
final Dimension customersDimension =
cube.getDimensions().get("Customers");
assertTrue(tupleType.usesDimension(storeDimension, false));
assertTrue(tupleType.usesDimension(genderDimension, false));
assertFalse(tupleType.usesDimension(measuresDimension, false));
// Other axis is a set of members
// ~ MemberType
final AxisNode rowsAxis = select.getAxisList().get(1);
final Type rowsType = rowsAxis.getExpression().getType();
assertTrue(rowsType instanceof SetType);
MemberType memberType =
(MemberType) ((SetType) rowsType).getElementType();
assertNotNull(memberType.toString());
// MemberType.getMember is null because we know it belongs to the City
// level, but no particular member of that level.
assertNull("Customers", memberType.getMember());
assertEquals("City", memberType.getLevel().getName());
assertEquals("Customers", memberType.getHierarchy().getName());
assertEquals("Customers", memberType.getDimension().getName());
assertFalse(memberType.usesDimension(storeDimension, false));
assertTrue(memberType.usesDimension(customersDimension, false));
assertTrue(memberType.usesDimension(customersDimension, true));
// Filter
final AxisNode filterAxis = select.getFilterAxis();
assertNull(filterAxis.getType());
final Type filterType = filterAxis.getExpression().getType();
assertTrue(filterType instanceof TupleType);
assertEquals(
"TupleType, MemberType>",
filterType.toString());
}
public void testParseQueryWithNoFilter() throws Exception {
if (tester.getFlavor() == TestContext.Tester.Flavor.XMLA
|| tester.getFlavor() != Tester.Flavor.REMOTE_XMLA)
{
// This test requires validator support.
return;
}
Class.forName(tester.getDriverClassName());
connection = tester.createConnection();
OlapConnection olapConnection =
tester.getWrapper().unwrap(connection, OlapConnection.class);
final MdxParserFactory parserFactory =
olapConnection.getParserFactory();
MdxParser mdxParser =
parserFactory.createMdxParser(olapConnection);
MdxValidator mdxValidator =
parserFactory.createMdxValidator(olapConnection);
SelectNode select =
mdxParser.parseSelect(
"select ([Gender], [Store]) on columns\n,"
+ "{[Customers].[City].Members} on rows\n"
+ "from [sales]");
select = mdxValidator.validateSelect(select);
AxisNode filterAxis = select.getFilterAxis();
assertNotNull(filterAxis);
assertNull(filterAxis.getExpression());
try {
select =
mdxParser.parseSelect(
"select ([Gender], [Store]) on columns\n,"
+ "{[Customers].[City].Members} on rows\n"
+ "from [sales]\n"
+ "where ()");
fail("expected parse error, got " + select);
} catch (RuntimeException e) {
assertTrue(
TestContext.getStackTrace(e).indexOf(
"Syntax error at [4:10], token ')'") >= 0);
}
}
public void testValidateError() throws Exception {
if (tester.getFlavor() == TestContext.Tester.Flavor.XMLA
|| tester.getFlavor() != Tester.Flavor.XMLA)
{
// This test requires validator support.
return;
}
Class.forName(tester.getDriverClassName());
connection = tester.createConnection();
OlapConnection olapConnection =
tester.getWrapper().unwrap(connection, OlapConnection.class);
final MdxParserFactory parserFactory =
olapConnection.getParserFactory();
MdxParser mdxParser =
parserFactory.createMdxParser(olapConnection);
MdxValidator mdxValidator =
parserFactory.createMdxValidator(olapConnection);
SelectNode select =
mdxParser.parseSelect(
"select ([Gender], [Store]) on columns\n,"
+ "crossjoin([Customers].[City].Members, [Gender].members) on rows\n"
+ "from [sales]");
AxisNode filterAxis = select.getFilterAxis();
assertNotNull(filterAxis);
assertNull(filterAxis.getExpression());
try {
select = mdxValidator.validateSelect(select);
fail("expected parse error, got " + select);
} catch (OlapException e) {
assertEquals("Validation error", e.getMessage());
final String stackTrace = TestContext.getStackTrace(e);
assertTrue(
stackTrace,
stackTrace.contains(
"Hierarchy '[Gender]' appears in more than one "
+ "independent axis."));
}
}
// TODO: test for HierarchyType
// TODO: test for DimensionType
// TODO: test for LevelType
/**
* Converts a list of members to a string, one per line.
*/
static String memberListToString(List list) {
final StringBuilder buf = new StringBuilder();
for (Member member : list) {
buf.append(member.getUniqueName()).append(TestContext.NL);
}
return buf.toString();
}
public void testStatementCancel() throws Throwable {
connection = tester.createConnection();
OlapConnection olapConnection =
tester.getWrapper().unwrap(connection, OlapConnection.class);
final OlapStatement olapStatement = olapConnection.createStatement();
final Throwable[] exceptions = {null};
new Thread(
new Runnable() {
public void run() {
try {
Thread.sleep(1000);
olapStatement.cancel();
} catch (Throwable e) {
exceptions[0] = e;
}
}
}
).start();
try {
final CellSet cellSet = olapStatement.executeOlapQuery(
"SELECT Filter(\n"
+ " [Product].Members *\n"
+ " [Customers].Members *\n"
+ " [Time].[Time].Members,\n"
+ " 1 = 0) on columns\n"
+ "from [Sales]");
fail(
"expected exception indicating stmt had been canceled,"
+ " got cellSet " + cellSet);
} catch (OlapException e) {
assertTrue(
e.getMessage(),
e.getMessage().indexOf("Query canceled") >= 0);
}
if (exceptions[0] != null) {
throw exceptions[0];
}
}
public void testStatementTimeout() throws Throwable {
connection = tester.createConnection();
OlapConnection olapConnection =
tester.getWrapper().unwrap(connection, OlapConnection.class);
final OlapStatement olapStatement = olapConnection.createStatement();
try {
olapStatement.setQueryTimeout(-1);
fail("expected exception");
} catch (SQLException e) {
assertTrue(e.getMessage().indexOf("illegal timeout value ") >= 0);
}
olapStatement.setQueryTimeout(1);
try {
final CellSet cellSet =
olapStatement.executeOlapQuery(
"SELECT Filter(\n"
+ " [Store].Members * \n"
+ " [Customers].Members * \n"
+ " [Time].[Time].Members, 1 = 0) on columns\n"
+ "from [Sales]");
fail(
"expected exception indicating timeout,"
+ " got cellSet " + cellSet);
} catch (OlapException e) {
assertTrue(
e.getMessage(),
e.getMessage().indexOf("Query timeout of ") >= 0);
}
}
public void testCellSetBug() throws SQLException {
if (!Bug.BugOlap4j3126853Fixed) {
return;
}
connection = tester.createConnection();
OlapConnection olapConnection =
tester.getWrapper().unwrap(connection, OlapConnection.class);
final OlapStatement olapStatement = olapConnection.createStatement();
// Note: substitute [Sales Ragged] for [Sales] below and the query
// takes a very long time against mondrian's XMLA driver, because
// mondrian has a performance bug assigning ordinals to ragged
// hierarchies, and XMLA requests ask for member ordinals along with
// the other attributes of members.
CellSet cellSet =
olapStatement.executeOlapQuery(
"SELECT "
+ "{[Product].[All Products].[Drink].[Alcoholic Beverages].Children, [Product].[All Products].[Food].[Baked Goods].Children} ON COLUMNS, "
+ "CrossJoin([Store].[USA].[CA].Children, [Time].[1997].[Q1].Children) ON ROWS "
+ "FROM [Sales]");
TestContext.assertEqualsVerbose(
"Axis #0:\n"
+ "{}\n"
+ "Axis #1:\n"
+ "{[Product].[Drink].[Alcoholic Beverages].[Beer and Wine]}\n"
+ "{[Product].[Food].[Baked Goods].[Bread]}\n"
+ "Axis #2:\n"
+ "{[Store].[USA].[CA].[Alameda], [Time].[1997].[Q1].[1]}\n"
+ "{[Store].[USA].[CA].[Alameda], [Time].[1997].[Q1].[2]}\n"
+ "{[Store].[USA].[CA].[Alameda], [Time].[1997].[Q1].[3]}\n"
+ "{[Store].[USA].[CA].[Beverly Hills], [Time].[1997].[Q1].[1]}\n"
+ "{[Store].[USA].[CA].[Beverly Hills], [Time].[1997].[Q1].[2]}\n"
+ "{[Store].[USA].[CA].[Beverly Hills], [Time].[1997].[Q1].[3]}\n"
+ "{[Store].[USA].[CA].[Los Angeles], [Time].[1997].[Q1].[1]}\n"
+ "{[Store].[USA].[CA].[Los Angeles], [Time].[1997].[Q1].[2]}\n"
+ "{[Store].[USA].[CA].[Los Angeles], [Time].[1997].[Q1].[3]}\n"
+ "{[Store].[USA].[CA].[San Diego], [Time].[1997].[Q1].[1]}\n"
+ "{[Store].[USA].[CA].[San Diego], [Time].[1997].[Q1].[2]}\n"
+ "{[Store].[USA].[CA].[San Diego], [Time].[1997].[Q1].[3]}\n"
+ "{[Store].[USA].[CA].[San Francisco], [Time].[1997].[Q1].[1]}\n"
+ "{[Store].[USA].[CA].[San Francisco], [Time].[1997].[Q1].[2]}\n"
+ "{[Store].[USA].[CA].[San Francisco], [Time].[1997].[Q1].[3]}\n"
+ "Row #0: \n"
+ "Row #0: \n"
+ "Row #1: \n"
+ "Row #1: \n"
+ "Row #2: \n"
+ "Row #2: \n"
+ "Row #3: 22\n"
+ "Row #3: 63\n"
+ "Row #4: 28\n"
+ "Row #4: 59\n"
+ "Row #5: 28\n"
+ "Row #5: 39\n"
+ "Row #6: 70\n"
+ "Row #6: 51\n"
+ "Row #7: 89\n"
+ "Row #7: 51\n"
+ "Row #8: 27\n"
+ "Row #8: 54\n"
+ "Row #9: 54\n"
+ "Row #9: 51\n"
+ "Row #10: 38\n"
+ "Row #10: 48\n"
+ "Row #11: 64\n"
+ "Row #11: 55\n"
+ "Row #12: 6\n"
+ "Row #12: 2\n"
+ "Row #13: 3\n"
+ "Row #13: 7\n"
+ "Row #14: 2\n"
+ "Row #14: 10\n",
TestContext.toString(cellSet));
}
public void testCellSetWithCalcMember() throws SQLException {
connection = tester.createConnection();
OlapConnection olapConnection =
tester.getWrapper().unwrap(connection, OlapConnection.class);
final OlapStatement olapStatement = olapConnection.createStatement();
CellSet cellSet =
olapStatement.executeOlapQuery(
"WITH MEMBER [Measures].[Average Profit] AS"
+ "'[Measures].[Profit] / [Measures].[Sales Count]'"
+ "SELECT {[Measures].[Average Profit]} ON 0,\n"
+ "{[Product].Children} ON 1\n"
+ "FROM [Sales]");
TestContext.assertEqualsVerbose(
"Axis #0:\n"
+ "{}\n"
+ "Axis #1:\n"
+ "{[Measures].[Average Profit]}\n"
+ "Axis #2:\n"
+ "{[Product].[Drink]}\n"
+ "{[Product].[Food]}\n"
+ "{[Product].[Non-Consumable]}\n"
+ "Row #0: $3.68\n"
+ "Row #1: $3.94\n"
+ "Row #2: $3.93\n", TestContext.toString(cellSet));
}
public void testBuildQuery() throws SQLException {
connection = tester.createConnection();
OlapConnection olapConnection =
tester.getWrapper().unwrap(connection, OlapConnection.class);
buildQuery(olapConnection, true);
buildQuery(olapConnection, false);
}
private void buildQuery(
OlapConnection olapConnection,
boolean useCubeObject)
throws OlapException
{
Catalog catalog =
olapConnection.getOlapCatalogs()
.get("FoodMart");
Schema schema = catalog.getSchemas().get("FoodMart");
Cube cube = schema.getCubes().get("Sales");
SelectNode query = new SelectNode();
ParseTreeNode cubeNode;
if (useCubeObject) {
cubeNode = IdentifierNode.parseIdentifier(cube.getUniqueName());
} else {
cubeNode = new CubeNode(null, cube);
}
query.setFrom(cubeNode);
AxisNode columnAxis =
new AxisNode(
null, false, Axis.COLUMNS, null,
new CallNode(
null, "MEMBERS", Syntax.Property,
IdentifierNode.parseIdentifier("[Gender]")));
AxisNode rowAxis =
new AxisNode(
null, false, Axis.ROWS, null,
new CallNode(
null, "CHILDREN", Syntax.Property,
IdentifierNode.parseIdentifier("[Customers].[USA]")));
query.getAxisList().add(columnAxis);
query.getAxisList().add(rowAxis);
OlapStatement statement = olapConnection.createStatement();
CellSet cellSet = statement.executeOlapQuery(query);
TestContext.assertEqualsVerbose(
"Axis #0:\n"
+ "{}\n"
+ "Axis #1:\n"
+ "{[Gender].[All Gender]}\n"
+ "{[Gender].[F]}\n"
+ "{[Gender].[M]}\n"
+ "Axis #2:\n"
+ "{[Customers].[USA].[CA]}\n"
+ "{[Customers].[USA].[OR]}\n"
+ "{[Customers].[USA].[WA]}\n"
+ "Row #0: 74,748\n"
+ "Row #0: 36,759\n"
+ "Row #0: 37,989\n"
+ "Row #1: 67,659\n"
+ "Row #1: 33,036\n"
+ "Row #1: 34,623\n"
+ "Row #2: 124,366\n"
+ "Row #2: 61,763\n"
+ "Row #2: 62,603\n",
TestContext.toString(cellSet));
}
public void testBuildQuery2() throws ClassNotFoundException, SQLException {
connection = tester.createConnection();
OlapConnection olapConnection =
tester.getWrapper().unwrap(connection, OlapConnection.class);
Schema schema =
olapConnection
.getOlapCatalogs()
.get("FoodMart")
.getSchemas()
.get("FoodMart");
Cube cube = schema.getCubes().get("Sales");
Measure measure = cube.getMeasures().get(0);
assertEquals("Unit Sales", measure.getName());
Dimension dimPromotionMedia =
cube.getDimensions().get("Promotion Media");
//
// IdentifierNode cubeNode =
// new IdentifierNode(
// new IdentifierNode.NameSegment(cube.getUniqueName()));
CubeNode cubeNode = new CubeNode(null, cube);
MemberNode measuresQuantity = new MemberNode(null, measure);
HierarchyNode promotionHierarchyNode =
new HierarchyNode(null, dimPromotionMedia.getDefaultHierarchy());
CallNode promotionChildren =
new CallNode(
null, "children", Syntax.Property, promotionHierarchyNode);
//
List columnDimensionProperties =
new ArrayList();
AxisNode columnAxis =
new AxisNode(
null, false,
Axis.COLUMNS,
columnDimensionProperties,
new CallNode(null, "{}", Syntax.Braces, measuresQuantity));
List rowDimensionProperties =
new ArrayList();
AxisNode rowAxis =
new AxisNode(
null, false,
Axis.ROWS,
rowDimensionProperties,
new CallNode(null, "{}", Syntax.Braces, promotionChildren));
//
SelectNode query = new SelectNode();
query.setFrom(cubeNode);
query.getAxisList().add(columnAxis);
query.getAxisList().add(rowAxis);
//
OlapStatement statement = olapConnection.createStatement();
CellSet cellSet = statement.executeOlapQuery(query);
final StringWriter sw = new StringWriter();
final PrintWriter pw = new PrintWriter(sw);
for (Position row : cellSet.getAxes().get(1)) {
for (Position column : cellSet.getAxes().get(0)) {
pw.print("ROW:");
for (Member member : row.getMembers()) {
pw.print("[" + member.getName() + "]");
}
pw.print(" COL:");
for (Member member : column.getMembers()) {
pw.print("[" + member.getName() + "]");
}
Cell cell = cellSet.getCell(column, row);
pw.println(" CELL:" + cell.getFormattedValue());
}
}
pw.flush();
TestContext.assertEqualsVerbose(
"ROW:[Bulk Mail] COL:[Unit Sales] CELL:4,320\n"
+ "ROW:[Cash Register Handout] COL:[Unit Sales] CELL:6,697\n"
+ "ROW:[Daily Paper] COL:[Unit Sales] CELL:7,738\n"
+ "ROW:[Daily Paper, Radio] COL:[Unit Sales] CELL:6,891\n"
+ "ROW:[Daily Paper, Radio, TV] COL:[Unit Sales] CELL:9,513\n"
+ "ROW:[In-Store Coupon] COL:[Unit Sales] CELL:3,798\n"
+ "ROW:[No Media] COL:[Unit Sales] CELL:195,448\n"
+ "ROW:[Product Attachment] COL:[Unit Sales] CELL:7,544\n"
+ "ROW:[Radio] COL:[Unit Sales] CELL:2,454\n"
+ "ROW:[Street Handout] COL:[Unit Sales] CELL:5,753\n"
+ "ROW:[Sunday Paper] COL:[Unit Sales] CELL:4,339\n"
+ "ROW:[Sunday Paper, Radio] COL:[Unit Sales] CELL:5,945\n"
+ "ROW:[Sunday Paper, Radio, TV] COL:[Unit Sales] CELL:2,726\n"
+ "ROW:[TV] COL:[Unit Sales] CELL:3,607\n",
sw.toString());
}
/**
* Verifies the order of dimensions; they must conform to their
* ordinal value.
* @throws Exception If something turns sour.
*/
public void testCubeDimensionsOrder() throws Exception {
String dimNames = "[Measures];[Store];[Store Size in SQFT];"
+ "[Store Type];[Time];[Product];[Promotion Media];[Promotions];"
+ "[Customers];[Education Level];[Gender];[Marital Status];"
+ "[Yearly Income];";
Class.forName(tester.getDriverClassName());
connection = tester.createConnection();
OlapConnection olapConnection =
tester.getWrapper().unwrap(connection, OlapConnection.class);
Cube cube =
olapConnection
.getOlapCatalogs()
.get("FoodMart")
.getSchemas()
.get("FoodMart")
.getCubes()
.get("Sales");
StringBuilder sb = new StringBuilder();
for (Dimension dimension : cube.getDimensions()) {
sb.append(dimension.getUniqueName())
.append(";");
}
TestContext.assertEqualsVerbose(
dimNames,
sb.toString());
}
public void testCubesDrillthrough() throws Exception {
Class.forName(tester.getDriverClassName());
connection = tester.createConnection();
OlapConnection olapConnection =
tester.getWrapper().unwrap(connection, OlapConnection.class);
Cube cube =
olapConnection
.getOlapCatalogs()
.get("FoodMart")
.getSchemas()
.get("FoodMart")
.getCubes()
.get("Sales");
switch (tester.getFlavor()) {
case MONDRIAN:
assertTrue(cube.isDrillThroughEnabled());
break;
case REMOTE_XMLA :
case XMLA:
assertFalse(cube.isDrillThroughEnabled());
break;
default:
fail();
break;
}
}
/**
* Query with dimension properties.
*
* Test case for
*
* bug 2951656, "Olap4j should not throw IllegalArgumentException".
*
* @throws java.sql.SQLException on error
*/
public void _testDimensionProperties() throws SQLException {
connection = tester.createConnection();
OlapConnection olapConnection =
tester.getWrapper().unwrap(connection, OlapConnection.class);
String mdx =
"select {[Product].[Product Family].Members} ON COLUMNS,\n"
+ "{[Store].[Store Name].Members}\n"
+ " DIMENSION PROPERTIES [Store].[Store Name].[Store Sqft] ON ROWS\n"
+ "from [Sales]\n"
+ "where [Measures].[Unit Sales]";
PreparedOlapStatement pstmt =
olapConnection.prepareOlapStatement(mdx);
pstmt.executeQuery();
}
/**
*
This test relates to
* sourceforge.net/projects/olap4j/forums/forum/577988/topic/3803726
*
*
Drivers should return a transaction isolation of
* {@link Connection#TRANSACTION_NONE}
*/
public void testTransactionIsolation() throws SQLException {
connection = tester.createConnection();
assertEquals(
Connection.TRANSACTION_NONE,
connection.getTransactionIsolation());
}
public void testSchemaAccessControl() throws Exception {
if (tester.getFlavor() == Flavor.XMLA
|| tester.getFlavor() == Flavor.REMOTE_XMLA)
{
/*
* TODO Implement a way to pass an XmlaRequestCallback to
* the tested servlet so we can pass the roles down.
*/
return;
}
connection = tester.createConnection();
final OlapConnection olapConnection =
tester.getWrapper().unwrap(connection, OlapConnection.class);
try {
olapConnection.setRoleName("California manager");
final List list = new ArrayList();
for (Schema schema
: olapConnection.getOlapSchemas())
{
list.add(schema.getName());
}
assertListsEquals(
Arrays.asList(
"FoodMart"),
list);
} finally {
olapConnection.setRoleName(null);
}
}
public void testCubeAccessControl() throws Exception {
if (tester.getFlavor() == Flavor.XMLA
|| tester.getFlavor() == Flavor.REMOTE_XMLA)
{
/*
* TODO Implement a way to pass an XmlaRequestCallback to
* the tested servlet so we can pass the roles down.
*/
return;
}
connection = tester.createConnection();
final OlapConnection olapConnection =
tester.getWrapper().unwrap(connection, OlapConnection.class);
try {
olapConnection.setRoleName("California manager");
final List list = new ArrayList();
for (Cube cube : olapConnection.getOlapSchema().getCubes()) {
list.add(cube.getName());
}
assertListsEquals(
Arrays.asList(
"Sales"),
list);
olapConnection.setRoleName("No HR Cube");
list.clear();
for (Cube cube : olapConnection.getOlapSchema().getCubes()) {
list.add(cube.getName());
}
assertListsEquals(
Arrays.asList(
"Sales Ragged",
"Warehouse",
"Warehouse and Sales",
"Sales 2",
"Store",
"Sales"),
list);
} finally {
olapConnection.setRoleName(null);
}
}
public void testDimensionAccessControl() throws Exception {
if (tester.getFlavor() == Flavor.XMLA
|| tester.getFlavor() == Flavor.REMOTE_XMLA)
{
/*
* TODO Implement a way to pass an XmlaRequestCallback to
* the tested servlet so we can pass the roles down.
*/
return;
}
connection = tester.createConnection();
final OlapConnection olapConnection =
tester.getWrapper().unwrap(connection, OlapConnection.class);
try {
olapConnection.setRoleName("California manager");
final List list = new ArrayList();
for (Dimension dimension
: olapConnection.getOlapSchema()
.getCubes().get("Sales").getDimensions())
{
list.add(dimension.getName());
}
assertListsEquals(
Arrays.asList(
"Measures",
"Store",
"Store Size in SQFT",
"Store Type",
"Time",
"Product",
"Promotion Media",
"Promotions",
"Customers",
"Education Level",
"Marital Status",
"Yearly Income"),
list);
} finally {
olapConnection.setRoleName(null);
}
}
public void testLevelAccessControl() throws Exception {
if (tester.getFlavor() == Flavor.XMLA
|| tester.getFlavor() == Flavor.REMOTE_XMLA)
{
/*
* TODO Implement a way to pass an XmlaRequestCallback to
* the tested servlet so we can pass the roles down.
*/
return;
}
connection = tester.createConnection();
final OlapConnection olapConnection =
tester.getWrapper().unwrap(connection, OlapConnection.class);
try {
olapConnection.setRoleName("California manager");
final List list = new ArrayList();
for (Level level
: olapConnection.getOlapSchema()
.getCubes().get("Sales")
.getDimensions().get("Customers")
.getHierarchies().get(0)
.getLevels())
{
list.add(level.getName());
}
assertListsEquals(
Arrays.asList(
"State Province",
"City"),
list);
} finally {
olapConnection.setRoleName(null);
}
}
public void testLevelMembersAccessControl() throws Exception {
if (tester.getFlavor() == Flavor.XMLA
|| tester.getFlavor() == Flavor.REMOTE_XMLA)
{
/*
* TODO Implement a way to pass an XmlaRequestCallback to
* the tested servlet so we can pass the roles down.
*/
return;
}
connection = tester.createConnection();
final OlapConnection olapConnection =
tester.getWrapper().unwrap(connection, OlapConnection.class);
try {
olapConnection.setRoleName("California manager");
final List list = new ArrayList();
for (Member member
: olapConnection.getOlapSchema()
.getCubes().get("Sales")
.getDimensions().get("Store")
.getHierarchies().get(0)
.getLevels().get(0)
.getMembers())
{
list.add(member.getName());
}
assertEquals(
Arrays.asList(
"USA"),
list);
list.clear();
for (Member member
: olapConnection.getOlapSchema()
.getCubes().get("Sales")
.getDimensions().get("Store")
.getHierarchies().get(0)
.getLevels().get(1)
.getMembers())
{
list.add(member.getName());
}
assertListsEquals(
Arrays.asList(
"CA"),
list);
list.clear();
for (Member member
: olapConnection.getOlapSchema()
.getCubes().get("Sales")
.getDimensions().get("Store")
.getHierarchies().get(0)
.getLevels().get(2)
.getMembers())
{
list.add(member.getName());
}
assertListsEquals(
Arrays.asList(
"Alameda",
"Beverly Hills",
"San Diego",
"San Francisco"),
list);
} finally {
olapConnection.setRoleName(null);
}
}
public void testParentChildAccessControl() throws Exception {
if (tester.getFlavor() == Flavor.XMLA
|| tester.getFlavor() == Flavor.REMOTE_XMLA)
{
/*
* TODO Implement a way to pass an XmlaRequestCallback to
* the tested servlet so we can pass the roles down.
*/
return;
}
connection = tester.createConnection();
final OlapConnection olapConnection =
tester.getWrapper().unwrap(connection, OlapConnection.class);
try {
olapConnection.setRoleName("California manager");
final Member city =
olapConnection.getOlapSchema()
.getCubes().get("Sales")
.getDimensions().get("Customers")
.getHierarchies().get(0)
.getLevels().get("City")
.getMembers().get(0);
assertEquals(
0,
city.getChildMembers().size());
final Member state =
olapConnection.getOlapSchema()
.getCubes().get("Sales")
.getDimensions().get("Customers")
.getHierarchies().get(0)
.getLevels().get("State Province")
.getMembers().get(0);
assertNull(state.getParentMember());
} finally {
olapConnection.setRoleName(null);
}
}
protected void assertListsEquals(List list1, List list2) {
Collections.sort(list1);
Collections.sort(list2);
assertEquals(list1, list2);
}
}
// End ConnectionTest.java
olap4j-1.0.1.500/testsrc/org/olap4j/XmlaTester.java 0000644 0001750 0001750 00000013510 11707524526 021514 0 ustar drazzib drazzib /*
// $Id: XmlaTester.java 493 2012-01-24 18:51:30Z lucboudreau $
//
// Licensed to Julian Hyde under one or more contributor license
// agreements. See the NOTICE file distributed with this work for
// additional information regarding copyright ownership.
//
// Julian Hyde licenses this file to you 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.olap4j;
import org.olap4j.driver.xmla.XmlaOlap4jDriver;
import org.olap4j.driver.xmla.proxy.XmlaOlap4jProxy;
import org.olap4j.test.TestContext;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.sql.*;
import java.util.*;
/**
* Implementation of {@link org.olap4j.test.TestContext.Tester} which speaks
* to the olap4j driver for XML/A.
*
* @author jhyde
* @version $Id: XmlaTester.java 493 2012-01-24 18:51:30Z lucboudreau $
*/
public class XmlaTester implements TestContext.Tester {
private final TestContext testContext;
final XmlaOlap4jProxy proxy;
static final String cookie = XmlaOlap4jDriver.nextCookie();
private Connection connection;
/**
* Creates an XmlaTester.
*
* The {@link org.olap4j.test.TestContext.Tester} API requires a public
* constructor with a {@link org.olap4j.test.TestContext} parameter.
*
* @param testContext Test context
*
* @throws ClassNotFoundException on error
* @throws IllegalAccessException on error
* @throws InstantiationException on error
* @throws NoSuchMethodException on error
* @throws InvocationTargetException on error
*/
public XmlaTester(TestContext testContext)
throws ClassNotFoundException, IllegalAccessException,
InstantiationException, NoSuchMethodException,
InvocationTargetException
{
this.testContext = testContext;
final Properties properties = testContext.getProperties();
final String catalogUrl =
properties.getProperty(
TestContext.Property.XMLA_CATALOG_URL.path, "http://foo");
// Include the same catalog URL twice with different catalog names. This
// allows us to detect whether operations are restricting to the current
// catalog. (Some should, most should not.)
Map catalogNameUrls =
new HashMap();
catalogNameUrls.put("FoodMart", catalogUrl);
catalogNameUrls.put("FoodMart2", catalogUrl);
String urlString =
properties.getProperty(
TestContext.Property.CONNECT_URL.path, "jdbc:mondrian:");
final Class> clazz = Class.forName(getProxyClassName());
final Constructor> constructor =
clazz.getConstructor(Map.class, String.class);
this.proxy =
(XmlaOlap4jProxy) constructor.newInstance(
catalogNameUrls, urlString);
XmlaOlap4jDriver.PROXY_MAP.put(cookie, proxy);
}
public TestContext getTestContext() {
return testContext;
}
public Connection createConnection() throws SQLException {
if (connection != null) {
connection.close();
connection = null;
}
try {
Class.forName(DRIVER_CLASS_NAME);
} catch (ClassNotFoundException e) {
throw new RuntimeException("oops", e);
}
Properties info = new Properties();
info.setProperty(
XmlaOlap4jDriver.Property.CATALOG.name(), "FoodMart");
connection =
DriverManager.getConnection(
getURL(),
info);
return connection;
}
public Connection createConnectionWithUserPassword() throws SQLException {
final Properties props = new Properties();
return createConnectionWithUserPassword(props);
}
public Connection createConnectionWithUserPassword(
Properties props)
throws SQLException
{
try {
Class.forName(DRIVER_CLASS_NAME);
} catch (ClassNotFoundException e) {
throw new RuntimeException("oops", e);
}
props.setProperty(
XmlaOlap4jDriver.Property.CATALOG.name(), "FoodMart");
if (USER != null) {
props.put("user", USER);
}
if (PASSWORD != null) {
props.put("password", PASSWORD);
}
return DriverManager.getConnection(getURL(), props);
}
public String getDriverUrlPrefix() {
return DRIVER_URL_PREFIX;
}
public String getDriverClassName() {
return DRIVER_CLASS_NAME;
}
public String getURL() {
return "jdbc:xmla:Server=http://foo;Catalog=FoodMart;TestProxyCookie="
+ cookie;
}
public Flavor getFlavor() {
return Flavor.XMLA;
}
public TestContext.Wrapper getWrapper() {
return TestContext.Wrapper.NONE;
}
public static void setProxyClassName(String clazz) {
PROXY_CLASS_NAME = clazz;
}
public static String getProxyClassName() {
return PROXY_CLASS_NAME;
}
public static final String DRIVER_CLASS_NAME =
"org.olap4j.driver.xmla.XmlaOlap4jDriver";
public static final String DRIVER_URL_PREFIX = "jdbc:xmla:";
private static final String USER = "user";
private static final String PASSWORD = "password";
private static String PROXY_CLASS_NAME =
"mondrian.olap4j.MondrianInprocProxy";
}
// End XmlaTester.java
olap4j-1.0.1.500/testsrc/org/olap4j/CellSetFormatterTest.java 0000644 0001750 0001750 00000065650 11711470530 023505 0 ustar drazzib drazzib /*
// $Id: CellSetFormatterTest.java 498 2012-01-30 16:30:42Z lucboudreau $
//
// Licensed to Julian Hyde under one or more contributor license
// agreements. See the NOTICE file distributed with this work for
// additional information regarding copyright ownership.
//
// Julian Hyde licenses this file to you 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.olap4j;
import org.olap4j.layout.RectangularCellSetFormatter;
import org.olap4j.layout.TraditionalCellSetFormatter;
import org.olap4j.test.TestContext;
import junit.framework.TestCase;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.sql.Connection;
import java.sql.SQLException;
/**
* Unit test for converting MDX CellSets to text.
*
* @see org.olap4j.layout.CellSetFormatter
* @see org.olap4j.layout.RectangularCellSetFormatter
* @see org.olap4j.layout.TraditionalCellSetFormatter
*
* @author jhyde
* @version $Id: CellSetFormatterTest.java 498 2012-01-30 16:30:42Z lucboudreau $
*/
public class CellSetFormatterTest extends TestCase {
private TestContext testContext = TestContext.instance();
private TestContext.Tester tester = testContext.getTester();
@Override
protected void tearDown() throws Exception {
testContext = null;
tester = null;
super.tearDown();
}
private static final String query1 =
"select\n"
+ " crossjoin(\n"
+ " {[Time].[1997].[Q1], [Time].[1997].[Q2].[4]},\n"
+ " {[Measures].[Unit Sales], [Measures].[Store Sales]}) on 0,\n"
+ " {[USA].[CA].[Los Angeles],\n"
+ " [USA].[WA].[Seattle],\n"
+ " [USA].[CA].[San Francisco]} on 1\n"
+ "FROM [Sales]";
/**
* Asserts that a query is formatted to an expected piece of text.
*
* @param queryString MDX query
* @param format Desired format
* @param expected Expected formatted text
* @throws SQLException On error
*/
private void assertFormat(
String queryString,
Format format,
String expected) throws SQLException
{
Connection connection = null;
try {
connection = tester.createConnection();
OlapConnection olapConnection =
tester.getWrapper().unwrap(
connection,
OlapConnection.class);
CellSet result =
olapConnection.prepareOlapStatement(queryString).executeQuery();
String resultString = toString(result, format);
TestContext.assertEqualsVerbose(
expected,
resultString);
} finally {
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
// ignore
}
}
}
}
/**
* Converts a {@link CellSet} to text.
*
* @param cellSet Query result
* @param format Format
* @return Result as text
*/
static String toString(CellSet cellSet, Format format) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
switch (format) {
case TRADITIONAL:
new TraditionalCellSetFormatter().format(cellSet, pw);
break;
case COMPACT_RECTANGULAR:
case RECTANGULAR:
new RectangularCellSetFormatter(
format == Format.COMPACT_RECTANGULAR)
.format(cellSet, pw);
break;
}
pw.flush();
return sw.toString();
}
public enum Format {
/**
* Traditional format, one row per cell.
*/
TRADITIONAL,
/**
* Rectangular format that is similar to {@link #RECTANGULAR} but omits
* vertical bars and is therefore more compact.
*/
COMPACT_RECTANGULAR,
/**
* Rectangular format that uses vertical bars and hyphens to draw a
* grid.
*/
RECTANGULAR
}
// ~ Tests follow ==========================================================
public void testQuery1Traditional() throws SQLException {
assertFormat(
query1,
Format.TRADITIONAL,
"Axis #0:\n"
+ "{}\n"
+ "Axis #1:\n"
+ "{[Time].[1997].[Q1], [Measures].[Unit Sales]}\n"
+ "{[Time].[1997].[Q1], [Measures].[Store Sales]}\n"
+ "{[Time].[1997].[Q2].[4], [Measures].[Unit Sales]}\n"
+ "{[Time].[1997].[Q2].[4], [Measures].[Store Sales]}\n"
+ "Axis #2:\n"
+ "{[Store].[USA].[CA].[Los Angeles]}\n"
+ "{[Store].[USA].[WA].[Seattle]}\n"
+ "{[Store].[USA].[CA].[San Francisco]}\n"
+ "Row #0: 6,373\n"
+ "Row #0: 13,736.97\n"
+ "Row #0: 1,865\n"
+ "Row #0: 3,917.49\n"
+ "Row #1: 6,098\n"
+ "Row #1: 12,760.64\n"
+ "Row #1: 2,121\n"
+ "Row #1: 4,444.06\n"
+ "Row #2: 439\n"
+ "Row #2: 936.51\n"
+ "Row #2: 149\n"
+ "Row #2: 327.33\n");
}
public void testQuery1Compact() throws SQLException {
assertFormat(
query1,
Format.COMPACT_RECTANGULAR,
" 1997 \n"
+ " Q1 Q2 \n"
+ " 4 \n"
+ " Unit Sales Store Sales Unit Sales Store Sales\n"
+ "=== == ============= ========== =========== ========== ===========\n"
+ "USA CA Los Angeles 6,373 13,736.97 1,865 3,917.49\n"
+ " WA Seattle 6,098 12,760.64 2,121 4,444.06\n"
+ " CA San Francisco 439 936.51 149 327.33\n");
}
public void testQuery1Rectangular() throws SQLException {
assertFormat(
query1,
Format.RECTANGULAR,
"| | 1997 |\n"
+ "| | Q1 | Q2 |\n"
+ "| | | 4 |\n"
+ "| | Unit Sales | Store Sales | Unit Sales | Store Sales |\n"
+ "+-----+----+---------------+------------+-------------+------------+-------------+\n"
+ "| USA | CA | Los Angeles | 6,373 | 13,736.97 | 1,865 | 3,917.49 |\n"
+ "| | WA | Seattle | 6,098 | 12,760.64 | 2,121 | 4,444.06 |\n"
+ "| | CA | San Francisco | 439 | 936.51 | 149 | 327.33 |\n");
}
public void testQueryAllRectangular() throws SQLException {
// Similar query with an 'all' member on rows. Need an extra column.
assertFormat(
"select\n"
+ " crossjoin(\n"
+ " {[Time].[1997].[Q1], [Time].[1997].[Q2].[4]},\n"
+ " {[Measures].[Unit Sales], [Measures].[Store Sales]}) on 0,\n"
+ " {[Store],\n"
+ " [Store].[USA],\n"
+ " [Store].[USA].[CA],\n"
+ " [Store].[USA].[CA].[Los Angeles],\n"
+ " [Store].[USA].[WA]} on 1\n"
+ "FROM [Sales]",
Format.COMPACT_RECTANGULAR,
" 1997 \n"
+ " Q1 Q2 \n"
+ " 4 \n"
+ " Unit Sales Store Sales Unit Sales Store Sales\n"
+ "========== === == =========== ========== =========== ========== ===========\n"
+ "All Stores 66,291 139,628.35 20,179 42,878.25\n"
+ " USA 66,291 139,628.35 20,179 42,878.25\n"
+ " CA 16,890 36,175.20 6,382 13,605.89\n"
+ " Los Angeles 6,373 13,736.97 1,865 3,917.49\n"
+ " WA 30,114 63,282.86 9,896 20,926.37\n");
}
public void testNonParentRepeatsRectangular() throws SQLException {
// "Food.Dairy" follows "Drink.Dairy" but there should still be a '|'
// because they are different members with the same caption.
assertFormat(
"select\n"
+ " {[Measures].[Unit Sales], [Measures].[Store Sales]} on 1,\n"
+ " {[Product],\n"
+ " [Product].[Drink].[Dairy],\n"
+ " [Product].[Food].[Dairy],\n"
+ " [Product].[Food]} on 0\n"
+ "FROM [Sales]",
Format.RECTANGULAR,
"| | All Products |\n"
+ "| | | Drink | Food |\n"
+ "| | | Dairy | Dairy | |\n"
+ "+-------------+--------------+--------------+--------------+--------------+\n"
+ "| Unit Sales | 266,773 | 4,186 | 12,885 | 191,940 |\n"
+ "| Store Sales | 565,238.13 | 7,058.60 | 30,508.85 | 409,035.59 |\n");
assertFormat(
"select\n"
+ " {[Measures].[Unit Sales], [Measures].[Store Sales]} on 1,\n"
+ " {[Product],\n"
+ " [Product].[Drink].[Dairy],\n"
+ " [Product].[Food].[Dairy],\n"
+ " [Product].[Food]} on 0\n"
+ "FROM [Sales]",
Format.COMPACT_RECTANGULAR,
" All Products \n"
+ " Drink Food \n"
+ " Dairy Dairy \n"
+ "=========== ============ ============ ============ ============\n"
+ "Unit Sales 266,773 4,186 12,885 191,940\n"
+ "Store Sales 565,238.13 7,058.60 30,508.85 409,035.59\n");
// Passes the test: Dairy is repeated.
// However, the empty last column, signifying [Food] with no child,
// is not ideal. What would be better?
assertFormat(
"select\n"
+ " {[Measures].[Unit Sales], [Measures].[Store Sales]} on 0,\n"
+ " {[Product],\n"
+ " [Product].[Drink].[Dairy],\n"
+ " [Product].[Food].[Dairy],\n"
+ " [Product].[Food]} on 1\n"
+ "FROM [Sales]",
Format.COMPACT_RECTANGULAR,
" Unit Sales Store Sales\n"
+ "============ ===== ===== ========== ===========\n"
+ "All Products 266,773 565,238.13\n"
+ " Drink Dairy 4,186 7,058.60\n"
+ " Food Dairy 12,885 30,508.85\n"
+ " 191,940 409,035.59\n");
}
public void testEmptyRowsRectangular() throws SQLException {
assertFormat(
"select\n"
+ " crossjoin(\n"
+ " {[Time].[1997].[Q1], [Time].[1997].[Q2].[4]},\n"
+ " {[Measures].[Unit Sales], [Measures].[Store Sales]}) on 0,\n"
+ " {[Store].Parent} on 1\n"
+ "FROM [Sales]",
Format.COMPACT_RECTANGULAR,
"1997 \n"
+ "Q1 Q2 \n"
+ " 4 \n"
+ "Unit Sales Store Sales Unit Sales Store Sales\n"
+ "========== =========== ========== ===========\n");
}
public void testEmptyColumnsRectangular() throws SQLException {
final
String
queryString =
"select\n"
+ " crossjoin(\n"
+ " {[Product].Parent},\n"
+ " {[Measures].[Unit Sales], [Measures].[Store Sales]}) on 0,\n"
+ " {[Store],\n"
+ " [Store].[USA],\n"
+ " [Store].[USA].[CA],\n"
+ " [Store].[USA].[CA].[Los Angeles],\n"
+ " [Store].[USA].[WA]} on 1\n"
+ "FROM [Sales]";
assertFormat(
queryString,
Format.COMPACT_RECTANGULAR,
"All Stores \n"
+ " USA \n"
+ " CA \n"
+ " Los Angeles\n"
+ " WA \n");
assertFormat(
queryString,
Format.RECTANGULAR,
"| All Stores | | | |\n"
+ "| | USA | | |\n"
+ "| | | CA | |\n"
+ "| | | | Los Angeles |\n"
+ "| | | WA | |\n");
}
public void testFilter() throws SQLException {
final String queryString =
"select\n"
+ " crossjoin(\n"
+ " {[Time].[1997].[Q1], [Time].[1997].[Q2].[4]},\n"
+ " {[Measures].[Unit Sales]}) on 0,\n"
+ " {[USA].[CA].[Los Angeles],\n"
+ " [USA].[CA].[San Francisco]} on 1\n"
+ "FROM [Sales]\n"
+ "WHERE ([Gender].[M], [Marital Status].[S])";
assertFormat(
queryString,
Format.TRADITIONAL,
"Axis #0:\n"
+ "{[Gender].[M], [Marital Status].[S]}\n"
+ "Axis #1:\n"
+ "{[Time].[1997].[Q1], [Measures].[Unit Sales]}\n"
+ "{[Time].[1997].[Q2].[4], [Measures].[Unit Sales]}\n"
+ "Axis #2:\n"
+ "{[Store].[USA].[CA].[Los Angeles]}\n"
+ "{[Store].[USA].[CA].[San Francisco]}\n"
+ "Row #0: 1,615\n"
+ "Row #0: 594\n"
+ "Row #1: 101\n"
+ "Row #1: 55\n");
// TODO: rectagular formatter should print filter
assertFormat(
queryString,
Format.COMPACT_RECTANGULAR,
" 1997 \n"
+ " Q1 Q2\n"
+ " 4\n"
+ " Unit Sales Unit Sales\n"
+ "=== == ============= ========== ==========\n"
+ "USA CA Los Angeles 1,615 594\n"
+ " San Francisco 101 55\n");
// TODO: rectagular formatter should print filter
assertFormat(
queryString,
Format.RECTANGULAR,
"| | 1997 |\n"
+ "| | Q1 | Q2 |\n"
+ "| | | 4 |\n"
+ "| | Unit Sales | Unit Sales |\n"
+ "+-----+----+---------------+------------+------------+\n"
+ "| USA | CA | Los Angeles | 1,615 | 594 |\n"
+ "| | | San Francisco | 101 | 55 |\n");
}
public void testFilterCompound() throws SQLException {
final String queryString =
"select\n"
+ " crossjoin(\n"
+ " {[Time].[1997].[Q1], [Time].[1997].[Q2].[4]},\n"
+ " {[Measures].[Unit Sales]}) on 0,\n"
+ " {[USA].[CA].[Los Angeles],\n"
+ " [USA].[CA].[San Francisco]} on 1\n"
+ "FROM [Sales]\n"
+ "WHERE [Gender].Children * [Marital Status].Members";
assertFormat(
queryString,
Format.TRADITIONAL,
"Axis #0:\n"
+ "{[Gender].[F], [Marital Status].[All Marital Status]}\n"
+ "{[Gender].[F], [Marital Status].[M]}\n"
+ "{[Gender].[F], [Marital Status].[S]}\n"
+ "{[Gender].[M], [Marital Status].[All Marital Status]}\n"
+ "{[Gender].[M], [Marital Status].[M]}\n"
+ "{[Gender].[M], [Marital Status].[S]}\n"
+ "Axis #1:\n"
+ "{[Time].[1997].[Q1], [Measures].[Unit Sales]}\n"
+ "{[Time].[1997].[Q2].[4], [Measures].[Unit Sales]}\n"
+ "Axis #2:\n"
+ "{[Store].[USA].[CA].[Los Angeles]}\n"
+ "{[Store].[USA].[CA].[San Francisco]}\n"
+ "Row #0: 6,373\n"
+ "Row #0: 1,865\n"
+ "Row #1: 439\n"
+ "Row #1: 149\n");
}
public void testZeroAxesRectangular() throws SQLException {
final String mdx =
"select\n"
+ "from [Sales]\n"
+ "where ([Measures].[Store Sales], [Time].[1997].[Q2])";
assertFormat(
mdx,
Format.RECTANGULAR, "| 132,666.27 |\n");
assertFormat(
mdx,
Format.COMPACT_RECTANGULAR, "132,666.27\n");
}
public void testOneAxisRectangular() throws SQLException {
assertFormat(
"select\n"
+ " crossjoin(\n"
+ " {[Time].[1997].[Q1], [Time].[1997].[Q2].[4]},\n"
+ " {[Measures].[Unit Sales], [Measures].[Store Sales]}) on 0\n"
+ "FROM [Sales]",
Format.RECTANGULAR,
"| 1997 |\n"
+ "| Q1 | Q2 |\n"
+ "| | 4 |\n"
+ "| Unit Sales | Store Sales | Unit Sales | Store Sales |\n"
+ "+------------+-------------+------------+-------------+\n"
+ "| 66,291 | 139,628.35 | 20,179 | 42,878.25 |\n");
}
public void testThreeAxes() throws SQLException {
assertFormat(
"select\n"
+ " crossjoin(\n"
+ " {[Time].[1997].[Q1], [Time].[1997].[Q2].[4]},\n"
+ " {[Measures].[Unit Sales], [Measures].[Store Sales]}) on 0,\n"
+ " {[Store],\n"
+ " [Store].[USA],\n"
+ " [Store].[USA].[CA],\n"
+ " [Store].[USA].[CA].[Los Angeles],\n"
+ " [Store].[USA].[WA]} on 1,\n"
+ " {[Product].[Drink], [Product].[Food].[Dairy]} on 2\n"
+ "FROM [Sales]",
Format.RECTANGULAR,
"\n"
+ "PAGES: [Product].[Drink]\n"
+ "| | 1997 |\n"
+ "| | Q1 | Q2 |\n"
+ "| | | 4 |\n"
+ "| | Unit Sales | Store Sales | Unit Sales | Store Sales |\n"
+ "+------------+-----+----+-------------+------------+-------------+------------+-------------+\n"
+ "| All Stores | | | | 5,976 | 11,585.80 | 1,948 | 3,884.53 |\n"
+ "| | USA | | | 5,976 | 11,585.80 | 1,948 | 3,884.53 |\n"
+ "| | | CA | | 1,654 | 3,309.75 | 583 | 1,212.78 |\n"
+ "| | | | Los Angeles | 650 | 1,267.04 | 141 | 289.16 |\n"
+ "| | | WA | | 2,679 | 5,106.36 | 1,007 | 1,978.99 |\n"
+ "\n"
+ "PAGES: [Product].[Food].[Dairy]\n"
+ "| | 1997 |\n"
+ "| | Q1 | Q2 |\n"
+ "| | | 4 |\n"
+ "| | Unit Sales | Store Sales | Unit Sales | Store Sales |\n"
+ "+------------+-----+----+-------------+------------+-------------+------------+-------------+\n"
+ "| All Stores | | | | 3,262 | 7,708.75 | 1,047 | 2,512.80 |\n"
+ "| | USA | | | 3,262 | 7,708.75 | 1,047 | 2,512.80 |\n"
+ "| | | CA | | 845 | 2,004.95 | 297 | 721.34 |\n"
+ "| | | | Los Angeles | 288 | 708.69 | 82 | 196.59 |\n"
+ "| | | WA | | 1,504 | 3,544.86 | 533 | 1,275.98 |\n");
}
public void testFourAxes() throws SQLException {
assertFormat(
"select\n"
+ " {[Time].[1997].[Q1], [Time].[1997].[Q2].[4]} on 0,\n"
+ " {[Store].[USA],\n"
+ " [Store].[USA].[OR]} on 1,\n"
+ " {[Product].[Drink], [Product].[Food].[Dairy]} on 2,\n"
+ " Crossjoin(\n"
+ " {[Marital Status].Members},\n"
+ " {[Gender].[F], [Gender].[M]}) on 3\n"
+ "FROM [Sales]\n"
+ "WHERE [Measures].[Store Sales]",
Format.RECTANGULAR,
"\n"
+ "CHAPTERS: [Marital Status].[All Marital Status], [Gender].[F]\n"
+ "PAGES: [Product].[Drink]\n"
+ "| | 1997 |\n"
+ "| | Q1 | Q2 |\n"
+ "| | | 4 |\n"
+ "+-----+----+----------+----------+\n"
+ "| USA | | 5,676.21 | 1,836.80 |\n"
+ "| | OR | 1,569.00 | 327.26 |\n"
+ "\n"
+ "CHAPTERS: [Marital Status].[All Marital Status], [Gender].[F]\n"
+ "PAGES: [Product].[Food].[Dairy]\n"
+ "| | 1997 |\n"
+ "| | Q1 | Q2 |\n"
+ "| | | 4 |\n"
+ "+-----+----+----------+----------+\n"
+ "| USA | | 3,873.00 | 1,378.20 |\n"
+ "| | OR | 1,069.88 | 284.91 |\n"
+ "\n"
+ "CHAPTERS: [Marital Status].[All Marital Status], [Gender].[M]\n"
+ "PAGES: [Product].[Drink]\n"
+ "| | 1997 |\n"
+ "| | Q1 | Q2 |\n"
+ "| | | 4 |\n"
+ "+-----+----+----------+----------+\n"
+ "| USA | | 5,909.59 | 2,047.73 |\n"
+ "| | OR | 1,600.69 | 365.50 |\n"
+ "\n"
+ "CHAPTERS: [Marital Status].[All Marital Status], [Gender].[M]\n"
+ "PAGES: [Product].[Food].[Dairy]\n"
+ "| | 1997 |\n"
+ "| | Q1 | Q2 |\n"
+ "| | | 4 |\n"
+ "+-----+----+----------+----------+\n"
+ "| USA | | 3,835.75 | 1,134.60 |\n"
+ "| | OR | 1,089.06 | 230.57 |\n"
+ "\n"
+ "CHAPTERS: [Marital Status].[M], [Gender].[F]\n"
+ "PAGES: [Product].[Drink]\n"
+ "| | 1997 |\n"
+ "| | Q1 | Q2 |\n"
+ "| | | 4 |\n"
+ "+-----+----+----------+--------+\n"
+ "| USA | | 3,099.69 | 971.79 |\n"
+ "| | OR | 767.62 | 134.02 |\n"
+ "\n"
+ "CHAPTERS: [Marital Status].[M], [Gender].[F]\n"
+ "PAGES: [Product].[Food].[Dairy]\n"
+ "| | 1997 |\n"
+ "| | Q1 | Q2 |\n"
+ "| | | 4 |\n"
+ "+-----+----+----------+--------+\n"
+ "| USA | | 2,125.13 | 732.95 |\n"
+ "| | OR | 581.31 | 160.55 |\n"
+ "\n"
+ "CHAPTERS: [Marital Status].[M], [Gender].[M]\n"
+ "PAGES: [Product].[Drink]\n"
+ "| | 1997 |\n"
+ "| | Q1 | Q2 |\n"
+ "| | | 4 |\n"
+ "+-----+----+----------+--------+\n"
+ "| USA | | 2,874.11 | 914.70 |\n"
+ "| | OR | 643.61 | 132.37 |\n"
+ "\n"
+ "CHAPTERS: [Marital Status].[M], [Gender].[M]\n"
+ "PAGES: [Product].[Food].[Dairy]\n"
+ "| | 1997 |\n"
+ "| | Q1 | Q2 |\n"
+ "| | | 4 |\n"
+ "+-----+----+----------+--------+\n"
+ "| USA | | 1,920.54 | 528.54 |\n"
+ "| | OR | 519.94 | 108.96 |\n"
+ "\n"
+ "CHAPTERS: [Marital Status].[S], [Gender].[F]\n"
+ "PAGES: [Product].[Drink]\n"
+ "| | 1997 |\n"
+ "| | Q1 | Q2 |\n"
+ "| | | 4 |\n"
+ "+-----+----+----------+--------+\n"
+ "| USA | | 2,576.52 | 865.01 |\n"
+ "| | OR | 801.38 | 193.24 |\n"
+ "\n"
+ "CHAPTERS: [Marital Status].[S], [Gender].[F]\n"
+ "PAGES: [Product].[Food].[Dairy]\n"
+ "| | 1997 |\n"
+ "| | Q1 | Q2 |\n"
+ "| | | 4 |\n"
+ "+-----+----+----------+--------+\n"
+ "| USA | | 1,747.87 | 645.25 |\n"
+ "| | OR | 488.57 | 124.36 |\n"
+ "\n"
+ "CHAPTERS: [Marital Status].[S], [Gender].[M]\n"
+ "PAGES: [Product].[Drink]\n"
+ "| | 1997 |\n"
+ "| | Q1 | Q2 |\n"
+ "| | | 4 |\n"
+ "+-----+----+----------+----------+\n"
+ "| USA | | 3,035.48 | 1,133.03 |\n"
+ "| | OR | 957.08 | 233.13 |\n"
+ "\n"
+ "CHAPTERS: [Marital Status].[S], [Gender].[M]\n"
+ "PAGES: [Product].[Food].[Dairy]\n"
+ "| | 1997 |\n"
+ "| | Q1 | Q2 |\n"
+ "| | | 4 |\n"
+ "+-----+----+----------+--------+\n"
+ "| USA | | 1,915.21 | 606.06 |\n"
+ "| | OR | 569.12 | 121.61 |\n");
}
}
// End CellSetFormatterTest.java
olap4j-1.0.1.500/testsrc/org/olap4j/transform/ 0000755 0001750 0001750 00000000000 11711470530 020562 5 ustar drazzib drazzib olap4j-1.0.1.500/testsrc/org/olap4j/transform/TransformTest.java 0000644 0001750 0001750 00000017307 11711470530 024250 0 ustar drazzib drazzib /*
// $Id: TransformTest.java 498 2012-01-30 16:30:42Z lucboudreau $
//
// Licensed to Julian Hyde under one or more contributor license
// agreements. See the NOTICE file distributed with this work for
// additional information regarding copyright ownership.
//
// Julian Hyde licenses this file to you 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.olap4j.transform;
import org.olap4j.*;
import org.olap4j.mdx.SelectNode;
import org.olap4j.mdx.parser.MdxParser;
import org.olap4j.test.TestContext;
import junit.framework.TestCase;
import java.sql.Connection;
import java.sql.SQLException;
/**
* Testcase for org.olap4j.transform package.
*
* @author etdub
* @author jhyde
* @version $Id: TransformTest.java 498 2012-01-30 16:30:42Z lucboudreau $
* @since Jul 28, 2008
*/
public class TransformTest extends TestCase {
private TestContext testContext = TestContext.instance();
private TestContext.Tester tester = testContext.getTester();
private Connection connection = null;
public TransformTest() {
super();
}
/**
* Simple strategy to prevent connection leaks: each test that needs a
* connection assigns it to this field, and {@link #tearDown()} closes it
* if it is not already closed.
*/
protected void tearDown() throws Exception {
// Simple strategy to prevent connection leaks
if (connection != null
&& !connection.isClosed())
{
connection.close();
connection = null;
}
testContext = null;
tester = null;
}
protected OlapConnection getConnection() throws SQLException {
if (connection == null) {
connection = tester.createConnection();
}
return tester.getWrapper().unwrap(connection, OlapConnection.class);
}
protected OlapStatement getStatement() throws SQLException {
return getConnection().createStatement();
}
/**
* Asserts the functionality of a transformation
*
* @param initialMdx initial MDX query to be transformed
* @param expectedMdx expected MDX query after applying transform; will
* be compared against the transformed query
* @param trans the transformation to apply to the initial query
*
* @throws java.sql.SQLException on error
*/
public void assertTransformTo(
String initialMdx,
String expectedMdx,
MdxQueryTransform trans) throws SQLException
{
OlapConnection olapConnection = getConnection();
MdxParser mdxParser =
olapConnection.getParserFactory().createMdxParser(olapConnection);
SelectNode before = mdxParser.parseSelect(initialMdx);
SelectNode after = trans.apply(before);
// we also parse the expected MDX in order to normalize it
// (eliminate any whitespace / capitalization differences)
// note: CallNodes are not aware of function names, and as such
// will be compared in a case-sensitive manner
// (i.e. [SomeMember].Children vs [SomeMember].children are not
// equal, even if they are equivalent in MDX)
SelectNode expected = mdxParser.parseSelect(expectedMdx);
// TODO: consider adding .equals() method to ParseTreeNode instead
// of comparing strings (we could ignore case when comparing
// function names in CallNodes ...)
assertEquals(expected.toString(), after.toString());
}
/**
* Unit test for DrillReplaceTransform.
*
* @throws java.sql.SQLException on error
*/
public void testDrillReplaceTransform() throws SQLException {
final String initialMdx =
"SELECT {[Measures].[Unit Sales], "
+ " [Measures].[Store Cost], "
+ " [Measures].[Store Sales]} ON COLUMNS, "
+ " {[Product].[All Products]} ON ROWS "
+ "FROM Sales "
+ "WHERE ([Time].[1997])";
final String expectedMdx =
"SELECT {[Measures].[Unit Sales], "
+ " [Measures].[Store Cost], "
+ " [Measures].[Store Sales]} ON COLUMNS, "
+ " {[Product].[All Products].Children} ON ROWS "
+ "FROM Sales "
+ "WHERE ([Time].[1997])";
CellSet cellSet = getStatement().executeOlapQuery(initialMdx);
MdxQueryTransform transform =
StandardTransformLibrary.createDrillReplaceTransform(
Axis.ROWS,
0, // position ordinal in axis
0, // member ordinal in position
cellSet);
assertTransformTo(initialMdx, expectedMdx, transform);
}
/**
* Unit test for RollUpLevelTransform.
*
* @throws java.sql.SQLException on error
*/
public void testRollUpLevelTransform() throws SQLException {
final String initialMdx =
"SELECT {[Measures].[Unit Sales], "
+ " [Measures].[Store Cost], "
+ " [Measures].[Store Sales]} ON COLUMNS, "
+ " {[Product].[All Products].[Food].[Deli]} ON ROWS "
+ "FROM Sales "
+ "WHERE ([Time].[1997])";
final String expectedMdx =
"SELECT {[Measures].[Unit Sales], "
+ " [Measures].[Store Cost], "
+ " [Measures].[Store Sales]} ON COLUMNS, "
+ " {[Product].[Food].[Deli].Parent.Level.Members} ON ROWS "
+ "FROM Sales "
+ "WHERE ([Time].[1997])";
CellSet cellSet = getStatement().executeOlapQuery(initialMdx);
MdxQueryTransform transform =
StandardTransformLibrary.createRollUpLevelTransform(
Axis.ROWS,
0, // position ordinal in axis
0, // member ordinal in position
cellSet);
assertTransformTo(initialMdx, expectedMdx, transform);
}
/**
* Unit test for DrillDownOnPositionTransform.
*
* @throws java.sql.SQLException on error
*/
public void _testDrillDownOnPositionTransform() throws SQLException {
// TODO: rewrite the initial and expected MDX once this transform
// is written.
// Will fail for now.
final String initialMdx =
"SELECT {[Measures].[Unit Sales], "
+ " [Measures].[Store Cost], "
+ " [Measures].[Store Sales]} ON COLUMNS, "
+ " {[Product].[All Products]} ON ROWS "
+ "FROM Sales "
+ "WHERE ([Time].[1997])";
final String expectedMdx =
"SELECT {[Measures].[Unit Sales], "
+ " [Measures].[Store Cost], "
+ " [Measures].[Store Sales]} ON COLUMNS, "
+ " {[Product].[All Products].Children} ON ROWS "
+ "FROM Sales "
+ "WHERE ([Time].[1997])";
CellSet cellSet = getStatement().executeOlapQuery(initialMdx);
MdxQueryTransform transform =
StandardTransformLibrary.createDrillDownOnPositionTransform(
Axis.ROWS,
0, // position ordinal in axis
0, // member ordinal in position
cellSet);
assertTransformTo(initialMdx, expectedMdx, transform);
}
}
// End TransformTest.java
olap4j-1.0.1.500/testsrc/org/olap4j/XmlaConnectionTest.java 0000644 0001750 0001750 00000041450 11713757606 023215 0 ustar drazzib drazzib /*
// $Id: XmlaConnectionTest.java 498 2012-01-30 16:30:42Z lucboudreau $
//
// Licensed to Julian Hyde under one or more contributor license
// agreements. See the NOTICE file distributed with this work for
// additional information regarding copyright ownership.
//
// Julian Hyde licenses this file to you 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.olap4j;
import org.olap4j.driver.xmla.XmlaOlap4jDriver;
import org.olap4j.driver.xmla.XmlaOlap4jServerInfos;
import org.olap4j.driver.xmla.proxy.XmlaOlap4jProxy;
import org.olap4j.driver.xmla.proxy.XmlaOlap4jProxyException;
import org.olap4j.test.TestContext;
import org.olap4j.test.TestContext.Tester;
import junit.framework.TestCase;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.sql.*;
import java.util.*;
import java.util.concurrent.Future;
/**
* Unit test for XMLA driver connections.
*
* @version $Id: XmlaConnectionTest.java 498 2012-01-30 16:30:42Z lucboudreau $
*/
public class XmlaConnectionTest extends TestCase {
private TestContext testContext = TestContext.instance();
private TestContext.Tester tester = testContext.getTester();
public static final String DRIVER_CLASS_NAME =
"org.olap4j.driver.xmla.XmlaOlap4jDriver";
static class XmlaOlap4jProxyMock implements XmlaOlap4jProxy {
public byte[] get(
XmlaOlap4jServerInfos serverInfos,
String request)
{
throw new RuntimeException("Non-Trivial Call!");
}
public String getEncodingCharsetName() {
return "UTF-8";
}
public Future submit(
XmlaOlap4jServerInfos serverInfos,
String request)
{
throw new RuntimeException("Non-Trivial Call!");
}
}
/**
* Implementation of {@link org.olap4j.driver.xmla.proxy.XmlaOlap4jProxy}
* that delegates all requests to an underlying proxy.
*/
public static class DelegatingTestProxy implements XmlaOlap4jProxy {
protected final XmlaOlap4jProxy proxy;
/**
* Creates a DelegatingTestProxy.
*
* @param proxy Underlying proxy
*/
public DelegatingTestProxy(XmlaOlap4jProxy proxy) {
this.proxy = proxy;
}
public byte[] get(XmlaOlap4jServerInfos serverInfos, String request)
throws XmlaOlap4jProxyException
{
return proxy.get(serverInfos, request);
}
public Future submit(
XmlaOlap4jServerInfos serverInfos,
String request)
{
return proxy.submit(serverInfos, request);
}
public String getEncodingCharsetName() {
return proxy.getEncodingCharsetName();
}
}
/**
* Proxy that checks that the same request does not occur twice.
*/
public static class DoubleSubmissionTestProxy extends DelegatingTestProxy {
final Map requests = new HashMap();
private static String PROXY_CLASS_NAME;
/**
* Creates a DoubleSubmissionTestProxy.
*
* Public constructor is required because this is instantiated via
* reflection.
*
*
Instantiates an underlying proxy whose name is given by
* {@link #getProxyClassName()}.
*
* @param catalogNameUrls Collection of catalog names and the URL where
* their catalog is to be found. For testing purposes, this should
* contain a catalog called "FoodMart".
*
* @param urlString JDBC connect string; must begin with
* "jdbc:mondrian:"
*/
public DoubleSubmissionTestProxy(
Map catalogNameUrls,
String urlString)
{
super(createProxy(catalogNameUrls, urlString));
}
/**
* Sets the name of the class which is the underlying proxy.
*
* @param clazz Proxy class name
*/
public static void setProxyClassName(String clazz) {
PROXY_CLASS_NAME = clazz;
}
/**
* Returns the name of the class which is the underlying proxy.
*
* @return Proxy class name
*/
public static String getProxyClassName() {
return PROXY_CLASS_NAME;
}
/**
* Creates the underlying proxy.
*
* @param catalogNameUrls Catalog name URLs
* @param urlString URL
* @return Proxy
*/
static XmlaOlap4jProxy createProxy(
Map catalogNameUrls,
String urlString)
{
try {
final Class> clazz = Class.forName(getProxyClassName());
final Constructor> constructor =
clazz.getConstructor(Map.class, String.class);
return
(XmlaOlap4jProxy) constructor.newInstance(
catalogNameUrls, urlString);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
} catch (InstantiationException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
}
}
public byte[] get(XmlaOlap4jServerInfos serverInfos, String request)
throws XmlaOlap4jProxyException
{
this.checkup(request);
return super.get(serverInfos, request);
}
/**
* Checks that a request has not been seen before.
*
* @param request Request
*
* @throws RuntimeException if proxy has been seen before
*/
private void checkup(String request) {
String hash = Encoder.convertToHex(request.getBytes());
if (request.indexOf("MDSCHEMA_CUBES")
== -1
&& this.requests.containsKey(hash))
{
throw new RuntimeException("DOUBLE-REQUEST");
} else {
this.requests.put(hash, request);
}
}
}
protected void tearDown() throws Exception {
testContext = null;
tester = null;
super.tearDown();
}
/**
* Verifies that the construction of the necessary
* XMLA objects during DriverManager.getConnection() do not make
* calls that could cause deadlocks.
*/
public void testNoNonTrivalCallsOnConnect() throws Exception {
String cookie = XmlaOlap4jDriver.nextCookie();
try {
XmlaOlap4jDriver.PROXY_MAP.put(cookie, new XmlaOlap4jProxyMock());
try {
Class.forName(DRIVER_CLASS_NAME);
} catch (ClassNotFoundException e) {
throw new RuntimeException("oops", e);
}
Properties info = new Properties();
info.setProperty(
XmlaOlap4jDriver.Property.CATALOG.name(), "FoodMart");
DriverManager.getConnection(
"jdbc:xmla:Server=http://foo;Catalog=FoodMart;TestProxyCookie="
+ cookie,
info);
} catch (Throwable t) {
t.printStackTrace();
fail(
"Non-Trival Call executed during construction of XmlaOlap4j "
+ "Connection");
}
}
public void testDbSchemaSchemata() throws Exception {
if (!testContext.getTester().getFlavor()
.equals(Tester.Flavor.XMLA))
{
return;
}
class Proxy extends DoubleSubmissionTestProxy {
boolean schemata = false;
boolean cubes = false;
public Proxy(
Map catalogNameUrls,
String urlString)
{
super(catalogNameUrls, urlString);
}
@Override
public byte[] get(
XmlaOlap4jServerInfos serverInfos,
String request)
throws XmlaOlap4jProxyException
{
if (request.contains("DBSCHEMA_SCHEMATA")) {
if (schemata || cubes) {
fail();
}
schemata = true;
} else if (request.contains("MDSCHEMA_CUBES")) {
if (!schemata || cubes) {
fail();
}
}
return super.get(serverInfos, request);
}
}
String oldValue = XmlaTester.getProxyClassName();
XmlaTester.setProxyClassName(
Proxy.class.getName());
DoubleSubmissionTestProxy.setProxyClassName(oldValue);
try {
Connection connection = tester.createConnection();
OlapConnection oConn =
tester.getWrapper().unwrap(connection, OlapConnection.class);
oConn.getOlapSchema().getCubes().size();
} finally {
XmlaTester.setProxyClassName(oldValue);
}
}
/**
* Tests that no request is sent to XMLA more than once.
* If the same request is sent twice, throws an exception. The only
* exception to this is the MDSCHEMA_CUBES query that is used to
* populate both the catalogs and the schemas associated to a
* given catalog. This was due to a flaw in SSAS; it doesn't
* return a SCHEMA_NAME column when asked to. We fixed it this
* way in some other revision.
* @throws Exception If the test fails.
*/
public void testNoDoubleQuerySubmission() throws Exception {
if (!testContext.getTester().getFlavor()
.equals(Tester.Flavor.XMLA)
&& !testContext.getTester().getFlavor()
.equals(Tester.Flavor.REMOTE_XMLA))
{
return;
}
String oldValue = XmlaTester.getProxyClassName();
XmlaTester.setProxyClassName(
DoubleSubmissionTestProxy.class.getName());
DoubleSubmissionTestProxy.setProxyClassName(oldValue);
try {
Connection connection = tester.createConnection();
Statement statement = connection.createStatement();
final OlapStatement olapStatement =
tester.getWrapper().unwrap(statement, OlapStatement.class);
CellSet cellSet =
olapStatement.executeOlapQuery(
"SELECT\n"
+ " {[Measures].[Unit Sales],\n"
+ " [Measures].[Store Sales]} ON COLUMNS\n,"
+ " Crossjoin({[Gender].[M]}, [Product].Children) ON ROWS\n"
+ "FROM [Sales]\n"
+ "WHERE [Time].[1997].[Q2]");
assertNotNull(cellSet);
cellSet =
olapStatement.executeOlapQuery(
"SELECT\n"
+ " {[Measures].[Unit Sales],\n"
+ " [Measures].[Store Sales]} ON COLUMNS\n,"
+ " Crossjoin({[Gender].[M]}, [Product].Children) ON ROWS\n"
+ "FROM [Sales]\n"
+ "WHERE [Time].[1997].[Q3]");
} finally {
XmlaTester.setProxyClassName(oldValue);
}
}
/**
* This is a test to verify that server specific properties
* can be sent to the server in the PropertyList element
* of SOAP messages. A property that is not part of those enumerated
* in {@link org.olap4j.driver.xmla.XmlaOlap4jDriver.Property} must
* not be sent to the server.
*/
public void testPropertyList() throws Exception {
if (!testContext.getTester().getFlavor()
.equals(Tester.Flavor.XMLA)
&& !testContext.getTester().getFlavor()
.equals(Tester.Flavor.REMOTE_XMLA))
{
return;
}
switch (testContext.getTester().getWrapper()) {
case DBCP:
return;
}
final String oldValue = XmlaTester.getProxyClassName();
try {
XmlaTester.setProxyClassName(
PropertyListTestProxy.class.getName());
OlapConnection connection =
tester.getWrapper().unwrap(
tester.createConnection(), OlapConnection.class);
OlapStatement olapStatement = connection.createStatement();
olapStatement.executeOlapQuery(
"SELECT\n"
+ " {[Measures].[Unit Sales],\n"
+ " [Measures].[Store Sales]} ON COLUMNS\n,"
+ " Crossjoin({[Gender].[M]}, [Product].Children) ON ROWS\n"
+ "FROM [Sales]\n"
+ "WHERE [Time].[1997].[Q2]");
assertEquals(0, PropertyListTestProxy.count);
connection.close();
connection =
tester.getWrapper().unwrap(
tester.createConnectionWithUserPassword(),
OlapConnection.class);
olapStatement = connection.createStatement();
olapStatement.executeOlapQuery(
"SELECT\n"
+ " {[Measures].[Unit Sales],\n"
+ " [Measures].[Store Sales]} ON COLUMNS\n,"
+ " Crossjoin({[Gender].[M]}, [Product].Children) ON ROWS\n"
+ "FROM [Sales]\n"
+ "WHERE [Time].[1997].[Q2]");
assertEquals(0, PropertyListTestProxy.count);
connection.close();
final Properties props = new Properties();
props.put("FOOBAR", "Bacon");
connection =
tester.getWrapper().unwrap(
((XmlaTester)tester)
.createConnectionWithUserPassword(props),
OlapConnection.class);
olapStatement = connection.createStatement();
try {
olapStatement.executeOlapQuery(
"SELECT\n"
+ " {[Measures].[Unit Sales],\n"
+ " [Measures].[Store Sales]} ON COLUMNS\n,"
+ " Crossjoin({[Gender].[M]}, [Product].Children) ON ROWS\n"
+ "FROM [Sales]\n"
+ "WHERE [Time].[1997].[Q2]");
} catch (Throwable e) {
assertTrue(e.getCause().getMessage().contains("FOOBAR"));
}
connection.close();
} finally {
XmlaTester.setProxyClassName(oldValue);
}
}
/**
* This is a class for the test
* {@link XmlaConnectionTest#testPropertyList()}.
*/
public static class PropertyListTestProxy extends DelegatingTestProxy {
public PropertyListTestProxy(XmlaOlap4jProxy proxy) {
super(proxy);
}
private final static String[] lookup =
new String[] {
""
};
private static int count = 0;
public byte[] get(
XmlaOlap4jServerInfos serverInfos, String request)
throws XmlaOlap4jProxyException
{
for (String token : lookup) {
if (request.contains(token)) {
count++;
}
}
return super.get(serverInfos, request);
}
}
private static class Encoder {
/**
* Converts an array of bytes to a hex string.
*
* For example, convertToHex(new byte[] {(byte) 0xDE,
* (byte) 0xAD})
returns "DEAD"
.
*
* @param data Array of bytes
* @return Bytes encoded as hex
*/
private static String convertToHex(byte[] data) {
StringBuilder buf = new StringBuilder();
for (int i = 0; i < data.length; i++) {
int halfbyte = (data[i] >>> 4) & 0x0F;
int two_halfs = 0;
do {
if ((0 <= halfbyte) && (halfbyte <= 9)) {
buf.append((char) ('0' + halfbyte));
} else {
buf.append((char) ('a' + (halfbyte - 10)));
}
halfbyte = data[i] & 0x0F;
} while (two_halfs++ < 1);
}
return buf.toString();
}
}
}
// End XmlaConnectionTest.java
olap4j-1.0.1.500/testsrc/org/olap4j/MetadataTest.java 0000644 0001750 0001750 00000115410 11711470530 021774 0 ustar drazzib drazzib /*
// $Id: MetadataTest.java 498 2012-01-30 16:30:42Z lucboudreau $
//
// Licensed to Julian Hyde under one or more contributor license
// agreements. See the NOTICE file distributed with this work for
// additional information regarding copyright ownership.
//
// Julian Hyde licenses this file to you 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.olap4j;
import org.olap4j.impl.Olap4jUtil;
import org.olap4j.metadata.*;
import org.olap4j.test.TestContext;
import junit.framework.TestCase;
import java.sql.*;
import java.util.*;
/**
* Unit test for olap4j metadata methods.
*
* @version $Id: MetadataTest.java 498 2012-01-30 16:30:42Z lucboudreau $
*/
public class MetadataTest extends TestCase {
private TestContext testContext = TestContext.instance();
private TestContext.Tester tester = testContext.getTester();
private static final String NL = System.getProperty("line.separator");
private Connection connection;
private String catalogName;
private OlapConnection olapConnection;
private OlapDatabaseMetaData olapDatabaseMetaData;
private final String propertyNamePattern = null;
private final String dataSourceName = "xx";
private static final List CUBE_COLUMN_NAMES = Arrays.asList(
"CATALOG_NAME", "SCHEMA_NAME", "CUBE_NAME", "CUBE_TYPE", "CUBE_GUID",
"CREATED_ON", "LAST_SCHEMA_UPDATE", "SCHEMA_UPDATED_BY",
"LAST_DATA_UPDATE", "DATA_UPDATED_BY", "IS_DRILLTHROUGH_ENABLED",
"IS_WRITE_ENABLED", "IS_LINKABLE", "IS_SQL_ENABLED", "DESCRIPTION");
private static final List LITERALS_COLUMN_NAMES = Arrays.asList(
"LITERAL_NAME", "LITERAL_VALUE", "LITERAL_INVALID_CHARS",
"LITERAL_INVALID_STARTING_CHARS", "LITERAL_MAX_LENGTH");
private static final List SETS_COLUMN_NAMES = Arrays.asList(
"CATALOG_NAME", "SCHEMA_NAME", "CUBE_NAME", "SET_NAME", "SCOPE");
private static final List PROPERTIES_COLUMN_NAMES = Arrays.asList(
"CATALOG_NAME", "SCHEMA_NAME", "CUBE_NAME", "DIMENSION_UNIQUE_NAME",
"HIERARCHY_UNIQUE_NAME", "LEVEL_UNIQUE_NAME", "MEMBER_UNIQUE_NAME",
"PROPERTY_NAME", "PROPERTY_CAPTION", "PROPERTY_TYPE", "DATA_TYPE",
"PROPERTY_CONTENT_TYPE", "DESCRIPTION");
private static final List MEMBERS_COLUMN_NAMES = Arrays.asList(
"CATALOG_NAME", "SCHEMA_NAME", "CUBE_NAME", "DIMENSION_UNIQUE_NAME",
"HIERARCHY_UNIQUE_NAME", "LEVEL_UNIQUE_NAME", "LEVEL_NUMBER",
"MEMBER_ORDINAL", "MEMBER_NAME", "MEMBER_UNIQUE_NAME", "MEMBER_TYPE",
"MEMBER_GUID", "MEMBER_CAPTION", "CHILDREN_CARDINALITY", "PARENT_LEVEL",
"PARENT_UNIQUE_NAME", "PARENT_COUNT", "TREE_OP", "DEPTH");
private static final List MEASURES_COLUMN_NAMES = Arrays.asList(
"CATALOG_NAME", "SCHEMA_NAME", "CUBE_NAME", "MEASURE_NAME",
"MEASURE_UNIQUE_NAME", "MEASURE_CAPTION", "MEASURE_GUID",
"MEASURE_AGGREGATOR", "DATA_TYPE", "MEASURE_IS_VISIBLE", "LEVELS_LIST",
"DESCRIPTION");
private static final List LEVELS_COLUMN_NAMES = Arrays.asList(
"CATALOG_NAME", "SCHEMA_NAME", "CUBE_NAME", "DIMENSION_UNIQUE_NAME",
"HIERARCHY_UNIQUE_NAME", "LEVEL_NAME", "LEVEL_UNIQUE_NAME",
"LEVEL_GUID", "LEVEL_CAPTION", "LEVEL_NUMBER", "LEVEL_CARDINALITY",
"LEVEL_TYPE", "CUSTOM_ROLLUP_SETTINGS", "LEVEL_UNIQUE_SETTINGS",
"LEVEL_IS_VISIBLE", "DESCRIPTION");
private static final List HIERARCHIES_COLUMN_NAMES = Arrays.asList(
"CATALOG_NAME", "SCHEMA_NAME", "CUBE_NAME", "DIMENSION_UNIQUE_NAME",
"HIERARCHY_NAME", "HIERARCHY_UNIQUE_NAME", "HIERARCHY_GUID",
"HIERARCHY_CAPTION", "DIMENSION_TYPE", "HIERARCHY_CARDINALITY",
"DEFAULT_MEMBER", "ALL_MEMBER", "DESCRIPTION", "STRUCTURE",
"IS_VIRTUAL", "IS_READWRITE", "DIMENSION_UNIQUE_SETTINGS",
"DIMENSION_IS_VISIBLE", "HIERARCHY_IS_VISIBLE", "HIERARCHY_ORDINAL",
"DIMENSION_IS_SHARED", "PARENT_CHILD");
private static final List FUNCTIONS_COLUMN_NAMES = Arrays.asList(
"FUNCTION_NAME", "DESCRIPTION", "PARAMETER_LIST", "RETURN_TYPE",
"ORIGIN", "INTERFACE_NAME", "LIBRARY_NAME", "CAPTION");
private static final List DIMENSIONS_COLUMN_NAMES = Arrays.asList(
"CATALOG_NAME", "SCHEMA_NAME", "CUBE_NAME", "DIMENSION_NAME",
"DIMENSION_UNIQUE_NAME", "DIMENSION_GUID", "DIMENSION_CAPTION",
"DIMENSION_ORDINAL", "DIMENSION_TYPE", "DIMENSION_CARDINALITY",
"DEFAULT_HIERARCHY", "DESCRIPTION", "IS_VIRTUAL", "IS_READWRITE",
"DIMENSION_UNIQUE_SETTINGS", "DIMENSION_MASTER_UNIQUE_NAME",
"DIMENSION_IS_VISIBLE");
private static final List DATABASE_PROPERTIES_COLUMN_NAMES =
Arrays.asList(
"PROPERTY_NAME", "PROPERTY_DESCRIPTION", "PROPERTY_TYPE",
"PROPERTY_ACCESS_TYPE", "IS_REQUIRED", "PROPERTY_VALUE");
private static final List DATASOURCES_COLUMN_NAMES = Arrays.asList(
"DATA_SOURCE_NAME", "DATA_SOURCE_DESCRIPTION", "URL",
"DATA_SOURCE_INFO", "PROVIDER_NAME", "PROVIDER_TYPE",
"AUTHENTICATION_MODE");
private static final List CATALOGS_COLUMN_NAMES = Arrays.asList(
"TABLE_CAT");
private static final List SCHEMAS_COLUMN_NAMES = Arrays.asList(
"TABLE_SCHEM", "TABLE_CAT");
private static final List ACTIONS_COLUMN_NAMES = Arrays.asList(
"CATALOG_NAME", "SCHEMA_NAME", "CUBE_NAME", "ACTION_NAME", "COORDINATE",
"COORDINATE_TYPE");
public MetadataTest() throws SQLException {
}
protected void setUp() throws SQLException {
connection = tester.createConnection();
catalogName = connection.getCatalog();
olapConnection =
tester.getWrapper().unwrap(connection, OlapConnection.class);
olapDatabaseMetaData = olapConnection.getMetaData();
}
protected void tearDown() throws Exception {
if (connection != null && !connection.isClosed()) {
connection.close();
connection = null;
}
connection = null;
olapConnection = null;
olapDatabaseMetaData = null;
testContext = null;
tester = null;
}
// ~ Helper methods ----------
private void assertContains(String seek, String s) {
if (s.indexOf(seek) < 0) {
fail("expected to find '" + seek + "' in '" + s + "'");
}
}
private void assertContainsLine(String partial, String seek, String s) {
if (partial == null) {
partial = seek;
}
int i = s.indexOf(partial);
if (i < 0) {
fail("expected to find '" + seek + "' in '" + s + "'");
}
int start = i;
while (start > 0
&& s.charAt(start - 1) != 0x0D
&& s.charAt(start - 1) != 0x0A)
{
--start;
}
int end = i;
while (end < s.length()
&& s.charAt(end) != 0x0D
&& s.charAt(end) != 0x0A)
{
++end;
}
String line = s.substring(start, end);
assertEquals(seek, line);
}
private void assertNotContains(String seek, String s) {
if (s.indexOf(seek) >= 0) {
fail("expected not to find '" + seek + "' in '" + s + "'");
}
}
private int linecount(String s) {
int i = 0;
int count = 0;
while (i < s.length()) {
int nl = s.indexOf('\n', i);
if (nl < 0) {
break;
}
i = nl + 1;
++count;
}
return count;
}
// ~ Tests follow -------------
public void testDatabaseMetaData() throws SQLException {
assertEquals("" + catalogName + "", catalogName);
DatabaseMetaData databaseMetaData = connection.getMetaData();
switch (tester.getFlavor()) {
case XMLA:
case REMOTE_XMLA:
// FIXME: implement getDatabaseXxxVersion in XMLA driver
break;
default:
assertTrue(databaseMetaData.getDatabaseMajorVersion() > 0);
assertTrue(databaseMetaData.getDatabaseMinorVersion() >= 0);
// assertTrue(databaseMetaData.getDatabaseProductName() != null);
assertTrue(databaseMetaData.getDatabaseProductVersion() != null);
break;
}
assertTrue(databaseMetaData.getDriverName() != null);
assertTrue(databaseMetaData.getDriverVersion() != null);
// mondrian-specific
switch (tester.getFlavor()) {
case MONDRIAN:
assertTrue(databaseMetaData.isReadOnly());
assertNull(databaseMetaData.getUserName());
assertNotNull(databaseMetaData.getURL());
break;
}
// unwrap connection; may or may not be the same object as connection;
// check extended methods
// also unwrap metadata from regular connection
assertTrue(
((OlapWrapper) databaseMetaData).isWrapperFor(
OlapDatabaseMetaData.class));
assertFalse(
((OlapWrapper) databaseMetaData).isWrapperFor(
OlapStatement.class));
OlapDatabaseMetaData olapDatabaseMetaData1 =
((OlapWrapper) databaseMetaData).unwrap(
OlapDatabaseMetaData.class);
assertTrue(
olapDatabaseMetaData1.getDriverName().equals(
olapDatabaseMetaData.getDriverName()));
switch (tester.getFlavor()) {
case XMLA:
case REMOTE_XMLA:
// FIXME: implement getDatabaseXxxVersion in XMLA driver
break;
default:
assertTrue(
olapDatabaseMetaData1.getDatabaseProductVersion().equals(
olapDatabaseMetaData.getDatabaseProductVersion()));
}
}
public void testSchemas() throws OlapException {
// check schema auto detection
final Schema schema1 = olapConnection.getOlapSchema();
assertEquals(
"Failed to auto detect the schema.",
schema1.getName(),
"FoodMart");
switch (tester.getFlavor()) {
case MONDRIAN:
// Setting a correct schema should work.
olapConnection.setSchema("FoodMart");
// setting a null schema should be ignored
olapConnection.setSchema(null);
// setting a non existent schema should be ignored
olapConnection.setSchema("Chunky Bacon");
break;
case XMLA:
case REMOTE_XMLA:
// Setting a correct schema should work.
olapConnection.setSchema(catalogName);
// setting a null schema should fail
try {
olapConnection.setSchema(null);
fail();
} catch (OlapException e) {
// no op.
}
// setting a non existent schema should fail
try {
olapConnection.setSchema("Chunky Bacon");
fail();
} catch (OlapException e) {
// no op.
}
break;
default:
fail("Unknown tester flavor.");
}
}
public void testCatalogs() throws SQLException {
final Catalog catalog = olapConnection.getOlapCatalog();
assertEquals(
"Failed to auto detect the catalog.",
catalog.getName(),
"FoodMart");
switch (tester.getFlavor()) {
case MONDRIAN:
// Setting a correct catalog should work.
olapConnection.setCatalog("FoodMart");
// setting a null catalog should be ignored
olapConnection.setCatalog(null);
// setting a non existent catalog should be ignored
olapConnection.setCatalog("Chunky Bacon");
break;
case XMLA:
case REMOTE_XMLA:
// Setting a correct catalog should work.
olapConnection.setCatalog(catalogName);
// setting a null catalog should fail
try {
olapConnection.setCatalog(null);
fail();
} catch (OlapException e) {
// no op.
}
// setting a non existent catalog should fail
try {
olapConnection.setCatalog("Chunky Bacon");
fail();
} catch (OlapException e) {
// no op.
}
break;
default:
fail("Unknown tester flavor.");
}
}
public void testDatabases() throws SQLException {
final Database database = olapConnection.getOlapDatabase();
assertTrue(
"Failed to auto detect the database.",
database.getName()
.equals("Provider=Mondrian;DataSource=MondrianFoodMart;")
|| database.getName()
.equals("FoodMart"));
switch (tester.getFlavor()) {
case MONDRIAN:
// Setting a correct database should work.
olapConnection.setDatabase("FoodMart");
// setting a null database should be ignored
olapConnection.setDatabase(null);
// setting a non existent database should be ignored
olapConnection.setDatabase("Chunky Bacon");
break;
case XMLA:
// Setting a correct database should work.
olapConnection.setDatabase(
"FoodMart");
// setting a null database should fail
try {
olapConnection.setDatabase(null);
fail();
} catch (OlapException e) {
// no op.
}
// setting a non existent database should fail
try {
olapConnection.setDatabase("Chunky Bacon");
fail();
} catch (OlapException e) {
// no op.
}
break;
case REMOTE_XMLA:
// Setting a correct database should work.
olapConnection.setDatabase(
"Provider=Mondrian;DataSource=MondrianFoodMart;");
// setting a null database should fail
try {
olapConnection.setDatabase(null);
fail();
} catch (OlapException e) {
// no op.
}
// setting a non existent database should fail
try {
olapConnection.setDatabase("Chunky Bacon");
fail();
} catch (OlapException e) {
// no op.
}
break;
default:
fail("Unknown tester flavor.");
}
}
public void testDatabaseMetaDataGetActions() throws SQLException {
String s = checkResultSet(
olapDatabaseMetaData.getActions(
catalogName, null, null, null),
ACTIONS_COLUMN_NAMES);
assertEquals("", s); // mondrian has no actions
}
public void testDatabaseMetaDataGetDatasources() throws SQLException {
String s = checkResultSet(
olapDatabaseMetaData.getDatabases(),
DATASOURCES_COLUMN_NAMES);
switch (tester.getFlavor()) {
case MONDRIAN:
TestContext.assertEqualsVerbose(
"DATA_SOURCE_NAME=FoodMart,"
+ " DATA_SOURCE_DESCRIPTION=null,"
+ " URL=null,"
+ " DATA_SOURCE_INFO=FoodMart,"
+ " PROVIDER_NAME=Mondrian,"
+ " PROVIDER_TYPE=MDP,"
+ " AUTHENTICATION_MODE=Unauthenticated\n",
s);
break;
case REMOTE_XMLA:
// This can be anything, depending on the remote server.
break;
case XMLA:
TestContext.assertEqualsVerbose(
"DATA_SOURCE_NAME=FoodMart,"
+ " DATA_SOURCE_DESCRIPTION=Mondrian FoodMart data source,"
+ " URL=http://localhost:8080/mondrian/xmla,"
+ " DATA_SOURCE_INFO=FoodMart,"
+ " PROVIDER_NAME=Mondrian,"
+ " PROVIDER_TYPE=MDP,"
+ " AUTHENTICATION_MODE=Unauthenticated\n",
s);
break;
}
}
public void testDatabaseMetaDataGetCatalogs() throws SQLException {
String s = checkResultSet(
olapDatabaseMetaData.getCatalogs(),
CATALOGS_COLUMN_NAMES);
final String expected;
switch (tester.getFlavor()) {
case XMLA:
// XMLA test uses dummy duplicate catalog to make sure that we
// get all catalogs
expected =
"TABLE_CAT=" + catalogName + "\n"
+ "TABLE_CAT=" + catalogName + "2\n";
break;
case REMOTE_XMLA:
default:
expected = "TABLE_CAT=" + catalogName + "\n";
break;
}
TestContext.assertEqualsVerbose(expected, s);
}
public void testDatabaseMetaDataGetSchemas() throws SQLException {
String s = checkResultSet(
olapDatabaseMetaData.getSchemas(),
SCHEMAS_COLUMN_NAMES);
final String expected;
switch (tester.getFlavor()) {
case XMLA:
// XMLA test uses dummy duplicate schema to make sure that we
// get all schemas
expected =
"TABLE_SCHEM=FoodMart, TABLE_CAT=" + catalogName + "\n"
+ "TABLE_SCHEM=FoodMart, TABLE_CAT=" + catalogName + "2\n";
break;
case REMOTE_XMLA:
default:
expected = "TABLE_SCHEM=FoodMart, TABLE_CAT=" + catalogName + "\n";
break;
}
TestContext.assertEqualsVerbose(expected, s);
}
public void testDatabaseMetaDataGetLiterals() throws SQLException {
String s = checkResultSet(
olapDatabaseMetaData.getLiterals(),
LITERALS_COLUMN_NAMES);
assertContains("LITERAL_NAME=DBLITERAL_QUOTE, LITERAL_VALUE=[, ", s);
}
public void testDatabaseMetaDataGetDatabaseProperties()
throws SQLException
{
String s = checkResultSet(
olapDatabaseMetaData.getDatabaseProperties(
dataSourceName, propertyNamePattern),
DATABASE_PROPERTIES_COLUMN_NAMES);
assertContains("PROPERTY_NAME=ProviderName, ", s);
}
public void testDatabaseMetaDataGetProperties() throws SQLException {
String s = checkResultSet(
olapDatabaseMetaData.getProperties(
catalogName, null, null, null, null, null, null, null),
PROPERTIES_COLUMN_NAMES);
assertContains(
"CATALOG_NAME=" + catalogName
+ ", SCHEMA_NAME=FoodMart, CUBE_NAME=Warehouse and Sales, DIMENSION_UNIQUE_NAME=[Store], HIERARCHY_UNIQUE_NAME=[Store], LEVEL_UNIQUE_NAME=[Store].[Store Name], MEMBER_UNIQUE_NAME=null, PROPERTY_NAME=Frozen Sqft, PROPERTY_CAPTION=Frozen Sqft, PROPERTY_TYPE=1, DATA_TYPE=5, PROPERTY_CONTENT_TYPE=0, DESCRIPTION=Warehouse and Sales Cube - Store Hierarchy - Store Name Level - Frozen Sqft Property",
s);
assertEquals(s, 66, linecount(s));
s = checkResultSet(
olapDatabaseMetaData.getProperties(
catalogName, "FoodMart", "Sales",
null, null, "[Store].[Store Name]",
null, null),
PROPERTIES_COLUMN_NAMES);
assertContains(
"CATALOG_NAME=" + catalogName
+ ", SCHEMA_NAME=FoodMart, CUBE_NAME=Sales, DIMENSION_UNIQUE_NAME=[Store], HIERARCHY_UNIQUE_NAME=[Store], LEVEL_UNIQUE_NAME=[Store].[Store Name], MEMBER_UNIQUE_NAME=null, PROPERTY_NAME=Has coffee bar, PROPERTY_CAPTION=Has coffee bar, PROPERTY_TYPE=1, DATA_TYPE=11, PROPERTY_CONTENT_TYPE=0, DESCRIPTION=Sales Cube - Store Hierarchy - Store Name Level - Has coffee bar Property",
s);
assertNotContains(
"CATALOG_NAME=" + catalogName
+ ", SCHEMA_NAME=FoodMart, CUBE_NAME=Warehouse and Sales, ",
s);
assertEquals(8, linecount(s));
}
public void testDatabaseMetaDataGetMdxKeywords() throws SQLException {
String keywords = olapDatabaseMetaData.getMdxKeywords();
assertNotNull(keywords);
assertContains(",From,", keywords);
}
public void testDatabaseMetaDataGetCubes() throws SQLException {
String s = checkResultSet(
olapDatabaseMetaData.getCubes(
catalogName,
null,
null),
CUBE_COLUMN_NAMES);
assertContains(
"CATALOG_NAME=" + catalogName
+ ", SCHEMA_NAME=FoodMart, CUBE_NAME=Sales, ",
s);
final int lineCount = linecount(s);
// Null catalog specified in metadata request, but connection has a
// catalog. Should return all cubes, ignoring the connection's catalog.
olapDatabaseMetaData.getConnection().setCatalog(catalogName);
s = checkResultSet(
olapDatabaseMetaData.getCubes(
null,
null,
null),
CUBE_COLUMN_NAMES);
assertContains(
"CATALOG_NAME=" + catalogName
+ ", SCHEMA_NAME=FoodMart, CUBE_NAME=Sales, ",
s);
final int lineCount3 = linecount(s);
if (tester.getFlavor() == TestContext.Tester.Flavor.XMLA) {
assertEquals(lineCount * 2, lineCount3);
}
s = checkResultSet(
olapDatabaseMetaData.getCubes(
"FoodMart",
"FoodMart",
"Sales"),
CUBE_COLUMN_NAMES);
switch (testContext.getTester().getFlavor()) {
case MONDRIAN:
assertTrue(s.contains(", IS_DRILLTHROUGH_ENABLED=true"));
break;
case XMLA:
case REMOTE_XMLA:
assertTrue(s.contains(", IS_DRILLTHROUGH_ENABLED=false"));
assertFalse(s.contains(", IS_DRILLTHROUGH_ENABLED=true"));
break;
default:
throw new RuntimeException("Unknown tester type.");
}
// If we ask for 'Warehouse and Sales' cube we should get it, but
// nothing else.
s = checkResultSet(
olapDatabaseMetaData.getCubes(
catalogName,
null,
"Warehouse and Sales"),
CUBE_COLUMN_NAMES);
assertContains(", CUBE_NAME=Warehouse and Sales,", s);
assertNotContains(", CUBE_NAME=Warehouse,", s);
// If we ask for a pattern, should get multiple hits.
s = checkResultSet(
olapDatabaseMetaData.getCubes(
catalogName,
null,
"Warehouse%"),
CUBE_COLUMN_NAMES);
assertTrue(s.contains(", CUBE_NAME=Warehouse and Sales"));
assertTrue(s.contains(", CUBE_NAME=Warehouse"));
assertFalse(s.contains(", CUBE_NAME=Sales"));
}
public void testDatabaseMetaDataGetDimensions() throws SQLException {
String s = checkResultSet(
olapDatabaseMetaData.getDimensions(
catalogName, null, null, null),
DIMENSIONS_COLUMN_NAMES);
assertContains(
"CATALOG_NAME=" + catalogName
+ ", SCHEMA_NAME=FoodMart, CUBE_NAME=Sales, DIMENSION_NAME=Education Level, DIMENSION_UNIQUE_NAME=[Education Level], DIMENSION_GUID=null, DIMENSION_CAPTION=Education Level, DIMENSION_ORDINAL=9, DIMENSION_TYPE=3, DIMENSION_CARDINALITY=6, DEFAULT_HIERARCHY=[Education Level], DESCRIPTION=Sales Cube - Education Level Dimension, IS_VIRTUAL=false, IS_READWRITE=false, DIMENSION_UNIQUE_SETTINGS=0, DIMENSION_MASTER_UNIQUE_NAME=null, DIMENSION_IS_VISIBLE=true",
s);
assertEquals(68, linecount(s));
}
public void testDatabaseMetaDataGetFunctions() throws SQLException {
String s = checkResultSet(
olapDatabaseMetaData.getOlapFunctions(null),
FUNCTIONS_COLUMN_NAMES);
assertContains(
"FUNCTION_NAME=Name, DESCRIPTION=Returns the name of a member., PARAMETER_LIST=Member, RETURN_TYPE=8, ORIGIN=1, INTERFACE_NAME=, LIBRARY_NAME=null, CAPTION=Name",
s);
// Mondrian has 361 functions (as of 2008/1/23)
final int functionCount = linecount(s);
assertTrue(functionCount + " functions", functionCount > 360);
// Mondrian has 13 variants of the Ascendants and Descendants functions
s = checkResultSet(
olapDatabaseMetaData.getOlapFunctions("%scendants"),
FUNCTIONS_COLUMN_NAMES);
assertEquals(s, 13, linecount(s));
}
public void testDatabaseMetaDataGetHierarchies() throws SQLException {
String s = checkResultSet(
olapDatabaseMetaData.getHierarchies(
catalogName, null, null, null, null),
HIERARCHIES_COLUMN_NAMES);
assertContains(
"CATALOG_NAME=" + catalogName
+ ", SCHEMA_NAME=FoodMart, CUBE_NAME=HR, DIMENSION_UNIQUE_NAME=[Employees], HIERARCHY_NAME=Employees, HIERARCHY_UNIQUE_NAME=[Employees], HIERARCHY_GUID=null, HIERARCHY_CAPTION=Employees, DIMENSION_TYPE=3, HIERARCHY_CARDINALITY=1156, DEFAULT_MEMBER=[Employees].[All Employees], ALL_MEMBER=[Employees].[All Employees], DESCRIPTION=HR Cube - Employees Hierarchy, STRUCTURE=0, IS_VIRTUAL=false, IS_READWRITE=false, DIMENSION_UNIQUE_SETTINGS=0, DIMENSION_IS_VISIBLE=true, HIERARCHY_IS_VISIBLE=true, HIERARCHY_ORDINAL=7, DIMENSION_IS_SHARED=true, PARENT_CHILD=true",
s);
s = checkResultSet(
olapDatabaseMetaData.getHierarchies(
catalogName, null, "Sales", null, "Store"),
HIERARCHIES_COLUMN_NAMES);
TestContext.assertEqualsVerbose(
"CATALOG_NAME=" + catalogName
+ ", SCHEMA_NAME=FoodMart, CUBE_NAME=Sales, DIMENSION_UNIQUE_NAME=[Store], HIERARCHY_NAME=Store, HIERARCHY_UNIQUE_NAME=[Store], HIERARCHY_GUID=null, HIERARCHY_CAPTION=Store, DIMENSION_TYPE=3, HIERARCHY_CARDINALITY=63, DEFAULT_MEMBER=[Store].[All Stores], ALL_MEMBER=[Store].[All Stores], DESCRIPTION=Sales Cube - Store Hierarchy, STRUCTURE=0, IS_VIRTUAL=false, IS_READWRITE=false, DIMENSION_UNIQUE_SETTINGS=0, DIMENSION_IS_VISIBLE=true, HIERARCHY_IS_VISIBLE=true, HIERARCHY_ORDINAL=1, DIMENSION_IS_SHARED=true, PARENT_CHILD=false\n",
s);
// With dimension unique name (bug 2527862).
s = checkResultSet(
olapDatabaseMetaData.getHierarchies(
catalogName, null, "Sales", "[Store]", null),
HIERARCHIES_COLUMN_NAMES);
TestContext.assertEqualsVerbose(
"CATALOG_NAME=" + catalogName
+ ", SCHEMA_NAME=FoodMart, CUBE_NAME=Sales, DIMENSION_UNIQUE_NAME=[Store], HIERARCHY_NAME=Store, HIERARCHY_UNIQUE_NAME=[Store], HIERARCHY_GUID=null, HIERARCHY_CAPTION=Store, DIMENSION_TYPE=3, HIERARCHY_CARDINALITY=63, DEFAULT_MEMBER=[Store].[All Stores], ALL_MEMBER=[Store].[All Stores], DESCRIPTION=Sales Cube - Store Hierarchy, STRUCTURE=0, IS_VIRTUAL=false, IS_READWRITE=false, DIMENSION_UNIQUE_SETTINGS=0, DIMENSION_IS_VISIBLE=true, HIERARCHY_IS_VISIBLE=true, HIERARCHY_ORDINAL=1, DIMENSION_IS_SHARED=true, PARENT_CHILD=false\n",
s);
}
public void testDatabaseMetaDataGetLevels() throws SQLException {
String s = checkResultSet(
olapDatabaseMetaData.getLevels(
catalogName, null, null, null, null, null),
LEVELS_COLUMN_NAMES);
assertContains(
"CATALOG_NAME=FoodMart, SCHEMA_NAME=FoodMart, CUBE_NAME=Sales, DIMENSION_UNIQUE_NAME=[Measures], HIERARCHY_UNIQUE_NAME=[Measures], LEVEL_NAME=MeasuresLevel, LEVEL_UNIQUE_NAME=[Measures].[MeasuresLevel], LEVEL_GUID=null, LEVEL_CAPTION=MeasuresLevel, LEVEL_NUMBER=0, LEVEL_CARDINALITY=9, LEVEL_TYPE=0, CUSTOM_ROLLUP_SETTINGS=0, LEVEL_UNIQUE_SETTINGS=0, LEVEL_IS_VISIBLE=true, DESCRIPTION=Sales Cube - Measures Hierarchy - MeasuresLevel Level",
s);
s = checkResultSet(
olapDatabaseMetaData.getLevels(
catalogName, null, "Sales", null, "[Store]", null),
LEVELS_COLUMN_NAMES);
assertEquals(s, 5, linecount(s));
}
public void testDatabaseMetaDataGetLiterals2() throws SQLException {
String s = checkResultSet(
olapDatabaseMetaData.getLiterals(),
LITERALS_COLUMN_NAMES);
assertContains(
"LITERAL_NAME=DBLITERAL_QUOTE, LITERAL_VALUE=[, LITERAL_INVALID_CHARS=null, LITERAL_INVALID_STARTING_CHARS=null, LITERAL_MAX_LENGTH=-1",
s);
assertEquals(17, linecount(s));
}
public void testDatabaseMetaDataGetMeasures() throws SQLException {
String s = checkResultSet(
olapDatabaseMetaData.getMeasures(
catalogName, null, null, null, null),
MEASURES_COLUMN_NAMES);
assertContains(
"CATALOG_NAME=" + catalogName
+ ", SCHEMA_NAME=FoodMart, CUBE_NAME=Sales, MEASURE_NAME=Profit, MEASURE_UNIQUE_NAME=[Measures].[Profit], MEASURE_CAPTION=Profit, MEASURE_GUID=null, MEASURE_AGGREGATOR=127, DATA_TYPE=130, MEASURE_IS_VISIBLE=true, LEVELS_LIST=null, DESCRIPTION=Sales Cube - Profit Member",
s);
// wildcard match
s = checkResultSet(
olapDatabaseMetaData.getMeasures(
catalogName, null, "Sales", "%Sales", null),
MEASURES_COLUMN_NAMES);
assertEquals(s, 3, linecount(s));
// wildcard match
s = checkResultSet(
olapDatabaseMetaData.getMeasures(
catalogName, null, "Sales", null, "[Measures].[Unit Sales]"),
MEASURES_COLUMN_NAMES);
assertEquals(s, 1, linecount(s));
}
public void testDatabaseMetaDataGetMembers() throws SQLException {
String s = checkResultSet(
olapDatabaseMetaData.getMembers(
catalogName, "FoodMart", "Sales", null, "[Gender]", null, null,
null),
MEMBERS_COLUMN_NAMES);
TestContext.assertEqualsVerbose(
"CATALOG_NAME=" + catalogName
+ ", SCHEMA_NAME=FoodMart, CUBE_NAME=Sales, DIMENSION_UNIQUE_NAME=[Gender], HIERARCHY_UNIQUE_NAME=[Gender], LEVEL_UNIQUE_NAME=[Gender].[(All)], LEVEL_NUMBER=0, MEMBER_ORDINAL=0, MEMBER_NAME=All Gender, MEMBER_UNIQUE_NAME=[Gender].[All Gender], MEMBER_TYPE=2, MEMBER_GUID=null, MEMBER_CAPTION=All Gender, CHILDREN_CARDINALITY=2, PARENT_LEVEL=0, PARENT_UNIQUE_NAME=null, PARENT_COUNT=0, TREE_OP=null, DEPTH=0\n"
+ "CATALOG_NAME=" + catalogName
+ ", SCHEMA_NAME=FoodMart, CUBE_NAME=Sales, DIMENSION_UNIQUE_NAME=[Gender], HIERARCHY_UNIQUE_NAME=[Gender], LEVEL_UNIQUE_NAME=[Gender].[Gender], LEVEL_NUMBER=1, MEMBER_ORDINAL=1, MEMBER_NAME=F, MEMBER_UNIQUE_NAME=[Gender].[F], MEMBER_TYPE=1, MEMBER_GUID=null, MEMBER_CAPTION=F, CHILDREN_CARDINALITY=0, PARENT_LEVEL=0, PARENT_UNIQUE_NAME=[Gender].[All Gender], PARENT_COUNT=1, TREE_OP=null, DEPTH=1\n"
+ "CATALOG_NAME=" + catalogName
+ ", SCHEMA_NAME=FoodMart, CUBE_NAME=Sales, DIMENSION_UNIQUE_NAME=[Gender], HIERARCHY_UNIQUE_NAME=[Gender], LEVEL_UNIQUE_NAME=[Gender].[Gender], LEVEL_NUMBER=1, MEMBER_ORDINAL=2, MEMBER_NAME=M, MEMBER_UNIQUE_NAME=[Gender].[M], MEMBER_TYPE=1, MEMBER_GUID=null, MEMBER_CAPTION=M, CHILDREN_CARDINALITY=0, PARENT_LEVEL=0, PARENT_UNIQUE_NAME=[Gender].[All Gender], PARENT_COUNT=1, TREE_OP=null, DEPTH=1\n",
s);
// by member unique name
s = checkResultSet(
olapDatabaseMetaData.getMembers(
catalogName, "FoodMart", "Sales", null, null, null,
"[Time].[1997].[Q2].[4]", null),
MEMBERS_COLUMN_NAMES);
TestContext.assertEqualsVerbose(
"CATALOG_NAME=" + catalogName
+ ", SCHEMA_NAME=FoodMart, CUBE_NAME=Sales, DIMENSION_UNIQUE_NAME=[Time], HIERARCHY_UNIQUE_NAME=[Time], LEVEL_UNIQUE_NAME=[Time].[Month], LEVEL_NUMBER=2, MEMBER_ORDINAL=6, MEMBER_NAME=4, MEMBER_UNIQUE_NAME=[Time].[1997].[Q2].[4], MEMBER_TYPE=1, MEMBER_GUID=null, MEMBER_CAPTION=4, CHILDREN_CARDINALITY=0, PARENT_LEVEL=1, PARENT_UNIQUE_NAME=[Time].[1997].[Q2], PARENT_COUNT=1, TREE_OP=null, DEPTH=2\n",
s);
// with treeop
s = checkResultSet(
olapDatabaseMetaData.getMembers(
catalogName, "FoodMart", "Sales", null, null, null,
"[Customers].[USA].[CA]",
Olap4jUtil.enumSetOf(
Member.TreeOp.ANCESTORS, Member.TreeOp.SIBLINGS)),
MEMBERS_COLUMN_NAMES);
switch (tester.getFlavor()) {
case MONDRIAN:
// TODO: fix mondrian driver so that members are returned sorted
// by level depth
TestContext.assertEqualsVerbose(
"CATALOG_NAME=" + catalogName
+ ", SCHEMA_NAME=FoodMart, CUBE_NAME=Sales, DIMENSION_UNIQUE_NAME=[Customers], HIERARCHY_UNIQUE_NAME=[Customers], LEVEL_UNIQUE_NAME=[Customers].[State Province], LEVEL_NUMBER=2, MEMBER_ORDINAL=7235, MEMBER_NAME=OR, MEMBER_UNIQUE_NAME=[Customers].[USA].[OR], MEMBER_TYPE=1, MEMBER_GUID=null, MEMBER_CAPTION=OR, CHILDREN_CARDINALITY=11, PARENT_LEVEL=1, PARENT_UNIQUE_NAME=[Customers].[USA], PARENT_COUNT=1, TREE_OP=null, DEPTH=2\n"
+ "CATALOG_NAME=" + catalogName
+ ", SCHEMA_NAME=FoodMart, CUBE_NAME=Sales, DIMENSION_UNIQUE_NAME=[Customers], HIERARCHY_UNIQUE_NAME=[Customers], LEVEL_UNIQUE_NAME=[Customers].[State Province], LEVEL_NUMBER=2, MEMBER_ORDINAL=8298, MEMBER_NAME=WA, MEMBER_UNIQUE_NAME=[Customers].[USA].[WA], MEMBER_TYPE=1, MEMBER_GUID=null, MEMBER_CAPTION=WA, CHILDREN_CARDINALITY=22, PARENT_LEVEL=1, PARENT_UNIQUE_NAME=[Customers].[USA], PARENT_COUNT=1, TREE_OP=null, DEPTH=2\n"
+ "CATALOG_NAME=" + catalogName
+ ", SCHEMA_NAME=FoodMart, CUBE_NAME=Sales, DIMENSION_UNIQUE_NAME=[Customers], HIERARCHY_UNIQUE_NAME=[Customers], LEVEL_UNIQUE_NAME=[Customers].[Country], LEVEL_NUMBER=1, MEMBER_ORDINAL=2966, MEMBER_NAME=USA, MEMBER_UNIQUE_NAME=[Customers].[USA], MEMBER_TYPE=1, MEMBER_GUID=null, MEMBER_CAPTION=USA, CHILDREN_CARDINALITY=3, PARENT_LEVEL=0, PARENT_UNIQUE_NAME=[Customers].[All Customers], PARENT_COUNT=1, TREE_OP=null, DEPTH=1\n"
+ "CATALOG_NAME=" + catalogName
+ ", SCHEMA_NAME=FoodMart, CUBE_NAME=Sales, DIMENSION_UNIQUE_NAME=[Customers], HIERARCHY_UNIQUE_NAME=[Customers], LEVEL_UNIQUE_NAME=[Customers].[(All)], LEVEL_NUMBER=0, MEMBER_ORDINAL=0, MEMBER_NAME=All Customers, MEMBER_UNIQUE_NAME=[Customers].[All Customers], MEMBER_TYPE=2, MEMBER_GUID=null, MEMBER_CAPTION=All Customers, CHILDREN_CARDINALITY=3, PARENT_LEVEL=0, PARENT_UNIQUE_NAME=null, PARENT_COUNT=0, TREE_OP=null, DEPTH=0\n",
s);
break;
default:
TestContext.assertEqualsVerbose(
"CATALOG_NAME=" + catalogName
+ ", SCHEMA_NAME=FoodMart, CUBE_NAME=Sales, DIMENSION_UNIQUE_NAME=[Customers], HIERARCHY_UNIQUE_NAME=[Customers], LEVEL_UNIQUE_NAME=[Customers].[(All)], LEVEL_NUMBER=0, MEMBER_ORDINAL=0, MEMBER_NAME=All Customers, MEMBER_UNIQUE_NAME=[Customers].[All Customers], MEMBER_TYPE=2, MEMBER_GUID=null, MEMBER_CAPTION=All Customers, CHILDREN_CARDINALITY=3, PARENT_LEVEL=0, PARENT_UNIQUE_NAME=null, PARENT_COUNT=0, TREE_OP=null, DEPTH=0\n"
+ "CATALOG_NAME=" + catalogName
+ ", SCHEMA_NAME=FoodMart, CUBE_NAME=Sales, DIMENSION_UNIQUE_NAME=[Customers], HIERARCHY_UNIQUE_NAME=[Customers], LEVEL_UNIQUE_NAME=[Customers].[Country], LEVEL_NUMBER=1, MEMBER_ORDINAL=2966, MEMBER_NAME=USA, MEMBER_UNIQUE_NAME=[Customers].[USA], MEMBER_TYPE=1, MEMBER_GUID=null, MEMBER_CAPTION=USA, CHILDREN_CARDINALITY=3, PARENT_LEVEL=0, PARENT_UNIQUE_NAME=[Customers].[All Customers], PARENT_COUNT=1, TREE_OP=null, DEPTH=1\n"
+ "CATALOG_NAME=" + catalogName
+ ", SCHEMA_NAME=FoodMart, CUBE_NAME=Sales, DIMENSION_UNIQUE_NAME=[Customers], HIERARCHY_UNIQUE_NAME=[Customers], LEVEL_UNIQUE_NAME=[Customers].[State Province], LEVEL_NUMBER=2, MEMBER_ORDINAL=7235, MEMBER_NAME=OR, MEMBER_UNIQUE_NAME=[Customers].[USA].[OR], MEMBER_TYPE=1, MEMBER_GUID=null, MEMBER_CAPTION=OR, CHILDREN_CARDINALITY=11, PARENT_LEVEL=1, PARENT_UNIQUE_NAME=[Customers].[USA], PARENT_COUNT=1, TREE_OP=null, DEPTH=2\n"
+ "CATALOG_NAME=" + catalogName
+ ", SCHEMA_NAME=FoodMart, CUBE_NAME=Sales, DIMENSION_UNIQUE_NAME=[Customers], HIERARCHY_UNIQUE_NAME=[Customers], LEVEL_UNIQUE_NAME=[Customers].[State Province], LEVEL_NUMBER=2, MEMBER_ORDINAL=8298, MEMBER_NAME=WA, MEMBER_UNIQUE_NAME=[Customers].[USA].[WA], MEMBER_TYPE=1, MEMBER_GUID=null, MEMBER_CAPTION=WA, CHILDREN_CARDINALITY=22, PARENT_LEVEL=1, PARENT_UNIQUE_NAME=[Customers].[USA], PARENT_COUNT=1, TREE_OP=null, DEPTH=2\n",
s);
break;
}
}
public void testDatabaseMetaDataGetSets() throws SQLException {
String s = checkResultSet(
olapDatabaseMetaData.getSets(
catalogName, null, null, null),
SETS_COLUMN_NAMES);
TestContext.assertEqualsVerbose(
"CATALOG_NAME=" + catalogName
+ ", SCHEMA_NAME=FoodMart, CUBE_NAME=Warehouse, SET_NAME=[Top Sellers], SCOPE=1\n",
s);
s = checkResultSet(
olapDatabaseMetaData.getSets(
catalogName, null, null, "non existent set"),
SETS_COLUMN_NAMES);
TestContext.assertEqualsVerbose("", s);
}
// todo: More tests required for other methods on DatabaseMetaData
private String checkResultSet(
ResultSet resultSet,
List columnNames) throws SQLException
{
ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
final int columnCount = resultSetMetaData.getColumnCount();
List rsColumnNames = new ArrayList();
if (columnNames != null) {
for (int k = 0; k < columnCount; k++) {
rsColumnNames.add(
resultSetMetaData.getColumnName(k + 1));
}
final HashSet set = new HashSet(columnNames);
set.removeAll(rsColumnNames);
assertTrue("Expected columns not found: " + set, set.isEmpty());
}
assertNotNull(resultSet);
int k = 0;
StringBuilder buf = new StringBuilder();
while (resultSet.next()) {
++k;
for (int i = 0; i < columnCount; i++) {
if (i > 0) {
buf.append(", ");
}
String s = resultSet.getString(i + 1);
buf.append(resultSetMetaData.getColumnName(i + 1))
.append('=')
.append(s);
}
buf.append(NL);
}
assertTrue(k >= 0);
assertTrue(resultSet.isAfterLast());
return buf.toString();
}
}
// End MetadataTest.java
olap4j-1.0.1.500/testsrc/org/olap4j/driver/ 0000755 0001750 0001750 00000000000 11421322444 020040 5 ustar drazzib drazzib olap4j-1.0.1.500/testsrc/org/olap4j/driver/xmla/ 0000755 0001750 0001750 00000000000 11421322444 021001 5 ustar drazzib drazzib olap4j-1.0.1.500/testsrc/org/olap4j/driver/xmla/cache/ 0000755 0001750 0001750 00000000000 11651266474 022063 5 ustar drazzib drazzib olap4j-1.0.1.500/testsrc/org/olap4j/driver/xmla/cache/XmlaShaEncoderTest.java 0000644 0001750 0001750 00000004534 11707254770 026427 0 ustar drazzib drazzib /*
// $Id: XmlaShaEncoderTest.java 482 2012-01-05 23:27:27Z jhyde $
//
// Licensed to Julian Hyde under one or more contributor license
// agreements. See the NOTICE file distributed with this work for
// additional information regarding copyright ownership.
//
// Julian Hyde licenses this file to you 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.olap4j.driver.xmla.cache;
import junit.framework.TestCase;
/**
* Test for {@link org.olap4j.driver.xmla.cache.XmlaOlap4jShaEncoder}.
*
* @author Luc Boudreau
* @version $Id: XmlaShaEncoderTest.java 482 2012-01-05 23:27:27Z jhyde $
*/
public class XmlaShaEncoderTest extends TestCase {
private static final String message_1 =
"This is my nifty message number 1";
private static final String message_2 =
"This is my nifty message number 2";
private static final String message_1_encoded =
"0821347e66167004f9aba546ae9e61ec5b471e59";
private static final String message_2_encoded =
"95dfe200baddc69e2f53e78feeac445a0bdbb4e7";
public void testSimpleEncoding() throws Exception {
String encoded = XmlaOlap4jShaEncoder.encodeSha1(message_1);
assertEquals(message_1_encoded, encoded);
}
public void testDoubleEncoding() throws Exception {
String encoded = XmlaOlap4jShaEncoder.encodeSha1(message_1);
assertEquals(message_1_encoded, encoded);
String encoded2 = XmlaOlap4jShaEncoder.encodeSha1(message_2);
assertEquals(message_2_encoded, encoded2);
assertFalse(encoded.equals(encoded2));
String encoded3 = XmlaOlap4jShaEncoder.encodeSha1(message_1);
assertEquals(message_1_encoded, encoded3);
String encoded4 = XmlaOlap4jShaEncoder.encodeSha1(message_1);
assertEquals(message_1_encoded, encoded4);
assertEquals(encoded3, encoded4);
}
}
// End XmlaShaEncoderTest.java
olap4j-1.0.1.500/testsrc/org/olap4j/driver/xmla/cache/XmlaDatabaseCache.java 0000644 0001750 0001750 00000015204 11707254770 026200 0 ustar drazzib drazzib /*
// $Id: XmlaDatabaseCache.java 483 2012-01-05 23:43:18Z jhyde $
//
// Licensed to Julian Hyde under one or more contributor license
// agreements. See the NOTICE file distributed with this work for
// additional information regarding copyright ownership.
//
// Julian Hyde licenses this file to you 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.olap4j.driver.xmla.cache;
import java.net.URL;
import java.sql.*;
import java.util.Map;
/**
* This mock server cache is only used to save and load
* runs of the XMLA driver as a database table.
*
* @see Properties
* @author LBoudreau
* @version $Id: XmlaDatabaseCache.java 483 2012-01-05 23:43:18Z jhyde $
*/
public class XmlaDatabaseCache implements XmlaOlap4jCache {
private static Connection connection = null;
private static final String CACHE_IDENT = "Panda steak!";
private Map props;
public static enum Properties {
/**
* Jdbc driver class to use. Defaults to
* org.hsqldb.jdbcDriver
*/
JDBC_DRIVER("org.hsqldb.jdbcDriver"),
/**
* Jdbc url to use. Defaults to
* jdbc:hsqldb:file:xmla-cache/xmla-cache-hsqldb
*/
JDBC_URL("jdbc:hsqldb:file:xmla-cache/xmla-cache-hsqldb"),
/**
* Jdbc username to use. Defaults to
* sa
*/
JDBC_USER("sa"),
/**
* Jdbc password to use. Defaults to
* an empty string
*/
JDBC_PASS(""),
/**
* Query to execute to insert elements. Defaults to
* insert into "cache" ("request", "response") values(?,?);
*/
QUERY_INSERT(
"insert into \"cache\"(\"request\", \"response\") values(?,?);"),
/**
* Query to execute to select elements. Defaults to
* select "request", "response" from "cache"
* where "request" = ?;
*/
QUERY_SELECT(
"select \"request\", \"response\" from \"cache\" where"
+ "\"request\" = ?;"),
/**
* Query to initialize the cache. Can be a batch of SQL. Defaults to
* create table "cache" ("request"
* varchar, "response" varchar);
*/
QUERY_INIT_CACHE(
"drop table \"cache\" if exists; create table \"cache\" (\"request\" varchar, \"response\" varchar);"),
/**
* Should the cache insert requests/responses.
* defaults to false.
*/
RECORD("false"),
/**
* Should the cache return cached responses.
* defaults to false.
*/
PLAY("false"),
/**
* Should the cache execute Properties.QUERY_INIT_CACHE.
* defaults to false.
*/
INIT("false");
private final String defaultValue;
private Properties(String defaultValue) {
this.defaultValue = defaultValue;
}
String getValueOrDefault(Map props) {
if (props.containsKey(this.name())) {
return props.get(name());
} else {
return this.defaultValue;
}
}
}
public void flushCache() {
// no op
}
public byte[] get(String id, URL url, byte[] request)
throws XmlaOlap4jInvalidStateException
{
if (!Boolean.valueOf(Properties.PLAY.getValueOrDefault(props))) {
return null;
}
try {
final PreparedStatement stm =
connection.prepareStatement(
Properties.QUERY_SELECT.getValueOrDefault(props));
try {
stm.setString(1, new String(request));
stm.execute();
ResultSet rs = stm.getResultSet();
if (rs.next()) {
return rs.getString(2).getBytes();
} else {
return null;
}
} finally {
stm.close();
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public void put(String id, URL url, byte[] request, byte[] response)
throws XmlaOlap4jInvalidStateException
{
if (!Boolean.valueOf(Properties.RECORD.getValueOrDefault(props))) {
return;
}
try {
final PreparedStatement stm =
connection.prepareStatement(
Properties.QUERY_INSERT.getValueOrDefault(props));
try {
stm.setString(1, new String(request));
stm.setString(2, new String(response));
stm.execute();
} finally {
stm.close();
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public String setParameters(
Map config,
Map props)
{
this.props = props;
if (connection == null) {
try {
Class.forName(Properties.JDBC_DRIVER.getValueOrDefault(props));
connection =
DriverManager.getConnection(
Properties.JDBC_URL.getValueOrDefault(props),
Properties.JDBC_USER.getValueOrDefault(props),
Properties.JDBC_PASS.getValueOrDefault(props));
if (Boolean.valueOf(
Properties.INIT.getValueOrDefault(props)))
{
final Statement stm = connection.createStatement();
try {
stm.addBatch(
Properties.QUERY_INIT_CACHE
.getValueOrDefault(props));
stm.executeBatch();
} catch (SQLException e) {
// no op
} finally {
stm.close();
}
flushCache();
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
return CACHE_IDENT;
}
}
// End XmlaDatabaseCache.java
olap4j-1.0.1.500/testsrc/org/olap4j/driver/xmla/proxy/ 0000755 0001750 0001750 00000000000 11542614630 022167 5 ustar drazzib drazzib olap4j-1.0.1.500/testsrc/org/olap4j/driver/xmla/proxy/XmlaCachedProxyTest.java 0000644 0001750 0001750 00000030431 11707254770 026736 0 ustar drazzib drazzib /*
// $Id: XmlaCachedProxyTest.java 482 2012-01-05 23:27:27Z jhyde $
//
// Licensed to Julian Hyde under one or more contributor license
// agreements. See the NOTICE file distributed with this work for
// additional information regarding copyright ownership.
//
// Julian Hyde licenses this file to you 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.olap4j.driver.xmla.proxy;
import org.olap4j.OlapException;
import org.olap4j.driver.xmla.XmlaOlap4jDriver;
import org.olap4j.driver.xmla.cache.XmlaOlap4jNamedMemoryCache;
import junit.framework.TestCase;
import java.util.HashMap;
import java.util.Map;
/**
* Tests both the CachedProxy implementation (HttpProxy) and the
* IXmlaOlap4jCache implementation (XmlaOlap4jNamedMemoryCache).
*
* @author Luc Boudreau
* @version $Id: XmlaCachedProxyTest.java 482 2012-01-05 23:27:27Z jhyde $
*/
public class XmlaCachedProxyTest extends TestCase {
final XmlaOlap4jDriver dummyDriver = new XmlaOlap4jDriver() {};
/**
*
Tests if a simple and valid configuration can be used.
* @throws Exception If the test fails.
*/
public void testCacheConfig() throws Exception
{
XmlaOlap4jCachedProxy proxy = new XmlaOlap4jHttpProxy(dummyDriver);
Map driverParameters = new HashMap();
Map cacheProperties = new HashMap();
driverParameters.put(
XmlaOlap4jDriver.Property.SERVER.name(),
"http://example.com");
driverParameters.put(
XmlaOlap4jDriver.Property.CATALOG.name(),
"CatalogName");
driverParameters.put(
XmlaOlap4jDriver.Property.CACHE.name(),
"org.olap4j.driver.xmla.cache.XmlaOlap4jNamedMemoryCache");
cacheProperties.put(
XmlaOlap4jNamedMemoryCache.Property.NAME.name(),
"testCacheConfig");
cacheProperties.put(
XmlaOlap4jNamedMemoryCache.Property.MODE.name(),
"LFU");
cacheProperties.put(
XmlaOlap4jNamedMemoryCache.Property.TIMEOUT.name(),
"30");
cacheProperties.put(
XmlaOlap4jNamedMemoryCache.Property.SIZE.name(),
"50");
proxy.setCache(driverParameters, cacheProperties);
}
/**
* Makes sure that the cache mode value is validated.
* @throws Exception If the test fails.
*/
public void testCacheModeError() throws Exception {
XmlaOlap4jCachedProxy proxy = new XmlaOlap4jHttpProxy(dummyDriver);
Map driverParameters = new HashMap();
Map cacheProperties = new HashMap();
driverParameters.put(
XmlaOlap4jDriver.Property.SERVER.name(),
"http://example.com");
driverParameters.put(
XmlaOlap4jDriver.Property.CATALOG.name(),
"CatalogName");
driverParameters.put(
XmlaOlap4jDriver.Property.CACHE.name(),
"org.olap4j.driver.xmla.cache.XmlaOlap4jNamedMemoryCache");
cacheProperties.put(
XmlaOlap4jNamedMemoryCache.Property.NAME.name(),
"testCacheModeError");
cacheProperties.put(
XmlaOlap4jNamedMemoryCache.Property.MODE.name(),
"ERRONOUS VALUE MWAHAHAHAHA");
cacheProperties.put(
XmlaOlap4jNamedMemoryCache.Property.TIMEOUT.name(),
"30");
cacheProperties.put(
XmlaOlap4jNamedMemoryCache.Property.SIZE.name(),
"50");
try {
proxy.setCache(driverParameters, cacheProperties);
} catch (OlapException e) {
return;
}
fail("The cache mode is not validated properly");
}
/**
* Makes sure that the cache timeout value is validated.
* @throws Exception If the test fails.
*/
public void testCacheTimeoutError() throws Exception
{
XmlaOlap4jCachedProxy proxy = new XmlaOlap4jHttpProxy(dummyDriver);
Map driverParameters = new HashMap();
Map cacheProperties = new HashMap();
driverParameters.put(
XmlaOlap4jDriver.Property.SERVER.name(),
"http://example.com");
driverParameters.put(
XmlaOlap4jDriver.Property.CATALOG.name(),
"CatalogName");
driverParameters.put(
XmlaOlap4jDriver.Property.CACHE.name(),
"org.olap4j.driver.xmla.cache.XmlaOlap4jNamedMemoryCache");
cacheProperties.put(
XmlaOlap4jNamedMemoryCache.Property.NAME.name(),
"testCacheTimeoutError");
cacheProperties.put(
XmlaOlap4jNamedMemoryCache.Property.MODE.name(),
"LFU");
cacheProperties.put(
XmlaOlap4jNamedMemoryCache.Property.TIMEOUT.name(),
"EEE");
cacheProperties.put(
XmlaOlap4jNamedMemoryCache.Property.SIZE.name(),
"50");
try {
proxy.setCache(driverParameters, cacheProperties);
} catch (OlapException t) {
try {
cacheProperties.put(
XmlaOlap4jNamedMemoryCache.Property.TIMEOUT.name(),
"-30");
proxy.setCache(driverParameters, cacheProperties);
} catch (OlapException t2) {
return;
}
}
fail("The cache timeout is not validated properly");
}
/**
* Makes sure that the cache size value is validated.
* @throws Exception If the test fails.
*/
public void testCacheSizeError() throws Exception
{
XmlaOlap4jCachedProxy proxy = new XmlaOlap4jHttpProxy(dummyDriver);
Map driverParameters = new HashMap();
Map cacheProperties = new HashMap();
driverParameters.put(
XmlaOlap4jDriver.Property.SERVER.name(),
"http://example.com");
driverParameters.put(
XmlaOlap4jDriver.Property.CATALOG.name(),
"CatalogName");
driverParameters.put(
XmlaOlap4jDriver.Property.CACHE.name(),
"org.olap4j.driver.xmla.cache.XmlaOlap4jNamedMemoryCache");
cacheProperties.put(
XmlaOlap4jNamedMemoryCache.Property.NAME.name(),
"testCacheSizeError");
cacheProperties.put(
XmlaOlap4jNamedMemoryCache.Property.MODE.name(),
"LFU");
cacheProperties.put(
XmlaOlap4jNamedMemoryCache.Property.TIMEOUT.name(),
"600");
cacheProperties.put(
XmlaOlap4jNamedMemoryCache.Property.SIZE.name(),
"EEE");
try {
proxy.setCache(driverParameters, cacheProperties);
} catch (OlapException t) {
try {
cacheProperties.put(
XmlaOlap4jNamedMemoryCache.Property.SIZE.name(),
"-30");
proxy.setCache(driverParameters, cacheProperties);
} catch (OlapException t2) {
return;
}
}
fail("The cache size is not validated properly");
}
/**
* Makes sure that the cache class name value is validated.
* @throws Exception If the test fails.
*/
public void testCacheNameError() throws Exception
{
XmlaOlap4jCachedProxy proxy = new XmlaOlap4jHttpProxy(dummyDriver);
Map driverParameters = new HashMap();
Map cacheProperties = new HashMap();
driverParameters.put(
XmlaOlap4jDriver.Property.SERVER.name(),
"http://example.com");
driverParameters.put(
XmlaOlap4jDriver.Property.CATALOG.name(),
"CatalogName");
driverParameters.put(
XmlaOlap4jDriver.Property.CACHE.name(),
"Class which doesn't exist");
cacheProperties.put(
XmlaOlap4jNamedMemoryCache.Property.NAME.name(),
"testCacheNameError");
cacheProperties.put(
XmlaOlap4jNamedMemoryCache.Property.MODE.name(),
"LFU");
cacheProperties.put(
XmlaOlap4jNamedMemoryCache.Property.TIMEOUT.name(),
"600");
cacheProperties.put(
XmlaOlap4jNamedMemoryCache.Property.SIZE.name(),
"50");
try {
proxy.setCache(driverParameters, cacheProperties);
} catch (OlapException e) {
return;
}
fail("The cache class name is not validated properly");
}
/**
* Makes sure that a cache name is properly shared in a static
* way and that the parameters are not overwritten by subsequent
* connection creations.
*
* @throws Exception If the test fails.
*/
public void testCacheSharing() throws Exception
{
XmlaOlap4jCachedProxy proxy = new XmlaOlap4jHttpProxy(dummyDriver);
Map driverParameters = new HashMap();
Map cacheProperties = new HashMap();
driverParameters.put(
XmlaOlap4jDriver.Property.SERVER.name(),
"http://example.com");
driverParameters.put(
XmlaOlap4jDriver.Property.CATALOG.name(),
"CatalogName");
driverParameters.put(
XmlaOlap4jDriver.Property.CACHE.name(),
"org.olap4j.driver.xmla.cache.XmlaOlap4jNamedMemoryCache");
cacheProperties.put(
XmlaOlap4jNamedMemoryCache.Property.NAME.name(),
"testCacheSharing");
cacheProperties.put(
XmlaOlap4jNamedMemoryCache.Property.MODE.name(),
"LFU");
cacheProperties.put(
XmlaOlap4jNamedMemoryCache.Property.TIMEOUT.name(),
"600");
cacheProperties.put(
XmlaOlap4jNamedMemoryCache.Property.SIZE.name(),
"50");
try {
proxy.setCache(driverParameters, cacheProperties);
} catch (Throwable e) {
fail("The cache class name is not validated properly");
}
driverParameters.put(
XmlaOlap4jDriver.Property.SERVER.name(),
"http://example2.com");
driverParameters.put(
XmlaOlap4jDriver.Property.CATALOG.name(),
"CatalogName2");
driverParameters.put(
XmlaOlap4jDriver.Property.CACHE.name(),
"org.olap4j.driver.xmla.cache.XmlaOlap4jNamedMemoryCache");
cacheProperties.put(
XmlaOlap4jNamedMemoryCache.Property.NAME.name(),
"testCacheSharing");
cacheProperties.put(
XmlaOlap4jNamedMemoryCache.Property.MODE.name(),
"Erronous value which won't trigger an exception since a shared cache should be used.");
cacheProperties.put(
XmlaOlap4jNamedMemoryCache.Property.TIMEOUT.name(),
"Erronous value which won't trigger an exception since a shared cache should be used.");
cacheProperties.put(
XmlaOlap4jNamedMemoryCache.Property.SIZE.name(),
"Erronous value which won't trigger an exception since a shared cache should be used.");
try {
// Create a new object and try with a faulty cache parameters,
// but use a name which already exists in the cache directory.
// This endures that 1 - the caches are shared in a static manner
// and that 2 - the cache is reused and it's
// parameters are not overwritten.
proxy = new XmlaOlap4jHttpProxy(dummyDriver);
proxy.setCache(driverParameters, cacheProperties);
} catch (Throwable e) {
fail(
"The cache is not properly shared since an error should not "
+ "have been thrown.");
}
}
}
// End XmlaCachedProxyTest.java
olap4j-1.0.1.500/testsrc/org/olap4j/driver/xmla/proxy/XmlaCookieManagerTest.java 0000644 0001750 0001750 00000007257 11707254770 027243 0 ustar drazzib drazzib /*
// $Id: XmlaCookieManagerTest.java 482 2012-01-05 23:27:27Z jhyde $
//
// Licensed to Julian Hyde under one or more contributor license
// agreements. See the NOTICE file distributed with this work for
// additional information regarding copyright ownership.
//
// Julian Hyde licenses this file to you 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.olap4j.driver.xmla.proxy;
import junit.framework.TestCase;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
/**
* Unit test for cookie manager.
*
* @version $Id: XmlaCookieManagerTest.java 482 2012-01-05 23:27:27Z jhyde $
* @author Luc Boudreau
*/
public class XmlaCookieManagerTest extends TestCase {
private static final String receivedCookieKey = "Set-Cookie";
public static final String sentCookieKey = "Cookie";
public static final String cookieValue =
"MyTestCookie=271B79EBCBAAA37C5C51B1979441E5AC";
/**
* This simple test makes sure that the cookie manager works as expected. It
* creates a connection stub which returns fake Set-Cookie response
* headers. The cookies are then stored in the cookie manager and a new
* connection stub is created. The second connection is then passed back to
* the manager and we check if the cookies were applied to the connection.
*
* @throws Exception
*/
public void testCookieManager() throws Exception {
UrlConnectionStub conn =
new UrlConnectionStub(new URL("http://example.com"));
XmlaOlap4jCookieManager manager = new XmlaOlap4jCookieManager();
conn.connect();
manager.storeCookies(conn);
conn = new UrlConnectionStub(new URL("http://example.com"));
manager.setCookies(conn);
assertEquals(sentCookieKey, conn.getInternalCookieKey());
assertEquals(cookieValue, conn.getInternalCookieValue());
}
private static class UrlConnectionStub extends HttpURLConnection {
private String internalCookieKey = null;
private String internalCookieValue = null;
protected UrlConnectionStub(URL u) {
super(u);
}
@Override
public void disconnect() {
}
@Override
public boolean usingProxy() {
return false;
}
@Override
public void connect() throws IOException {
this.connected = true;
}
@Override
public String getHeaderFieldKey(int n) {
if (n == 1) {
return receivedCookieKey;
} else {
return null;
}
}
@Override
public String getHeaderField(int n) {
if (n == 1) {
return cookieValue;
} else {
return null;
}
}
@Override
public void setRequestProperty(String key, String value) {
this.internalCookieKey = key;
this.internalCookieValue = value;
}
public String getInternalCookieKey() {
return internalCookieKey;
}
public String getInternalCookieValue() {
return internalCookieValue;
}
}
}
// End XmlaCookieManagerTest.java
olap4j-1.0.1.500/testsrc/org/olap4j/RemoteXmlaTester.java 0000644 0001750 0001750 00000007221 11707254770 022673 0 ustar drazzib drazzib /*
// $Id: RemoteXmlaTester.java 482 2012-01-05 23:27:27Z jhyde $
//
// Licensed to Julian Hyde under one or more contributor license
// agreements. See the NOTICE file distributed with this work for
// additional information regarding copyright ownership.
//
// Julian Hyde licenses this file to you 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.olap4j;
import org.olap4j.test.TestContext;
import org.olap4j.test.TestContext.Tester;
import org.olap4j.test.TestContext.Wrapper;
import java.sql.*;
import java.util.Properties;
/**
* Implementation of {@link org.olap4j.test.TestContext.Tester} which speaks
* to remote XML/A servers.
*
* @author Luc Boudreau
* @version $Id: RemoteXmlaTester.java 482 2012-01-05 23:27:27Z jhyde $
*/
public class RemoteXmlaTester implements Tester {
public static final String DRIVER_URL_PREFIX = "jdbc:xmla:";
public static final String DRIVER_CLASS_NAME =
"org.olap4j.driver.xmla.XmlaOlap4jDriver";
private String url = null;
private String user = null;
private String password = null;
private final TestContext testContext;
/**
* Creates a RemoteXmlaTester.
*
* The {@link org.olap4j.test.TestContext.Tester} API requires a public
* constructor with a {@link org.olap4j.test.TestContext} parameter.
*
* @param testContext Test context
*/
public RemoteXmlaTester(TestContext testContext) {
this.testContext = testContext;
final Properties properties = testContext.getProperties();
this.url =
properties.getProperty(
TestContext.Property.REMOTE_XMLA_URL.path);
if (url == null) {
throw new RuntimeException(
"Property " + TestContext.Property.REMOTE_XMLA_URL
+ " must be specified");
}
this.user =
properties.getProperty(
TestContext.Property.REMOTE_XMLA_USERNAME.path);
this.password =
properties.getProperty(
TestContext.Property.REMOTE_XMLA_PASSWORD.path);
}
public TestContext getTestContext() {
return testContext;
}
public Connection createConnection() throws SQLException {
return this.createConnection(url, null, null);
}
public Connection createConnectionWithUserPassword() throws SQLException {
return this.createConnection(url, user, password);
}
private Connection createConnection(
String url, String user, String password)
{
try {
Class.forName(DRIVER_CLASS_NAME);
return DriverManager.getConnection(url, user, password);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public String getDriverClassName() {
return DRIVER_CLASS_NAME;
}
public String getDriverUrlPrefix() {
return DRIVER_URL_PREFIX;
}
public Flavor getFlavor() {
return Flavor.REMOTE_XMLA;
}
public String getURL() {
return this.url;
}
public void setUrl(String url) {
this.url = url;
}
public Wrapper getWrapper() {
return TestContext.Wrapper.NONE;
}
}
// End RemoteXmlaTester.java
olap4j-1.0.1.500/testsrc/org/olap4j/test/ 0000755 0001750 0001750 00000000000 11540707144 017532 5 ustar drazzib drazzib olap4j-1.0.1.500/testsrc/org/olap4j/test/package.html 0000644 0001750 0001750 00000000164 11421322442 022004 0 ustar drazzib drazzib
Contains tests for the olap4j API.
Not part of the olap4j public API.
olap4j-1.0.1.500/testsrc/org/olap4j/test/TestContext.java 0000644 0001750 0001750 00000062750 11707521222 022667 0 ustar drazzib drazzib /*
// $Id: TestContext.java 482 2012-01-05 23:27:27Z jhyde $
//
// Licensed to Julian Hyde under one or more contributor license
// agreements. See the NOTICE file distributed with this work for
// additional information regarding copyright ownership.
//
// Julian Hyde licenses this file to you 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.olap4j.test;
import org.olap4j.CellSet;
import org.olap4j.OlapWrapper;
import org.olap4j.impl.Olap4jUtil;
import org.olap4j.layout.TraditionalCellSetFormatter;
import org.olap4j.mdx.*;
import junit.framework.*;
import org.apache.commons.dbcp.*;
import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.sql.*;
import java.util.List;
import java.util.Properties;
import java.util.regex.Pattern;
/**
* Context for olap4j tests.
*
* Also provides static utility methods such as {@link #fold(String)}.
*
*
Properties used by the test framework are described in
* {@link org.olap4j.test.TestContext.Property}.
*
* @author jhyde
* @version $Id: TestContext.java 482 2012-01-05 23:27:27Z jhyde $
* @since Jun 7, 2007
*/
public class TestContext {
public static final String NL = System.getProperty("line.separator");
private static final String indent = " ";
private static final String lineBreak2 = "\\\\n\"" + NL + indent + "+ \"";
private static final String lineBreak3 = "\\n\"" + NL + indent + "+ \"";
private static final Pattern LineBreakPattern =
Pattern.compile("\r\n|\r|\n");
private static final Pattern TabPattern = Pattern.compile("\t");
private static Properties testProperties;
private static final ThreadLocal THREAD_INSTANCE =
new ThreadLocal() {
protected TestContext initialValue() {
return new TestContext();
}
};
/**
* The following classes are part of the TCK. Each driver should call them.
*/
public static final Class>[] TCK_CLASSES = {
org.olap4j.ConnectionTest.class,
org.olap4j.CellSetFormatterTest.class,
org.olap4j.MetadataTest.class,
org.olap4j.mdx.MdxTest.class,
org.olap4j.transform.TransformTest.class,
org.olap4j.XmlaConnectionTest.class,
org.olap4j.OlapTreeTest.class,
org.olap4j.OlapTest.class,
};
/**
* The following tests do not depend upon the driver implementation.
* They should be executed once, in olap4j's test suite, not for each
* provider's test suite.
*/
public static final Class>[] NON_TCK_CLASSES = {
org.olap4j.impl.ConnectStringParserTest.class,
org.olap4j.impl.Olap4jUtilTest.class,
org.olap4j.impl.Base64Test.class,
org.olap4j.test.ParserTest.class,
org.olap4j.test.ArrayMapTest.class,
org.olap4j.driver.xmla.cache.XmlaShaEncoderTest.class,
org.olap4j.driver.xmla.proxy.XmlaCookieManagerTest.class,
org.olap4j.driver.xmla.proxy.XmlaCachedProxyTest.class,
};
private final Tester tester;
private final Properties properties;
/**
* Intentionally private: use {@link #instance()}.
*/
private TestContext() {
this(getStaticTestProperties());
}
private TestContext(Properties properties) {
assert properties != null;
this.properties = properties;
this.tester = createTester(this, properties);
}
/**
* Adds all of the test classes in the TCK (Test Compatibility Kit)
* to a given junit test suite.
*
* @param suite Suite to which to add tests
*/
private static void addTck(TestSuite suite) {
for (Class> tckClass : TCK_CLASSES) {
suite.addTestSuite(tckClass);
}
}
/**
* Converts a string constant into platform-specific line endings.
*
* @param string String where line endings are represented as linefeed "\n"
* @return String where all linefeeds have been converted to
* platform-specific (CR+LF on Windows, LF on Unix/Linux)
*/
public static SafeString fold(String string) {
if (!NL.equals("\n")) {
string = Olap4jUtil.replace(string, "\n", NL);
}
if (string == null) {
return null;
} else {
return new SafeString(string);
}
}
/**
* Reverses the effect of {@link #fold}; converts platform-specific line
* endings in a string info linefeeds.
*
* @param string String where all linefeeds have been converted to
* platform-specific (CR+LF on Windows, LF on Unix/Linux)
* @return String where line endings are represented as linefeed "\n"
*/
public static String unfold(String string) {
if (!NL.equals("\n")) {
string = Olap4jUtil.replace(string, NL, "\n");
}
if (string == null) {
return null;
} else {
return string;
}
}
/**
* Converts an MDX parse tree to an MDX string
*
* @param node Parse tree
* @return MDX string
*/
public static String toString(ParseTreeNode node) {
StringWriter sw = new StringWriter();
ParseTreeWriter parseTreeWriter = new ParseTreeWriter(sw);
node.unparse(parseTreeWriter);
return sw.toString();
}
/**
* Formats a {@link org.olap4j.CellSet}.
*
* @param cellSet Cell set
* @return String representation of cell set
*/
public static String toString(CellSet cellSet) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
new TraditionalCellSetFormatter().format(cellSet, pw);
pw.flush();
return sw.toString();
}
/**
* The default instance of TestContext.
*
* @return default TestContext
*/
public static TestContext instance() {
return THREAD_INSTANCE.get();
}
/**
* Checks that an actual string matches an expected string. If they do not,
* throws a {@link junit.framework.ComparisonFailure} and prints the
* difference, including the actual string as an easily pasted Java string
* literal.
*
* @param expected Expected string
* @param actual Actual string returned by test case
*/
public static void assertEqualsVerbose(
String expected,
String actual)
{
assertEqualsVerbose(expected, actual, true, null);
}
/**
* Checks that an actual string matches an expected string.
*
* If they do not, throws a {@link ComparisonFailure} and prints the
* difference, including the actual string as an easily pasted Java string
* literal.
*
* @param expected Expected string
* @param actual Actual string
* @param java Whether to generate actual string as a Java string literal
* if the values are not equal
* @param message Message to display, optional
*/
public static void assertEqualsVerbose(
String expected,
String actual,
boolean java,
String message)
{
assertEqualsVerbose(
fold(expected), actual, java, message);
}
/**
* Checks that an actual string matches an expected string. If they do not,
* throws a {@link junit.framework.ComparisonFailure} and prints the
* difference, including the actual string as an easily pasted Java string
* literal.
*
* @param safeExpected Expected string, where all line endings have been
* converted into platform-specific line endings
* @param actual Actual string returned by test case
* @param java Whether to print the actual value as a Java string literal
* if the strings differ
* @param message Message to print if the strings differ
*/
public static void assertEqualsVerbose(
SafeString safeExpected,
String actual,
boolean java,
String message)
{
String expected = safeExpected == null ? null : safeExpected.s;
if ((expected == null) && (actual == null)) {
return;
}
if ((expected != null) && expected.equals(actual)) {
return;
}
if (message == null) {
message = "";
} else {
message += NL;
}
message +=
"Expected:" + NL + expected + NL
+ "Actual:" + NL + actual + NL;
if (java) {
message += "Actual java:" + NL + toJavaString(actual) + NL;
}
throw new ComparisonFailure(message, expected, actual);
}
/**
* Converts a string (which may contain quotes and newlines) into a java
* literal.
*
*
For example,
* string with "quotes" split
* across lines
*
becomes
* "string with \"quotes\" split" + NL +
* "across lines"
*
*/
static String toJavaString(String s) {
// Convert [string with "quotes" split
// across lines]
// into ["string with \"quotes\" split\n"
// + "across lines
//
s = Olap4jUtil.replace(s, "\\", "\\\\");
s = Olap4jUtil.replace(s, "\"", "\\\"");
s = LineBreakPattern.matcher(s).replaceAll(lineBreak2);
s = TabPattern.matcher(s).replaceAll("\\\\t");
s = "\"" + s + "\"";
String spurious = NL + indent + "+ \"\"";
if (s.endsWith(spurious)) {
s = s.substring(0, s.length() - spurious.length());
}
if (s.indexOf(lineBreak3) >= 0) {
s = "fold(" + NL + indent + s + ")";
}
return s;
}
/**
* Quotes a pattern.
*/
public static String quotePattern(String s)
{
s = s.replaceAll("\\\\", "\\\\");
s = s.replaceAll("\\.", "\\\\.");
s = s.replaceAll("\\+", "\\\\+");
s = s.replaceAll("\\{", "\\\\{");
s = s.replaceAll("\\}", "\\\\}");
s = s.replaceAll("\\|", "\\\\||");
s = s.replaceAll("[$]", "\\\\\\$");
s = s.replaceAll("\\?", "\\\\?");
s = s.replaceAll("\\*", "\\\\*");
s = s.replaceAll("\\(", "\\\\(");
s = s.replaceAll("\\)", "\\\\)");
s = s.replaceAll("\\[", "\\\\[");
s = s.replaceAll("\\]", "\\\\]");
return s;
}
/**
* Factory method for the {@link Tester}
* object which determines which driver to test.
*
* @param testContext Test context
* @param testProperties Properties that define the properties of the tester
* @return a new Tester
*/
private static Tester createTester(
TestContext testContext,
Properties testProperties)
{
String helperClassName =
testProperties.getProperty(Property.HELPER_CLASS_NAME.path);
if (helperClassName == null) {
helperClassName = "org.olap4j.XmlaTester";
if (!testProperties.containsKey(
TestContext.Property.XMLA_CATALOG_URL.path))
{
testProperties.setProperty(
TestContext.Property.XMLA_CATALOG_URL.path,
"dummy_xmla_catalog_url");
}
}
Tester tester;
try {
Class> clazz = Class.forName(helperClassName);
final Constructor> constructor =
clazz.getConstructor(TestContext.class);
tester = (Tester) constructor.newInstance(testContext);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (InstantiationException e) {
throw new RuntimeException(e);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
}
// Apply a wrapper, if the "org.olap4j.test.wrapper" property is
// specified.
String wrapperName = testProperties.getProperty(Property.WRAPPER.path);
Wrapper wrapper;
if (wrapperName == null || wrapperName.equals("")) {
wrapper = Wrapper.NONE;
} else {
try {
wrapper = Enum.valueOf(Wrapper.class, wrapperName);
} catch (IllegalArgumentException e) {
throw new IllegalArgumentException(
"Unknown wrapper value '" + wrapperName + "'");
}
}
switch (wrapper) {
case NONE:
break;
case DBCP:
final BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName(tester.getDriverClassName());
dataSource.setUrl(tester.getURL());
// need access to underlying connection so that we can call
// olap4j-specific methods
dataSource.setAccessToUnderlyingConnectionAllowed(true);
tester = new DelegatingTester(tester) {
public Connection createConnection()
throws SQLException
{
return dataSource.getConnection();
}
public Wrapper getWrapper() {
return Wrapper.DBCP;
}
};
break;
}
return tester;
}
/**
* Creates a test suite that executes the olap4j TCK with the given
* set of properties. The properties are the same as those you can put in
* {@code "test.properties"}.
*
* @param properties Properties
* @param name Name of test suite
* @return Test suite that executes the TCK
*/
public static TestSuite createTckSuite(Properties properties, String name) {
TestContext testContext = new TestContext(properties);
THREAD_INSTANCE.set(testContext);
try {
final TestSuite suite = new TestSuite();
suite.setName(name);
addTck(suite);
return suite;
} finally {
THREAD_INSTANCE.remove();
}
}
public Properties getProperties() {
return properties;
}
/**
* Enumeration of valid values for the
* {@link org.olap4j.test.TestContext.Property#WRAPPER} property.
*/
public enum Wrapper {
/**
* No wrapper.
*/
NONE {
public T unwrap(
Statement statement,
Class clazz) throws SQLException
{
return ((OlapWrapper) statement).unwrap(clazz);
}
public T unwrap(
Connection connection,
Class clazz) throws SQLException
{
return ((OlapWrapper) connection).unwrap(clazz);
}
},
/**
* Instructs the olap4j testing framework to wrap connections using
* the Apache commons-dbcp connection-pooling framework.
*/
DBCP {
public T unwrap(
Statement statement,
Class clazz) throws SQLException
{
return clazz.cast(
((DelegatingStatement) statement).getInnermostDelegate());
}
public T unwrap(
Connection connection,
Class clazz) throws SQLException
{
return clazz.cast(
((DelegatingConnection) connection).getInnermostDelegate());
}
};
/**
* Removes wrappers from a statement.
*
* @param statement Statement
* @param clazz Desired result type
* @return Unwrapped object
* @throws SQLException on database error
*/
public abstract T unwrap(
Statement statement,
Class clazz) throws SQLException;
/**
* Removes wrappers from a connection.
*
* @param connection Connection
* @param clazz Desired result type
* @return Unwrapped object
* @throws SQLException on database error
*/
public abstract T unwrap(
Connection connection,
Class clazz) throws SQLException;
}
/**
* Returns an object containing all properties needed by the test suite.
*
* Consists of system properties, overridden by the contents of
* "test.properties" in the current directory, if it exists, and
* in any parent or ancestor directory. This allows you to invoke the
* test from any sub-directory of the source root and still pick up the
* right test parameters.
*
* @return object containing properties needed by the test suite
*/
private static synchronized Properties getStaticTestProperties() {
if (testProperties == null) {
testProperties = new Properties(System.getProperties());
File dir = new File(System.getProperty("user.dir"));
while (dir != null) {
File file = new File(dir, "test.properties");
if (file.exists()) {
try {
testProperties.load(new FileInputStream(file));
} catch (IOException e) {
// ignore
}
}
file = new File(new File(dir, "olap4j"), "test.properties");
if (file.exists()) {
try {
testProperties.load(new FileInputStream(file));
} catch (IOException e) {
// ignore
}
}
dir = dir.getParentFile();
}
}
return testProperties;
}
/**
* Converts a {@link Throwable} to a stack trace.
*/
public static String getStackTrace(Throwable e) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
pw.flush();
return sw.toString();
}
/**
* Shorthand way to convert array of names into segment list.
*
* @param names Array of names
* @return Segment list
*/
public static List nameList(String... names) {
return IdentifierNode.ofNames(names).getSegmentList();
}
/**
* Checks that an exception is not null and the stack trace contains a
* given string. Fails otherwise.
*
* @param throwable Stack trace
* @param pattern Seek string
*/
public static void checkThrowable(Throwable throwable, String pattern) {
if (throwable == null) {
Assert.fail("query did not yield an exception");
}
String stackTrace = getStackTrace(throwable);
if (stackTrace.indexOf(pattern) < 0) {
Assert.fail(
"error does not match pattern '" + pattern
+ "'; error is [" + stackTrace + "]");
}
}
/**
* Returns this context's tester.
*
* @return a tester
*/
public Tester getTester() {
return tester;
}
/**
* Abstracts the information about specific drivers and database instances
* needed by this test. This allows the same test suite to be used for
* multiple implementations of olap4j.
*
* Must have a public constructor that takes a
* {@link org.olap4j.test.TestContext} as parameter.
*/
public interface Tester {
/**
* Returns the test context.
*
* @return Test context
*/
TestContext getTestContext();
/**
* Creates a connection
*
* @return connection
* @throws SQLException on error
*/
Connection createConnection() throws SQLException;
/**
* Returns the prefix of URLs recognized by this driver, for example
* "jdbc:mondrian:"
*
* @return URL prefix
*/
String getDriverUrlPrefix();
/**
* Returns the class name of the driver, for example
* "mondrian.olap4j.MondrianOlap4jDriver".
*
* @return driver class name
*/
String getDriverClassName();
/**
* Creates a connection using the
* {@link java.sql.DriverManager#getConnection(String, String, String)}
* method.
*
* @return connection
* @throws SQLException on error
*/
Connection createConnectionWithUserPassword() throws SQLException;
/**
* Returns the URL of the FoodMart database.
*
* @return URL of the FoodMart database
*/
String getURL();
/**
* Returns an enumeration indicating the driver (or strictly, the family
* of drivers) supported by this Tester. Allows the test suite to
* disable tests or expect slightly different results if the
* capabilities of OLAP servers are different.
*
* @return Flavor of driver/OLAP engine we are connecting to
*/
Flavor getFlavor();
/**
* Returns a description of the wrapper, if any, around this connection.
*/
Wrapper getWrapper();
enum Flavor {
MONDRIAN,
XMLA,
REMOTE_XMLA
}
}
/**
* Implementation of {@link Tester} that delegates to an underlying tester.
*/
public static abstract class DelegatingTester implements Tester {
protected final Tester tester;
/**
* Creates a DelegatingTester.
*
* @param tester Underlying tester to which calls are delegated
*/
protected DelegatingTester(Tester tester) {
this.tester = tester;
}
public TestContext getTestContext() {
return tester.getTestContext();
}
public Connection createConnection() throws SQLException {
return tester.createConnection();
}
public String getDriverUrlPrefix() {
return tester.getDriverUrlPrefix();
}
public String getDriverClassName() {
return tester.getDriverClassName();
}
public Connection createConnectionWithUserPassword()
throws SQLException
{
return tester.createConnectionWithUserPassword();
}
public String getURL() {
return tester.getURL();
}
public Flavor getFlavor() {
return tester.getFlavor();
}
public Wrapper getWrapper() {
return tester.getWrapper();
}
}
/**
* Enumeration of system properties that mean something to the olap4j
* testing framework.
*/
public enum Property {
/**
* Name of the class used by the test infrastructure to make connections
* to the olap4j data source and perform other housekeeping operations.
* Valid values include "mondrian.test.MondrianOlap4jTester" (the
* default, per test.properties) and "org.olap4j.XmlaTester".
*/
HELPER_CLASS_NAME("org.olap4j.test.helperClassName"),
/**
* Test property that provides the value of returned by the
* {@link Tester#getURL} method.
*/
CONNECT_URL("org.olap4j.test.connectUrl"),
/**
* Test property that provides the URL name of the catalog for the XMLA
* driver.
*/
XMLA_CATALOG_URL("org.olap4j.XmlaTester.CatalogUrl"),
/**
* Test property related to the remote XMLA tester.
* Must be a valid XMLA driver URL.
*/
REMOTE_XMLA_URL("org.olap4j.RemoteXmlaTester.JdbcUrl"),
/**
* Test property related to the remote XMLA tester.
* User name to use.
*/
REMOTE_XMLA_USERNAME("org.olap4j.RemoteXmlaTester.Username"),
/**
* Test property related to the remote XMLA tester.
* Password to use.
*/
REMOTE_XMLA_PASSWORD("org.olap4j.RemoteXmlaTester.Password"),
/**
* Test property that indicates the wrapper to place around the
* connection. Valid values are defined by the {@link Wrapper}
* enumeration, such as "Dbcp". If not specified, the connection is used
* without a connection pool.
*/
WRAPPER("org.olap4j.test.wrapper"),
;
public final String path;
/**
* Creates a Property enum value.
*
* @param path Full name of property, e.g. "org.olap4.foo.Bar".
*/
private Property(String path) {
this.path = path;
}
}
/**
* Wrapper around a string that indicates that all line endings have been
* converted to platform-specific line endings.
*
* @see TestContext#fold
*/
public static class SafeString {
public final String s;
/**
* Creates a SafeString.
* @param s String
*/
private SafeString(String s) {
this.s = s;
}
}
}
// End TestContext.java
olap4j-1.0.1.500/testsrc/org/olap4j/test/ParserTest.java 0000644 0001750 0001750 00000106000 11707254766 022502 0 ustar drazzib drazzib /*
// $Id: ParserTest.java 482 2012-01-05 23:27:27Z jhyde $
//
// Licensed to Julian Hyde under one or more contributor license
// agreements. See the NOTICE file distributed with this work for
// additional information regarding copyright ownership.
//
// Julian Hyde licenses this file to you 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.olap4j.test;
import org.olap4j.Axis;
import org.olap4j.OlapConnection;
import org.olap4j.mdx.*;
import org.olap4j.mdx.parser.MdxParseException;
import org.olap4j.mdx.parser.MdxParser;
import junit.framework.AssertionFailedError;
import junit.framework.TestCase;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Collections;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Tests the MDX parser.
*
* @author gjohnson, jhyde
* @version $Id: ParserTest.java 482 2012-01-05 23:27:27Z jhyde $
*/
public class ParserTest extends TestCase {
private static final Pattern lineColPattern =
Pattern.compile("At line ([0-9]+), column ([0-9]+)");
private static final Pattern lineColTwicePattern =
Pattern.compile(
"(?s)From line ([0-9]+), column ([0-9]+) to line ([0-9]+), column ([0-9]+): (.*)");
final TestContext testContext = TestContext.instance();
private Connection connection;
public ParserTest(String name) {
super(name);
}
protected OlapConnection getOlapConnection() throws SQLException {
if (connection == null) {
connection = testContext.getTester().createConnection();
}
return testContext.getTester().getWrapper().unwrap(
connection, OlapConnection.class);
}
protected void tearDown() throws Exception {
if (connection != null && !connection.isClosed()) {
connection.close();
connection = null;
}
}
private MdxParser createParser() {
try {
OlapConnection olapConnection = getOlapConnection();
return olapConnection.getParserFactory()
.createMdxParser(olapConnection);
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
public void testAddCarets()
{
assertEquals(
"values (^foo^)",
new ParseRegion(1, 9, 1, 11).annotate("values (foo)"));
assertEquals(
"abc^def",
new ParseRegion(1, 4, 1, 4).annotate("abcdef"));
assertEquals(
"abcdef^",
new ParseRegion(1, 7, 1, 7).annotate("abcdef"));
assertEquals(
"[1:9, 1:11]",
ParseRegion.findPos("values (^foo^)").region.toString());
assertEquals(
"[1:4]",
ParseRegion.findPos("abc^def").region.toString());
assertEquals(
"[1:7]",
ParseRegion.findPos("abcdef^").region.toString());
assertNull(ParseRegion.findPos("abc").region);
}
public void testAxisParsing() throws Exception {
checkAxisAllWays(0, "COLUMNS");
checkAxisAllWays(1, "ROWS");
checkAxisAllWays(2, "PAGES");
checkAxisAllWays(3, "CHAPTERS");
checkAxisAllWays(4, "SECTIONS");
}
private void checkAxisAllWays(int axisOrdinal, String axisName) {
checkAxis(axisOrdinal + "", axisName);
checkAxis("AXIS(" + axisOrdinal + ")", axisName);
checkAxis(axisName, axisName);
}
private void checkAxis(
String s,
String expectedName)
{
MdxParser p = createParser();
String q = "select [member] on " + s + " from [cube]";
SelectNode selectNode = p.parseSelect(q);
List axes = selectNode.getAxisList();
assertEquals("Number of axes must be 1", 1, axes.size());
assertEquals(
"Axis index name must be correct",
expectedName, axes.get(0).getAxis().name());
}
public void testNegativeCases() throws Exception {
assertParseQueryFails(
"^s^ from sales",
"Syntax error at \\[1:1\\], token 's'");
assertParseQueryFails(
"^seleg^ from sales",
"Syntax error at \\[1:1, 1:5\\], token 'seleg'");
assertParseQueryFails(
"^seleg^ from sales",
"Syntax error at \\[1:1, 1:5\\], token 'seleg'");
assertParseQueryFails(
"select [member] on ^axis(1.7)^ from sales",
"(?s).*The axis number must be a non-negative integer, but it was 1.7.");
assertParseQueryFails(
"select [member] on ^foobar^ from sales",
"Syntax error at \\[1:20, 1:25\\], token 'foobar'");
assertParseQueryFails(
"select [member] on axis(-^ ^1) from sales",
"Syntax error at \\[1:26\\], token '-'");
assertParseQueryFails(
"select [member] on axis(-^1^) from sales",
"Syntax error at \\[1:26\\], token '-'");
// used to be an error, but no longer
assertParseQuery(
"select [member] on axis(5) from sales",
"SELECT\n"
+ "[member] ON AXIS(5)\n"
+ "FROM sales");
assertParseQueryFails(
"select [member] on ^axes^(0) from sales",
"Syntax error at \\[1:20, 1:23\\], token 'axes'");
assertParseQueryFails(
"select [member] on ^0.5^ from sales",
"Invalid axis specification\\. The axis number must be a non-negative integer, but it was 0\\.5\\.");
assertParseQuery(
"select [member] on 555 from sales",
"SELECT\n"
+ "[member] ON AXIS(555)\n"
+ "FROM sales");
}
public void testScannerPunc() {
assertParseQuery(
"with member [Measures].__Foo as 1 + 2\n"
+ "select __Foo on 0\n"
+ "from _Bar_Baz",
"WITH\n"
+ "MEMBER [Measures].__Foo AS\n"
+ " (1 + 2)\n"
+ "SELECT\n"
+ "__Foo ON COLUMNS\n"
+ "FROM _Bar_Baz");
// # is not allowed
assertParseQueryFails(
"with member [Measures].#^_Foo as 1 + 2\n"
+ "select __Foo on 0\n"
+ "from _Bar#Baz",
"Unexpected character '#'");
assertParseQueryFails(
"with member [Measures].Foo as 1 + 2\n"
+ "select Foo on 0\n"
+ "from Bar#B^az",
"Unexpected character '#'");
// The spec doesn't allow $ but SSAS allows it so we allow it too.
assertParseQuery(
"with member [Measures].$Foo as 1 + 2\n"
+ "select $Foo on 0\n"
+ "from Bar$Baz",
"WITH\n"
+ "MEMBER [Measures].$Foo AS\n"
+ " (1 + 2)\n"
+ "SELECT\n"
+ "$Foo ON COLUMNS\n"
+ "FROM Bar$Baz");
// '$' is OK inside brackets too
assertParseQuery(
"select [measures].[$foo] on columns from sales",
"SELECT\n"
+ "[measures].[$foo] ON COLUMNS\n"
+ "FROM sales");
// ']' unexpected
assertParseQueryFails(
"select { Customers]^.^Children } on columns from [Sales]",
"Unexpected character ']'");
}
public void testUnparse() {
checkUnparse(
"with member [Measures].[Foo] as ' 123 '\n"
+ "select {[Measures].members} on columns,\n"
+ " CrossJoin([Product].members, {[Gender].Children}) on rows\n"
+ "from [Sales]\n"
+ "where [Marital Status].[S]",
"WITH\n"
+ "MEMBER [Measures].[Foo] AS\n"
+ " 123\n"
+ "SELECT\n"
+ "{[Measures].members} ON COLUMNS,\n"
+ "CrossJoin([Product].members, {[Gender].Children}) ON ROWS\n"
+ "FROM [Sales]\n"
+ "WHERE [Marital Status].[S]");
}
private void checkUnparse(String queryString, final String expected) {
try {
OlapConnection olapConnection = getOlapConnection();
MdxParser mdxParser =
olapConnection.getParserFactory()
.createMdxParser(olapConnection);
final SelectNode query = mdxParser.parseSelect(queryString);
String unparsedQueryString = TestContext.toString(query);
TestContext.assertEqualsVerbose(expected, unparsedQueryString);
} catch (SQLException e) {
throw new RuntimeException("error during parse");
}
}
private void assertParseQueryFails(String query, String expected) {
checkFails(createParser(), query, expected);
}
private void assertParseExprFails(String expr, String expected) {
checkFails(createParser(), wrapExpr(expr), expected);
}
private void checkFails(MdxParser p, String query, String expected) {
final ParseRegion.RegionAndSource ras = ParseRegion.findPos(query);
try {
SelectNode selectNode = p.parseSelect(ras.source);
fail("Must return an error, got " + selectNode);
} catch (Exception e) {
checkEx(e, expected, ras);
}
}
/**
* Checks whether an exception matches the pattern and expected position
* expected.
*
* @param ex Exception thrown
* @param expectedMsgPattern Expected pattern
* @param ras Query and position in query
*/
public static void checkEx(
Throwable ex,
String expectedMsgPattern,
ParseRegion.RegionAndSource ras)
{
String NL = TestContext.NL;
if (null == ex) {
if (expectedMsgPattern == null) {
// No error expected, and no error happened.
return;
} else {
throw new AssertionFailedError(
"Expected query to throw exception, but it did not; "
+ "query [" + ras.source
+ "]; expected [" + expectedMsgPattern + "]");
}
}
Throwable actualException = ex;
String actualMessage = actualException.getMessage();
int actualLine = -1;
int actualColumn = -1;
int actualEndLine = 100;
int actualEndColumn = 99;
// Search for a SqlParseException -- with its position set -- somewhere
// in the stack.
MdxParseException mpe = null;
for (Throwable x = ex; x != null; x = x.getCause()) {
if ((x instanceof MdxParseException)
&& (((MdxParseException) x).getRegion() != null))
{
mpe = (MdxParseException) x;
break;
}
if (x.getCause() == x) {
break;
}
}
if (mpe != null) {
final ParseRegion region = mpe.getRegion();
actualLine = region.getStartLine();
actualColumn = region.getStartColumn();
actualEndLine = region.getEndLine();
actualEndColumn = region.getEndColumn();
actualException = mpe;
actualMessage = actualException.getMessage();
} else {
final String message = ex.getMessage();
if (message != null) {
Matcher matcher = lineColTwicePattern.matcher(message);
if (matcher.matches()) {
actualLine = Integer.parseInt(matcher.group(1));
actualColumn = Integer.parseInt(matcher.group(2));
actualEndLine = Integer.parseInt(matcher.group(3));
actualEndColumn = Integer.parseInt(matcher.group(4));
actualMessage = matcher.group(5);
} else {
matcher = lineColPattern.matcher(message);
if (matcher.matches()) {
actualLine = Integer.parseInt(matcher.group(1));
actualColumn = Integer.parseInt(matcher.group(2));
}
}
}
}
if (null == expectedMsgPattern) {
if (null != actualException) {
actualException.printStackTrace();
fail(
"Validator threw unexpected exception"
+ "; query [" + ras.source
+ "]; exception [" + actualMessage
+ "]; pos [line " + actualLine
+ " col " + actualColumn
+ " thru line " + actualLine
+ " col " + actualColumn + "]");
}
} else if (null != expectedMsgPattern) {
if (null == actualException) {
fail(
"Expected validator to throw "
+ "exception, but it did not; query [" + ras.source
+ "]; expected [" + expectedMsgPattern + "]");
} else {
if ((actualColumn <= 0)
|| (actualLine <= 0)
|| (actualEndColumn <= 0)
|| (actualEndLine <= 0))
{
throw new AssertionFailedError(
"Error did not have position: "
+ " actual pos [line " + actualLine
+ " col " + actualColumn
+ " thru line " + actualEndLine
+ " col " + actualEndColumn + "]");
}
String sqlWithCarets =
new ParseRegion(
actualLine,
actualColumn,
actualEndLine,
actualEndColumn).annotate(ras.source);
if (ras.region == null) {
throw new AssertionFailedError(
"todo: add carets to sql: " + sqlWithCarets);
}
if ((actualMessage == null)
|| !actualMessage.matches(expectedMsgPattern))
{
actualException.printStackTrace();
final String actualJavaRegexp =
(actualMessage == null) ? "null"
: TestContext.toJavaString(
TestContext.quotePattern(actualMessage));
fail(
"Validator threw different "
+ "exception than expected; query [" + ras.source
+ "];" + NL
+ " expected pattern [" + expectedMsgPattern
+ "];" + NL
+ " actual [" + actualMessage
+ "];" + NL
+ " actual as java regexp [" + actualJavaRegexp
+ "]; pos [" + actualLine
+ " col " + actualColumn
+ " thru line " + actualEndLine
+ " col " + actualEndColumn
+ "]; sql [" + sqlWithCarets + "]");
} else if (
(ras.region != null)
&& ((actualLine != ras.region.getStartLine())
|| (actualColumn != ras.region.getStartColumn())
|| (actualEndLine != ras.region.getEndLine())
|| (actualEndColumn != ras.region.getEndColumn())))
{
fail(
"Validator threw expected "
+ "exception [" + actualMessage
+ "]; but at pos [line " + actualLine
+ " col " + actualColumn
+ " thru line " + actualEndLine
+ " col " + actualEndColumn
+ "]; sql [" + sqlWithCarets + "]");
}
}
}
}
public void testMultipleAxes() throws Exception {
MdxParser p = createParser();
String query = "select {[axis0mbr]} on axis(0), "
+ "{[axis1mbr]} on axis(1) from cube";
SelectNode select = p.parseSelect(query);
assertNotNull(select);
List axes = select.getAxisList();
assertEquals("Number of axes", 2, axes.size());
assertEquals(
"Axis index name must be correct",
Axis.Factory.forOrdinal(0),
axes.get(0).getAxis());
assertEquals(
"Axis index name must be correct",
Axis.Factory.forOrdinal(1),
axes.get(1).getAxis());
// now a similar query with axes reversed
query = "select {[axis1mbr]} on aXiS(1), "
+ "{[axis0mbr]} on AxIs(0) from cube";
select = p.parseSelect(query);
axes = select.getAxisList();
assertEquals("Number of axes", 2, axes.size());
assertEquals(
"Axis index name must be correct",
Axis.Factory.forOrdinal(0),
axes.get(0).getAxis());
assertEquals(
"Axis index name must be correct",
Axis.Factory.forOrdinal(1),
axes.get(1).getAxis());
ParseTreeNode colsSetExpr = axes.get(0).getExpression();
assertNotNull("Column tuples", colsSetExpr);
CallNode fun = (CallNode)colsSetExpr;
IdentifierNode identifier = (IdentifierNode) (fun.getArgList().get(0));
assertEquals(1, identifier.getSegmentList().size());
assertEquals(
"Correct member on axis",
"axis0mbr",
identifier.getSegmentList().get(0).getName());
ParseTreeNode rowsSetExpr = axes.get(1).getExpression();
assertNotNull("Row tuples", rowsSetExpr);
fun = (CallNode) rowsSetExpr;
identifier = (IdentifierNode) (fun.getArgList().get(0));
assertEquals(1, identifier.getSegmentList().size());
assertEquals(
"Correct member on axis",
"axis1mbr",
identifier.getSegmentList().get(0).getName());
}
public void testCaseTest() {
assertParseQuery(
"with member [Measures].[Foo] as "
+ " ' case when x = y then \"eq\" when x < y then \"lt\" else \"gt\" end '"
+ "select {[foo]} on axis(0) from cube",
"WITH\n"
+ "MEMBER [Measures].[Foo] AS\n"
+ " CASE WHEN (x = y) THEN \"eq\" WHEN (x < y) THEN \"lt\" ELSE \"gt\" END\n"
+ "SELECT\n"
+ "{[foo]} ON COLUMNS\n"
+ "FROM cube");
}
public void testCaseSwitch() {
assertParseQuery(
"with member [Measures].[Foo] as "
+ " ' case x when 1 then 2 when 3 then 4 else 5 end '"
+ "select {[foo]} on axis(0) from cube",
"WITH\n"
+ "MEMBER [Measures].[Foo] AS\n"
+ " CASE x WHEN 1 THEN 2 WHEN 3 THEN 4 ELSE 5 END\n"
+ "SELECT\n"
+ "{[foo]} ON COLUMNS\n"
+ "FROM cube");
}
public void testDimensionProperties() {
assertParseQuery(
"select {[foo]} properties p1, p2 on columns from [cube]",
"SELECT\n"
+ "{[foo]} DIMENSION PROPERTIES p1, p2 ON COLUMNS\n"
+ "FROM [cube]");
}
public void testCellProperties() {
assertParseQuery(
"select {[foo]} on columns from [cube] CELL PROPERTIES FORMATTED_VALUE",
"SELECT\n"
+ "{[foo]} ON COLUMNS\n"
+ "FROM [cube]\n"
+ "CELL PROPERTIES FORMATTED_VALUE");
}
public void testIsEmpty() {
assertParseExpr(
"[Measures].[Unit Sales] IS EMPTY",
"([Measures].[Unit Sales] IS EMPTY)");
assertParseExpr(
"[Measures].[Unit Sales] IS EMPTY AND 1 IS NULL",
"(([Measures].[Unit Sales] IS EMPTY) AND (1 IS NULL))");
// FIXME: "NULL" should associate as "IS NULL" rather than "NULL + 56"
assertParseExpr(
"- x * 5 is empty is empty is null + 56",
"(((((- x) * 5) IS EMPTY) IS EMPTY) IS (NULL + 56))");
}
public void testIs() {
assertParseExpr(
"[Measures].[Unit Sales] IS [Measures].[Unit Sales] AND [Measures].[Unit Sales] IS NULL",
"(([Measures].[Unit Sales] IS [Measures].[Unit Sales]) AND ([Measures].[Unit Sales] IS NULL))");
}
public void testIsNull() {
assertParseExpr(
"[Measures].[Unit Sales] IS NULL",
"([Measures].[Unit Sales] IS NULL)");
assertParseExpr(
"[Measures].[Unit Sales] IS NULL AND 1 <> 2",
"(([Measures].[Unit Sales] IS NULL) AND (1 <> 2))");
assertParseExpr(
"x is null or y is null and z = 5",
"((x IS NULL) OR ((y IS NULL) AND (z = 5)))");
assertParseExpr(
"(x is null) + 56 > 6",
"(((x IS NULL) + 56) > 6)");
// FIXME: Should be:
// "(((((x IS NULL) AND (a = b)) OR ((c = (d + 5))) IS NULL) + 5)"
assertParseExpr(
"x is null and a = b or c = d + 5 is null + 5",
"(((x IS NULL) AND (a = b)) OR ((c = (d + 5)) IS (NULL + 5)))");
}
public void testNull() {
assertParseExpr(
"Filter({[Measures].[Foo]}, Iif(1 = 2, NULL, 'X'))",
"Filter({[Measures].[Foo]}, Iif((1 = 2), NULL, \"X\"))");
}
public void testCast() {
assertParseExpr(
"Cast([Measures].[Unit Sales] AS Numeric)",
"CAST([Measures].[Unit Sales] AS Numeric)");
assertParseExpr(
"Cast(1 + 2 AS String)",
"CAST((1 + 2) AS String)");
}
public void testId() {
assertParseExpr("foo", "foo");
assertParseExpr("fOo", "fOo");
assertParseExpr("[Foo].[Bar Baz]", "[Foo].[Bar Baz]");
assertParseExpr("[Foo].&[Bar]", "[Foo].&[Bar]");
}
public void testIdWithKey() {
// two segments each with a compound key
final String mdx = "[Foo].&Key1&Key2.&[Key3]&Key4&[5]";
assertParseExpr(mdx, mdx);
MdxParser p = createParser();
final String mdxQuery = wrapExpr(mdx);
final SelectNode selectNode = p.parseSelect(mdxQuery);
assertEquals(1, selectNode.getWithList().size());
WithMemberNode withMember =
(WithMemberNode) selectNode.getWithList().get(0);
final ParseTreeNode expr = withMember.getExpression();
IdentifierNode id = (IdentifierNode) expr;
assertNotNull(id.getRegion());
assertEquals(3, id.getSegmentList().size());
final IdentifierSegment seg0 = id.getSegmentList().get(0);
assertNotNull(seg0.getRegion());
assertEquals("Foo", seg0.getName());
assertEquals(Quoting.QUOTED, seg0.getQuoting());
final IdentifierSegment seg1 = id.getSegmentList().get(1);
assertEquals(Quoting.KEY, seg1.getQuoting());
assertNull(seg1.getName());
List keyParts = seg1.getKeyParts();
assertNotNull(keyParts);
assertEquals(2, keyParts.size());
assertEquals("Key1", keyParts.get(0).getName());
assertEquals(
Quoting.UNQUOTED, keyParts.get(0).getQuoting());
assertEquals("Key2", keyParts.get(1).getName());
assertEquals(
Quoting.UNQUOTED, keyParts.get(1).getQuoting());
final IdentifierSegment seg2 = id.getSegmentList().get(2);
assertNotNull(seg2.getRegion());
assertEquals(Quoting.KEY, seg2.getQuoting());
List keyParts2 = seg2.getKeyParts();
assertNotNull(keyParts2);
assertEquals(3, keyParts2.size());
assertEquals(
Quoting.QUOTED, keyParts2.get(0).getQuoting());
assertEquals(
Quoting.UNQUOTED, keyParts2.get(1).getQuoting());
assertEquals(
Quoting.QUOTED, keyParts2.get(2).getQuoting());
assertEquals("5", keyParts2.get(2).getName());
assertNotNull(keyParts2.get(2).getRegion());
final String actual = TestContext.toString(expr);
TestContext.assertEqualsVerbose(mdx, actual);
}
public void testIdComplex() {
// simple key
assertParseExpr(
"[Foo].&[Key1]&[Key2].[Bar]",
"[Foo].&[Key1]&[Key2].[Bar]");
// compound key
assertParseExpr(
"[Foo].&[1]&[Key 2]&[3].[Bar]",
"[Foo].&[1]&[Key 2]&[3].[Bar]");
// compound key sans brackets
assertParseExpr(
"[Foo].&Key1&Key2 + 4",
"([Foo].&Key1&Key2 + 4)");
// brackets are requred for numbers
assertParseExprFails(
"[Foo].&[1]&[Key2]&^3.[Bar]",
"Syntax error at \\[1:51\\], token '&'");
// space between ampersand and key is unacceptable
assertParseExprFails(
"[Foo].&^ [Key2].[Bar]",
"Syntax error at \\[1:40\\], token '&'");
// underscore after ampersand is unacceptable
assertParseExprFails(
"[Foo].&^_Key2.[Bar]",
"Syntax error at \\[1:40\\], token '&'");
// but underscore is OK within brackets
assertParseExpr(
"[Foo].&[_Key2].[Bar]",
"[Foo].&[_Key2].[Bar]");
}
// todo: enable this
public void _testCloneQuery() throws SQLException {
OlapConnection olapConnection = getOlapConnection();
MdxParser mdxParser =
olapConnection.getParserFactory()
.createMdxParser(olapConnection);
final SelectNode query = mdxParser.parseSelect(
"select {[Measures].Members} on columns,\n"
+ " {[Store].Members} on rows\n"
+ "from [Sales]\n"
+ "where ([Gender].[M])");
SelectNode selectClone = null; // select.copy();
assertTrue(selectClone instanceof SelectNode);
assertEquals(
TestContext.toString(selectClone),
TestContext.toString(query));
}
/**
* Tests parsing of numbers.
*/
public void testNumbers() {
// Number: [+-] [ . ] [e [+-] ]
assertParseExpr("2", "2");
// leading '-' is treated as an operator -- that's ok
assertParseExpr("-3", "(- 3)");
// leading '+' is ignored -- that's ok
assertParseExpr("+45", "45");
// space bad
assertParseExprFails(
"4 ^5^",
"Syntax error at \\[1:35\\], token '5\\'");
assertParseExpr("3.14", "3.14");
assertParseExpr(".12345", "0.12345");
// lots of digits left and right of point
assertParseExpr("31415926535.89793", "31415926535.89793");
assertParseExpr(
"31415926535897.9314159265358979",
"31415926535897.9314159265358979");
assertParseExpr("3.141592653589793", "3.141592653589793");
assertParseExpr(
"-3141592653589793.14159265358979",
"(- 3141592653589793.14159265358979)");
// exponents akimbo
assertParseExpr("1e2", "100");
assertParseExprFails(
"1e2e^3^", // todo: fix parser; should be "1e2^e3^"
"Syntax error at .* token 'e3'");
assertParseExpr("1.2e3", "1200");
assertParseExpr("-1.2345e3", "(- 1234.5)");
assertParseExprFails(
"1.2e3.^4^", // todo: fix parser; should be "1.2e3^.4^"
"Syntax error at .* token '0.4'");
assertParseExpr(".00234e0003", "2.34");
assertParseExpr(".00234e-0067", "2.34E-70");
}
/**
* Testcase for bug 1688645, "High precision number in MDX causes overflow".
* The problem was that "5000001234" exceeded the precision of the int being
* used to gather the mantissa.
*/
public void testLargePrecision() {
// Now, a query with several numeric literals. This is the original
// testcase for the bug.
assertParseQuery(
"with member [Measures].[Small Number] as '[Measures].[Store Sales] / 9000'\n"
+ "select\n"
+ "{[Measures].[Small Number]} on columns,\n"
+ "{Filter([Product].[Product Department].members, [Measures].[Small Number] >= 0.3\n"
+ "and [Measures].[Small Number] <= 0.5000001234)} on rows\n"
+ "from Sales\n"
+ "where ([Time].[1997].[Q2].[4])",
"WITH\n"
+ "MEMBER [Measures].[Small Number] AS\n"
+ " ([Measures].[Store Sales] / 9000)\n"
+ "SELECT\n"
+ "{[Measures].[Small Number]} ON COLUMNS,\n"
+ "{Filter([Product].[Product Department].members, (([Measures].[Small Number] >= 0.3) AND ([Measures].[Small Number] <= 0.5000001234)))} ON ROWS\n"
+ "FROM Sales\n"
+ "WHERE ([Time].[1997].[Q2].[4])");
}
public void testIdentifier() {
// must have at least one segment
IdentifierNode id;
try {
id = new IdentifierNode();
fail("expected exception");
} catch (IllegalArgumentException e) {
// ok
}
id = new IdentifierNode(
new NameSegment("foo"));
assertEquals("[foo]", id.toString());
// append does not mutate
IdentifierNode id2 = id.append(
new KeySegment(
new NameSegment(
null, "bar", Quoting.QUOTED)));
assertTrue(id != id2);
assertEquals("[foo]", id.toString());
assertEquals("[foo].&[bar]", id2.toString());
// cannot mutate segment list
final List segments = id.getSegmentList();
try {
segments.remove(0);
fail("expected exception");
} catch (UnsupportedOperationException e) {
// ok
}
try {
segments.clear();
fail("expected exception");
} catch (UnsupportedOperationException e) {
// ok
}
try {
segments.add(
new NameSegment("baz"));
fail("expected exception");
} catch (UnsupportedOperationException e) {
// ok
}
}
/**
* Test case for empty expressions. Test case for bug 3030772, "DrilldownLevelTop parser error".
*/
public void testEmptyExpr() {
assertParseQuery(
"select NON EMPTY HIERARCHIZE(\n"
+ " {DrillDownLevelTop(\n"
+ " {[Product].[All Products]},3,,[Measures].[Unit Sales])}"
+ " ) ON COLUMNS\n"
+ "from [Sales]\n",
"SELECT\n"
+ "NON EMPTY HIERARCHIZE({DrillDownLevelTop({[Product].[All Products]}, 3, , [Measures].[Unit Sales])}) ON COLUMNS\n"
+ "FROM [Sales]");
// more advanced; the actual test case in the bug
assertParseQuery(
"SELECT {[Measures].[NetSales]}"
+ " DIMENSION PROPERTIES PARENT_UNIQUE_NAME ON COLUMNS ,"
+ " NON EMPTY HIERARCHIZE(AddCalculatedMembers("
+ "{DrillDownLevelTop({[ProductDim].[Name].[All]}, 10, ,"
+ " [Measures].[NetSales])}))"
+ " DIMENSION PROPERTIES PARENT_UNIQUE_NAME ON ROWS "
+ "FROM [cube]",
"SELECT\n"
+ "{[Measures].[NetSales]} DIMENSION PROPERTIES PARENT_UNIQUE_NAME ON COLUMNS,\n"
+ "NON EMPTY HIERARCHIZE(AddCalculatedMembers({DrillDownLevelTop({[ProductDim].[Name].[All]}, 10, , [Measures].[NetSales])})) DIMENSION PROPERTIES PARENT_UNIQUE_NAME ON ROWS\n"
+ "FROM [cube]");
}
/**
* Test case for SELECT in the FROM clause.
*/
public void testInnerSelect() {
assertParseQuery(
"SELECT FROM "
+ "(SELECT ({[ProductDim].[Product Group].&[Mobile Phones]}) "
+ "ON COLUMNS FROM [cube]) CELL PROPERTIES VALUE",
"SELECT\n"
+ "FROM (\n"
+ " SELECT\n"
+ " {[ProductDim].[Product Group].&[Mobile Phones]} ON COLUMNS\n"
+ " FROM [cube])\n"
+ "CELL PROPERTIES VALUE");
}
/**
* Test case for adding to WITH clause.
*/
public void testWithAdd() {
SelectNode selectNode = new SelectNode();
IdentifierNode startDate =
new IdentifierNode(
new NameSegment("Date"),
new NameSegment("2010-01-03"));
IdentifierNode endDate =
new IdentifierNode(
new NameSegment("Date"),
new NameSegment("2010-10-03"));
IdentifierNode name =
new IdentifierNode(
new NameSegment("Date"),
new NameSegment("Date Range"));
CallNode cn = new CallNode(null, ":", Syntax.Infix, startDate, endDate);
ParseTreeNode exp =
new CallNode(
null,
"Aggregate",
Syntax.Function,
new CallNode(
null,
"{}",
Syntax.Braces,
cn));
WithMemberNode withMemberNode =
new WithMemberNode(
null, name, exp, Collections.emptyList());
selectNode.setFrom(
IdentifierNode.parseIdentifier("Sales"));
selectNode.getWithList().add(withMemberNode);
final String queryString = selectNode.toString();
TestContext.assertEqualsVerbose(
"WITH\n"
+ "MEMBER [Date].[Date Range] AS\n"
+ " Aggregate({([Date].[2010-01-03] : [Date].[2010-10-03])})\n"
+ "SELECT\n"
+ "FROM Sales",
queryString);
// check that unparsed string is valid
assertParseQuery(queryString, TestContext.unfold(queryString));
}
/**
* Parses an MDX query and asserts that the result is as expected when
* unparsed.
*
* @param mdx MDX query
* @param expected Expected result of unparsing
*/
private void assertParseQuery(String mdx, final String expected) {
MdxParser p = createParser();
final SelectNode selectNode = p.parseSelect(mdx);
final String actual = TestContext.toString(selectNode);
TestContext.assertEqualsVerbose(expected, actual);
}
/**
* Parses an MDX expression and asserts that the result is as expected when
* unparsed.
*
* @param expr MDX query
* @param expected Expected result of unparsing
*/
private void assertParseExpr(String expr, final String expected) {
MdxParser p = createParser();
final String mdx = wrapExpr(expr);
final SelectNode selectNode = p.parseSelect(mdx);
assertEquals(1, selectNode.getWithList().size());
WithMemberNode withMember =
(WithMemberNode) selectNode.getWithList().get(0);
final String actual = TestContext.toString(withMember.getExpression());
TestContext.assertEqualsVerbose(expected, actual);
}
private String wrapExpr(String expr) {
return "with member [Measures].[Foo] as "
+ expr
+ "\n select from [Sales]";
}
}
// End ParserTest.java
olap4j-1.0.1.500/testsrc/org/olap4j/test/ArrayMapTest.java 0000644 0001750 0001750 00000031030 11707254766 022762 0 ustar drazzib drazzib /*
// $Id: ArrayMapTest.java 482 2012-01-05 23:27:27Z jhyde $
//
// Licensed to Julian Hyde under one or more contributor license
// agreements. See the NOTICE file distributed with this work for
// additional information regarding copyright ownership.
//
// Julian Hyde licenses this file to you 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.olap4j.test;
import org.olap4j.impl.ArrayMap;
import org.olap4j.impl.UnmodifiableArrayMap;
import junit.framework.TestCase;
import java.util.*;
/**
* Unit test for {@link org.olap4j.impl.ArrayMap}.
*
* @author jhyde
* @version $Id: ArrayMapTest.java 482 2012-01-05 23:27:27Z jhyde $
* @since Dec 9, 2007
*/
public class ArrayMapTest extends TestCase {
public void testArrayMap() {
final ArrayMap map =
new ArrayMap();
// clear empty map
map.clear();
assertEquals(0, map.size());
assertTrue(map.isEmpty());
map.put("Paul", 4);
assertEquals(1, map.size());
assertFalse(map.isEmpty());
assertTrue(map.containsKey("Paul"));
assertFalse(map.containsKey("Keith"));
Integer value = map.put("Paul", 5);
assertEquals(1, map.size());
assertEquals(4, value.intValue());
assertEquals(5, map.get("Paul").intValue());
// null values are allowed
map.put("Paul", null);
assertNull(map.get("Paul"));
assertTrue(map.containsKey("Paul"));
// null keys are allowed
map.put(null, -99);
assertEquals(-99, map.get(null).intValue());
assertTrue(map.containsKey(null));
assertEquals(-99, map.remove(null).intValue());
final Map beatles =
new ArrayMap();
beatles.put("John", 4);
beatles.put("Paul", 4);
beatles.put("George", 6);
beatles.put("Ringo", 5);
map.putAll(beatles);
assertEquals(4, map.size());
assertEquals(
new HashSet(
Arrays.asList("John", "Paul", "George", "Ringo")),
map.keySet());
assertEquals(Arrays.asList(4, 4, 6, 5), map.values());
String keys = "";
int valueTotal = 0;
for (Map.Entry entry : map.entrySet()) {
valueTotal += entry.getValue();
keys += entry.getKey();
}
assertEquals(19, valueTotal);
assertEquals("PaulJohnGeorgeRingo", keys);
value = map.remove("Mick");
assertNull(value);
assertEquals(4, map.size());
// corner case: remove last value
value = map.remove("Ringo");
assertEquals(5, value.intValue());
assertEquals(3, map.size());
// corner case: remove first value
value = map.remove("Paul");
assertEquals(4, value.intValue());
assertEquals(2, map.size());
// add key back in and it becomes last value
map.put("Paul", 27);
assertEquals(Arrays.asList(4, 6, 27), map.values());
// remove an interior value
map.remove("George");
assertEquals(2, map.size());
}
/**
* Oops, forgot that I had written the first test and wrote another. Mostly
* overlap with {@link #testArrayMap()}, but can't hurt.
*/
public void testArrayMap2() {
final ArrayMap map = new ArrayMap();
final HashMap hashMap = new HashMap();
assertEquals(0, map.size());
assertEquals(map, hashMap);
assertEquals(map.hashCode(), hashMap.hashCode());
// put
map.put("foo", 0);
assertEquals(1, map.size());
assertEquals(1, map.keySet().size());
assertEquals(1, map.values().size());
// equivalence to hashmap
hashMap.put("foo", 0);
assertEquals(map, hashMap);
assertEquals(hashMap, map);
assertEquals(map.hashCode(), hashMap.hashCode());
// containsKey, get
assertTrue(map.containsKey("foo"));
assertFalse(map.containsKey("bar"));
assertEquals(Integer.valueOf(0), map.get("foo"));
assertNull(map.get("baz"));
// putall
final Map hashMap2 = new HashMap();
hashMap2.put("bar", 1);
hashMap2.put("foo", 2);
hashMap2.put("baz", 0);
map.putAll(hashMap2);
hashMap.putAll(hashMap2);
assertEquals(3, map.size());
assertEquals(map, hashMap);
assertEquals(hashMap, map);
assertEquals(map.hashCode(), hashMap.hashCode());
assertEquals(map.keySet(), hashMap.keySet());
// values collections have same contents, not necessarily in same order
assertEquals(
new HashSet(map.values()),
new HashSet(hashMap.values()));
// replace existing key
map.put("foo", -5);
hashMap.put("foo", -5);
assertEquals(3, map.size());
assertEquals(Integer.valueOf(-5), map.get("foo"));
assertEquals(map, hashMap);
assertEquals(hashMap, map);
// null key
assertFalse(map.containsKey(null));
map.put(null, 75);
assertEquals(Integer.valueOf(75), map.get(null));
assertTrue(map.containsKey(null));
// null value
map.put("zzzz", null);
assertTrue(map.containsKey("zzzz"));
assertNull(map.get("zzzz"));
// compare to hashmap
hashMap.put(null, 75);
hashMap.put("zzzz", null);
assertEquals(map, hashMap);
assertEquals(hashMap, map);
// isEmpty, clear
assertFalse(map.isEmpty());
map.clear();
assertTrue(map.isEmpty());
assertEquals(0, map.size());
// putAll to populate empty map (uses different code path than putAll
// on non-empty map)
final Map map2 =
new ArrayMap();
map2.putAll(hashMap);
assertEquals(map2, hashMap);
// copy constructor
final Map map3 =
new ArrayMap(hashMap);
assertEquals(map3, hashMap);
// of
final Map map4 =
ArrayMap.of(
"foo", -5,
"bar", 1,
"baz", 0,
null, 75,
"zzzz", null);
assertEquals(map4, hashMap);
// toString
assertEquals(
"{foo=-5, bar=1, baz=0, null=75, zzzz=null}",
map4.toString());
assertEquals("{}", new ArrayMap().toString());
}
/**
* Test for {@link org.olap4j.impl.UnmodifiableArrayMap}.
*/
public void testUnmodifiableArrayMap() {
Map map;
final Map hashMap = new HashMap();
map = new UnmodifiableArrayMap(hashMap);
assertEquals(0, map.size());
assertEquals(map, hashMap);
assertEquals(map.hashCode(), hashMap.hashCode());
// put
try {
int x = map.put("foo", 0);
fail("expected fail, got " + x);
} catch (UnsupportedOperationException e) {
// ok
}
hashMap.put("foo", 0);
map = new UnmodifiableArrayMap(hashMap);
assertEquals(1, map.size());
assertEquals(1, map.keySet().size());
assertEquals(1, map.values().size());
// equivalence to hashmap
assertEquals(map, hashMap);
assertEquals(hashMap, map);
assertEquals(map.hashCode(), hashMap.hashCode());
// containsKey, get
assertTrue(map.containsKey("foo"));
assertFalse(map.containsKey("bar"));
assertEquals(Integer.valueOf(0), map.get("foo"));
assertNull(map.get("baz"));
// putall
final Map hashMap2 = new HashMap();
hashMap2.put("bar", 1);
hashMap2.put("foo", 2);
hashMap2.put("baz", 0);
try {
map.putAll(hashMap2);
fail("expected fail");
} catch (UnsupportedOperationException e) {
// ok
}
hashMap.putAll(hashMap2);
map = new UnmodifiableArrayMap(hashMap);
assertEquals(3, map.size());
assertEquals(map, hashMap);
assertEquals(hashMap, map);
assertEquals(map.hashCode(), hashMap.hashCode());
assertEquals(map.keySet(), hashMap.keySet());
// values collections have same contents, not necessarily in same order
assertEquals(
new HashSet(map.values()),
new HashSet(hashMap.values()));
// replace existing key
try {
int x = map.put("foo", -5);
fail("expected fail, got " + x);
} catch (UnsupportedOperationException e) {
// ok
}
hashMap.put("foo", -5);
map = new UnmodifiableArrayMap(hashMap);
assertEquals(3, map.size());
assertEquals(Integer.valueOf(-5), map.get("foo"));
assertEquals(map, hashMap);
assertEquals(hashMap, map);
// null key
assertFalse(map.containsKey(null));
hashMap.put(null, 75);
map = new UnmodifiableArrayMap(hashMap);
assertEquals(Integer.valueOf(75), map.get(null));
assertTrue(map.containsKey(null));
// null value
hashMap.put("zzzz", null);
map = new UnmodifiableArrayMap(hashMap);
assertTrue(map.containsKey("zzzz"));
assertNull(map.get("zzzz"));
// compare to hashmap
assertEquals(map, hashMap);
assertEquals(hashMap, map);
// isEmpty, clear
assertFalse(map.isEmpty());
try {
map.clear();
fail("expected fail");
} catch (UnsupportedOperationException e) {
// ok
}
assertTrue(
new UnmodifiableArrayMap(
Collections.emptyMap()).isEmpty());
// copy constructor
final Map map3 =
new UnmodifiableArrayMap(hashMap);
assertEquals(map3, hashMap);
// of
final Map map4 =
UnmodifiableArrayMap.of(
"foo", -5,
"bar", 1,
"baz", 0,
null, 75,
"zzzz", null);
assertEquals(map4, hashMap);
// order is preserved
final List keyList = Arrays.asList(
"foo", "bar", "baz", null, "zzzz");
assertEquals(
new ArrayList(map4.keySet()), keyList);
final List valueList = Arrays.asList(-5, 1, 0, 75, null);
assertEquals(
new ArrayList(map4.values()), valueList);
final Iterator valueIter = valueList.iterator();
final Iterator keyIter = keyList.iterator();
for (Map.Entry entry : map4.entrySet()) {
assertEquals(entry.getKey(), keyIter.next());
assertEquals(entry.getValue(), valueIter.next());
}
assertFalse(keyIter.hasNext());
assertFalse(valueIter.hasNext());
// of(Map) - zero entries
hashMap.clear();
final Map map5 = UnmodifiableArrayMap.of(hashMap);
assertTrue(map5 == Collections.emptyMap());
// of(Map) - one entry
hashMap.put("foo", -5);
final Map map6 = UnmodifiableArrayMap.of(hashMap);
assertTrue(
map6.getClass() == Collections.singletonMap("7", "y").getClass());
// of(Map) - 2 or more entries
hashMap.put("bar", 1);
hashMap.put("baz", 0);
final Map map7 = UnmodifiableArrayMap.of(hashMap);
assertEquals(map7, hashMap);
// toString
assertEquals(
"{foo=-5, bar=1, baz=0, null=75, zzzz=null}",
map4.toString());
assertEquals("{}", map5.toString());
}
}
// End ArrayMapTest.java
olap4j-1.0.1.500/testsrc/org/olap4j/OlapTreeTest.java 0000644 0001750 0001750 00000005543 11707254770 022007 0 ustar drazzib drazzib /*
// $Id: OlapTreeTest.java 482 2012-01-05 23:27:27Z jhyde $
//
// Licensed to Julian Hyde under one or more contributor license
// agreements. See the NOTICE file distributed with this work for
// additional information regarding copyright ownership.
//
// Julian Hyde licenses this file to you 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.olap4j;
import org.olap4j.metadata.*;
import org.olap4j.test.TestContext;
import junit.framework.TestCase;
import java.sql.Connection;
import java.util.HashMap;
import java.util.Map;
/**
* Tests some particularities of the OLAP tree objects.
* @author Luc Boudreau
*/
public class OlapTreeTest extends TestCase {
private final TestContext.Tester tester =
TestContext.instance().getTester();
/**
* Simple strategy to prevent connection leaks: each test that needs a
* connection assigns it to this field, and {@link #tearDown()} closes it
* if it is not already closed.
*/
private Connection connection;
protected void tearDown() throws Exception {
// Simple strategy to prevent connection leaks
if (connection != null
&& !connection.isClosed())
{
connection.close();
connection = null;
}
}
/**
* Tests if olap objects can be included in collections and
* retrieved properly.
*/
public void testHashCompatibility() throws Exception {
connection = tester.createConnection();
OlapConnection olapConnection =
tester.getWrapper().unwrap(connection, OlapConnection.class);
Schema schema = olapConnection.getOlapSchema();
Cube cube = schema.getCubes().get("Sales");
Map dimensionMap =
new HashMap();
Dimension dim1 = cube.getDimensions().get("Promotion Media");
dimensionMap.put(dim1, "Test1");
assertTrue(dimensionMap.containsKey(dim1));
assertEquals("Test1", dimensionMap.get(dim1));
Map hierarchyMap =
new HashMap();
Hierarchy hchy1 = dim1.getDefaultHierarchy();
hierarchyMap.put(hchy1, "Test2");
assertTrue(hierarchyMap.containsKey(hchy1));
assertEquals("Test2", hierarchyMap.get(hchy1));
assertTrue(dimensionMap.containsKey(hchy1.getDimension()));
}
}
// End OlapTreeTest.java
olap4j-1.0.1.500/testsrc/org/olap4j/mdx/ 0000755 0001750 0001750 00000000000 11430532676 017347 5 ustar drazzib drazzib olap4j-1.0.1.500/testsrc/org/olap4j/mdx/MdxTest.java 0000644 0001750 0001750 00000016574 11707254770 021622 0 ustar drazzib drazzib /*
// $Id: MdxTest.java 482 2012-01-05 23:27:27Z jhyde $
//
// Licensed to Julian Hyde under one or more contributor license
// agreements. See the NOTICE file distributed with this work for
// additional information regarding copyright ownership.
//
// Julian Hyde licenses this file to you 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.olap4j.mdx;
import org.olap4j.mdx.parser.MdxParser;
import org.olap4j.mdx.parser.impl.DefaultMdxParserImpl;
import org.olap4j.test.TestContext;
import junit.framework.TestCase;
import java.util.*;
/**
* Testcase for org.olap4j.mdx package.
*
* @author jhyde
* @version $Id: MdxTest.java 482 2012-01-05 23:27:27Z jhyde $
* @since Dec 12, 2007
*/
public class MdxTest extends TestCase {
/**
* Tests methods {@link IdentifierNode#quoteMdxIdentifier(String)},
* {@link IdentifierNode#unparseIdentifierList(java.util.List)}.
*/
public void testQuoteMdxIdentifier() {
assertEquals(
"[San Francisco]",
IdentifierNode.quoteMdxIdentifier("San Francisco"));
assertEquals(
"[a [bracketed]] string]",
IdentifierNode.quoteMdxIdentifier("a [bracketed] string"));
assertEquals(
"[Store].[USA].[California]",
IdentifierNode.unparseIdentifierList(
Arrays.asList(
new NameSegment(
null, "Store", Quoting.QUOTED),
new NameSegment(
null, "USA", Quoting.QUOTED),
new NameSegment(
null, "California", Quoting.QUOTED))));
}
public void testImplode() {
List fooBar =
Arrays.asList(
new NameSegment(
null, "foo", Quoting.UNQUOTED),
new NameSegment(
null, "bar", Quoting.QUOTED));
assertEquals(
"foo.[bar]",
IdentifierNode.unparseIdentifierList(fooBar));
List empty = Collections.emptyList();
assertEquals("", IdentifierNode.unparseIdentifierList(empty));
List nasty =
Arrays.asList(
new NameSegment(
null, "string", Quoting.QUOTED),
new NameSegment(
null, "with", Quoting.QUOTED),
new NameSegment(
null, "a [bracket] in it", Quoting.QUOTED));
assertEquals(
"[string].[with].[a [bracket]] in it]",
IdentifierNode.unparseIdentifierList(nasty));
}
public void testParseIdentifier() {
List segments =
IdentifierNode.parseIdentifier(
"[string].[with].[a [bracket]] in it]").getSegmentList();
assertEquals(3, segments.size());
assertEquals(
"a [bracket] in it",
segments.get(2).getName());
assertEquals(
Quoting.QUOTED,
segments.get(2).getQuoting());
segments = IdentifierNode.parseIdentifier(
"[Worklog].[All].[calendar-[LANGUAGE]].js]").getSegmentList();
assertEquals(3, segments.size());
assertEquals(
"calendar-[LANGUAGE].js",
segments.get(2).getName());
segments = IdentifierNode.parseIdentifier("[foo].bar").getSegmentList();
assertEquals(2, segments.size());
assertEquals(
Quoting.QUOTED,
segments.get(0).getQuoting());
assertEquals(
Quoting.UNQUOTED,
segments.get(1).getQuoting());
try {
segments =
IdentifierNode.parseIdentifier("[foo].[bar").getSegmentList();
fail("expected exception, got " + segments);
} catch (RuntimeException e) {
assertEquals(
"Expected ']', in member identifier '[foo].[bar'",
e.getMessage());
}
}
/**
* Unit test for {@link org.olap4j.mdx.IdentifierNode#ofNames(String...)}.
*/
public void testIdentifierOfNames() {
IdentifierNode identifierNode =
IdentifierNode.ofNames(
"string", "with", "a [bracket] in it");
List segments =
identifierNode.getSegmentList();
assertEquals(3, segments.size());
assertEquals(
"a [bracket] in it",
segments.get(2).getName());
assertEquals(
Quoting.QUOTED,
segments.get(2).getQuoting());
assertEquals(
"[string].[with].[a [bracket]] in it]",
identifierNode.toString());
// Empty array is invalid.
try {
identifierNode = IdentifierNode.ofNames();
fail("expected error, got " + identifierNode);
} catch (IllegalArgumentException e) {
// ok
}
// Array containing null is not valid.
try {
identifierNode =
IdentifierNode.ofNames("foo", null, "bar");
fail("expected error, got " + identifierNode);
} catch (NullPointerException e) {
// ok
}
}
/**
* Tests that escaped single quotes ('') nested inside a quoted
* part of a query are handled correctly. The MDX language allows
* expressions for calculated members and sets to be specified with and
* without single quotes; the unparser generates expressions without quotes.
*/
public void testQuoteEscaping() {
String query =
"WITH\n"
+ "MEMBER [CustomerDim].[CustomerName].[XL_QZX] AS 'Aggregate"
+ "({[CustomerDim].[CustomerName].&[ABC INT''L],"
+ " [CustomerDim].[CustomerName].&[XYZ]})'\n"
+ "SELECT\n"
+ "{[Measures].[Sales]} ON COLUMNS\n"
+ "FROM [cube]\n"
+ "WHERE ([CustomerDim].[CustomerName].[XL_QZX])";
final MdxParser parser = new DefaultMdxParserImpl();
SelectNode rootNode = parser.parseSelect(query);
TestContext.assertEqualsVerbose(
"WITH\n"
+ "MEMBER [CustomerDim].[CustomerName].[XL_QZX] AS\n"
+ " Aggregate({[CustomerDim].[CustomerName].&[ABC INT'L], [CustomerDim].[CustomerName].&[XYZ]})\n"
+ "SELECT\n"
+ "{[Measures].[Sales]} ON COLUMNS\n"
+ "FROM [cube]\n"
+ "WHERE ([CustomerDim].[CustomerName].[XL_QZX])",
rootNode.toString());
// Now named set
query =
"WITH SET Foo as Filter(Bar.Members, Instr(Name, \"'\") > 0)\n"
+ "SELECT FROM [Cube]";
rootNode = parser.parseSelect(query);
TestContext.assertEqualsVerbose(
"WITH\n"
+ "SET Foo AS\n"
+ " Filter(Bar.Members, (Instr(Name, \"'\") > 0))\n"
+ "SELECT\n"
+ "FROM [Cube]",
rootNode.toString());
}
}
// End MdxTest.java
olap4j-1.0.1.500/testsrc/org/olap4j/OlapTest.java 0000644 0001750 0001750 00000177017 11711470530 021162 0 ustar drazzib drazzib /*
// $Id: OlapTest.java 498 2012-01-30 16:30:42Z lucboudreau $
//
// Licensed to Julian Hyde under one or more contributor license
// agreements. See the NOTICE file distributed with this work for
// additional information regarding copyright ownership.
//
// Julian Hyde licenses this file to you 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.olap4j;
import org.olap4j.impl.Bug;
import org.olap4j.mdx.SelectNode;
import org.olap4j.metadata.*;
import org.olap4j.query.*;
import org.olap4j.query.QueryDimension.HierarchizeMode;
import org.olap4j.query.Selection.Operator;
import org.olap4j.test.TestContext;
import junit.framework.TestCase;
import java.sql.Connection;
import java.sql.DriverManager;
import static org.olap4j.test.TestContext.nameList;
/**
* Unit test illustrating sequence of calls to olap4j API from a graphical
* client.
*
* @since May 22, 2007
* @author James Dixon
* @version $Id: OlapTest.java 498 2012-01-30 16:30:42Z lucboudreau $
*/
public class OlapTest extends TestCase {
private TestContext testContext = TestContext.instance();
private TestContext.Tester tester = testContext.getTester();
private Connection connection;
public OlapTest() {
super();
}
protected void tearDown() throws Exception {
// Simple strategy to prevent connection leaks
if (connection != null
&& !connection.isClosed())
{
connection.close();
connection = null;
}
testContext = null;
tester = null;
}
public Cube getFoodmartCube(String cubeName) throws Exception {
connection = tester.createConnection();
OlapConnection olapConnection =
tester.getWrapper().unwrap(connection, OlapConnection.class);
Catalog catalog = olapConnection.getOlapCatalogs().get("FoodMart");
NamedList schemas = catalog.getSchemas();
if (schemas.size() == 0) {
return null;
}
// Use the first schema
Schema schema = schemas.get(0);
// Get a list of cube objects and dump their names
NamedList cubes = schema.getCubes();
if (cubes.size() == 0) {
// no cubes where present
return null;
}
// take the first cube
return cubes.get(cubeName);
}
public void testModel() throws Exception {
if (false) {
// define the connection information
String schemaUri = "file:/open/mondrian/demo/FoodMart.xml";
String schemaName = "FoodMart";
String userName = "foodmartuser";
String password = "foodmartpassword";
String jdbc =
"jdbc:mysql://localhost/foodmart?user=foodmartuser"
+ "&password=foodmartpassword";
// Create a connection object to the specific implementation of an
// olap4j source. This is the only provider-specific code.
Class.forName("mondrian.olap4j.MondrianOlap4jDriver");
connection = DriverManager.getConnection(
"jdbc:mondrian:Jdbc=" + jdbc
+ ";User=" + userName
+ ";Password=" + password
+ ";Catalog=" + schemaUri);
} else {
connection = tester.createConnection();
}
OlapConnection olapConnection =
tester.getWrapper().unwrap(connection, OlapConnection.class);
// REVIEW: jhyde: Why do you want to name connections? We could add
// a connect string property 'description', if that helps
// connection.setName("First Connection");
// The code from here on is generic olap4j stuff
// Get a list of the schemas available from this connection and dump
// their names.
Catalog catalog = olapConnection.getOlapCatalogs().get("FoodMart");
NamedList schemas = catalog.getSchemas();
if (schemas.size() == 0) {
// No schemas were present
return;
}
// Use the first schema
Schema schema = schemas.get(0);
// Get a list of cube objects and dump their names
NamedList cubes = schema.getCubes();
if (cubes.size() == 0) {
// no cubes where present
return;
}
// take the "Sales" cube
Cube cube = cubes.get("Sales");
// The code from this point on is for the Foodmart schema
// Create a new query
Query query = new Query("my query", cube);
QueryDimension productQuery = query.getDimension("Product");
QueryDimension storeQuery = query.getDimension("Store");
QueryDimension timeQuery = query.getDimension("Time");
Member productMember =
cube.lookupMember(nameList("Product", "Drink"));
// create some selections for Store
storeQuery.include(
Selection.Operator.CHILDREN, nameList("Store", "USA"));
// create some selections for Product
productQuery.clearInclusions();
productQuery.include(
Selection.Operator.CHILDREN, productMember);
productQuery.include(
Selection.Operator.CHILDREN, nameList("Product", "Food"));
// create some selections for Time
timeQuery.include(
Selection.Operator.CHILDREN, nameList("Time", "1997"));
// place our dimensions on the axes
query.getAxis(Axis.COLUMNS).addDimension(productQuery);
assert productQuery.getAxis() == query.getAxis(Axis.COLUMNS);
query.getAxis(Axis.ROWS).addDimension(storeQuery);
query.getAxis(Axis.ROWS).addDimension(timeQuery);
try {
query.getAxis(Axis.ROWS).addDimension(storeQuery);
fail("expected exception");
} catch (Exception e) {
assertTrue(
e.getMessage().contains("dimension already on this axis"));
}
query.validate();
query.execute();
// for shits and giggles we'll swap the axes over
query.swapAxes();
query.validate();
query.execute();
}
public void testSelectionModes() throws Exception {
Cube cube = getFoodmartCube("Sales");
if (cube == null) {
fail("Could not find Sales cube");
}
Query query = new Query("my query", cube);
// TEST CHILDREN SELECTION
QueryDimension productDimension = query.getDimension("Product");
productDimension.include(
Selection.Operator.CHILDREN, nameList("Product", "Drink"));
QueryDimension measuresDimension = query.getDimension("Measures");
measuresDimension.include(nameList("Measures", "Store Sales"));
query.getAxis(Axis.ROWS).addDimension(productDimension);
query.getAxis(Axis.COLUMNS).addDimension(measuresDimension);
query.validate();
SelectNode mdx = query.getSelect();
String mdxString = mdx.toString();
TestContext.assertEqualsVerbose(
"SELECT\n"
+ "{[Measures].[Store Sales]} ON COLUMNS,\n"
+ "{[Product].[Drink].Children} ON ROWS\n"
+ "FROM [Sales]",
mdxString);
// TEST ANCESTORS SELECTION
productDimension.clearInclusions();
productDimension.include(
Selection.Operator.ANCESTORS, nameList("Product", "Drink"));
query.validate();
mdx = query.getSelect();
mdxString = mdx.toString();
TestContext.assertEqualsVerbose(
"SELECT\n"
+ "{[Measures].[Store Sales]} ON COLUMNS,\n"
+ "{Ascendants([Product].[Drink])} ON ROWS\n"
+ "FROM [Sales]",
mdxString);
// TEST DESCENDANTS SELECTION
productDimension.clearInclusions();
productDimension.include(
Selection.Operator.DESCENDANTS, nameList("Product", "Drink"));
query.validate();
mdx = query.getSelect();
mdxString = mdx.toString();
TestContext.assertEqualsVerbose(
"SELECT\n"
+ "{[Measures].[Store Sales]} ON COLUMNS,\n"
+ "{Descendants([Product].[Drink])} ON ROWS\n"
+ "FROM [Sales]",
mdxString);
// TEST INCLUDE_CHILDREN SELECTION
productDimension.clearInclusions();
productDimension.include(
Selection.Operator.INCLUDE_CHILDREN,
nameList("Product", "Drink"));
query.validate();
mdx = query.getSelect();
mdxString = mdx.toString();
TestContext.assertEqualsVerbose(
"SELECT\n"
+ "{[Measures].[Store Sales]} ON COLUMNS,\n"
+ "{{[Product].[Drink], [Product].[Drink].Children}} ON ROWS\n"
+ "FROM [Sales]",
mdxString);
// TEST SIBLINGS SELECTION
productDimension.clearInclusions();
productDimension.include(
Selection.Operator.SIBLINGS, nameList("Product", "Drink"));
query.validate();
mdx = query.getSelect();
mdxString = mdx.toString();
TestContext.assertEqualsVerbose(
"SELECT\n"
+ "{[Measures].[Store Sales]} ON COLUMNS,\n"
+ "{[Product].[Drink].Siblings} ON ROWS\n"
+ "FROM [Sales]",
mdxString);
// TEST LEVEL MEMBERS SELECTION
NamedList productLevels =
productDimension.getDimension().getDefaultHierarchy().getLevels();
Level productDepartments = productLevels.get("Product Department");
productDimension.include(productDepartments);
query.validate();
mdx = query.getSelect();
mdxString = mdx.toString();
TestContext.assertEqualsVerbose(
"SELECT\n"
+ "{[Measures].[Store Sales]} ON COLUMNS,\n"
+ "{[Product].[Drink].Siblings, [Product].[Product Department].Members} ON ROWS\n"
+ "FROM [Sales]", mdxString);
}
public void testMultipleDimensionSelections() throws Exception {
Cube cube = getFoodmartCube("Sales");
if (cube == null) {
fail("Could not find Sales cube");
}
Query query = new Query("my query", cube);
// create selections
QueryDimension productDimension = query.getDimension("Product");
productDimension.include(
Selection.Operator.CHILDREN, nameList("Product", "Drink"));
QueryDimension storeDimension = query.getDimension("Store");
storeDimension.include(
Selection.Operator.INCLUDE_CHILDREN, nameList("Store", "USA"));
QueryDimension timeDimension = query.getDimension("Time");
timeDimension.include(
Selection.Operator.CHILDREN, nameList("Time", "1997"));
QueryDimension measuresDimension = query.getDimension("Measures");
measuresDimension.include(nameList("Measures", "Store Sales"));
query.getAxis(Axis.ROWS).addDimension(productDimension);
query.getAxis(Axis.ROWS).addDimension(storeDimension);
query.getAxis(Axis.ROWS).addDimension(timeDimension);
query.getAxis(Axis.COLUMNS).addDimension(measuresDimension);
query.validate();
SelectNode mdx = query.getSelect();
String mdxString = mdx.toString();
TestContext.assertEqualsVerbose(
"SELECT\n"
+ "{[Measures].[Store Sales]} ON COLUMNS,\n"
+ "CrossJoin([Product].[Drink].Children, "
+ "CrossJoin({[Store].[USA], "
+ "[Store].[USA].Children}, "
+ "[Time].[1997].Children)) ON ROWS\n"
+ "FROM [Sales]", mdxString);
}
public void testSwapAxes() throws Exception {
Cube cube = getFoodmartCube("Sales");
if (cube == null) {
fail("Could not find Sales cube");
}
Query query = new Query("my query", cube);
// create selections
QueryDimension productDimension = query.getDimension("Product");
productDimension.include(
Selection.Operator.CHILDREN, nameList("Product", "Drink"));
QueryDimension measuresDimension = query.getDimension("Measures");
measuresDimension.include(nameList("Measures", "Store Sales"));
query.getAxis(Axis.ROWS).addDimension(productDimension);
query.getAxis(Axis.COLUMNS).addDimension(measuresDimension);
query.validate();
assertEquals(
Axis.ROWS,
productDimension.getAxis().getLocation());
assertEquals(
Axis.COLUMNS,
measuresDimension.getAxis().getLocation());
SelectNode mdx = query.getSelect();
String mdxString = mdx.toString();
TestContext.assertEqualsVerbose(
"SELECT\n"
+ "{[Measures].[Store Sales]} ON COLUMNS,\n"
+ "{[Product].[Drink].Children} ON ROWS\n"
+ "FROM [Sales]",
mdxString);
query.swapAxes();
assertEquals(
Axis.COLUMNS,
productDimension.getAxis().getLocation());
assertEquals(
Axis.ROWS,
measuresDimension.getAxis().getLocation());
mdx = query.getSelect();
mdxString = mdx.toString();
TestContext.assertEqualsVerbose(
"SELECT\n"
+ "{[Product].[Drink].Children} ON COLUMNS,\n"
+ "{[Measures].[Store Sales]} ON ROWS\n"
+ "FROM [Sales]",
mdxString);
query.swapAxes();
}
public void testSortDimension() throws Exception {
Cube cube = getFoodmartCube("Sales");
if (cube == null) {
fail("Could not find Sales cube");
}
Query query = new Query("my query", cube);
// create selections
QueryDimension productDimension = query.getDimension("Product");
productDimension.include(
Selection.Operator.INCLUDE_CHILDREN,
nameList("Product", "Drink"));
QueryDimension measuresDimension = query.getDimension("Measures");
measuresDimension.include(nameList("Measures", "Store Sales"));
QueryDimension timeDimension = query.getDimension("Time");
timeDimension.include(nameList("Time", "Year", "1997", "Q3", "7"));
query.getAxis(Axis.ROWS).addDimension(productDimension);
query.getAxis(Axis.COLUMNS).addDimension(measuresDimension);
query.getAxis(Axis.FILTER).addDimension(timeDimension);
query.validate();
assertEquals(
Axis.ROWS,
productDimension.getAxis().getLocation());
assertEquals(
Axis.COLUMNS,
measuresDimension.getAxis().getLocation());
SelectNode mdx = query.getSelect();
String mdxString = mdx.toString();
TestContext.assertEqualsVerbose(
"SELECT\n"
+ "{[Measures].[Store Sales]} ON COLUMNS,\n"
+ "{{[Product].[Drink], [Product].[Drink].Children}} ON ROWS\n"
+ "FROM [Sales]\n"
+ "WHERE {[Time].[1997].[Q3].[7]}",
mdxString);
// Sort the products in ascending order.
query.getDimension("Product").sort(SortOrder.DESC);
SelectNode sortedMdx = query.getSelect();
String sortedMdxString = sortedMdx.toString();
TestContext.assertEqualsVerbose(
"SELECT\n"
+ "{[Measures].[Store Sales]} ON COLUMNS,\n"
+ "{Order({{[Product].[Drink], [Product].[Drink].Children}}, [Product].CurrentMember.Name, DESC)} ON ROWS\n"
+ "FROM [Sales]\n"
+ "WHERE {[Time].[1997].[Q3].[7]}",
sortedMdxString);
CellSet results = query.execute();
String s = TestContext.toString(results);
TestContext.assertEqualsVerbose(
"Axis #0:\n"
+ "{[Time].[1997].[Q3].[7]}\n"
+ "Axis #1:\n"
+ "{[Measures].[Store Sales]}\n"
+ "Axis #2:\n"
+ "{[Product].[Drink]}\n"
+ "{[Product].[Drink].[Dairy]}\n"
+ "{[Product].[Drink].[Beverages]}\n"
+ "{[Product].[Drink].[Alcoholic Beverages]}\n"
+ "Row #0: 4,409.58\n"
+ "Row #1: 629.69\n"
+ "Row #2: 2,477.02\n"
+ "Row #3: 1,302.87\n",
s);
}
public void testSortMultipleDimension() throws Exception {
Cube cube = getFoodmartCube("Sales");
if (cube == null) {
fail("Could not find Sales cube");
}
Query query = new Query("my query", cube);
// create selections
QueryDimension productDimension = query.getDimension("Product");
productDimension.include(
Selection.Operator.CHILDREN, nameList("Product", "Drink"));
QueryDimension measuresDimension = query.getDimension("Measures");
measuresDimension.include(nameList("Measures", "Store Sales"));
QueryDimension timeDimension = query.getDimension("Time");
timeDimension.include(nameList("Time", "Year", "1997", "Q3", "7"));
query.getAxis(Axis.ROWS).addDimension(timeDimension);
query.getAxis(Axis.ROWS).addDimension(productDimension);
query.getAxis(Axis.COLUMNS).addDimension(measuresDimension);
query.validate();
assertEquals(
Axis.ROWS,
timeDimension.getAxis().getLocation());
assertEquals(
Axis.ROWS,
productDimension.getAxis().getLocation());
assertEquals(
Axis.COLUMNS,
measuresDimension.getAxis().getLocation());
SelectNode mdx = query.getSelect();
String mdxString = mdx.toString();
TestContext.assertEqualsVerbose(
"SELECT\n"
+ "{[Measures].[Store Sales]} ON COLUMNS,\n"
+ "CrossJoin({[Time].[1997].[Q3].[7]}, [Product].[Drink].Children) ON ROWS\n"
+ "FROM [Sales]",
mdxString);
// Sort the products in ascending order.
query.getDimension("Product").sort(SortOrder.DESC);
SelectNode sortedMdx = query.getSelect();
String sortedMdxString = sortedMdx.toString();
TestContext.assertEqualsVerbose(
"SELECT\n"
+ "{[Measures].[Store Sales]} ON COLUMNS,\n"
+ "CrossJoin({[Time].[1997].[Q3].[7]}, Order({[Product].[Drink].Children}, [Product].CurrentMember.Name, DESC)) ON ROWS\n"
+ "FROM [Sales]",
sortedMdxString);
CellSet results = query.execute();
String s = TestContext.toString(results);
TestContext.assertEqualsVerbose(
"Axis #0:\n"
+ "{}\n"
+ "Axis #1:\n"
+ "{[Measures].[Store Sales]}\n"
+ "Axis #2:\n"
+ "{[Time].[1997].[Q3].[7], [Product].[Drink].[Dairy]}\n"
+ "{[Time].[1997].[Q3].[7], [Product].[Drink].[Beverages]}\n"
+ "{[Time].[1997].[Q3].[7], [Product].[Drink].[Alcoholic Beverages]}\n"
+ "Row #0: 629.69\n"
+ "Row #1: 2,477.02\n"
+ "Row #2: 1,302.87\n",
s);
// Just to be sure we execute the sort on a NON EMPTY axis again
query.getAxis(Axis.ROWS).setNonEmpty(true);
productDimension.clearInclusions();
productDimension.include(
Selection.Operator.CHILDREN, nameList("Product", "Food"));
SelectNode sortedMdxNonEmpty = query.getSelect();
String sortedMdxNonEmptyString = sortedMdxNonEmpty.toString();
TestContext.assertEqualsVerbose(
"SELECT\n"
+ "{[Measures].[Store Sales]} ON COLUMNS,\n"
+ "NON EMPTY CrossJoin({[Time].[1997].[Q3].[7]}, Order({[Product].[Food].Children}, [Product].CurrentMember.Name, DESC)) ON ROWS\n"
+ "FROM [Sales]",
sortedMdxNonEmptyString);
CellSet results2 = query.execute();
String s2 = TestContext.toString(results2);
TestContext.assertEqualsVerbose(
"Axis #0:\n"
+ "{}\n"
+ "Axis #1:\n"
+ "{[Measures].[Store Sales]}\n"
+ "Axis #2:\n"
+ "{[Time].[1997].[Q3].[7], [Product].[Food].[Starchy Foods]}\n"
+ "{[Time].[1997].[Q3].[7], [Product].[Food].[Snacks]}\n"
+ "{[Time].[1997].[Q3].[7], [Product].[Food].[Snack Foods]}\n"
+ "{[Time].[1997].[Q3].[7], [Product].[Food].[Seafood]}\n"
+ "{[Time].[1997].[Q3].[7], [Product].[Food].[Produce]}\n"
+ "{[Time].[1997].[Q3].[7], [Product].[Food].[Meat]}\n"
+ "{[Time].[1997].[Q3].[7], [Product].[Food].[Frozen Foods]}\n"
+ "{[Time].[1997].[Q3].[7], [Product].[Food].[Eggs]}\n"
+ "{[Time].[1997].[Q3].[7], [Product].[Food].[Deli]}\n"
+ "{[Time].[1997].[Q3].[7], [Product].[Food].[Dairy]}\n"
+ "{[Time].[1997].[Q3].[7], [Product].[Food].[Canned Products]}\n"
+ "{[Time].[1997].[Q3].[7], [Product].[Food].[Canned Foods]}\n"
+ "{[Time].[1997].[Q3].[7], [Product].[Food].[Breakfast Foods]}\n"
+ "{[Time].[1997].[Q3].[7], [Product].[Food].[Baking Goods]}\n"
+ "{[Time].[1997].[Q3].[7], [Product].[Food].[Baked Goods]}\n"
+ "Row #0: 1,059.06\n"
+ "Row #1: 1,248.92\n"
+ "Row #2: 6,342.01\n"
+ "Row #3: 383.20\n"
+ "Row #4: 7,084.85\n"
+ "Row #5: 304.61\n"
+ "Row #6: 5,027.30\n"
+ "Row #7: 930.70\n"
+ "Row #8: 2,222.69\n"
+ "Row #9: 2,896.81\n"
+ "Row #10: 250.84\n"
+ "Row #11: 3,301.38\n"
+ "Row #12: 551.95\n"
+ "Row #13: 3,232.70\n"
+ "Row #14: 1,487.74\n",
s2);
}
public void testSelectionContext() throws Exception {
Cube cube = getFoodmartCube("Sales");
if (cube == null) {
fail("Could not find Sales cube");
}
Query query = new Query("my query", cube);
// create selections
QueryDimension productDimension = query.getDimension("Product");
productDimension.include(
Selection.Operator.INCLUDE_CHILDREN,
nameList("Product", "All Products"));
QueryDimension timeDimension = query.getDimension("Time");
timeDimension.include(
Selection.Operator.MEMBER, nameList("Time", "Year", "1997"));
Selection selection =
timeDimension.include(
Selection.Operator.CHILDREN, nameList("Time", "Year", "1997"));
selection.addContext(
productDimension.createSelection(
nameList("Product", "All Products", "Drink")));
// [Store].[All Stores]
QueryDimension storeDimension = query.getDimension("Store");
storeDimension.include(
Selection.Operator.MEMBER, nameList("Store", "All Stores"));
Selection children =
storeDimension.include(
Selection.Operator.CHILDREN, nameList("Store", "All Stores"));
children.addContext(
productDimension.createSelection(
nameList("Product", "All Products", "Drink")));
children.addContext(
timeDimension.createSelection(nameList("Time", "1997", "Q3")));
QueryDimension measuresDimension = query.getDimension("Measures");
measuresDimension.include(nameList("Measures", "Store Sales"));
query.getAxis(Axis.ROWS).addDimension(productDimension);
query.getAxis(Axis.ROWS).addDimension(timeDimension);
query.getAxis(Axis.ROWS).addDimension(storeDimension);
query.getAxis(Axis.COLUMNS).addDimension(measuresDimension);
query.validate();
assertEquals(
Axis.ROWS,
productDimension.getAxis().getLocation());
assertEquals(
Axis.COLUMNS,
measuresDimension.getAxis().getLocation());
SelectNode mdx = query.getSelect();
String mdxString = mdx.toString();
TestContext.assertEqualsVerbose(
"SELECT\n"
+ "{[Measures].[Store Sales]} ON COLUMNS,\n"
+ "Hierarchize(Union(CrossJoin({[Product].[All Products], [Product].[All Products].Children}, CrossJoin({[Time].[1997]}, {[Store].[All Stores]})), Union(CrossJoin({[Product].[Drink]}, CrossJoin({[Time].[1997].[Q3]}, [Store].[All Stores].Children)), CrossJoin({[Product].[Drink]}, CrossJoin([Time].[1997].Children, {[Store].[All Stores]}))))) ON ROWS\n"
+ "FROM [Sales]",
mdxString);
// Sort the rows in ascending order.
query.getAxis(Axis.ROWS).sort(
SortOrder.ASC,
nameList("Measures", "Store Sales"));
SelectNode sortedMdx = query.getSelect();
String sortedMdxString = sortedMdx.toString();
TestContext.assertEqualsVerbose(
"SELECT\n"
+ "{[Measures].[Store Sales]} ON COLUMNS,\n"
+ "Order(Hierarchize(Union(CrossJoin({[Product].[All Products], [Product].[All Products].Children}, CrossJoin({[Time].[1997]}, {[Store].[All Stores]})), Union(CrossJoin({[Product].[Drink]}, CrossJoin({[Time].[1997].[Q3]}, [Store].[All Stores].Children)), CrossJoin({[Product].[Drink]}, CrossJoin([Time].[1997].Children, {[Store].[All Stores]}))))), [Measures].[Store Sales], ASC) ON ROWS\n"
+ "FROM [Sales]",
sortedMdxString);
CellSet results = query.execute();
String s = TestContext.toString(results);
TestContext.assertEqualsVerbose(
"Axis #0:\n"
+ "{}\n"
+ "Axis #1:\n"
+ "{[Measures].[Store Sales]}\n"
+ "Axis #2:\n"
+ "{[Product].[All Products], [Time].[1997], [Store].[All Stores]}\n"
+ "{[Product].[Drink], [Time].[1997], [Store].[All Stores]}\n"
+ "{[Product].[Drink], [Time].[1997].[Q1], [Store].[All Stores]}\n"
+ "{[Product].[Drink], [Time].[1997].[Q2], [Store].[All Stores]}\n"
+ "{[Product].[Drink], [Time].[1997].[Q3], [Store].[All Stores]}\n"
+ "{[Product].[Drink], [Time].[1997].[Q3], [Store].[Canada]}\n"
+ "{[Product].[Drink], [Time].[1997].[Q3], [Store].[Mexico]}\n"
+ "{[Product].[Drink], [Time].[1997].[Q3], [Store].[USA]}\n"
+ "{[Product].[Drink], [Time].[1997].[Q4], [Store].[All Stores]}\n"
+ "{[Product].[Non-Consumable], [Time].[1997], [Store].[All Stores]}\n"
+ "{[Product].[Food], [Time].[1997], [Store].[All Stores]}\n"
+ "Row #0: 565,238.13\n"
+ "Row #1: 48,836.21\n"
+ "Row #2: 11,585.80\n"
+ "Row #3: 11,914.58\n"
+ "Row #4: 11,994.00\n"
+ "Row #5: \n"
+ "Row #6: \n"
+ "Row #7: 11,994.00\n"
+ "Row #8: 13,341.83\n"
+ "Row #9: 107,366.33\n"
+ "Row #10: 409,035.59\n",
s);
}
public void testComplexSelectionContext() throws Exception {
Cube cube = getFoodmartCube("Sales");
if (cube == null) {
fail("Could not find Sales cube");
}
Query query = new Query("my query", cube);
// create selections
QueryDimension productDimension = query.getDimension("Product");
productDimension.include(
Selection.Operator.MEMBER, nameList("Product", "All Products"));
productDimension.include(
Selection.Operator.CHILDREN, nameList("Product", "All Products"));
QueryDimension timeDimension = query.getDimension("Time");
Selection selection = timeDimension.include(
Selection.Operator.CHILDREN, nameList("Time", "Year", "1997"));
selection.addContext(
productDimension.createSelection(
nameList("Product", "All Products")));
QueryDimension measuresDimension = query.getDimension("Measures");
measuresDimension.include(nameList("Measures", "Store Sales"));
query.getAxis(Axis.ROWS).addDimension(productDimension);
query.getAxis(Axis.ROWS).addDimension(timeDimension);
query.getAxis(Axis.COLUMNS).addDimension(measuresDimension);
query.validate();
assertEquals(
Axis.ROWS,
productDimension.getAxis().getLocation());
assertEquals(
Axis.ROWS,
timeDimension.getAxis().getLocation());
assertEquals(
Axis.COLUMNS,
measuresDimension.getAxis().getLocation());
if (!Bug.BugOlap4j3106220Fixed) {
return;
}
SelectNode mdx = query.getSelect();
String mdxString = mdx.toString();
TestContext.assertEqualsVerbose(
"SELECT\n"
+ "{[Measures].[Store Sales]} ON COLUMNS,\n"
+ "Hierarchize(Union(CrossJoin({[Product].[All Products]}, [Time].[1997].Children), CrossJoin([Product].[All Products].Children, [Time].[1997].Children))) ON ROWS\n"
+ "FROM [Sales]",
mdxString);
CellSet results = query.execute();
String s = TestContext.toString(results);
TestContext.assertEqualsVerbose(
"Axis #0:\n"
+ "{}\n"
+ "Axis #1:\n"
+ "{[Measures].[Store Sales]}\n"
+ "Axis #2:\n"
+ "{[Product].[All Products], [Time].[1997].[Q1]}\n"
+ "{[Product].[All Products], [Time].[1997].[Q2]}\n"
+ "{[Product].[All Products], [Time].[1997].[Q3]}\n"
+ "{[Product].[All Products], [Time].[1997].[Q4]}\n"
+ "{[Product].[Drink], [Time].[1997].[Q1]}\n"
+ "{[Product].[Drink], [Time].[1997].[Q2]}\n"
+ "{[Product].[Drink], [Time].[1997].[Q3]}\n"
+ "{[Product].[Drink], [Time].[1997].[Q4]}\n"
+ "{[Product].[Food], [Time].[1997].[Q1]}\n"
+ "{[Product].[Food], [Time].[1997].[Q2]}\n"
+ "{[Product].[Food], [Time].[1997].[Q3]}\n"
+ "{[Product].[Food], [Time].[1997].[Q4]}\n"
+ "{[Product].[Non-Consumable], [Time].[1997].[Q1]}\n"
+ "{[Product].[Non-Consumable], [Time].[1997].[Q2]}\n"
+ "{[Product].[Non-Consumable], [Time].[1997].[Q3]}\n"
+ "{[Product].[Non-Consumable], [Time].[1997].[Q4]}\n"
+ "Row #0: 139,628.35\n"
+ "Row #1: 132,666.27\n"
+ "Row #2: 140,271.89\n"
+ "Row #3: 152,671.62\n"
+ "Row #4: 11,585.80\n"
+ "Row #5: 11,914.58\n"
+ "Row #6: 11,994.00\n"
+ "Row #7: 13,341.83\n"
+ "Row #8: 101,261.32\n"
+ "Row #9: 95,436.00\n"
+ "Row #10: 101,807.60\n"
+ "Row #11: 110,530.67\n"
+ "Row #12: 26,781.23\n"
+ "Row #13: 25,315.69\n"
+ "Row #14: 26,470.29\n"
+ "Row #15: 28,799.12\n",
s);
}
public void testSortAxis() throws Exception {
Cube cube = getFoodmartCube("Sales");
if (cube == null) {
fail("Could not find Sales cube");
}
Query query = new Query("my query", cube);
// create selections
QueryDimension productDimension = query.getDimension("Product");
productDimension.include(
Selection.Operator.INCLUDE_CHILDREN,
nameList("Product", "Drink"));
QueryDimension measuresDimension = query.getDimension("Measures");
measuresDimension.include(nameList("Measures", "Store Sales"));
QueryDimension timeDimension = query.getDimension("Time");
timeDimension.include(nameList("Time", "Year", "1997", "Q3", "7"));
query.getAxis(Axis.ROWS).addDimension(productDimension);
query.getAxis(Axis.COLUMNS).addDimension(measuresDimension);
query.getAxis(Axis.FILTER).addDimension(timeDimension);
query.validate();
assertEquals(
Axis.ROWS,
productDimension.getAxis().getLocation());
assertEquals(
Axis.COLUMNS,
measuresDimension.getAxis().getLocation());
SelectNode mdx = query.getSelect();
String mdxString = mdx.toString();
TestContext.assertEqualsVerbose(
"SELECT\n"
+ "{[Measures].[Store Sales]} ON COLUMNS,\n"
+ "{{[Product].[Drink], [Product].[Drink].Children}} ON ROWS\n"
+ "FROM [Sales]\n"
+ "WHERE {[Time].[1997].[Q3].[7]}",
mdxString);
// Sort the rows in ascending order.
query.getAxis(Axis.ROWS).sort(
SortOrder.BASC,
nameList("Measures", "Store Sales"));
SelectNode sortedMdx = query.getSelect();
String sortedMdxString = sortedMdx.toString();
TestContext.assertEqualsVerbose(
"SELECT\n"
+ "{[Measures].[Store Sales]} ON COLUMNS,\n"
+ "Order({{[Product].[Drink], [Product].[Drink].Children}}, [Measures].[Store Sales], BASC) ON ROWS\n"
+ "FROM [Sales]\n"
+ "WHERE {[Time].[1997].[Q3].[7]}",
sortedMdxString);
CellSet results = query.execute();
String s = TestContext.toString(results);
TestContext.assertEqualsVerbose(
"Axis #0:\n"
+ "{[Time].[1997].[Q3].[7]}\n"
+ "Axis #1:\n"
+ "{[Measures].[Store Sales]}\n"
+ "Axis #2:\n"
+ "{[Product].[Drink].[Dairy]}\n"
+ "{[Product].[Drink].[Alcoholic Beverages]}\n"
+ "{[Product].[Drink].[Beverages]}\n"
+ "{[Product].[Drink]}\n"
+ "Row #0: 629.69\n"
+ "Row #1: 1,302.87\n"
+ "Row #2: 2,477.02\n"
+ "Row #3: 4,409.58\n",
s);
}
public void testDimensionsOrder() throws Exception {
Cube cube = getFoodmartCube("Sales");
if (cube == null) {
fail("Could not find Sales cube");
}
Query query = new Query("my query", cube);
// create selections
QueryDimension productDimension = query.getDimension("Product");
productDimension.include(
Selection.Operator.CHILDREN, nameList("Product", "Drink"));
QueryDimension storeDimension = query.getDimension("Store");
storeDimension.include(
Selection.Operator.INCLUDE_CHILDREN, nameList("Store", "USA"));
QueryDimension timeDimension = query.getDimension("Time");
timeDimension.include(
Selection.Operator.CHILDREN, nameList("Time", "1997"));
QueryDimension measuresDimension = query.getDimension("Measures");
measuresDimension.include(nameList("Measures", "Store Sales"));
query.getAxis(Axis.ROWS).addDimension(productDimension);
query.getAxis(Axis.ROWS).addDimension(storeDimension);
query.getAxis(Axis.ROWS).addDimension(timeDimension);
query.getAxis(Axis.COLUMNS).addDimension(measuresDimension);
query.validate();
SelectNode mdx = query.getSelect();
String mdxString = mdx.toString();
TestContext.assertEqualsVerbose(
"SELECT\n"
+ "{[Measures].[Store Sales]} ON COLUMNS,\n"
+ "CrossJoin([Product].[Drink].Children, "
+ "CrossJoin({[Store].[USA], "
+ "[Store].[USA].Children}, "
+ "[Time].[1997].Children)) ON ROWS\n"
+ "FROM [Sales]",
mdxString);
// Push down the Products dimension.
query.getAxis(Axis.ROWS).pushDown(0);
query.validate();
mdx = query.getSelect();
mdxString = mdx.toString();
TestContext.assertEqualsVerbose(
"SELECT\n"
+ "{[Measures].[Store Sales]} ON COLUMNS,\n"
+ "CrossJoin({[Store].[USA], "
+ "[Store].[USA].Children}, "
+ "CrossJoin([Product].[Drink].Children, "
+ "[Time].[1997].Children)) ON ROWS\n"
+ "FROM [Sales]",
mdxString);
// Pull Up the Time dimension.
query.getAxis(Axis.ROWS).pullUp(2);
query.validate();
mdx = query.getSelect();
mdxString = mdx.toString();
TestContext.assertEqualsVerbose(
"SELECT\n"
+ "{[Measures].[Store Sales]} ON COLUMNS,\n"
+ "CrossJoin({[Store].[USA], "
+ "[Store].[USA].Children}, "
+ "CrossJoin([Time].[1997].Children, "
+ "[Product].[Drink].Children)) ON ROWS\n"
+ "FROM [Sales]",
mdxString);
}
/**
* Note: hierarchize mode only works when a single dimension is selected.
*/
public void testDimensionsHierarchize() throws Exception {
Cube cube = getFoodmartCube("Sales");
if (cube == null) {
fail("Could not find Sales cube");
}
Query query = new Query("my query", cube);
// create selections
QueryDimension storeDimension = query.getDimension("Store");
storeDimension.include(
Selection.Operator.INCLUDE_CHILDREN, nameList("Store", "USA"));
storeDimension.setHierarchizeMode(HierarchizeMode.POST);
QueryDimension measuresDimension = query.getDimension("Measures");
measuresDimension.include(nameList("Measures", "Store Sales"));
query.getAxis(Axis.ROWS).addDimension(storeDimension);
query.getAxis(Axis.COLUMNS).addDimension(measuresDimension);
query.validate();
SelectNode mdx = query.getSelect();
String mdxString = mdx.toString();
TestContext.assertEqualsVerbose(
"SELECT\n"
+ "{[Measures].[Store Sales]} ON COLUMNS,\n"
+ "{Hierarchize({{[Store].[USA], "
+ "[Store].[USA].Children}}, POST)} ON ROWS\n"
+ "FROM [Sales]",
mdxString);
storeDimension.setHierarchizeMode(HierarchizeMode.PRE);
query.validate();
mdx = query.getSelect();
mdxString = mdx.toString();
TestContext.assertEqualsVerbose(
"SELECT\n"
+ "{[Measures].[Store Sales]} ON COLUMNS,\n"
+ "{Hierarchize({{[Store].[USA], "
+ "[Store].[USA].Children}})} ON ROWS\n"
+ "FROM [Sales]",
mdxString);
}
/**
* This test makes sure that the generated MDX model is not affected
* by subsequent operations performed on the source query model.
*/
public void testQueryVersusParseTreeIndependence() throws Exception {
Cube cube = getFoodmartCube("Sales");
if (cube == null) {
fail("Could not find Sales cube");
}
// Setup a base query.
Query query = new Query("my query", cube);
QueryDimension productDimension = query.getDimension("Product");
productDimension.include(
Selection.Operator.INCLUDE_CHILDREN,
nameList("Product", "Drink"));
QueryDimension measuresDimension = query.getDimension("Measures");
measuresDimension.include(nameList("Measures", "Store Sales"));
query.getAxis(Axis.ROWS).addDimension(productDimension);
query.getAxis(Axis.COLUMNS).addDimension(measuresDimension);
query.validate();
assertEquals(
Axis.ROWS,
productDimension.getAxis().getLocation());
assertEquals(
Axis.COLUMNS,
measuresDimension.getAxis().getLocation());
// These variables are important. We will evaluate those
// to decide if there are links between the MDX and the Query
SelectNode originalMdx = query.getSelect();
String originalMdxString = originalMdx.toString();
TestContext.assertEqualsVerbose(
"SELECT\n"
+ "{[Measures].[Store Sales]} ON COLUMNS,\n"
+ "{{[Product].[Drink], [Product].[Drink].Children}} ON ROWS\n"
+ "FROM [Sales]",
originalMdxString);
// change selections
measuresDimension.include(
Selection.Operator.SIBLINGS,
nameList("Measures", "Customer Count"));
productDimension.include(
Selection.Operator.SIBLINGS,
nameList(
"Product", "All Products", "Drink", "Alcoholic Beverages"));
// Add something to crossjoin with
query.getAxis(Axis.ROWS).addDimension(
query.getDimension("Gender"));
query.getDimension("Gender").include(
Operator.CHILDREN, nameList("Gender", "All Gender"));
query.getAxis(null).addDimension(
query.getDimension("Product"));
query.validate();
// Check if the MDX object tree is still the same
assertEquals(originalMdxString, originalMdx.toString());
}
public void testExclusionModes() throws Exception {
Cube cube = getFoodmartCube("Sales");
if (cube == null) {
fail("Could not find Sales cube");
}
// Setup a base query.
Query query = new Query("my query", cube);
QueryDimension productDimension = query.getDimension("Product");
productDimension.include(
Selection.Operator.CHILDREN,
nameList("Product", "Drink", "Beverages"));
productDimension.include(
Selection.Operator.CHILDREN,
nameList("Product", "Food", "Frozen Foods"));
QueryDimension measuresDimension = query.getDimension("Measures");
measuresDimension.include(nameList("Measures", "Sales Count"));
QueryDimension timeDimension = query.getDimension("Time");
timeDimension.include(nameList("Time", "Year", "1997", "Q3", "7"));
query.getAxis(Axis.ROWS).addDimension(productDimension);
query.getAxis(Axis.COLUMNS).addDimension(measuresDimension);
query.getAxis(Axis.FILTER).addDimension(timeDimension);
query.validate();
// Validate the generated MDX
String mdxString = query.getSelect().toString();
TestContext.assertEqualsVerbose(
"SELECT\n"
+ "{[Measures].[Sales Count]} ON COLUMNS,\n"
+ "{[Product].[Drink].[Beverages].Children, [Product].[Food].[Frozen Foods].Children} ON ROWS\n"
+ "FROM [Sales]\n"
+ "WHERE {[Time].[1997].[Q3].[7]}",
mdxString);
// Validate the returned results
CellSet results = query.execute();
String resultsString = TestContext.toString(results);
TestContext.assertEqualsVerbose(
"Axis #0:\n"
+ "{[Time].[1997].[Q3].[7]}\n"
+ "Axis #1:\n"
+ "{[Measures].[Sales Count]}\n"
+ "Axis #2:\n"
+ "{[Product].[Drink].[Beverages].[Carbonated Beverages]}\n"
+ "{[Product].[Drink].[Beverages].[Drinks]}\n"
+ "{[Product].[Drink].[Beverages].[Hot Beverages]}\n"
+ "{[Product].[Drink].[Beverages].[Pure Juice Beverages]}\n"
+ "{[Product].[Food].[Frozen Foods].[Breakfast Foods]}\n"
+ "{[Product].[Food].[Frozen Foods].[Frozen Desserts]}\n"
+ "{[Product].[Food].[Frozen Foods].[Frozen Entrees]}\n"
+ "{[Product].[Food].[Frozen Foods].[Meat]}\n"
+ "{[Product].[Food].[Frozen Foods].[Pizza]}\n"
+ "{[Product].[Food].[Frozen Foods].[Vegetables]}\n"
+ "Row #0: 103\n"
+ "Row #1: 65\n"
+ "Row #2: 125\n"
+ "Row #3: 100\n"
+ "Row #4: 143\n"
+ "Row #5: 185\n"
+ "Row #6: 68\n"
+ "Row #7: 81\n"
+ "Row #8: 105\n"
+ "Row #9: 212\n",
resultsString);
// Exclude the Carbonated Beverages because they are not good
// for your health.
query.getDimension("Product").exclude(
nameList(
"Product", "Drink", "Beverages", "Carbonated Beverages"));
// Validate the generated MDX
query.validate();
mdxString = query.getSelect().toString();
TestContext.assertEqualsVerbose(
"SELECT\n"
+ "{[Measures].[Sales Count]} ON COLUMNS,\n"
+ "{Except({[Product].[Drink].[Beverages].Children, [Product].[Food].[Frozen Foods].Children}, {[Product].[Drink].[Beverages].[Carbonated Beverages]})} ON ROWS\n"
+ "FROM [Sales]\n"
+ "WHERE {[Time].[1997].[Q3].[7]}",
mdxString);
// Validate the returned results
results = query.execute();
resultsString = TestContext.toString(results);
TestContext.assertEqualsVerbose(
"Axis #0:\n"
+ "{[Time].[1997].[Q3].[7]}\n"
+ "Axis #1:\n"
+ "{[Measures].[Sales Count]}\n"
+ "Axis #2:\n"
+ "{[Product].[Drink].[Beverages].[Drinks]}\n"
+ "{[Product].[Drink].[Beverages].[Hot Beverages]}\n"
+ "{[Product].[Drink].[Beverages].[Pure Juice Beverages]}\n"
+ "{[Product].[Food].[Frozen Foods].[Breakfast Foods]}\n"
+ "{[Product].[Food].[Frozen Foods].[Frozen Desserts]}\n"
+ "{[Product].[Food].[Frozen Foods].[Frozen Entrees]}\n"
+ "{[Product].[Food].[Frozen Foods].[Meat]}\n"
+ "{[Product].[Food].[Frozen Foods].[Pizza]}\n"
+ "{[Product].[Food].[Frozen Foods].[Vegetables]}\n"
+ "Row #0: 65\n"
+ "Row #1: 125\n"
+ "Row #2: 100\n"
+ "Row #3: 143\n"
+ "Row #4: 185\n"
+ "Row #5: 68\n"
+ "Row #6: 81\n"
+ "Row #7: 105\n"
+ "Row #8: 212\n",
resultsString);
}
public void testExclusionMultipleDimensionModes() throws Exception {
Cube cube = getFoodmartCube("Sales");
if (cube == null) {
fail("Could not find Sales cube");
}
// Setup a base query.
Query query = new Query("my query", cube);
QueryDimension productDimension = query.getDimension("Product");
productDimension.include(
Selection.Operator.CHILDREN,
nameList("Product", "Drink", "Beverages"));
productDimension.include(
Selection.Operator.CHILDREN,
nameList("Product", "Food", "Frozen Foods"));
QueryDimension measuresDimension = query.getDimension("Measures");
measuresDimension.include(nameList("Measures", "Sales Count"));
QueryDimension timeDimension = query.getDimension("Time");
timeDimension.include(nameList("Time", "Year", "1997", "Q3", "7"));
QueryDimension storeDimension = query.getDimension("Store");
storeDimension.include(
Selection.Operator.MEMBER, nameList("Store", "USA"));
query.getAxis(Axis.ROWS).addDimension(storeDimension);
query.getAxis(Axis.ROWS).addDimension(productDimension);
query.getAxis(Axis.FILTER).addDimension(timeDimension);
query.getAxis(Axis.COLUMNS).addDimension(measuresDimension);
query.validate();
// Validate the generated MDX
String mdxString = query.getSelect().toString();
TestContext.assertEqualsVerbose(
"SELECT\n"
+ "{[Measures].[Sales Count]} ON COLUMNS,\n"
+ "Hierarchize(Union(CrossJoin({[Store].[USA]}, [Product].[Drink].[Beverages].Children), CrossJoin({[Store].[USA]}, [Product].[Food].[Frozen Foods].Children))) ON ROWS\n"
+ "FROM [Sales]\n"
+ "WHERE {[Time].[1997].[Q3].[7]}",
mdxString);
// Validate the returned results
CellSet results = query.execute();
String resultsString = TestContext.toString(results);
TestContext.assertEqualsVerbose(
"Axis #0:\n"
+ "{[Time].[1997].[Q3].[7]}\n"
+ "Axis #1:\n"
+ "{[Measures].[Sales Count]}\n"
+ "Axis #2:\n"
+ "{[Store].[USA], [Product].[Drink].[Beverages].[Carbonated Beverages]}\n"
+ "{[Store].[USA], [Product].[Drink].[Beverages].[Drinks]}\n"
+ "{[Store].[USA], [Product].[Drink].[Beverages].[Hot Beverages]}\n"
+ "{[Store].[USA], [Product].[Drink].[Beverages].[Pure Juice Beverages]}\n"
+ "{[Store].[USA], [Product].[Food].[Frozen Foods].[Breakfast Foods]}\n"
+ "{[Store].[USA], [Product].[Food].[Frozen Foods].[Frozen Desserts]}\n"
+ "{[Store].[USA], [Product].[Food].[Frozen Foods].[Frozen Entrees]}\n"
+ "{[Store].[USA], [Product].[Food].[Frozen Foods].[Meat]}\n"
+ "{[Store].[USA], [Product].[Food].[Frozen Foods].[Pizza]}\n"
+ "{[Store].[USA], [Product].[Food].[Frozen Foods].[Vegetables]}\n"
+ "Row #0: 103\n"
+ "Row #1: 65\n"
+ "Row #2: 125\n"
+ "Row #3: 100\n"
+ "Row #4: 143\n"
+ "Row #5: 185\n"
+ "Row #6: 68\n"
+ "Row #7: 81\n"
+ "Row #8: 105\n"
+ "Row #9: 212\n",
resultsString);
// Exclude the Carbonated Beverages because they are not good
// for your health.
query.getDimension("Product").exclude(
nameList(
"Product", "Drink", "Beverages", "Carbonated Beverages"));
// Validate the generated MDX
query.validate();
mdxString = query.getSelect().toString();
TestContext.assertEqualsVerbose(
"SELECT\n"
+ "{[Measures].[Sales Count]} ON COLUMNS,\n"
+ "Hierarchize(Union(CrossJoin({[Store].[USA]}, Except({[Product].[Drink].[Beverages].Children}, {[Product].[Drink].[Beverages].[Carbonated Beverages]})), CrossJoin({[Store].[USA]}, Except({[Product].[Food].[Frozen Foods].Children}, {[Product].[Drink].[Beverages].[Carbonated Beverages]})))) ON ROWS\n"
+ "FROM [Sales]\n"
+ "WHERE {[Time].[1997].[Q3].[7]}",
mdxString);
// Validate the returned results
results = query.execute();
resultsString = TestContext.toString(results);
TestContext.assertEqualsVerbose(
"Axis #0:\n"
+ "{[Time].[1997].[Q3].[7]}\n"
+ "Axis #1:\n"
+ "{[Measures].[Sales Count]}\n"
+ "Axis #2:\n"
+ "{[Store].[USA], [Product].[Drink].[Beverages].[Drinks]}\n"
+ "{[Store].[USA], [Product].[Drink].[Beverages].[Hot Beverages]}\n"
+ "{[Store].[USA], [Product].[Drink].[Beverages].[Pure Juice Beverages]}\n"
+ "{[Store].[USA], [Product].[Food].[Frozen Foods].[Breakfast Foods]}\n"
+ "{[Store].[USA], [Product].[Food].[Frozen Foods].[Frozen Desserts]}\n"
+ "{[Store].[USA], [Product].[Food].[Frozen Foods].[Frozen Entrees]}\n"
+ "{[Store].[USA], [Product].[Food].[Frozen Foods].[Meat]}\n"
+ "{[Store].[USA], [Product].[Food].[Frozen Foods].[Pizza]}\n"
+ "{[Store].[USA], [Product].[Food].[Frozen Foods].[Vegetables]}\n"
+ "Row #0: 65\n"
+ "Row #1: 125\n"
+ "Row #2: 100\n"
+ "Row #3: 143\n"
+ "Row #4: 185\n"
+ "Row #5: 68\n"
+ "Row #6: 81\n"
+ "Row #7: 105\n"
+ "Row #8: 212\n",
resultsString);
}
public void testCompoundFilter() throws Exception {
Cube cube = getFoodmartCube("Sales");
if (cube == null) {
fail("Could not find Sales cube");
}
// Setup a base query.
Query query = new Query("my query", cube);
QueryDimension productDimension = query.getDimension("Product");
productDimension.include(
Selection.Operator.MEMBER,
nameList("Product", "Drink", "Beverages"));
productDimension.include(
Selection.Operator.MEMBER,
nameList("Product", "Food", "Frozen Foods"));
QueryDimension measuresDimension = query.getDimension("Measures");
measuresDimension.include(nameList("Measures", "Sales Count"));
QueryDimension timeDimension = query.getDimension("Time");
timeDimension.include(nameList("Time", "Year", "1997", "Q3", "7"));
QueryDimension storeDimension = query.getDimension("Store");
storeDimension.include(
Selection.Operator.MEMBER, nameList("Store", "USA"));
query.getAxis(Axis.ROWS).addDimension(storeDimension);
query.getAxis(Axis.FILTER).addDimension(productDimension);
query.getAxis(Axis.FILTER).addDimension(timeDimension);
query.getAxis(Axis.COLUMNS).addDimension(measuresDimension);
query.validate();
// Validate the generated MDX
String mdxString = query.getSelect().toString();
TestContext.assertEqualsVerbose(
"SELECT\n"
+ "{[Measures].[Sales Count]} ON COLUMNS,\n"
+ "{[Store].[USA]} ON ROWS\n"
+ "FROM [Sales]\n"
+ "WHERE Hierarchize(Union(CrossJoin({[Product].[Drink].[Beverages]}, {[Time].[1997].[Q3].[7]}), CrossJoin({[Product].[Food].[Frozen Foods]}, {[Time].[1997].[Q3].[7]})))",
mdxString);
// Validate the returned results
CellSet results = query.execute();
String resultsString = TestContext.toString(results);
TestContext.assertEqualsVerbose(
"Axis #0:\n"
+ "{[Product].[Drink].[Beverages], [Time].[1997].[Q3].[7]}\n"
+ "{[Product].[Food].[Frozen Foods], [Time].[1997].[Q3].[7]}\n"
+ "Axis #1:\n"
+ "{[Measures].[Sales Count]}\n"
+ "Axis #2:\n"
+ "{[Store].[USA]}\n"
+ "Row #0: 1,187\n",
resultsString);
}
public void testMultipleHierarchyConsistency() throws Exception {
Cube cube = getFoodmartCube("Sales");
if (cube == null) {
fail("Could not find Sales cube");
}
// Setup a base query.
Query query = new Query("my query", cube);
QueryDimension timeDimension = query.getDimension("Time");
timeDimension.setHierarchyConsistent(true);
timeDimension.include(nameList("Time.Weekly", "1997", "10", "23"));
timeDimension.include(nameList("Time.Weekly", "1997", "10", "28"));
timeDimension.include(nameList("Time.Weekly", "Year", "1997"));
QueryDimension measuresDimension = query.getDimension("Measures");
measuresDimension.include(nameList("Measures", "Sales Count"));
query.getAxis(Axis.COLUMNS).addDimension(measuresDimension);
query.getAxis(Axis.ROWS).addDimension(timeDimension);
query.validate();
// Validate the generated MDX
String mdxString = query.getSelect().toString();
TestContext.assertEqualsVerbose(
"SELECT\n"
+ "{[Measures].[Sales Count]} ON COLUMNS,\n"
+ "{{[Time.Weekly].[1997]}, Filter({{[Time.Weekly].[1997].[10].[23], [Time.Weekly].[1997].[10].[28]}}, (Ancestor([Time.Weekly].CurrentMember, [Time.Weekly].[Year]) IN {[Time.Weekly].[1997]}))} ON ROWS\n"
+ "FROM [Sales]",
mdxString);
// Validate the returned results
CellSet results = query.execute();
String resultsString = TestContext.toString(results);
TestContext.assertEqualsVerbose(
"Axis #0:\n"
+ "{}\n"
+ "Axis #1:\n"
+ "{[Measures].[Sales Count]}\n"
+ "Axis #2:\n"
+ "{[Time.Weekly].[1997]}\n"
+ "{[Time.Weekly].[1997].[10].[23]}\n"
+ "{[Time.Weekly].[1997].[10].[28]}\n"
+ "Row #0: 86,837\n"
+ "Row #1: 123\n"
+ "Row #2: \n",
resultsString);
query.validate();
}
public void testHierarchyConsistency() throws Exception {
Cube cube = getFoodmartCube("Sales");
if (cube == null) {
fail("Could not find Sales cube");
}
// Setup a base query.
Query query = new Query("my query", cube);
QueryDimension productDimension = query.getDimension("Product");
productDimension.setHierarchyConsistent(true);
NamedList productLevels =
productDimension.getDimension()
.getDefaultHierarchy().getLevels();
Level productLevel = productLevels.get("Product Category");
productDimension.include(productLevel);
productDimension.include(
Selection.Operator.MEMBER,
nameList("Product", "Food", "Deli"));
productDimension.include(
Selection.Operator.MEMBER,
nameList("Product", "Food", "Dairy"));
productDimension.include(
Selection.Operator.MEMBER,
nameList("Product", "Product Family", "Food"));
productDimension.include(
Selection.Operator.MEMBER,
nameList("Product", "All Products"));
QueryDimension timeDimension = query.getDimension("Time");
timeDimension.setHierarchyConsistent(true);
timeDimension.include(nameList("Time", "Year", "1997", "Q3", "7"));
timeDimension.include(nameList("Time", "Year", "1997", "Q4", "11"));
timeDimension.include(nameList("Time", "Year", "1997"));
QueryDimension measuresDimension = query.getDimension("Measures");
measuresDimension.include(nameList("Measures", "Sales Count"));
query.getAxis(Axis.COLUMNS).addDimension(productDimension);
query.getAxis(Axis.ROWS).addDimension(timeDimension);
query.validate();
// Validate the generated MDX
String mdxString = query.getSelect().toString();
TestContext.assertEqualsVerbose(
"SELECT\n"
+ "{{[Product].[All Products]}, {[Product].[Food]}, Filter({{[Product].[Food].[Deli], [Product].[Food].[Dairy]}}, (Ancestor([Product].CurrentMember, [Product].[Product Family]) IN {[Product].[Food]})), Filter({{[Product].[Product Category].Members}}, ((Ancestor([Product].CurrentMember, [Product].[Product Family]) IN {[Product].[Food]}) AND (Ancestor([Product].CurrentMember, [Product].[Product Department]) IN {[Product].[Food].[Deli], [Product].[Food].[Dairy]})))} ON COLUMNS,\n"
+ "{{[Time].[1997]}, Filter({{[Time].[1997].[Q3].[7], [Time].[1997].[Q4].[11]}}, (Ancestor([Time].CurrentMember, [Time].[Year]) IN {[Time].[1997]}))} ON ROWS\n"
+ "FROM [Sales]",
mdxString);
// Validate the returned results
CellSet results = query.execute();
String resultsString = TestContext.toString(results);
TestContext.assertEqualsVerbose(
"Axis #0:\n"
+ "{}\n"
+ "Axis #1:\n"
+ "{[Product].[All Products]}\n"
+ "{[Product].[Food]}\n"
+ "{[Product].[Food].[Deli]}\n"
+ "{[Product].[Food].[Dairy]}\n"
+ "{[Product].[Food].[Dairy].[Dairy]}\n"
+ "{[Product].[Food].[Deli].[Meat]}\n"
+ "{[Product].[Food].[Deli].[Side Dishes]}\n"
+ "Axis #2:\n"
+ "{[Time].[1997]}\n"
+ "{[Time].[1997].[Q3].[7]}\n"
+ "{[Time].[1997].[Q4].[11]}\n"
+ "Row #0: 266,773\n"
+ "Row #0: 191,940\n"
+ "Row #0: 12,037\n"
+ "Row #0: 12,885\n"
+ "Row #0: 12,885\n"
+ "Row #0: 9,433\n"
+ "Row #0: 2,604\n"
+ "Row #1: 23,763\n"
+ "Row #1: 17,036\n"
+ "Row #1: 1,050\n"
+ "Row #1: 1,229\n"
+ "Row #1: 1,229\n"
+ "Row #1: 847\n"
+ "Row #1: 203\n"
+ "Row #2: 25,270\n"
+ "Row #2: 18,278\n"
+ "Row #2: 1,312\n"
+ "Row #2: 1,232\n"
+ "Row #2: 1,232\n"
+ "Row #2: 1,033\n"
+ "Row #2: 279\n",
resultsString);
query.validate();
query.getAxis(Axis.ROWS).addDimension(measuresDimension);
productDimension.clearInclusions();
productDimension.include(
Selection.Operator.MEMBER,
nameList("Product", "Product Family", "Food"));
// Validate the generated MDX
String mdxString2 = query.getSelect().toString();
TestContext.assertEqualsVerbose(
"SELECT\n"
+ "{[Product].[Food]} ON COLUMNS,\n"
+ "Hierarchize(Union(CrossJoin(Filter({[Time].[1997].[Q3].[7]}, (Ancestor([Time].CurrentMember, [Time].[Year]) IN {[Time].[1997]})), {[Measures].[Sales Count]}), Union(CrossJoin(Filter({[Time].[1997].[Q4].[11]}, (Ancestor([Time].CurrentMember, [Time].[Year]) IN {[Time].[1997]})), {[Measures].[Sales Count]}), CrossJoin({[Time].[1997]}, {[Measures].[Sales Count]})))) ON ROWS\n"
+ "FROM [Sales]",
mdxString2);
// Validate the returned results
CellSet results2 = query.execute();
String resultsString2 = TestContext.toString(results2);
TestContext.assertEqualsVerbose(
"Axis #0:\n"
+ "{}\n"
+ "Axis #1:\n"
+ "{[Product].[Food]}\n"
+ "Axis #2:\n"
+ "{[Time].[1997], [Measures].[Sales Count]}\n"
+ "{[Time].[1997].[Q3].[7], [Measures].[Sales Count]}\n"
+ "{[Time].[1997].[Q4].[11], [Measures].[Sales Count]}\n"
+ "Row #0: 62,445\n"
+ "Row #1: 5,552\n"
+ "Row #2: 5,944\n",
resultsString2);
QueryDimension customerDimension = query.getDimension("Customers");
customerDimension.setHierarchyConsistent(true);
NamedList customerLevels =
customerDimension.getDimension()
.getDefaultHierarchy().getLevels();
Level country = customerLevels.get("Country");
Level state = customerLevels.get("State Province");
customerDimension.include(country);
customerDimension.include(state);
query.getAxis(Axis.ROWS).removeDimension(timeDimension);
query.getAxis(Axis.ROWS).addDimension(customerDimension);
String mdxString3 = query.getSelect().toString();
TestContext.assertEqualsVerbose(
"SELECT\n"
+ "{[Product].[Food]} ON COLUMNS,\n"
+ "Hierarchize(Union(CrossJoin({[Measures].[Sales Count]}, [Customers].[Country].Members), CrossJoin({[Measures].[Sales Count]}, [Customers].[State Province].Members))) ON ROWS\n"
+ "FROM [Sales]",
mdxString3);
}
public void testNonMandatoryQueryAxis() throws Exception {
Cube cube = getFoodmartCube("Sales");
if (cube == null) {
fail("Could not find Sales cube");
}
Query query = new Query("my query", cube);
// create selections
QueryDimension productDimension = query.getDimension("Product");
productDimension.include(
Selection.Operator.CHILDREN, nameList("Product", "Drink"));
QueryDimension storeDimension = query.getDimension("Store");
storeDimension.include(
Selection.Operator.INCLUDE_CHILDREN, nameList("Store", "USA"));
storeDimension.setHierarchizeMode(HierarchizeMode.POST);
QueryDimension timeDimension = query.getDimension("Time");
timeDimension.include(
Selection.Operator.CHILDREN, nameList("Time", "1997"));
QueryDimension measuresDimension = query.getDimension("Measures");
measuresDimension.include(nameList("Measures", "Store Sales"));
//query.getAxis(Axis.ROWS).addDimension(productDimension);
//query.getAxis(Axis.ROWS).addDimension(storeDimension);
//query.getAxis(Axis.ROWS).addDimension(timeDimension);
query.getAxis(Axis.COLUMNS).addDimension(measuresDimension);
//query.validate();
SelectNode mdx = query.getSelect();
String mdxString = mdx.toString();
TestContext.assertEqualsVerbose(
"SELECT\n"
+ "{[Measures].[Store Sales]} ON COLUMNS\n"
+ "FROM [Sales]",
mdxString);
try {
query.validate();
fail();
} catch (OlapException e) {
assertEquals(0, e.getCause().getMessage().indexOf(
"A valid Query requires at least one "
+ "dimension on the rows axis."));
}
}
public static void main(String args[]) throws Exception {
OlapTest olapTest = new OlapTest();
olapTest.testModel();
}
}
// End OlapTest.java
olap4j-1.0.1.500/testsrc/org/olap4j/impl/ 0000755 0001750 0001750 00000000000 11421322444 017506 5 ustar drazzib drazzib olap4j-1.0.1.500/testsrc/org/olap4j/impl/Olap4jUtilTest.java 0000644 0001750 0001750 00000063546 11707254766 023240 0 ustar drazzib drazzib /*
// $Id: Olap4jUtilTest.java 482 2012-01-05 23:27:27Z jhyde $
//
// Licensed to Julian Hyde under one or more contributor license
// agreements. See the NOTICE file distributed with this work for
// additional information regarding copyright ownership.
//
// Julian Hyde licenses this file to you 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.olap4j.impl;
import org.olap4j.mdx.*;
import junit.framework.TestCase;
import java.util.*;
/**
* Tests for methods in {@link org.olap4j.impl.Olap4jUtil}.
*
* @author jhyde
* @version $Id: Olap4jUtilTest.java 482 2012-01-05 23:27:27Z jhyde $
* @since Dec 12, 2007
*/
public class Olap4jUtilTest extends TestCase {
//~ Helper methods =========================================================
/**
* Asserts that two integer arrays have equal length and contents.
*
* @param expected Expected integer array
* @param actual Actual integer array
*/
public void assertEqualsArray(int[] expected, int[] actual) {
if (expected == null) {
assertEquals(expected, actual);
} else {
List expectedList = new ArrayList();
for (int i : expected) {
expectedList.add(i);
}
List actualList = new ArrayList();
for (int i : actual) {
actualList.add(i);
}
assertEquals(expectedList, actualList);
}
}
//~ Tests follow ===========================================================
/**
* Tests {@link Olap4jUtil#camelToUpper}.
*/
public void testCamel() {
assertEquals(
"FOO_BAR",
Olap4jUtil.camelToUpper("FooBar"));
assertEquals(
"FOO_BAR",
Olap4jUtil.camelToUpper("fooBar"));
assertEquals(
"URL",
Olap4jUtil.camelToUpper("URL"));
assertEquals(
"URLTO_CLICK_ON",
Olap4jUtil.camelToUpper("URLtoClickOn"));
assertEquals(
"",
Olap4jUtil.camelToUpper(""));
}
/**
* Tests {@link Olap4jUtil#equal}.
*/
public void testEqual() {
assertTrue(Olap4jUtil.equal("x", "x"));
assertFalse(Olap4jUtil.equal("x", "y"));
assertTrue(Olap4jUtil.equal("xy", "x" + "y"));
assertTrue(Olap4jUtil.equal(null, null));
assertFalse(Olap4jUtil.equal(null, "x"));
assertFalse(Olap4jUtil.equal("x", null));
final Integer TWO = 1 + 1;
assertTrue(Olap4jUtil.equal(2, TWO));
}
/**
* Tests {@link Olap4jUtil#wildcardToRegexp(java.util.List)}.
*/
public void testWildcard() {
assertEquals(
".\\QFoo\\E.|\\QBar\\E.*\\QBAZ\\E",
Olap4jUtil.wildcardToRegexp(
Arrays.asList("_Foo_", "Bar%BAZ")));
}
/**
* Tests {@link org.olap4j.impl.CoordinateIterator}.
*/
public void testCoordinateIterator() {
// no axes, should produce one result
CoordinateIterator iter = new CoordinateIterator(new int[]{});
assertTrue(iter.hasNext());
assertEqualsArray(iter.next(), new int[] {});
// one axis of length n, should produce n elements
iter = new CoordinateIterator(new int[]{2});
assertTrue(iter.hasNext());
assertEqualsArray(iter.next(), new int[] {0});
assertTrue(iter.hasNext());
assertEqualsArray(iter.next(), new int[] {1});
assertFalse(iter.hasNext());
// one axis of length 0, should produce 0 elements
iter = new CoordinateIterator(new int[]{0});
assertFalse(iter.hasNext());
// two axes of length 0, should produce 0 elements
iter = new CoordinateIterator(new int[]{0, 0});
assertFalse(iter.hasNext());
// five axes of length 0, should produce 0 elements
iter = new CoordinateIterator(new int[]{0, 0, 0, 0, 0});
assertFalse(iter.hasNext());
// two axes, neither empty
iter = new CoordinateIterator(new int[]{2, 3});
assertTrue(iter.hasNext());
assertEqualsArray(iter.next(), new int[] {0, 0});
assertTrue(iter.hasNext());
assertEqualsArray(iter.next(), new int[] {0, 1});
assertTrue(iter.hasNext());
assertEqualsArray(iter.next(), new int[] {0, 2});
assertTrue(iter.hasNext());
assertEqualsArray(iter.next(), new int[] {1, 0});
assertTrue(iter.hasNext());
assertEqualsArray(iter.next(), new int[] {1, 1});
assertTrue(iter.hasNext());
assertEqualsArray(iter.next(), new int[] {1, 2});
assertFalse(iter.hasNext());
// three axes, one of length 0, should produce 0 elements
iter = new CoordinateIterator(new int[]{10, 0, 2});
assertFalse(iter.hasNext());
iter = new CoordinateIterator(new int[]{0, 10, 2});
assertFalse(iter.hasNext());
// if any axis has negative length, produces 0 elements
iter = new CoordinateIterator(new int[]{3, 4, 5, -6, 7});
assertFalse(iter.hasNext());
iter = new CoordinateIterator(new int[]{3, 4, 5, 6, -7});
assertFalse(iter.hasNext());
iter = new CoordinateIterator(new int[]{-3, 4, 5, 6, 7});
assertFalse(iter.hasNext());
}
/**
* Tests a little-endian {@link org.olap4j.impl.CoordinateIterator}.
*/
public void testCoordinateIteratorLittleEndian() {
// two axes, neither empty
CoordinateIterator iter =
new CoordinateIterator(new int[]{2, 3}, true);
assertTrue(iter.hasNext());
assertEqualsArray(iter.next(), new int[] {0, 0});
assertTrue(iter.hasNext());
assertEqualsArray(iter.next(), new int[] {1, 0});
assertTrue(iter.hasNext());
assertEqualsArray(iter.next(), new int[] {0, 1});
assertTrue(iter.hasNext());
assertEqualsArray(iter.next(), new int[] {1, 1});
assertTrue(iter.hasNext());
assertEqualsArray(iter.next(), new int[] {0, 2});
assertTrue(iter.hasNext());
assertEqualsArray(iter.next(), new int[] {1, 2});
assertFalse(iter.hasNext());
}
/**
* Tests {@link org.olap4j.impl.UnmodifiableArrayList}.
*/
public void testUnmodifiableArrayList() {
String[] a = {"x", "y"};
final UnmodifiableArrayList list =
new UnmodifiableArrayList(a);
final UnmodifiableArrayList copyList =
UnmodifiableArrayList.asCopyOf(a);
assertEquals(2, list.size());
assertEquals("x", list.get(0));
assertEquals("y", list.get(1));
try {
final String s = list.get(2);
fail("expected error, got " + s);
} catch (IndexOutOfBoundsException e) {
// ok
}
// check various equality relations
assertTrue(list.equals(copyList));
assertTrue(copyList.equals(list));
assertTrue(list.equals(list));
assertEquals(list.hashCode(), copyList.hashCode());
assertEquals(Arrays.asList(a), list);
assertEquals(list, Arrays.asList(a));
String sum = "";
for (String s : list) {
sum = sum + s;
}
assertEquals("xy", sum);
final Iterator iterator = list.iterator();
assertTrue(iterator.hasNext());
assertEquals("x", iterator.next());
try {
iterator.remove();
fail("expected error");
} catch (UnsupportedOperationException e) {
// ok
}
a[1] = "z";
assertTrue(iterator.hasNext());
assertEquals("z", iterator.next());
assertFalse(iterator.hasNext());
// modifying the array modifies the list, but not the clone list
assertEquals("z", list.get(1));
assertEquals("y", copyList.get(1));
// test the of(Collection) method
final List arrayList = new ArrayList();
arrayList.add("foo");
arrayList.add("bar");
final UnmodifiableArrayList