Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions base/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,13 @@
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.mariadb.jdbc</groupId>
<artifactId>mariadb-java-client</artifactId>
<version>3.5.7</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>com.oracle.database.jdbc</groupId>
<artifactId>ojdbc11</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@
import com.evolveum.polygon.sql.base.build.api.SqlObjectClassDefinition;
import com.evolveum.polygon.sql.base.build.api.SqlSchemaBuilder;
import com.evolveum.polygon.sql.base.build.api.SqlSchemaBuilderImpl;
import com.evolveum.polygon.sql.base.dev.SqlDevelopmentMode;
import com.evolveum.polygon.sql.base.dev.SqlObjectClassDevHandler;
import com.evolveum.polygon.sql.base.dev.SqlTableDevHandler;
import com.evolveum.polygon.sql.base.groovy.SqlHandlerLoader;
import com.evolveum.polygon.sql.base.groovy.SqlSchemaDefinitionLoader;
import com.evolveum.polygon.sql.base.groovy.impl.SqlOperationSupportBuilderImpl;
Expand Down Expand Up @@ -175,8 +177,11 @@ private void initialize0(boolean allowConnection) {
additional.addAll(ConnDevSchema.objectClassInfos(
List.of(ConnDevSchema.embeddedBlock(SQL_BLOCK, SQL_BLOCK_TYPE)), List.of()));
additional.add(sqlObjectClassBlock());
additional.add(SqlDevelopmentMode.tableObjectClassInfo());
}

// Detect the database structure once. The same snapshot is translated into the normal
// connector schema and, in development mode, exposed as raw conndev_SqlTable metadata.
List<SqlTableInfo> tables;
try {
if (tableFilter.isDiscoveryEnabled()) {
Expand Down Expand Up @@ -233,12 +238,18 @@ private void initialize0(boolean allowConnection) {
var name = new ObjectClass(ConnDevObjectClass.OBJECT_CLASS_NAME);
var handler = CompositeObjectClassHandler.of(name,ObjectSearchOperation.class, new SqlObjectClassDevHandler(context));
handlers.put(name, handler);

var tableName = new ObjectClass(SqlDevelopmentMode.TABLE_OC_NAME);
var tableHandler = CompositeObjectClassHandler.of(
tableName, ObjectSearchOperation.class, new SqlTableDevHandler(context));
handlers.put(tableName, tableHandler);
}

context.handlers(handlers);
}

private static void populateTableInfo(SqlBaseContext context, List<SqlTableInfo> tables) {
context.setDetectedTables(tables);
var tableMap = new LinkedHashMap<String, SqlTableInfo>();
for (SqlTableInfo table : tables) {
// Use lowercase table name as key for case-insensitive lookup
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import org.identityconnectors.framework.common.objects.ObjectClass;

import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
Expand All @@ -37,6 +38,7 @@ public class SqlBaseContext implements ConnectorContext, ContextLookup, Retrieva
private volatile HikariConnectionPool connectionPool;
private SQLTemplates templates;
private Map<String, SqlTableInfo> tableInfos;
private List<SqlTableInfo> detectedTables = List.of();

public SqlBaseContext(SqlConnectorConfiguration configuration) {
this.configuration = configuration;
Expand Down Expand Up @@ -180,6 +182,15 @@ void setTableInfos(Map<String, SqlTableInfo> tableInfos) {
this.tableInfos = tableInfos != null ? Map.copyOf(tableInfos) : null;
}

void setDetectedTables(List<SqlTableInfo> detectedTables) {
this.detectedTables = detectedTables != null ? List.copyOf(detectedTables) : List.of();
}

/** Returns every detected table, including equal table names from different schemas. */
public List<SqlTableInfo> getDetectedTables() {
return detectedTables;
}

/**
* Returns the table info map for custom query building.
*/
Expand All @@ -199,4 +210,4 @@ public SqlTableInfo findTableInfo(String tableName) {
}
return null;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ public class SqlConnectorConfiguration extends BaseGroovyConnectorConfiguration
private String scanExcludeTables;
private String scanExcludeViews;
private String testConnectionQuery;
private String pgDumpPath = "pg_dump";

@ConfigurationProperty(required = true, order = 0)
public String getJdbcUrl() {
Expand Down Expand Up @@ -182,4 +183,17 @@ public String getTestConnectionQuery() {
public void setTestConnectionQuery(String testConnectionQuery) {
this.testConnectionQuery = testConnectionQuery;
}
}

/**
* Executable used to read native PostgreSQL table and view definitions in development mode.
* May be an absolute path or a command available on {@code PATH}. A blank value disables it.
*/
@ConfigurationProperty(order = 110)
public String getPgDumpPath() {
return pgDumpPath;
}

public void setPgDumpPath(String pgDumpPath) {
this.pgDumpPath = pgDumpPath;
}
}
40 changes: 40 additions & 0 deletions base/src/main/java/com/evolveum/polygon/sql/base/SqlDatabase.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* Copyright (c) 2026 Evolveum and contributors
*
* This work is licensed under European Union Public License v1.2. See LICENSE file for details.
*
*/
package com.evolveum.polygon.sql.base;

import java.util.List;

/** Supported database products identified from JDBC metadata. */
public enum SqlDatabase {

H2("H2"),
MARIADB("MariaDB"),
MYSQL("MySQL"),
ORACLE("Oracle"),
POSTGRESQL("PostgreSQL"),
SQLITE("SQLite"),
UNKNOWN();

private final List<String> jdbcProductNames;

SqlDatabase(String... jdbcProductNames) {
this.jdbcProductNames = List.of(jdbcProductNames);
}

public static SqlDatabase fromJdbcProductName(String productName) {
if (productName == null) {
return UNKNOWN;
}
for (var database : values()) {
if (database.jdbcProductNames.stream()
.anyMatch(productName::equalsIgnoreCase)) {
return database;
}
}
return UNKNOWN;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import com.evolveum.polygon.conndev.schema.BaseSchemaBuilder;
import com.evolveum.polygon.sql.base.schema.SqlSchemaDetector;
import com.querydsl.core.types.PathMetadataFactory;
import com.querydsl.core.types.Path;
import com.querydsl.sql.RelationalPathBase;
import groovy.lang.Closure;
import org.identityconnectors.framework.common.objects.Name;
Expand Down Expand Up @@ -105,7 +106,26 @@ public String getTableName() {


public RelationalPathBase<?> pathAlias(String alias) {
return new RelationalPathBase<>(Object.class, PathMetadataFactory.forVariable(alias), schema.value(), table.value());
var schemaName = schema.value();
if (schemaName == null || schemaName.isBlank() || "null".equalsIgnoreCase(schemaName)) {
schemaName = null;
}
return new DynamicRelationalPath(
Object.class, PathMetadataFactory.forVariable(alias), schemaName, table.value());
}
}

/** Dynamic QueryDSL path that can expose a detected generated key to JDBC drivers. */
public static final class DynamicRelationalPath extends RelationalPathBase<Object> {

private DynamicRelationalPath(
Class<?> type, com.querydsl.core.types.PathMetadata metadata,
String schema, String table) {
super(type, metadata, schema, table);
}

public void registerPrimaryKey(Path<?> path) {
createPrimaryKey(path);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* Copyright (c) 2026 Evolveum and contributors
*
* This work is licensed under European Union Public License v1.2. See LICENSE file for details.
*
*/
package com.evolveum.polygon.sql.base.dev;

import org.identityconnectors.framework.common.objects.AttributeInfo;
import org.identityconnectors.framework.common.objects.AttributeInfoBuilder;
import org.identityconnectors.framework.common.objects.Name;
import org.identityconnectors.framework.common.objects.ObjectClassInfo;
import org.identityconnectors.framework.common.objects.ObjectClassInfoBuilder;
import org.identityconnectors.framework.common.objects.Uid;

/** Development-only SQL metadata object classes. */
public final class SqlDevelopmentMode {

public static final String TABLE_OC_NAME = "conndev_SqlTable";
public static final String CATALOG_ATTRIBUTE = "catalog";
public static final String SCHEMA_ATTRIBUTE = "schema";
public static final String TABLE_TYPE_ATTRIBUTE = "tableType";
public static final String REMARKS_ATTRIBUTE = "remarks";
public static final String DEFINITION_ATTRIBUTE = "definition";
public static final String TABLE_CONTENT_ATTRIBUTE = "tableContent";

private SqlDevelopmentMode() {
}

/** Raw detected table/view metadata, analogous to the SCIM development metadata exports. */
public static ObjectClassInfo tableObjectClassInfo() {
var builder = new ObjectClassInfoBuilder();
builder.setType(TABLE_OC_NAME);
builder.addAttributeInfo(readOnly(Uid.NAME));
builder.addAttributeInfo(readOnly(Name.NAME));
builder.addAttributeInfo(readOnly(CATALOG_ATTRIBUTE));
builder.addAttributeInfo(readOnly(SCHEMA_ATTRIBUTE));
builder.addAttributeInfo(readOnly(TABLE_TYPE_ATTRIBUTE));
builder.addAttributeInfo(readOnly(REMARKS_ATTRIBUTE));
builder.addAttributeInfo(readOnly(DEFINITION_ATTRIBUTE));
builder.addAttributeInfo(readOnly(TABLE_CONTENT_ATTRIBUTE));
return builder.build();
}

private static AttributeInfo readOnly(String name) {
return AttributeInfoBuilder.define(name)
.setType(String.class)
.setCreateable(false)
.setUpdateable(false)
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
* Search handler for the {@code conndev_ObjectClass} object class of the SQL connector. Serializes the
* framework schema model (conndev {@code BaseSchema}, translated from the detected tables) via the
* shared {@link ConnDevObjectClassSerializer}. Supports equals filters on {@code __UID__} / {@code __NAME__}.
*
* <p>This is the connector-oriented view of the schema. {@link SqlTableDevHandler} exposes the raw
* JDBC-oriented view, but both views originate from the same schema-discovery snapshot.</p>
*/
public class SqlObjectClassDevHandler implements ObjectSearchOperation {

Expand Down
Loading