View Javadoc
1   /*
2    * The contents of this file are subject to the terms of the Common Development and
3    * Distribution License (the License). You may not use this file except in compliance with the
4    * License.
5    *
6    * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
7    * specific language governing permission and limitations under the License.
8    *
9    * When distributing Covered Software, include this CDDL Header Notice in each file and include
10   * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
11   * Header, with the fields enclosed by brackets [] replaced by your own identifying
12   * information: "Portions copyright [year] [name of copyright owner]".
13   *
14   * Copyright 2015-2016 ForgeRock AS.
15   */
16  package org.forgerock.audit.handlers.jdbc;
17  
18  import static org.forgerock.util.Utils.joinAsString;
19  
20  import java.util.ArrayList;
21  import java.util.LinkedList;
22  import java.util.List;
23  
24  import org.forgerock.audit.AuditException;
25  import org.forgerock.json.JsonPointer;
26  import org.forgerock.json.JsonValue;
27  import org.forgerock.json.resource.QueryRequest;
28  import org.forgerock.json.resource.SortKey;
29  import org.slf4j.Logger;
30  import org.slf4j.LoggerFactory;
31  
32  /**
33   * Provides the query event for an oracle database.
34   */
35  class OracleDatabaseStatementProvider extends BaseDatabaseStatementProvider {
36      private static final Logger logger = LoggerFactory.getLogger(OracleDatabaseStatementProvider.class);
37  
38      private final StringSqlQueryFilterVisitor queryFilterVisitor = new StringSqlQueryFilterVisitor();
39  
40      /**
41       * Builds a {@link JdbcAuditEvent} that will query an oracle database.
42       * {@inheritDoc}
43       */
44      @Override
45      public JdbcAuditEvent buildQueryEvent(final TableMapping mapping, final QueryRequest queryRequest,
46              final JsonValue eventTopicMetaData) throws AuditException {
47          final String querySelectStatement;
48          final TableMappingParametersPair tableMappingParametersPair = new TableMappingParametersPair(mapping);
49  
50          querySelectStatement = buildQuerySql(queryRequest, tableMappingParametersPair);
51          logger.info("Built query select statement: {}", querySelectStatement);
52  
53          final SqlStatementParser sqlStatementParser = new SqlStatementParser(querySelectStatement);
54          final List<Parameter> params = new LinkedList<>();
55          for (String field : sqlStatementParser.getNamedParameters()) {
56              params.add(
57                      new Parameter(
58                              getParameterType(eventTopicMetaData, new JsonPointer(field)),
59                              tableMappingParametersPair.getParameters().get(field)));
60          }
61          return new JdbcAuditEvent(sqlStatementParser.getSqlStatement(), params);
62      }
63  
64      private String buildQuerySql(final QueryRequest queryRequest,
65              final TableMappingParametersPair tableMappingParametersPair) {
66          final int offsetParam = queryRequest.getPagedResultsOffset();
67          int pageSizeParam = queryRequest.getPageSize();
68          if (pageSizeParam == 0) {
69              pageSizeParam = Integer.MAX_VALUE;
70          }
71  
72          final String filterString = queryRequest.getQueryFilter().accept(queryFilterVisitor, tableMappingParametersPair)
73                  .toSql();
74  
75          // default to ordering by id
76          String keysClause = "ORDER BY id ASC";
77  
78          // JsonValue-cheat to avoid an unchecked cast
79          final List<SortKey> sortKeys = queryRequest.getSortKeys();
80          // Check for sort keys and build up order-by syntax
81  
82          if (sortKeys != null && sortKeys.size() > 0) {
83              final List<String> keys = new ArrayList<>();
84              for (final SortKey sortKey : sortKeys) {
85                  keys.add(tableMappingParametersPair.getColumnName(sortKey.getField()) + (sortKey.isAscendingOrder()
86                          ? " ASC" : " DESC"));
87              }
88              keysClause = "ORDER BY " + joinAsString(", ", keys);
89          }
90  
91          final String tableName = tableMappingParametersPair.getTableMapping().getTable();
92          return String.format("SELECT * "
93                  + "FROM ( SELECT %s.*, row_number() OVER ( %s ) AS R FROM %s WHERE %s ) "
94                  + "WHERE R BETWEEN %d AND %d ORDER BY R",
95                  tableName,
96                  keysClause,
97                  tableName,
98                  filterString,
99                  offsetParam + 1,
100                 offsetParam + pageSizeParam);
101     }
102 
103 }