use of mondrian.spi.Dialect in project mondrian by pentaho.
the class JdbcDialectFactory method createDialectHelper.
/**
* Creates a temporary connection and calls
* {@link mondrian.spi.DialectFactory#createDialect(javax.sql.DataSource, java.sql.Connection)}.
*
* <p>Helper method, called when {@code createDialect} is called without a
* {@link java.sql.Connection} and the dialect factory
* cannot create a dialect with {@link javax.sql.DataSource} alone.
*
* <p>It is a user error if {@code dataSource} is null (since this implies
* that {@code createDialect} was called with {@code dataSource} and
* {@code connection} both null.</p>
*
* @param factory Dialect factory
* @param dataSource Data source, must not be null
* @return Dialect, or null if factory cannot create suitable dialect
*/
public static Dialect createDialectHelper(DialectFactory factory, DataSource dataSource) {
if (dataSource == null) {
throw new IllegalArgumentException("Must specify either dataSource or connection");
}
Connection connection = null;
try {
connection = dataSource.getConnection();
if (connection == null) {
// let's be cautious.
throw new IllegalArgumentException();
}
final Dialect dialect = factory.createDialect(dataSource, connection);
// Close the connection in such a way that if there is a
// SQLException,
// (a) we propagate the exception,
// (b) we don't try to close the connection again.
Connection connection2 = connection;
connection = null;
connection2.close();
return dialect;
} catch (SQLException e) {
throw Util.newError(e, "Error while creating dialect");
} finally {
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
// ignore
}
}
}
}
use of mondrian.spi.Dialect in project mondrian by pentaho.
the class NumberSqlCompilerTest method setUp.
@Override
public void setUp() throws Exception {
super.setUp();
Dialect dialect = mock(Dialect.class);
when(dialect.getDatabaseProduct()).thenReturn(Dialect.DatabaseProduct.MYSQL);
SqlQuery query = mock(SqlQuery.class);
when(query.getDialect()).thenReturn(dialect);
RolapNativeSql sql = new RolapNativeSql(query, null, null, null);
compiler = sql.new NumberSqlCompiler();
}
use of mondrian.spi.Dialect in project mondrian by pentaho.
the class RolapConnectionTest method testDataSourceOverrideUserPass.
public void testDataSourceOverrideUserPass() throws SQLException, NamingException {
// use the datasource property to connect to the database
Util.PropertyList properties = spy(TestContext.instance().getConnectionProperties().clone());
final Dialect dialect = TestContext.instance().getDialect();
if (dialect.getDatabaseProduct() == Dialect.DatabaseProduct.ACCESS) {
// Access doesn't accept user/password, so this test is pointless.
return;
}
final String jdbcUser = properties.get(RolapConnectionProperties.JdbcUser.name());
final String jdbcPassword = properties.get(RolapConnectionProperties.JdbcPassword.name());
if (jdbcUser == null || jdbcPassword == null) {
// Can only run this test if username and password are explicit.
return;
}
// Define a data source with bogus user and password.
properties.put(RolapConnectionProperties.JdbcUser.name(), "bogususer");
properties.put(RolapConnectionProperties.JdbcPassword.name(), "boguspassword");
properties.put(RolapConnectionProperties.PoolNeeded.name(), "false");
final StringBuilder buf = new StringBuilder();
final DataSource dataSource = RolapConnection.createDataSource(null, properties, buf);
final String desc = buf.toString();
assertTrue(desc, desc.startsWith("Jdbc="));
assertTrue(desc, desc.indexOf("JdbcUser=bogususer") >= 0);
verify(properties, atLeastOnce()).get(RolapConnectionProperties.JdbcPassword.name());
final String jndiName = "jndiDataSource";
THREAD_INITIAL_CONTEXT.set(new InitialContext() {
public Object lookup(String str) {
return str.equals(jndiName) ? dataSource : null;
}
});
// Create a property list that we will use for the actual mondrian
// connection. Replace the original JDBC info with the data source we
// just created.
final Util.PropertyList properties2 = new Util.PropertyList();
for (Pair<String, String> entry : properties) {
properties2.put(entry.getKey(), entry.getValue());
}
properties2.remove(RolapConnectionProperties.Jdbc.name());
properties2.put(RolapConnectionProperties.DataSource.name(), jndiName);
// With JdbcUser and JdbcPassword credentials in the mondrian connect
// string, the data source's "user" and "password" properties are
// overridden and the connection succeeds.
properties2.put(RolapConnectionProperties.JdbcUser.name(), jdbcUser);
properties2.put(RolapConnectionProperties.JdbcPassword.name(), jdbcPassword);
mondrian.olap.Connection connection = null;
try {
connection = DriverManager.getConnection(properties2, null);
Query query = connection.parseQuery("select from [Sales]");
final Result result = connection.execute(query);
assertNotNull(result);
} finally {
if (connection != null) {
connection.close();
connection = null;
}
}
// If we don't specify JdbcUser and JdbcPassword in the mondrian
// connection properties, mondrian uses the data source's
// bogus credentials, and the connection fails.
properties2.remove(RolapConnectionProperties.JdbcUser.name());
properties2.remove(RolapConnectionProperties.JdbcPassword.name());
for (String poolNeeded : Arrays.asList("false", "true")) {
// Important to test with & without pooling. Connection pools
// typically do not let you change user, so it's important that
// mondrian handles these right.
properties2.put(RolapConnectionProperties.PoolNeeded.name(), poolNeeded);
try {
connection = DriverManager.getConnection(properties2, null);
fail("Expected exception");
} catch (MondrianException e) {
final String s = TestContext.getStackTrace(e);
assertTrue(s, s.indexOf("Error while creating SQL connection: " + "DataSource=jndiDataSource") >= 0);
switch(dialect.getDatabaseProduct()) {
case DERBY:
assertTrue(s, s.indexOf("Caused by: java.sql.SQLException: " + "Schema 'BOGUSUSER' does not exist") >= 0);
break;
case ORACLE:
assertTrue(s, s.indexOf("Caused by: java.sql.SQLException: ORA-01017: " + "invalid username/password; logon denied") >= 0);
break;
case MYSQL:
case MARIADB:
assertTrue(s, s.indexOf("Caused by: java.sql.SQLException: Access denied " + "for user 'bogususer'") >= 0);
break;
case POSTGRESQL:
assertTrue(s, s.indexOf("Caused by: org.postgresql.util.PSQLException: " + "FATAL: password authentication failed for " + "user \"bogususer\"") >= 0);
break;
}
} finally {
if (connection != null) {
connection.close();
connection = null;
}
}
}
}
use of mondrian.spi.Dialect in project mondrian by pentaho.
the class BatchTestCase method assertQuerySqlOrNot.
/**
* During MDX query parse and execution, checks that the query results
* (or does not result) in a particular SQL statement being generated.
*
* <p>Parses and executes the MDX query once for each SQL
* pattern in the current dialect. If there are multiple patterns, runs the
* MDX query multiple times, and expects to see each SQL statement appear.
* If there are no patterns in this dialect, the test trivially succeeds.
*
* @param testContext non-default test context if required
* @param mdxQuery MDX query
* @param patterns Set of patterns
* @param negative false to assert if SQL is generated;
* true to assert if SQL is NOT generated
* @param bypassSchemaCache whether to grab a new connection and bypass the
* schema cache before parsing the MDX query
* @param clearCache whether to clear cache before executing the MDX query
*/
protected void assertQuerySqlOrNot(TestContext testContext, String mdxQuery, SqlPattern[] patterns, boolean negative, boolean bypassSchemaCache, boolean clearCache) {
Connection connection = testContext.getConnection();
mdxQuery = testContext.upgradeQuery(mdxQuery);
// Run the test once for each pattern in this dialect.
// (We could optimize and run it once, collecting multiple queries, and
// comparing all queries at the end.)
Dialect dialect = testContext.getDialect();
Dialect.DatabaseProduct d = dialect.getDatabaseProduct();
boolean patternFound = false;
for (SqlPattern sqlPattern : patterns) {
if (!sqlPattern.hasDatabaseProduct(d)) {
// message if required.
continue;
}
patternFound = true;
String sql = sqlPattern.getSql();
String trigger = sqlPattern.getTriggerSql();
sql = dialectize(d, sql);
trigger = dialectize(d, trigger);
// Create a dummy DataSource which will throw a 'bomb' if it is
// asked to execute a particular SQL statement, but will otherwise
// behave exactly the same as the current DataSource.
final TriggerHook hook = new TriggerHook(trigger);
RolapUtil.setHook(hook);
Bomb bomb = null;
try {
if (bypassSchemaCache) {
connection = testContext.withSchemaPool(false).getConnection();
}
final Query query = connection.parseQuery(mdxQuery);
if (clearCache) {
clearCache((RolapCube) query.getCube());
}
final Result result = connection.execute(query);
Util.discard(result);
bomb = null;
} catch (Bomb e) {
bomb = e;
} catch (RuntimeException e) {
// Walk up the exception tree and see if the root cause
// was a SQL bomb.
bomb = Util.getMatchingCause(e, Bomb.class);
if (bomb == null) {
throw e;
}
} finally {
RolapUtil.setHook(null);
}
if (negative) {
if (bomb != null || hook.foundMatch()) {
fail("forbidden query [" + sql + "] detected");
}
} else {
if (bomb == null && !hook.foundMatch()) {
fail("expected query [" + sql + "] did not occur");
}
if (bomb != null) {
assertEquals(replaceQuotes(sql.replaceAll("\r\n", "\n")), replaceQuotes(bomb.sql.replaceAll("\r\n", "\n")));
}
}
}
// dialect.
if (!patternFound) {
String warnDialect = MondrianProperties.instance().WarnIfNoPatternForDialect.get();
if (warnDialect.equals(d.toString())) {
System.out.println("[No expected SQL statements found for dialect \"" + dialect.toString() + "\" and test not run]");
}
}
}
use of mondrian.spi.Dialect in project mondrian by pentaho.
the class FastBatchingCellReaderTest method testCanBatchForBatchWithDifferentAggregationTable.
public void testCanBatchForBatchWithDifferentAggregationTable() {
final Dialect dialect = getTestContext().getDialect();
final Dialect.DatabaseProduct product = dialect.getDatabaseProduct();
switch(product) {
case TERADATA:
case INFOBRIGHT:
case NEOVIEW:
// tables, so this test will fail.
return;
}
final BatchLoader fbcr = createFbcr(null, salesCube);
BatchLoader.Batch summaryBatch = createBatch(fbcr, new String[] { tableTime }, new String[] { fieldYear }, new String[][] { fieldValuesYear }, cubeNameSales, measureUnitSales);
BatchLoader.Batch detailedBatch = createBatch(fbcr, new String[] { tableTime, tableCustomer }, new String[] { fieldYear, fieldGender }, new String[][] { fieldValuesYear, fieldValuesGender }, cubeNameSales, measureUnitSales);
if (MondrianProperties.instance().UseAggregates.get() && MondrianProperties.instance().ReadAggregates.get()) {
assertFalse(detailedBatch.canBatch(summaryBatch));
assertFalse(summaryBatch.canBatch(detailedBatch));
} else {
assertTrue(detailedBatch.canBatch(summaryBatch));
assertFalse(summaryBatch.canBatch(detailedBatch));
}
}
Aggregations