Skip to content

Commit

Permalink
Fixed getting parameter metadata for store proc with packages
Browse files Browse the repository at this point in the history
- (BIRT-2313) Fixed an error with Oracle thin JDBC driver when
retrieving parameter metadata for a stored procedure inside a package.
- Cleaned up compilation warnings
- Correctly parse stored procedure call when procedure name is identity
quoted.

Signed-off-by: Gary Xue <xxue@opentext.com>
  • Loading branch information
Gary Xue committed Jul 19, 2016
1 parent 04a31fb commit 33104c3
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 68 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -460,30 +460,6 @@ public IResultSet executeQuery( ) throws OdaException
}
}

/*
* The method is for retrieving resultSet from database-specific
* outPutParams. Note in 2.2.0M2 only the first resultSet will be returned
* due to single IResultSet policy, assuming there is one or more. null will
* be returned otherwise for a pseudo resultSet.
*/
private java.sql.ResultSet getOutputParamResultSet( ) throws OdaException,
SQLException
{
if ( parameterDefn != null )
{
for ( int i = 1; i <= parameterDefn.getParameterCount( ); i++ )
{
if ( parameterDefn.getParameterMode( i ) == IParameterMetaData.parameterModeOut )
{
Object expected = callStat.getObject( i );
if ( expected instanceof java.sql.ResultSet )
return (java.sql.ResultSet) expected;
}
}
}

return null;
}

private void populateOutputParamResultSet( )
throws OdaException, SQLException
Expand Down Expand Up @@ -1136,7 +1112,6 @@ public void setBoolean( int parameterId, boolean value )
public void setObject( String parameterName, Object value )
throws OdaException
{
// TODO Auto-generated method stub
throw new UnsupportedOperationException();
}

Expand All @@ -1145,7 +1120,6 @@ public void setObject( String parameterName, Object value )
*/
public void setObject( int parameterId, Object value ) throws OdaException
{
// TODO Auto-generated method stub
throw new UnsupportedOperationException();
}

Expand Down Expand Up @@ -1731,7 +1705,6 @@ public boolean getBoolean( int parameterId ) throws OdaException
*/
public Object getObject( int parameterId ) throws OdaException
{
// TODO Auto-generated method stub
throw new UnsupportedOperationException();
}

Expand All @@ -1740,7 +1713,6 @@ public Object getObject( int parameterId ) throws OdaException
*/
public Object getObject( String parameterName ) throws OdaException
{
// TODO Auto-generated method stub
throw new UnsupportedOperationException();
}

Expand Down Expand Up @@ -1903,8 +1875,8 @@ public IParameterMetaData getParameterMetaData( ) throws OdaException
return this.cachedParameterMetaData;
int[] positionArray = paramUtil.getParameterPositions( );

List paramMetaList1 = this.getCallableParamMetaData( );
List paramMetaList2 = new ArrayList( );
List<ParameterDefn> paramMetaList1 = this.getCallableParamMetaData( );
List<ParameterDefn> paramMetaList2 = new ArrayList<ParameterDefn>( );

int containsReturnValue = 0;
if ( paramMetaList1.size( ) > 0 )
Expand Down Expand Up @@ -1933,14 +1905,16 @@ public IParameterMetaData getParameterMetaData( ) throws OdaException
/**
* get parameter metadata from database matadata
*/
private java.util.List getCallableParamMetaData( )
private List<ParameterDefn> getCallableParamMetaData( ) throws OdaException
{
java.util.List paramMetaDataList = new ArrayList( );
List<ParameterDefn> params = new ArrayList<ParameterDefn>( );

try
{
DatabaseMetaData metaData = conn.getMetaData( );
String cataLog = conn.getCatalog( );
String procedureNamePattern = getNamePattern( this.paramUtil.getProcedure( ) );
String catalog = conn.getCatalog( );
String procedureNamePattern = getNamePattern(
this.paramUtil.getProcedure( ) );
String schemaPattern = null;
if ( this.paramUtil.getSchema( ) != null )
{
Expand All @@ -1949,16 +1923,58 @@ private java.util.List getCallableParamMetaData( )

// handles schema.package.storedprocedure for databases such as
// Oracle
if ( !metaData.supportsCatalogsInProcedureCalls( ) )
if ( !metaData.supportsCatalogsInProcedureCalls( )
&& this.paramUtil.getPackage( ) != null )
{
if (this.paramUtil.getPackage( ) != null)
{
cataLog = getNamePattern( this.paramUtil.getPackage( ) );
}
catalog = getNamePattern( this.paramUtil.getPackage( ) );
}

java.sql.ResultSet rs = null;
rs = metaData.getProcedureColumns( cataLog,
queryProcedureParams( schemaPattern,
catalog,
procedureNamePattern,
params );

if ( params.isEmpty( ) && catalog == null && schemaPattern != null )
{
// Deals with special case when calling "abc.proc()". Earlier
// code assumes "abc" is the name
// of the schema, which results in no match if it is actually a
// package name in the user's schema.
// For DBs like Oracle (when using Oracle thin JDBC driver), we
// should also search the
// current user's schema (using "" as schema name) using "abc"
// as package (i.e., catalog) name
queryProcedureParams( "",
schemaPattern,
procedureNamePattern,
params );
}
}
catch ( SQLException e )
{
logger.log( Level.SEVERE, "Fail to get SP paramters", e );
}
return params;
}

/**
* Calls JDBC DatabaseMetaData to find parameter definitions for a stored procedure
* @param schemaPattern Pattern for matching schema name. If null, matches any schema. If empty, matches current user's schema
* @param catalog Pattern for matching catalog. If null, matches any catalog
* @param procedureNamePattern Pattern for matching procedure name
* @param params Definitions of parameters are added to the list, in call order
* @throws SQLException
*/
private void queryProcedureParams( String schemaPattern, String catalog,
String procedureNamePattern, List<ParameterDefn> params )
throws SQLException
{

DatabaseMetaData metaData = conn.getMetaData( );
java.sql.ResultSet rs = null;
try
{
rs = metaData.getProcedureColumns( catalog,
schemaPattern,
procedureNamePattern,
null );
Expand All @@ -1974,19 +1990,16 @@ private java.util.List getCallableParamMetaData( )
p.setIsNullable( rs.getInt( "NULLABLE" ) );
if ( p.getParamType( ) == Types.OTHER )
correctParamType( p );
paramMetaDataList.add( p );
params.add( p );
}
rs.close( );
}
catch ( SQLException e )
{
logger.log( Level.SEVERE, "Fail to get SP paramters", e );
}
catch( JDBCException ex)
finally
{
logger.log( Level.SEVERE, "Fail to get SP paramters", ex );
// Make sure result set is closed in case of error
if ( rs != null )
rs.close( );
}
return paramMetaDataList;

}

private String getNamePattern( SPElement spElement ) throws SQLException
Expand Down Expand Up @@ -2081,7 +2094,6 @@ public SortSpec getSortSpec( ) throws OdaException
/* (non-Javadoc)
* @see org.eclipse.datatools.connectivity.oda.IQuery#setSpecification(org.eclipse.datatools.connectivity.oda.spec.QuerySpecification)
*/
@SuppressWarnings("restriction")
public void setSpecification( QuerySpecification querySpec )
throws OdaException, UnsupportedOperationException
{
Expand All @@ -2098,7 +2110,6 @@ public void setSpecification( QuerySpecification querySpec )
/* (non-Javadoc)
* @see org.eclipse.datatools.connectivity.oda.IQuery#getSpecification()
*/
@SuppressWarnings("restriction")
public QuerySpecification getSpecification()
{
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.eclipse.birt.report.data.oda.i18n.ResourceConstants;
import org.eclipse.datatools.connectivity.oda.OdaException;
Expand Down Expand Up @@ -244,23 +246,37 @@ private void parseProcedureName( String sqlTxt, int[] point ) throws JDBCExcepti
}

String name = sqlTxt.substring( start + 4, end ).trim( );
String[] pattern = name.split( "\\Q.\\E" );
spElements = new SPElement[pattern.length];
for( int i=0; i< pattern.length; i++ )
{
if (pattern[i].startsWith( identifierQuoteString )
&& pattern[i].endsWith( identifierQuoteString ))
{
String pureName = pattern[i].substring( identifierQuoteString.length( ),
pattern[i].length( ) - identifierQuoteString.length( ) );
spElements[i] = new SPElement( pureName, true );
}
else
{
spElements[i] = new SPElement( pattern[i], false);

// Split name into period-separated elements. Note that quotes can be used to enclose an element that contains periods.
// E.g.,
// schema.package.function ==> ["schema", "package", "function"]
// schema."package.function" ==> ["schema", "package.function"]
// "schema"."package"."function" ==> ["schema", "package", "function"]
// Some drivers such as DataDirect for Oracle handles packages by giving us composite name such as "package.proc"
// as a stored proc name. In order to us to correctly parse the SQL, such composite names must always be identity quoted.

String idq = Pattern.quote(identifierQuoteString);
// To explain the following pattern: the group matches either of these:
// (a) a unquoted name (doesn't start with quote, and greedily matches all characters until the next period)
// (b) a quoted name (starts with a quote, then reluctantly matches all characters until the next quote)
// Groups are separated by period character.
String patternStr = "([^" + idq + "][^\\.]*|" + idq + ".*?" + idq + ")\\.{0,1}";

Matcher matcher = Pattern.compile(patternStr).matcher(name);
ArrayList<SPElement> elemList= new ArrayList<SPElement>();
while ( matcher.find() ) {
String elem = matcher.group(1);
if ( elem.startsWith(identifierQuoteString) && elem.endsWith(identifierQuoteString) ) {
// Strip quotes at both ends
elem = elem.substring(identifierQuoteString.length(),
elem.length() - identifierQuoteString.length());
elemList.add( new SPElement(elem, true) );
} else {
elemList.add( new SPElement(elem, false) );
}
}
}
}

spElements = elemList.toArray( new SPElement[elemList.size()]); }


/**
Expand Down

0 comments on commit 33104c3

Please sign in to comment.