diff --git a/API_OVERVIEW.md b/API_OVERVIEW.md new file mode 100644 index 0000000..146ea2e --- /dev/null +++ b/API_OVERVIEW.md @@ -0,0 +1,500 @@ +# API 简介 + +## 元数据接口 + +接口总览与支持情况 + +| 接口 | Sqlite | 达梦(DM) | KingBase | GBase8a | GBase8s | GBase8t | Hive | Es (jdbc) | Hbase (phoenix) | Mysql | Mariodb | Mssql | Oracle | PostgreSQL | +|---------------------------|----------|----------|----------|----------|----------|----------|----------|-----------|-----------------|----------|----------|----------|----------|------------| +| 测试数据库连接(testConnection) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| 创建数据库连接(createConnection) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| 关闭数据库连接(closeConnection) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| 获取数据库模式名(getSchema) | 不涉及 | ✓ | ✓ | ✓ | 不涉及 | 不涉及 | 不涉及 | 不涉及 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| 获取表名(getTables) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| 获取视图名(getViews) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | 不涉及 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| 获取所有函数(getFuncs) | 不涉及 | ✓ | ✓ | ✓ | ✓ | ✓ | 不涉及 | 不涉及 | 不涉及 | ✓ | ✓ | ✓ | ✓ | ✓ | +| 获取表元数据(getMetaData) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | 不涉及 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| 获取表属性(getTableAttribute) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| 获取主键(getPrimaryKeys) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | 不涉及 | 不涉及 | 不涉及 | ✓ | ✓ | ✓ | ✓ | ✓ | +| 获取唯一键(getUniqueKeys) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | 不涉及 | 不涉及 | 不涉及 | ✓ | ✓ | ✓ | ✓ | ✓ | +| 获取索引信息(getIndex) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | 不涉及 | 不涉及 | 不涉及 | ✓ | ✓ | ✓ | ✓ | ✓ | + + +### 1、测试数据库连接接口(testConnection) +该接口用于测试与数据库的连接。它接收以下参数: + +- `driver`:JDBC驱动类的完全限定名。 +- `url`:数据库的JDBC URL。 +- `username`:数据库连接的用户名。 +- `password`:数据库连接的密码。 + +接口返回一个布尔值,表示连接是否成功(`true`)或失败(`false`)。这个函数主要用于验证数据库连接参数的正确性,以确保应用程序能够顺利与数据库进行通信。 + +### 2、创建数据库连接接口(createConnection) + +该接口根据提供的参数创建一个数据库连接。它接收以下参数: + +- `driver`:JDBC驱动类的完全限定名。 +- `url`:数据库的JDBC URL。 +- `username`:数据库连接的用户名。 +- `password`:数据库连接的密码。 + +如果连接成功建立,接口将返回一个`Connection`对象;否则,返回`null`。通过此接口,可以方便地根据指定的参数创建与数据库的连接,并用于后续的数据库操作。 + +### 3、关闭数据库连接接口(closeConnection) + +该接口用于关闭一个已建立的数据库连接。它接收以下参数: + +- `connection`:需要关闭的`Connection`对象。 +- `dbType`:数据库类型(例如,"SQLite"、"Mysql"、"DM"、"Hive"等)。 + +接口返回一个布尔值,表示连接是否成功关闭。通过此接口,可以在完成数据库操作后及时关闭与数据库的连接,以避免资源泄露和其他潜在问题。 + +### 4、获取数据库模式名(Schema)接口(getSchema) + +该接口用于获取指定数据库类型的所有模式名。它接收以下参数: + +- `connection`:一个表示与数据库的连接的`java.sql.Connection`对象。 +- `dbType`:表示数据库类型的字符串(例如,"Mysql"、"DM"、"Oracle"等)。 + +接口返回一个包含模式名字符串的列表。通过此接口,可以轻松地获取数据库中所有可用的模式名,从而方便地进行数据库表和视图的管理操作。 + +### 5、获取指定模式下的所有表名接口(getTables) + +该接口用于获取指定数据库模式下的所有表名。它接收以下参数: + +- `connection`:一个表示与数据库的连接的`java.sql.Connection`对象。 +- `dbType`:表示数据库类型的字符串(例如,"SQLite"、"Mysql"、"DM"、"Hive"等)。 +- `schemaName`:要获取表名的模式的名称。 + +接口返回一个包含指定模式下表名的列表。通过此接口,可以轻松地获取数据库模式中所有可用的表名,从而方便地进行数据表的查询和管理操作。 + + +### 6、获取指定模式下的所有视图名接口(getViews) + +该接口用于获取指定数据库模式下的所有视图名。它接收以下参数: + +- `connection`:一个表示与数据库的连接的`java.sql.Connection`对象。 +- `dbType`:表示数据库类型的字符串(例如,"SQLite"、"Mysql"、"DM"、"Hive"等)。 +- `schemaName`:要获取视图名的模式的名称。 + +接口返回一个包含指定模式下视图名的列表。通过此接口,可以轻松地获取数据库模式中所有可用的视图名,从而方便地进行数据视图的查询和管理操作。 + +### 7、获取指定模式下的所有函数接口(getFuncs) + +该接口用于获取指定数据库模式下的所有函数。它接收以下参数: + +- `connection`:一个表示与数据库的连接的`java.sql.Connection`对象。 +- `dbType`:表示数据库类型的字符串(例如,"Mysql"、"DM"、"Hive"等)。 +- `schemaName`:要获取函数的模式的名称。 + +接口返回一个包含指定模式下所有函数的`DatabaseFunction`对象列表。通过此接口,可以轻松地获取数据库模式中所有可用的函数,从而方便地进行数据库函数的查询和管理操作。 + +### 8、获取指定模式下的表元数据接口(getMetaData) + +该接口用于获取指定数据库模式下的表元数据。它接收以下参数: + +- `connection`:一个表示与数据库的连接的`java.sql.Connection`对象。 +- `dbType`:表示数据库类型的字符串(例如,"SQLite"、"Mysql"、"DM"、"Hive"等)。 +- `schemaName`:要获取元数据的模式的名称。 + +接口返回一个包含指定模式下表元数据的`TableMetaData`对象列表。通过此接口,可以轻松地获取数据库模式中所有表的元数据,从而方便地进行数据库表结构的查询和管理操作。 + +### 9、获取指定表的属性接口(getTableAttribute) + +该接口用于获取指定模式下某个表的属性。它接收以下参数: + +- `connection`:一个表示与数据库的连接的`java.sql.Connection`对象。 +- `dbType`:表示数据库类型的字符串(例如,"SQLite"、"Mysql"、"DM"、"Hive"等)。 +- `schemaName`:表所在的模式的名称。 +- `table`:要获取属性的表名。 + +接口返回一个包含指定表属性的`TableAttribute`对象列表。通过此接口,可以轻松地获取数据库表的属性,从而方便地进行数据库表结构的查询和管理操作。 + +### 10、获取指定数据库表的主键接口(getPrimaryKeys) + +该接口用于获取指定模式下某个表的主键。它接收以下参数: + +- `connection`:一个表示与数据库的连接的`java.sql.Connection`对象。 +- `dbType`:表示数据库类型的字符串(例如,"SQLite"、"Mysql"、"DM"、"Hive"等)。 +- `schemaName`:指定的模式名称。 +- `table`:指定的表名称。 + +接口返回一个字符串的`List`。通过此接口,可以轻松地获取数据库表的主键信息,从而方便地进行数据库表结构的查询和管理操作。 + +### 11、获取指定数据库表的唯一键接口(getUniqueKeys) + +该接口用于获取指定模式下某个表的唯一键。它接收以下参数: + +- `connection`:一个表示与数据库的连接的`java.sql.Connection`对象。 +- `dbType`:表示数据库类型的字符串(例如,"SQLite"、"Mysql"、"DM"、"Hive"等)。 +- `schemaName`:指定的模式名称。 +- `table`:指定的表名称。 + +接口返回一个`Map`,其中键是唯一键的名称,值是包含唯一键列名的集合。通过此接口,可以轻松地获取数据库表的唯一键信息,从而方便地进行数据库表结构的查询和管理操作。 + +### 12、获取指定表的索引信息接口(getIndex) + +该接口用于获取给定模式中指定表的索引信息。它接收以下参数: + +- `connection`:一个表示与数据库的连接的`java.sql.Connection`对象。 +- `dbType`:表示数据库类型的字符串(例如,"SQLite"、"Mysql"、"DM"、"Hive"等)。 +- `schemaName`:表所在的模式名称。 +- `table`:要获取索引信息的表名称。 + +接口返回一个`TableIndex`对象列表,每个对象包含指定表中一个索引的信息。通过此接口,可以轻松地获取数据库表的索引信息,从而方便地进行数据库表结构的查询和管理操作。 + + +## 数据处理接口 + +接口总览与支持情况 + +| 接口 | Sqlite | 达梦(DM) | KingBase | GBase8a | GBase8s | GBase8t | Hive | Es (jdbc) | Hbase (phoenix) | Mysql | Mariodb | Mssql | Oracle | PostgreSQL | +|-----------------------------------|----------|----------|----------|----------|----------|----------|-----------------|-----------|-----------------|----------|----------|----------|----------|------------| +| 执行更新 SQL(executeUpdateSQL) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | 返回值为0 | 不涉及 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| 批量执行更新 SQL(executeUpdateSQLBatch) | ✓ | ✓ | ✓ | ✓ | 不支持事务 | 不支持事务 | 返回值为0, 且不支持事务 | 不涉及 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| 执行查询 SQL(executeQuerySQL) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| 批量执行查询 SQL(executeQuerySQLBatch) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| 执行通用 SQL(executeSQL) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | 不涉及 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| 批量执行通用 SQL(executeSQLBatch) | ✓ | ✓ | ✓ | 不支持事务 | 不支持事务 | 不支持事务 | 返回值为0, 且不支持事务 | 不涉及 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| 执行通用 SQL 脚本(executeSQLScript) | ✓ | ✓ | ✓ | 不支持事务 | 不支持事务 | 不支持事务 | 更新操作返回0, 且不支持事务 | 仅支持查询操作 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| 设置自动提交模式(setAutoCommit) | ✓ | ✓ | ✓ | ✓ | 不涉及 | 不涉及 | 不涉及 | 不涉及 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| 提交事务(commit) | ✓ | ✓ | ✓ | ✓ | 不涉及 | 不涉及 | 不涉及 | 不涉及 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| 回滚事务(rollback) | ✓ | ✓ | ✓ | ✓ | 不涉及 | 不涉及 | 不涉及 | 不涉及 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| 获取表格或视图数据(getTableOrViewData) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| 带分页的数据获取接口(getDataWithPage) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | 不支持 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| 执行数据库函数(executeFunction) | 不涉及 | ✓ | ✓ | ✓ | ✓ | ✓ | 不涉及 | 不涉及 | 不涉及 | ✓ | ✓ | ✓ | ✓ | ✓ | + + + +### 1、执行更新 SQL 接口(executeUpdateSQL) + +该接口用于使用提供的数据库连接执行给定的更新 SQL 语句。它接收以下参数: + +- `connection`:一个表示与数据库的连接的`java.sql.Connection`对象。 +- `dbType`:表示数据库类型的字符串(例如,"SQLite"、"Mysql"、"DM"、"Hive"等)。 +- `sql`:要执行的 SQL 查询字符串。 + +接口返回一个整数,表示受查询影响的行数。通过此接口,可以方便地执行更新、插入或删除操作,并获取受操作影响的记录数量,从而方便地进行数据库表内容的管理操作。 + +### 2、批量执行更新 SQL 接口(executeUpdateSQLBatch) + +该接口用于执行一批更新 SQL 语句,并返回成功更新的记录数。它接收以下参数: + +- `connection`:用于执行批量更新的数据库连接(`java.sql.Connection`)。 +- `dbType`:表示数据库类型的字符串(例如,"SQLite"、"Mysql"、"DM"、"Hive"等)。 +- `sqlList`:要执行的更新 SQL 语句列表。 + +接口返回一个整数,表示成功更新的记录数。通过此接口,可以批量执行更新、插入或删除操作,并获取成功更新的记录数量,从而提高数据库表内容管理操作的效率。 + +### 3、执行查询 SQL 并返回结果接口(executeQuerySQL) + +该接口用于执行 SQL 查询,并将结果返回为一个由映射组成的列表。它接收以下参数: + +- `connection`:用于执行查询的数据库连接(`java.sql.Connection`)。 +- `dbType`:表示数据库类型的字符串(例如,"SQLite"、"Mysql"、"DM"、"Hive"等)。 +- `sql`:要执行的 SQL 查询字符串(String)。 + +接口返回一个列表,其中每个映射表示查询结果中的一行,键为列名,值为相应的数据。通过此接口,可以方便地执行查询操作,并将结果处理为易于操作和使用的数据结构。 + +### 4、批量执行查询 SQL 并返回结果接口(executeQuerySQLBatch) + +该接口用于批量执行 SQL 查询,并将结果返回为一个由列表组成的列表,每个列表由映射组成。它接收以下参数: + +- `connection`:用于执行查询的数据库连接(`java.sql.Connection`)。 +- `dbType`:表示数据库类型的字符串(例如,"SQLite"、"Mysql"、"DM"、"Hive"等)。 +- `sqlList`:要执行的 SQL 查询字符串列表。 + +接口返回一个列表,其中每个内部列表表示一个查询结果,每个映射表示结果集中的一行,键为列名,值为相应的数据。通过此接口,可以方便地批量执行查询操作,并将结果处理为易于操作和使用的数据结构。 + +### 5、执行通用 SQL 并返回结果接口(executeSQL) + +该接口用于执行 SQL 查询,并将结果返回为一个由映射组成的列表。它接收以下参数: + +- `connection`:用于执行sql的数据库连接(`java.sql.Connection`)。 +- `dbType`:表示数据库类型的字符串(例如,"SQLite"、"Mysql"、"DM"、"Hive"等)。 +- `sql`:要执行的查询或更新 SQL 字符串,(String)。 + +若无法确定 SQL 语句的类型,可使用此接口。接口返回一个列表,其中每个映射表示查询或更新结果中的一行,键为列名,值为相应的数据;对于更新操作,返回的列表中只包含一个键值对,键为"rows",值为受影响的记录数。 + +### 6、批量执行通用 SQL 并返回结果接口(executeSQLBatch) + +该接口用于批量执行 SQL 查询,并将结果返回为一个由映射组成的列表。它接收以下参数: + +- `connection`:用于执行sql的数据库连接(`java.sql.Connection`)。 +- `dbType`:表示数据库类型的字符串(例如,"SQLite"、"Mysql"、"DM"、"Hive"等)。 +- `sqlList`:要执行的查询或更新 SQL 字符串列表。 + +接口返回一个列表,其中每个内部列表表示一个查询或更新的结果,每个映射表示结果集中的一行,键为列名,值为相应的数据。对于更新操作,返回的列表中只包含一个键值对,键为"rows",值为受影响的记录数。 +是 executeSQL 的批量执行接口,默认支持事务执行。 + +### 7、执行通用 SQL 脚本并返回结果接口(executeSQLScript) + +该接口用于执行 SQL 查询,并将结果返回为一个由映射组成的列表。它接收以下参数: + +- `connection`:用于执行sql的数据库连接(`java.sql.Connection`)。 +- `dbType`:表示数据库类型的字符串(例如,"SQLite"、"Mysql"、"DM"、"Hive"等)。 +- `sqlScript`:要执行的查询或更新 SQL 脚本,可包含多条 SQL 语句,以分号";"分隔。 + +接口返回一个列表,其中每个内部列表表示一个查询或更新的结果,每个映射表示结果集中的一行,键为列名,值为相应的数据。对于更新操作,返回的列表中只包含一个键值对,键为"rows",值为受影响的记录数。 +通过此接口,可以方便地执行以分号分隔的 SQL 脚本,默认支持事务执行。 + + +### 8、设置自动提交模式接口(setAutoCommit) + +该接口用于设置给定数据库连接的自动提交模式。它接收以下参数: + +- `connection`:需要设置自动提交模式的数据库连接(`java.sql.Connection`)。 +- `dbType`:表示数据库类型的字符串(例如,"SQLite"、"Mysql"、"DM"等)。 +- `autoCommit`:要为连接设置的自动提交模式(布尔值)。 + +接口返回一个布尔值,如果自动提交模式成功设置,则返回 true,否则返回 false。通过此接口,可以控制数据库连接是否在每次执行操作后自动提交事务,以便根据应用程序需求进行调整。 + +### 9、提交事务接口(commit) + +该接口用于提交给定数据库连接上的事务。它接收以下参数: + +- `connection`:正在执行事务的数据库连接(`java.sql.Connection`)。 +- `dbType`:表示数据库类型的字符串(例如,"SQLite"、"Mysql"、"DM"等)。 + +接口返回一个布尔值,如果事务成功提交,则返回 true,否则返回 false。通过此接口,可以在执行批量操作或需要保证数据一致性的操作时,确保事务得到正确提交。 + +### 10、回滚事务接口(rollback) + +该接口用于回滚给定数据库连接上的事务。它接收以下参数: + +- `connection`:正在执行事务的数据库连接(`java.sql.Connection`)。 +- `dbType`:表示数据库类型的字符串(例如,"SQLite"、"Mysql"、"DM"等)。 + +接口返回一个布尔值,如果事务成功回滚,则返回 true,否则返回 false。通过此接口,可以在事务执行过程中遇到错误时撤销之前的操作,以确保数据库数据的一致性。 + +### 11、获取表格或视图数据接口(getTableOrViewData) + +该接口用于从给定数据库连接的指定表格或视图中获取数据。它接收以下参数: + +- `connection`:要从中获取数据的数据库连接(`java.sql.Connection`)。 +- `dbType`:表示数据库类型的字符串(例如,"SQLite"、"Mysql"、"DM"、"Hive"等)。 +- `schemaName`:表格所在的模式名。 +- `name`:要获取数据的表格或视图的名称。 + +接口返回一个包含表格或视图数据的 Map 列表,其中每个 Map 代表一行,列名作为键。通过此接口,可以方便地从数据库中的表格或视图获取数据,用于分析和处理。 + +### 12、带分页的数据获取接口(getDataWithPage) + +该接口从数据库中获取表或视图数据,支持分页与列选择。它接收以下参数: + +- `connection`:要从中获取数据的数据库连接(`java.sql.Connection`)。 +- `dbType`:表示数据库类型的字符串(例如,"SQLite"、"Mysql"、"DM"、"Hive"等)。 +- `schemaName`:表格所在的模式名。 +- `tableName`:要获取数据的表格或视图的名称。 +- `columnList`:要选择列的列表。如果为空或者没有元素,则选择所有列。 +- `pageOffset`:分页的偏移量。如果小于或等于0,则返回所有数据,不进行分页。 +- `pageSize`:每页大小。如果小于或等于0,则返回所有数据,不进行分页。 + +接口返回一个 Map 对象,包含了 'results' 中获取到的数据以及 'totalPages' 中的数据总页数。通过此接口,可以从数据库中以分页的方式获取表格或视图获取数据,便于处理大数据量的表格或视图。 + +### 13、执行数据库函数接口(executeFunction) + +该接口用于在给定数据库连接上执行指定的数据库函数,并传入指定的参数。它接收以下参数: + +- `connection`:用于执行函数的数据库连接(`java.sql.Connection`)。 +- `dbType`:表示数据库类型的字符串(例如,"Mysql"、"DM"、"Oracle"等)。 +- `schemaName`:表格所在的模式名。 +- `functionName`:要执行的函数的名称。 +- `params`:传递给函数的参数列表。 + +接口返回一个包含函数结果的 Map 列表,其中每个 Map 代表一行,列名作为键。通过此接口,可以方便地在数据库中执行复杂的计算和操作,并获取结果用于进一步分析和处理。 + + +## 敏感数据处理接口 + +接口总览与支持情况 + +| 接口 | Sqlite | 达梦(DM) | KingBase | GBase8a | GBase8s | GBase8t | Hive | Es (jdbc) | Hbase (phoenix) | Mysql | Mariodb | Mssql | Oracle | PostgreSQL | +|-----------------------------------------|----------|----------|----------|----------|----------|----------|-----------------|-----------|-----------------|----------|----------|----------|----------|------------| +| 数据遮掩接口(mask) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| 数据截取接口 (truncate) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| 正则替换接口 (replaceWithRegex) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| 数据泛化接口 (generalize) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| 数据加噪接口 (addNoise) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| 通用脱敏接口 (doObfuscation) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| 带脱敏的表或视图数据获取接口 (getDataWithMask) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| 带脱敏的数据分页获取接口 (getDataWithPageAndMask) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | 不支持 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| 带脱敏的 SQL 查询接口 (execQuerySQLWithMask) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| 带脱敏的 SQL 脚本执行接口 (execSQLScriptWithMask) | ✓ | ✓ | ✓ | 不支持事务 | 不支持事务 | 不支持事务 | 更新操作返回0, 且不支持事务 | 仅支持查询操作 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| 敏感数据扫描接口 (scanTableData) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | + + +### 1、数据遮掩接口(mask) + +该接口用于将输入字符串的一部分替换为指定的遮罩字符。它接收以下参数: + +- `input`:要进行遮罩处理的输入字符串。 +- `start`:遮罩部分的起始索引(包含)。 +- `end`:遮罩部分的结束索引(不包含)。 +- `maskChar`:用于遮罩输入字符串的字符。 + +接口返回一个经过遮罩处理的字符串,指定部分被遮罩字符替换。通过此接口,可以在处理敏感信息时保护用户隐私,例如对手机号、邮箱地址、身份证号等数据进行遮罩处理。 + + +### 2、数据截取接口 (truncate) + +该接口用于将输入字符串进行截取,返回一个原始字符串的子字符串。它接收以下参数: + +- `input`:要进行截取处理的输入字符串。 +- `start`:子字符串的起始索引(包含)。 +- `end`:子字符串的结束索引(不包含)。 + +接口返回一个从输入字符串中提取的子字符串,如果索引无效,则返回原始字符串。通过此接口,可以方便地从原始字符串中提取出指定部分的内容,例如从复杂文本中截取指定长度的摘要等。 + +### 3、正则替换接口 (replaceWithRegex) + +该接口用于使用给定的替换字符串替换输入字符串中匹配给定正则表达式模式的所有出现。它接收以下参数: + +- `input`:要进行处理的输入字符串。 +- `regex`:要匹配的正则表达式模式。 +- `replacement`:用于替换每个匹配项的替换字符串。 + +接口返回一个结果字符串,其中所有匹配的出现都被给定的替换字符串替换。通过此接口,可以方便地在字符串中查找和替换满足特定模式的内容,例如替换电话号码、邮箱地址等敏感信息。 + +### 4、数据泛化接口 (generalize) + +该接口用于将一个整数值泛化为一个范围。它接收以下参数: + +- `data`:要泛化的整数值。 +- `range`:泛化的范围大小。 + +接口返回一个表示泛化范围的字符串,格式为 "lowerBound-upperBound"。通过此接口,可以方便地对整数数据进行分组和泛化,例如将年龄数据分组到指定范围,以便在不暴露具体值的情况下进行分析。 + + +### 5、数据加噪接口 (addNoise) + +该接口用于在给定的噪声范围内为原始值添加随机噪声。它接收以下参数: + +- `originalValue`:要添加噪声的原始双精度浮点值。 +- `noiseRange`:要添加的随机噪声范围。实际添加的噪声将介于 -noiseRange/2 和 +noiseRange/2 之间。 + +接口返回一个双精度浮点值,该值在指定的噪声范围内添加了噪声。通过此接口,可以在数据处理过程中为数值添加一定程度的随机噪声,从而提高数据的隐私性。 + +### 6、通用脱敏接口 (doObfuscation) + +该接口根据提供的脱敏规则对数据进行脱敏处理。接收以下参数: + +- `data`:要脱敏处理的数据。 +- `obfuscationRule`:要应用的脱敏处理规则。 + +该接口返回经过脱敏处理的数据。根据 obfuscationRule 中指定的 ObfuscationMethod 类型,该接口将调用相应的方法进行数据脱敏处理。这可以确保根据特定的规则对敏感数据进行适当的处理,以保护数据隐私。 + +### 7、带脱敏的表或视图数据获取接口 (getDataWithMask) + +该接口从数据库获取表或视图数据,并对指定列应用脱敏规则。接收以下参数: + +- `connection`:数据库连接对象。 +- `dbType`:数据库类型(例如,"SQLite"、"Mysql"、"DM"、"Hive"等)。。 +- `schemaName`:表所在的schema名称。 +- `name`:表或视图的名称。 +- `obfuscationRules`:一个映射,其中键是列名,值是要应用于该列的 ObfuscationRule 对象。 + +该接口返回一个列表,列表中的每个映射表示表或视图的一行,其中指定的脱敏规则已被应用。 + +### 8、带脱敏的数据分页获取接口 (getDataWithPageAndMask) + +该接口从数据库中获取表或视图数据,支持分页与列选择,并对指定列应用脱敏规则。接收以下参数: + +- `connection`:数据库连接对象。 +- `dbType`:数据库类型(例如,"SQLite"、"Mysql"、"DM"、"Hive"等)。。 +- `schemaName`:表所在的schema名称。 +- `tableName`:表或视图的名称。 +- `columnList`:要选择列的列表。如果为空或者没有元素,则选择所有列。 +- `pageOffset`:分页的偏移量。如果小于或等于0,则返回所有数据,不进行分页。 +- `pageSize`:每页大小。如果小于或等于0,则返回所有数据,不进行分页。 +- `obfuscationRules`:一个映射,其中键是列名,值是要应用于该列的 ObfuscationRule 对象。 + +接口返回一个 Map 对象,包含了 'results' 中获取到的数据以及 'totalPages' 中的数据总页数。其中'results' 的数据,会依据指定脱敏规则进行脱敏。 +通过此接口,可以从数据库中以分页的方式获取脱敏后的表格或视图获取数据,便于处理大数据量的表格或视图。 + +### 9、带脱敏的 SQL 查询接口 (execQuerySQLWithMask) + +此接口用于执行SQL查询并将结果返回为列表,同时将指定列应用脱敏规则。接收以下参数: + +- `connection`:用于执行查询的数据库连接(java.sql.Connection)。 +- `dbType`:数据库类型(例如 "sqlite","mysql" 等)。 +- `sql`:要执行的SQL查询字符串(String)。 +- `obfuscationRules`:一个映射,其中键是列名,值是要应用于该列的 ObfuscationRule 对象。 + +该接口返回一个列表,其中每个映射表示查询结果中的一行,键是列名,值是相应的脱敏后数据。 + +### 10、带脱敏的 SQL 脚本执行接口 (execSQLScriptWithMask) + +此接口用于执行SQL脚本并将结果返回为列表,同时将指定列应用脱敏规则。接收以下参数: + +- `connection`:用于执行查询的数据库连接(java.sql.Connection)。 +- `dbType`:数据库类型(例如 "sqlite","mysql" 等)。 +- `sqlScript`:要执行的SQL脚本字符串(String),可包含多条 SQL 语句,以分号";"分隔。。 +- `obfuscationRules`:一个映射,其中键是列名,值是要应用于该列的 ObfuscationRule 对象。 + +该接口返回一个列表,其中每个映射表示查询结果中的一行,键是列名,值是相应的脱敏后数据。 + + +### 11、敏感数据扫描接口 (scanTableData) + +该接口基于一组正则表达式扫描数据库表或视图中的敏感数据。接收以下参数: + +- `connection`:数据库的 SQL 连接。 +- `dbType`:数据库类型(如:SQLite、MySQL、PostgreSQL)。 +- `schemaName`:表所在的 schema 名称。 +- `tableName`:要扫描的表或视图的名称。 +- `regexList`:用于匹配敏感数据的正则表达式列表。 + +该接口返回一个 `SensitiveColumn` 实例列表,其中包含匹配到的敏感数据。仅返回实际匹配到敏感数据的列。对于每个 `SensitiveColumn`,最多 5 个(可配置)匹配的数据将存储在 `matchData` 属性中。 + + +## SQL 生成接口 + +接口总览与支持情况 + +| 接口 | Sqlite | 达梦(DM) | KingBase | GBase8a | GBase8s | GBase8t | Hive | Es (jdbc) | Hbase (phoenix) | Mysql | Mariodb | Mssql | Oracle | PostgreSQL | +|-------------------------------|----------|----------|----------|----------|----------|----------|----------|-----------|-----------------|----------|----------|----------|----------|------------| +| 生成插入数据 SQL(generateInsertSql) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | 不涉及 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| 生成更新数据 SQL(generateUpdateSql) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | 不支持 | 不涉及 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| 生成删除数据 SQL(generateDeleteSql) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | 不支持 | 不涉及 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | + +### 1、生成插入数据 SQL (generateInsertSql) + +该接口基于给定的数据生成 SQL 插入语句。接收以下参数: + +- `connection`:数据库的 SQL 连接。 +- `dbType`:数据库类型(如:SQLite、MySQL、PostgreSQL)。 +- `schemaName`:表所在的 schema 名称。 +- `tableName`:要插入数据的表名称。 +- `data`:要插入的数据,以一个包含列名和对应值的映射形式呈现。 + +该接口返回一个代表 SQL 插入语句的字符串。如果提供的数据为空,或者表名、数据库连接或数据库类型为空,则会抛出 IllegalArgumentException 异常。 此外,如果在执行与数据库相关的操作时遇到任何错误,它还会抛出 `SQLException` 异常。通过该接口,开发者可以方便地为特定数据库生成 SQL 插入语句,无需关心不同数据库之间的 SQL 语法差异,从而大大提升代码的可复用性和维护性。 + +### 2、生成更新数据 SQL (generateUpdateSql) + +该接口基于给定的数据生成 SQL 更新语句。接收以下参数: + +- `connection`:已激活的数据库 SQL 连接。 +- `dbType`:数据库类型,例如:"MySQL"、"PostgreSQL"。 +- `schemaName`:表所在的 schema 名称。 +- `tableName`:要更新数据的表名称。 +- `setData`:表示要更新的列及其对应值的键值对。 +- `condition`:确定将更新哪些行的条件。 +- `filteredByUniqueKey`:标志指示是否根据唯一键筛选条件。 + +该接口返回一个代表 SQL 更新语句的字符串。如果提供的数据为空,或者表名、数据库连接或数据库类型为空,则会抛出 IllegalArgumentException 异常。此外,如果在执行与数据库相关的操作时遇到任何错误,它还会抛出 `SQLException` 异常。通过此接口,开发者可以轻松地为特定的数据库生成 SQL 更新语句,而无需担心不同数据库之间的 SQL 语法差异,从而极大地提高代码的可复用性和维护性。 + +### 3、生成删除数据 SQL (generateDeleteSql) + +该接口基于给定的条件生成 SQL 删除语句。接收以下参数: + +- `connection`:数据库的 SQL 连接。 +- `dbType`:数据库类型(如:SQLite、MySQL、PostgreSQL)。 +- `schemaName`:表所在的 schema 名称。 +- `tableName`:要删除数据的表名称。 +- `condition`:删除数据所需满足的条件,以一个包含列名和对应值的映射形式呈现。 +- `filteredByUniqueKey`:如果设置为 true,则删除条件会被筛选,只保留唯一键作为条件。 + +该接口返回一个代表 SQL 删除语句的字符串。如果提供的条件、表名、数据库连接或数据库类型为空,则会抛出 `IllegalArgumentException` 异常。此外,如果在执行与数据库相关的操作时遇到任何错误,它还会抛出 `SQLException` 异常。通过该接口,开发者可以方便地为特定数据库生成 SQL 删除语句,无需关心不同数据库之间的 SQL 语法差异,从而大大提升代码的可复用性和维护性。 + diff --git a/README.md b/README.md index 8f294ab..5146fce 100644 --- a/README.md +++ b/README.md @@ -42,478 +42,7 @@ DBMasker 为数据库管理员、开发人员、数据安全专家、数据科 数据治理和审计:DBMasker 可助于开发数据治理和审计工具,可以帮助企业在进行数据治理和审计时,实现对敏感数据的保护。例如,在对数据库系统进行审计时,可以使用 DBMasker 提供的敏感数据处理接口对审计数据进行脱敏处理,确保审计过程中不泄露敏感信息。 -# API 简介 - -## 元数据接口 - -接口总览与支持情况 - -| 接口 | Sqlite | 达梦(DM) | KingBase | GBase8a | GBase8s | GBase8t | Hive | Es (jdbc) | Hbase (phoenix) | Mysql | Mariodb | Mssql | Oracle | PostgreSQL | -|---------------------------|----------|----------|----------|----------|----------|----------|----------|-----------|-----------------|----------|----------|----------|----------|------------| -| 测试数据库连接(testConnection) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | -| 创建数据库连接(createConnection) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | -| 关闭数据库连接(closeConnection) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | -| 获取数据库模式名(getSchema) | 不涉及 | ✓ | ✓ | ✓ | 不涉及 | 不涉及 | 不涉及 | 不涉及 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | -| 获取表名(getTables) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | -| 获取视图名(getViews) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | 不涉及 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | -| 获取所有函数(getFuncs) | 不涉及 | ✓ | ✓ | ✓ | ✓ | ✓ | 不涉及 | 不涉及 | 不涉及 | ✓ | ✓ | ✓ | ✓ | ✓ | -| 获取表元数据(getMetaData) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | 不涉及 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | -| 获取表属性(getTableAttribute) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | -| 获取主键(getPrimaryKeys) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | 不涉及 | 不涉及 | 不涉及 | ✓ | ✓ | ✓ | ✓ | ✓ | -| 获取唯一键(getUniqueKeys) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | 不涉及 | 不涉及 | 不涉及 | ✓ | ✓ | ✓ | ✓ | ✓ | -| 获取索引信息(getIndex) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | 不涉及 | 不涉及 | 不涉及 | ✓ | ✓ | ✓ | ✓ | ✓ | - - -### 1、测试数据库连接接口(testConnection) -该接口用于测试与数据库的连接。它接收以下参数: - -- `driver`:JDBC驱动类的完全限定名。 -- `url`:数据库的JDBC URL。 -- `username`:数据库连接的用户名。 -- `password`:数据库连接的密码。 - -接口返回一个布尔值,表示连接是否成功(`true`)或失败(`false`)。这个函数主要用于验证数据库连接参数的正确性,以确保应用程序能够顺利与数据库进行通信。 - -### 2、创建数据库连接接口(createConnection) - -该接口根据提供的参数创建一个数据库连接。它接收以下参数: - -- `driver`:JDBC驱动类的完全限定名。 -- `url`:数据库的JDBC URL。 -- `username`:数据库连接的用户名。 -- `password`:数据库连接的密码。 - -如果连接成功建立,接口将返回一个`Connection`对象;否则,返回`null`。通过此接口,可以方便地根据指定的参数创建与数据库的连接,并用于后续的数据库操作。 - -### 3、关闭数据库连接接口(closeConnection) - -该接口用于关闭一个已建立的数据库连接。它接收以下参数: - -- `connection`:需要关闭的`Connection`对象。 -- `dbType`:数据库类型(例如,"SQLite"、"Mysql"、"DM"、"Hive"等)。 - -接口返回一个布尔值,表示连接是否成功关闭。通过此接口,可以在完成数据库操作后及时关闭与数据库的连接,以避免资源泄露和其他潜在问题。 - -### 4、获取数据库模式名(Schema)接口(getSchema) - -该接口用于获取指定数据库类型的所有模式名。它接收以下参数: - -- `connection`:一个表示与数据库的连接的`java.sql.Connection`对象。 -- `dbType`:表示数据库类型的字符串(例如,"Mysql"、"DM"、"Oracle"等)。 - -接口返回一个包含模式名字符串的列表。通过此接口,可以轻松地获取数据库中所有可用的模式名,从而方便地进行数据库表和视图的管理操作。 - -### 5、获取指定模式下的所有表名接口(getTables) - -该接口用于获取指定数据库模式下的所有表名。它接收以下参数: - -- `connection`:一个表示与数据库的连接的`java.sql.Connection`对象。 -- `dbType`:表示数据库类型的字符串(例如,"SQLite"、"Mysql"、"DM"、"Hive"等)。 -- `schemaName`:要获取表名的模式的名称。 - -接口返回一个包含指定模式下表名的列表。通过此接口,可以轻松地获取数据库模式中所有可用的表名,从而方便地进行数据表的查询和管理操作。 - - -### 6、获取指定模式下的所有视图名接口(getViews) - -该接口用于获取指定数据库模式下的所有视图名。它接收以下参数: - -- `connection`:一个表示与数据库的连接的`java.sql.Connection`对象。 -- `dbType`:表示数据库类型的字符串(例如,"SQLite"、"Mysql"、"DM"、"Hive"等)。 -- `schemaName`:要获取视图名的模式的名称。 - -接口返回一个包含指定模式下视图名的列表。通过此接口,可以轻松地获取数据库模式中所有可用的视图名,从而方便地进行数据视图的查询和管理操作。 - -### 7、获取指定模式下的所有函数接口(getFuncs) - -该接口用于获取指定数据库模式下的所有函数。它接收以下参数: - -- `connection`:一个表示与数据库的连接的`java.sql.Connection`对象。 -- `dbType`:表示数据库类型的字符串(例如,"Mysql"、"DM"、"Hive"等)。 -- `schemaName`:要获取函数的模式的名称。 - -接口返回一个包含指定模式下所有函数的`DatabaseFunction`对象列表。通过此接口,可以轻松地获取数据库模式中所有可用的函数,从而方便地进行数据库函数的查询和管理操作。 - -### 8、获取指定模式下的表元数据接口(getMetaData) - -该接口用于获取指定数据库模式下的表元数据。它接收以下参数: - -- `connection`:一个表示与数据库的连接的`java.sql.Connection`对象。 -- `dbType`:表示数据库类型的字符串(例如,"SQLite"、"Mysql"、"DM"、"Hive"等)。 -- `schemaName`:要获取元数据的模式的名称。 - -接口返回一个包含指定模式下表元数据的`TableMetaData`对象列表。通过此接口,可以轻松地获取数据库模式中所有表的元数据,从而方便地进行数据库表结构的查询和管理操作。 - -### 9、获取指定表的属性接口(getTableAttribute) - -该接口用于获取指定模式下某个表的属性。它接收以下参数: - -- `connection`:一个表示与数据库的连接的`java.sql.Connection`对象。 -- `dbType`:表示数据库类型的字符串(例如,"SQLite"、"Mysql"、"DM"、"Hive"等)。 -- `schemaName`:表所在的模式的名称。 -- `table`:要获取属性的表名。 - -接口返回一个包含指定表属性的`TableAttribute`对象列表。通过此接口,可以轻松地获取数据库表的属性,从而方便地进行数据库表结构的查询和管理操作。 - -### 10、获取指定数据库表的主键接口(getPrimaryKeys) - -该接口用于获取指定模式下某个表的主键。它接收以下参数: - -- `connection`:一个表示与数据库的连接的`java.sql.Connection`对象。 -- `dbType`:表示数据库类型的字符串(例如,"SQLite"、"Mysql"、"DM"、"Hive"等)。 -- `schemaName`:指定的模式名称。 -- `table`:指定的表名称。 - -接口返回一个字符串的`List`。通过此接口,可以轻松地获取数据库表的主键信息,从而方便地进行数据库表结构的查询和管理操作。 - -### 11、获取指定数据库表的唯一键接口(getUniqueKeys) - -该接口用于获取指定模式下某个表的唯一键。它接收以下参数: - -- `connection`:一个表示与数据库的连接的`java.sql.Connection`对象。 -- `dbType`:表示数据库类型的字符串(例如,"SQLite"、"Mysql"、"DM"、"Hive"等)。 -- `schemaName`:指定的模式名称。 -- `table`:指定的表名称。 - -接口返回一个`Map`,其中键是唯一键的名称,值是包含唯一键列名的集合。通过此接口,可以轻松地获取数据库表的唯一键信息,从而方便地进行数据库表结构的查询和管理操作。 - -### 12、获取指定表的索引信息接口(getIndex) - -该接口用于获取给定模式中指定表的索引信息。它接收以下参数: - -- `connection`:一个表示与数据库的连接的`java.sql.Connection`对象。 -- `dbType`:表示数据库类型的字符串(例如,"SQLite"、"Mysql"、"DM"、"Hive"等)。 -- `schemaName`:表所在的模式名称。 -- `table`:要获取索引信息的表名称。 - -接口返回一个`TableIndex`对象列表,每个对象包含指定表中一个索引的信息。通过此接口,可以轻松地获取数据库表的索引信息,从而方便地进行数据库表结构的查询和管理操作。 - - -## 数据处理接口 - -接口总览与支持情况 - -| 接口 | Sqlite | 达梦(DM) | KingBase | GBase8a | GBase8s | GBase8t | Hive | Es (jdbc) | Hbase (phoenix) | Mysql | Mariodb | Mssql | Oracle | PostgreSQL | -|-----------------------------------|----------|----------|----------|----------|----------|----------|-----------------|-----------|-----------------|----------|----------|----------|----------|------------| -| 执行更新 SQL(executeUpdateSQL) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | 返回值为0 | 不涉及 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | -| 批量执行更新 SQL(executeUpdateSQLBatch) | ✓ | ✓ | ✓ | ✓ | 不支持事务 | 不支持事务 | 返回值为0, 且不支持事务 | 不涉及 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | -| 执行查询 SQL(executeQuerySQL) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | -| 批量执行查询 SQL(executeQuerySQLBatch) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | -| 执行通用 SQL(executeSQL) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | 不涉及 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | -| 批量执行通用 SQL(executeSQLBatch) | ✓ | ✓ | ✓ | 不支持事务 | 不支持事务 | 不支持事务 | 返回值为0, 且不支持事务 | 不涉及 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | -| 执行通用 SQL 脚本(executeSQLScript) | ✓ | ✓ | ✓ | 不支持事务 | 不支持事务 | 不支持事务 | 更新操作返回0, 且不支持事务 | 仅支持查询操作 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | -| 设置自动提交模式(setAutoCommit) | ✓ | ✓ | ✓ | ✓ | 不涉及 | 不涉及 | 不涉及 | 不涉及 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | -| 提交事务(commit) | ✓ | ✓ | ✓ | ✓ | 不涉及 | 不涉及 | 不涉及 | 不涉及 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | -| 回滚事务(rollback) | ✓ | ✓ | ✓ | ✓ | 不涉及 | 不涉及 | 不涉及 | 不涉及 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | -| 获取表格或视图数据(getTableOrViewData) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | -| 带分页的数据获取接口(getDataWithPage) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | 不支持 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | -| 执行数据库函数(executeFunction) | 不涉及 | ✓ | ✓ | ✓ | ✓ | ✓ | 不涉及 | 不涉及 | 不涉及 | ✓ | ✓ | ✓ | ✓ | ✓ | - - - -### 1、执行更新 SQL 接口(executeUpdateSQL) - -该接口用于使用提供的数据库连接执行给定的更新 SQL 语句。它接收以下参数: - -- `connection`:一个表示与数据库的连接的`java.sql.Connection`对象。 -- `dbType`:表示数据库类型的字符串(例如,"SQLite"、"Mysql"、"DM"、"Hive"等)。 -- `sql`:要执行的 SQL 查询字符串。 - -接口返回一个整数,表示受查询影响的行数。通过此接口,可以方便地执行更新、插入或删除操作,并获取受操作影响的记录数量,从而方便地进行数据库表内容的管理操作。 - -### 2、批量执行更新 SQL 接口(executeUpdateSQLBatch) - -该接口用于执行一批更新 SQL 语句,并返回成功更新的记录数。它接收以下参数: - -- `connection`:用于执行批量更新的数据库连接(`java.sql.Connection`)。 -- `dbType`:表示数据库类型的字符串(例如,"SQLite"、"Mysql"、"DM"、"Hive"等)。 -- `sqlList`:要执行的更新 SQL 语句列表。 - -接口返回一个整数,表示成功更新的记录数。通过此接口,可以批量执行更新、插入或删除操作,并获取成功更新的记录数量,从而提高数据库表内容管理操作的效率。 - -### 3、执行查询 SQL 并返回结果接口(executeQuerySQL) - -该接口用于执行 SQL 查询,并将结果返回为一个由映射组成的列表。它接收以下参数: - -- `connection`:用于执行查询的数据库连接(`java.sql.Connection`)。 -- `dbType`:表示数据库类型的字符串(例如,"SQLite"、"Mysql"、"DM"、"Hive"等)。 -- `sql`:要执行的 SQL 查询字符串(String)。 - -接口返回一个列表,其中每个映射表示查询结果中的一行,键为列名,值为相应的数据。通过此接口,可以方便地执行查询操作,并将结果处理为易于操作和使用的数据结构。 - -### 4、批量执行查询 SQL 并返回结果接口(executeQuerySQLBatch) - -该接口用于批量执行 SQL 查询,并将结果返回为一个由列表组成的列表,每个列表由映射组成。它接收以下参数: - -- `connection`:用于执行查询的数据库连接(`java.sql.Connection`)。 -- `dbType`:表示数据库类型的字符串(例如,"SQLite"、"Mysql"、"DM"、"Hive"等)。 -- `sqlList`:要执行的 SQL 查询字符串列表。 - -接口返回一个列表,其中每个内部列表表示一个查询结果,每个映射表示结果集中的一行,键为列名,值为相应的数据。通过此接口,可以方便地批量执行查询操作,并将结果处理为易于操作和使用的数据结构。 - -### 5、执行通用 SQL 并返回结果接口(executeSQL) - -该接口用于执行 SQL 查询,并将结果返回为一个由映射组成的列表。它接收以下参数: - -- `connection`:用于执行sql的数据库连接(`java.sql.Connection`)。 -- `dbType`:表示数据库类型的字符串(例如,"SQLite"、"Mysql"、"DM"、"Hive"等)。 -- `sql`:要执行的查询或更新 SQL 字符串,(String)。 - -若无法确定 SQL 语句的类型,可使用此接口。接口返回一个列表,其中每个映射表示查询或更新结果中的一行,键为列名,值为相应的数据;对于更新操作,返回的列表中只包含一个键值对,键为"rows",值为受影响的记录数。 - -### 6、批量执行通用 SQL 并返回结果接口(executeSQLBatch) - -该接口用于批量执行 SQL 查询,并将结果返回为一个由映射组成的列表。它接收以下参数: - -- `connection`:用于执行sql的数据库连接(`java.sql.Connection`)。 -- `dbType`:表示数据库类型的字符串(例如,"SQLite"、"Mysql"、"DM"、"Hive"等)。 -- `sqlList`:要执行的查询或更新 SQL 字符串列表。 - -接口返回一个列表,其中每个内部列表表示一个查询或更新的结果,每个映射表示结果集中的一行,键为列名,值为相应的数据。对于更新操作,返回的列表中只包含一个键值对,键为"rows",值为受影响的记录数。 -是 executeSQL 的批量执行接口,默认支持事务执行。 - -### 7、执行通用 SQL 脚本并返回结果接口(executeSQLScript) - -该接口用于执行 SQL 查询,并将结果返回为一个由映射组成的列表。它接收以下参数: - -- `connection`:用于执行sql的数据库连接(`java.sql.Connection`)。 -- `dbType`:表示数据库类型的字符串(例如,"SQLite"、"Mysql"、"DM"、"Hive"等)。 -- `sqlScript`:要执行的查询或更新 SQL 脚本,可包含多条 SQL 语句,以分号";"分隔。 - -接口返回一个列表,其中每个内部列表表示一个查询或更新的结果,每个映射表示结果集中的一行,键为列名,值为相应的数据。对于更新操作,返回的列表中只包含一个键值对,键为"rows",值为受影响的记录数。 -通过此接口,可以方便地执行以分号分隔的 SQL 脚本,默认支持事务执行。 - - -### 8、设置自动提交模式接口(setAutoCommit) - -该接口用于设置给定数据库连接的自动提交模式。它接收以下参数: - -- `connection`:需要设置自动提交模式的数据库连接(`java.sql.Connection`)。 -- `dbType`:表示数据库类型的字符串(例如,"SQLite"、"Mysql"、"DM"等)。 -- `autoCommit`:要为连接设置的自动提交模式(布尔值)。 - -接口返回一个布尔值,如果自动提交模式成功设置,则返回 true,否则返回 false。通过此接口,可以控制数据库连接是否在每次执行操作后自动提交事务,以便根据应用程序需求进行调整。 - -### 9、提交事务接口(commit) - -该接口用于提交给定数据库连接上的事务。它接收以下参数: - -- `connection`:正在执行事务的数据库连接(`java.sql.Connection`)。 -- `dbType`:表示数据库类型的字符串(例如,"SQLite"、"Mysql"、"DM"等)。 - -接口返回一个布尔值,如果事务成功提交,则返回 true,否则返回 false。通过此接口,可以在执行批量操作或需要保证数据一致性的操作时,确保事务得到正确提交。 - -### 10、回滚事务接口(rollback) - -该接口用于回滚给定数据库连接上的事务。它接收以下参数: - -- `connection`:正在执行事务的数据库连接(`java.sql.Connection`)。 -- `dbType`:表示数据库类型的字符串(例如,"SQLite"、"Mysql"、"DM"等)。 - -接口返回一个布尔值,如果事务成功回滚,则返回 true,否则返回 false。通过此接口,可以在事务执行过程中遇到错误时撤销之前的操作,以确保数据库数据的一致性。 - -### 11、获取表格或视图数据接口(getTableOrViewData) - -该接口用于从给定数据库连接的指定表格或视图中获取数据。它接收以下参数: - -- `connection`:要从中获取数据的数据库连接(`java.sql.Connection`)。 -- `dbType`:表示数据库类型的字符串(例如,"SQLite"、"Mysql"、"DM"、"Hive"等)。 -- `schemaName`:表格所在的模式名。 -- `name`:要获取数据的表格或视图的名称。 - -接口返回一个包含表格或视图数据的 Map 列表,其中每个 Map 代表一行,列名作为键。通过此接口,可以方便地从数据库中的表格或视图获取数据,用于分析和处理。 - -### 12、带分页的数据获取接口(getDataWithPage) - -该接口从数据库中获取表或视图数据,支持分页与列选择。它接收以下参数: - -- `connection`:要从中获取数据的数据库连接(`java.sql.Connection`)。 -- `dbType`:表示数据库类型的字符串(例如,"SQLite"、"Mysql"、"DM"、"Hive"等)。 -- `schemaName`:表格所在的模式名。 -- `tableName`:要获取数据的表格或视图的名称。 -- `columnList`:要选择列的列表。如果为空或者没有元素,则选择所有列。 -- `pageOffset`:分页的偏移量。如果小于或等于0,则返回所有数据,不进行分页。 -- `pageSize`:每页大小。如果小于或等于0,则返回所有数据,不进行分页。 - -接口返回一个 Map 对象,包含了 'results' 中获取到的数据以及 'totalPages' 中的数据总页数。通过此接口,可以从数据库中以分页的方式获取表格或视图获取数据,便于处理大数据量的表格或视图。 - -### 13、执行数据库函数接口(executeFunction) - -该接口用于在给定数据库连接上执行指定的数据库函数,并传入指定的参数。它接收以下参数: - -- `connection`:用于执行函数的数据库连接(`java.sql.Connection`)。 -- `dbType`:表示数据库类型的字符串(例如,"Mysql"、"DM"、"Oracle"等)。 -- `schemaName`:表格所在的模式名。 -- `functionName`:要执行的函数的名称。 -- `params`:传递给函数的参数列表。 - -接口返回一个包含函数结果的 Map 列表,其中每个 Map 代表一行,列名作为键。通过此接口,可以方便地在数据库中执行复杂的计算和操作,并获取结果用于进一步分析和处理。 - - -## 敏感数据处理接口 - -接口总览与支持情况 - -| 接口 | Sqlite | 达梦(DM) | KingBase | GBase8a | GBase8s | GBase8t | Hive | Es (jdbc) | Hbase (phoenix) | Mysql | Mariodb | Mssql | Oracle | PostgreSQL | -|-----------------------------------------|----------|----------|----------|----------|----------|----------|-----------------|-----------|-----------------|----------|----------|----------|----------|------------| -| 数据遮掩接口(mask) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | -| 数据截取接口 (truncate) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | -| 正则替换接口 (replaceWithRegex) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | -| 数据泛化接口 (generalize) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | -| 数据加噪接口 (addNoise) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | -| 通用脱敏接口 (doObfuscation) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | -| 带脱敏的表或视图数据获取接口 (getDataWithMask) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | -| 带脱敏的数据分页获取接口 (getDataWithPageAndMask) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | 不支持 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | -| 带脱敏的 SQL 查询接口 (execQuerySQLWithMask) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | -| 带脱敏的 SQL 脚本执行接口 (execSQLScriptWithMask) | ✓ | ✓ | ✓ | 不支持事务 | 不支持事务 | 不支持事务 | 更新操作返回0, 且不支持事务 | 仅支持查询操作 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | -| 敏感数据扫描接口 (scanTableData) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | - - -### 1、数据遮掩接口(mask) - -该接口用于将输入字符串的一部分替换为指定的遮罩字符。它接收以下参数: - -- `input`:要进行遮罩处理的输入字符串。 -- `start`:遮罩部分的起始索引(包含)。 -- `end`:遮罩部分的结束索引(不包含)。 -- `maskChar`:用于遮罩输入字符串的字符。 - -接口返回一个经过遮罩处理的字符串,指定部分被遮罩字符替换。通过此接口,可以在处理敏感信息时保护用户隐私,例如对手机号、邮箱地址、身份证号等数据进行遮罩处理。 - - -### 2、数据截取接口 (truncate) - -该接口用于将输入字符串进行截取,返回一个原始字符串的子字符串。它接收以下参数: - -- `input`:要进行截取处理的输入字符串。 -- `start`:子字符串的起始索引(包含)。 -- `end`:子字符串的结束索引(不包含)。 - -接口返回一个从输入字符串中提取的子字符串,如果索引无效,则返回原始字符串。通过此接口,可以方便地从原始字符串中提取出指定部分的内容,例如从复杂文本中截取指定长度的摘要等。 - -### 3、正则替换接口 (replaceWithRegex) - -该接口用于使用给定的替换字符串替换输入字符串中匹配给定正则表达式模式的所有出现。它接收以下参数: - -- `input`:要进行处理的输入字符串。 -- `regex`:要匹配的正则表达式模式。 -- `replacement`:用于替换每个匹配项的替换字符串。 - -接口返回一个结果字符串,其中所有匹配的出现都被给定的替换字符串替换。通过此接口,可以方便地在字符串中查找和替换满足特定模式的内容,例如替换电话号码、邮箱地址等敏感信息。 - -### 4、数据泛化接口 (generalize) - -该接口用于将一个整数值泛化为一个范围。它接收以下参数: - -- `data`:要泛化的整数值。 -- `range`:泛化的范围大小。 - -接口返回一个表示泛化范围的字符串,格式为 "lowerBound-upperBound"。通过此接口,可以方便地对整数数据进行分组和泛化,例如将年龄数据分组到指定范围,以便在不暴露具体值的情况下进行分析。 - - -### 5、数据加噪接口 (addNoise) - -该接口用于在给定的噪声范围内为原始值添加随机噪声。它接收以下参数: - -- `originalValue`:要添加噪声的原始双精度浮点值。 -- `noiseRange`:要添加的随机噪声范围。实际添加的噪声将介于 -noiseRange/2 和 +noiseRange/2 之间。 - -接口返回一个双精度浮点值,该值在指定的噪声范围内添加了噪声。通过此接口,可以在数据处理过程中为数值添加一定程度的随机噪声,从而提高数据的隐私性。 - -### 6、通用脱敏接口 (doObfuscation) - -该接口根据提供的脱敏规则对数据进行脱敏处理。接收以下参数: - -- `data`:要脱敏处理的数据。 -- `obfuscationRule`:要应用的脱敏处理规则。 - -该接口返回经过脱敏处理的数据。根据 obfuscationRule 中指定的 ObfuscationMethod 类型,该接口将调用相应的方法进行数据脱敏处理。这可以确保根据特定的规则对敏感数据进行适当的处理,以保护数据隐私。 - -### 7、带脱敏的表或视图数据获取接口 (getDataWithMask) - -该接口从数据库获取表或视图数据,并对指定列应用脱敏规则。接收以下参数: - -- `connection`:数据库连接对象。 -- `dbType`:数据库类型(例如,"SQLite"、"Mysql"、"DM"、"Hive"等)。。 -- `schemaName`:表所在的schema名称。 -- `name`:表或视图的名称。 -- `obfuscationRules`:一个映射,其中键是列名,值是要应用于该列的 ObfuscationRule 对象。 - -该接口返回一个列表,列表中的每个映射表示表或视图的一行,其中指定的脱敏规则已被应用。 - -### 8、带脱敏的数据分页获取接口 (getDataWithPageAndMask) - -该接口从数据库中获取表或视图数据,支持分页与列选择,并对指定列应用脱敏规则。接收以下参数: - -- `connection`:数据库连接对象。 -- `dbType`:数据库类型(例如,"SQLite"、"Mysql"、"DM"、"Hive"等)。。 -- `schemaName`:表所在的schema名称。 -- `tableName`:表或视图的名称。 -- `columnList`:要选择列的列表。如果为空或者没有元素,则选择所有列。 -- `pageOffset`:分页的偏移量。如果小于或等于0,则返回所有数据,不进行分页。 -- `pageSize`:每页大小。如果小于或等于0,则返回所有数据,不进行分页。 -- `obfuscationRules`:一个映射,其中键是列名,值是要应用于该列的 ObfuscationRule 对象。 - -接口返回一个 Map 对象,包含了 'results' 中获取到的数据以及 'totalPages' 中的数据总页数。其中'results' 的数据,会依据指定脱敏规则进行脱敏。 -通过此接口,可以从数据库中以分页的方式获取脱敏后的表格或视图获取数据,便于处理大数据量的表格或视图。 - -### 9、带脱敏的 SQL 查询接口 (execQuerySQLWithMask) - -此接口用于执行SQL查询并将结果返回为列表,同时将指定列应用脱敏规则。接收以下参数: - -- `connection`:用于执行查询的数据库连接(java.sql.Connection)。 -- `dbType`:数据库类型(例如 "sqlite","mysql" 等)。 -- `sql`:要执行的SQL查询字符串(String)。 -- `obfuscationRules`:一个映射,其中键是列名,值是要应用于该列的 ObfuscationRule 对象。 - -该接口返回一个列表,其中每个映射表示查询结果中的一行,键是列名,值是相应的脱敏后数据。 - -### 10、带脱敏的 SQL 脚本执行接口 (execSQLScriptWithMask) - -此接口用于执行SQL脚本并将结果返回为列表,同时将指定列应用脱敏规则。接收以下参数: - -- `connection`:用于执行查询的数据库连接(java.sql.Connection)。 -- `dbType`:数据库类型(例如 "sqlite","mysql" 等)。 -- `sqlScript`:要执行的SQL脚本字符串(String),可包含多条 SQL 语句,以分号";"分隔。。 -- `obfuscationRules`:一个映射,其中键是列名,值是要应用于该列的 ObfuscationRule 对象。 - -该接口返回一个列表,其中每个映射表示查询结果中的一行,键是列名,值是相应的脱敏后数据。 - - -### 11、敏感数据扫描接口 (scanTableData) - -该接口基于一组正则表达式扫描数据库表或视图中的敏感数据。接收以下参数: - -- `connection`:数据库的 SQL 连接。 -- `dbType`:数据库类型(如:SQLite、MySQL、PostgreSQL)。 -- `schemaName`:表所在的 schema 名称。 -- `tableName`:要扫描的表或视图的名称。 -- `regexList`:用于匹配敏感数据的正则表达式列表。 - -该接口返回一个 `SensitiveColumn` 实例列表,其中包含匹配到的敏感数据。仅返回实际匹配到敏感数据的列。对于每个 `SensitiveColumn`,最多 5 个(可配置)匹配的数据将存储在 `matchData` 属性中。 - - -## SQL 生成接口 - -接口总览与支持情况 - -| 接口 | Sqlite | 达梦(DM) | KingBase | GBase8a | GBase8s | GBase8t | Hive | Es (jdbc) | Hbase (phoenix) | Mysql | Mariodb | Mssql | Oracle | PostgreSQL | -|-------------------------------|----------|----------|----------|----------|----------|----------|----------|-----------|-----------------|----------|----------|----------|----------|------------| -| 生成插入数据 SQL(generateInsertSql) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | 不涉及 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | - -### 1、生成插入数据 SQL (generateInsertSql) - -该接口基于给定的数据生成 SQL 插入语句。接收以下参数: - -- `connection`:数据库的 SQL 连接。 -- `dbType`:数据库类型(如:SQLite、MySQL、PostgreSQL)。 -- `schemaName`:表所在的 schema 名称。 -- `tableName`:要插入数据的表名称。 -- `data`:要插入的数据,以一个包含列名和对应值的映射形式呈现。 - -该接口返回一个代表 SQL 插入语句的字符串。每个插入的数据都对应于表中的一个列,并通过 Dialect 对象转换为适当的数据类型。如果提供的数据为空,或者表名、数据库连接或数据库类型为空,则会抛出 IllegalArgumentException 异常。 -通过该接口,开发者可以方便地为特定数据库生成 SQL 插入语句,无需关心不同数据库之间的 SQL 语法差异,从而大大提升代码的可复用性和维护性。 - +# [API 概览](API_OVERVIEW.md) # Getting Started diff --git a/src/main/java/com/dbmasker/api/DBDialectManager.java b/src/main/java/com/dbmasker/api/DBDialectManager.java index 6cc212b..10625f2 100644 --- a/src/main/java/com/dbmasker/api/DBDialectManager.java +++ b/src/main/java/com/dbmasker/api/DBDialectManager.java @@ -45,4 +45,58 @@ public static String generateInsertSql(Connection connection, String dbType, Str Dialect dialect = new DialectFactory().getDialect(dbType); return dialect.generateInsertSql(connection, schemaName, tableName, data, dbType); } + + /** + * Generates an SQL UPDATE statement for the specified table with the provided conditions. + * + * @param connection The active database connection. + * @param dbType The type of the database (e.g., "MySQL", "PostgreSQL"). + * @param schemaName The name of the schema. + * @param tableName The name of the table for which the SQL update statement is to be generated. + * @param setData The key-value pairs representing columns and their corresponding values to be updated. + * @param condition The conditions that determine which rows will be updated. + * @param filteredByUniqueKey Flag indicating whether to filter the conditions by unique keys. + * @return A string representing the SQL UPDATE statement. + * @throws SQLException If any SQL-related error occurs. + */ + public static String generateUpdateSql(Connection connection, String dbType, String schemaName, + String tableName, Map setData, Map condition, + boolean filteredByUniqueKey) throws SQLException { + if (connection == null || dbType == null) { + throw new IllegalArgumentException(ErrorMessages.NULL_CONNECTION_OR_DB_TYPE_ERROR); + } + + if (tableName == null) { + throw new IllegalArgumentException(ErrorMessages.NULL_TABLE_OR_VIEW_NAME_ERROR); + } + + Dialect dialect = new DialectFactory().getDialect(dbType); + return dialect.generateUpdateSql(connection, dbType, schemaName, tableName, setData, condition, filteredByUniqueKey); + } + + /** + * Generates a SQL DELETE statement for the given table and conditions. + * + * @param connection The database connection. + * @param dbType The type of the database. + * @param schemaName The name of the schema. + * @param tableName The name of the table. + * @param condition A map representing the conditions for the DELETE operation. + * @param filteredByUniqueKey If true, the conditions are filtered by the unique keys. + * @return The SQL DELETE statement as a string. + * @throws SQLException If any SQL related error occurs. + */ + public static String generateDeleteSql(Connection connection, String dbType, String schemaName, String tableName, + Map condition, boolean filteredByUniqueKey) throws SQLException { + if (connection == null || dbType == null) { + throw new IllegalArgumentException(ErrorMessages.NULL_CONNECTION_OR_DB_TYPE_ERROR); + } + + if (tableName == null) { + throw new IllegalArgumentException(ErrorMessages.NULL_TABLE_OR_VIEW_NAME_ERROR); + } + + Dialect dialect = new DialectFactory().getDialect(dbType); + return dialect.generateDeleteSql(connection, dbType, schemaName, tableName, condition, filteredByUniqueKey); + } } diff --git a/src/main/java/com/dbmasker/api/DBManager.java b/src/main/java/com/dbmasker/api/DBManager.java index c85786a..530d9e8 100644 --- a/src/main/java/com/dbmasker/api/DBManager.java +++ b/src/main/java/com/dbmasker/api/DBManager.java @@ -223,10 +223,10 @@ public static List getTableAttribute(Connection connection, Stri * @param dbType the type of the database, such as "sqlite", "mysql", etc. * @param schemaName The specified schema name. * @param table The specified table name. - * @return Returns a list of primary key column names for the specified table. + * @return Returns a Set of primary key column names for the specified table. * @throws SQLException if a database access error occurs */ - public static List getPrimaryKeys(Connection connection, String dbType, + public static Set getPrimaryKeys(Connection connection, String dbType, String schemaName, String table) throws SQLException { if (connection == null || dbType == null) { throw new IllegalArgumentException(ErrorMessages.NULL_CONNECTION_OR_DB_TYPE_ERROR); diff --git a/src/main/java/com/dbmasker/database/BaseDatabase.java b/src/main/java/com/dbmasker/database/BaseDatabase.java index e0d359b..b14fd20 100644 --- a/src/main/java/com/dbmasker/database/BaseDatabase.java +++ b/src/main/java/com/dbmasker/database/BaseDatabase.java @@ -213,11 +213,11 @@ public static List getTableAttribute(Connection connection, Stri * @param connection A valid database connection. * @param schemaName The specified schema name. * @param table The specified table name. - * @return Returns a list of primary key column names for the specified table. + * @return Returns a Set of primary key column names for the specified table. * @throws SQLException if a database access error occurs */ @Override - public List getPrimaryKeys(Connection connection, String schemaName, String table) throws SQLException { + public Set getPrimaryKeys(Connection connection, String schemaName, String table) throws SQLException { return getPrimaryKeys(connection, null, schemaName, table); } @@ -228,10 +228,10 @@ public List getPrimaryKeys(Connection connection, String schemaName, Str * @param catalog a catalog name, must match the catalog name as it is stored in the database; * @param schemaName The specified schema name. * @param table The specified table name. - * @return Returns a list of primary key column names for the specified table. + * @return Returns a Set of primary key column names for the specified table. * @throws SQLException if a database access error occurs */ - public List getPrimaryKeys(Connection connection, String catalog, String schemaName, String table) throws SQLException { + public Set getPrimaryKeys(Connection connection, String catalog, String schemaName, String table) throws SQLException { // Get metadata from the connection DatabaseMetaData metaData = connection.getMetaData(); @@ -240,7 +240,7 @@ public List getPrimaryKeys(Connection connection, String catalog, String ResultSet primaryKeyResultSet = metaData.getPrimaryKeys(catalog, schemaName, table); // Iterate through the ResultSet and add each primary key to the list - List primaryKeys = new ArrayList<>(); + Set primaryKeys = new HashSet<>(); while (primaryKeyResultSet.next()) { primaryKeys.add(primaryKeyResultSet.getString("COLUMN_NAME")); } @@ -475,7 +475,6 @@ public List> execQuerySQLWithMask(Connection connection, Str public List>> executeQuerySQLBatch(Connection connection, List sqlList) throws SQLException { List>> batchResult = new ArrayList<>(); - // Use try-with-resources to ensure proper resource management try { // Iterate through the SQL query list for (String sql : sqlList) { diff --git a/src/main/java/com/dbmasker/database/Database.java b/src/main/java/com/dbmasker/database/Database.java index 227af16..5743a30 100644 --- a/src/main/java/com/dbmasker/database/Database.java +++ b/src/main/java/com/dbmasker/database/Database.java @@ -92,10 +92,10 @@ public interface Database { * @param connection A valid database connection. * @param schemaName The specified schema name. * @param table The specified table name. - * @return Returns a list of primary key column names for the specified table. + * @return Returns a Set of primary key column names for the specified table. * @throws SQLException if a database access error occurs */ - List getPrimaryKeys(Connection connection, String schemaName, String table) throws SQLException; + Set getPrimaryKeys(Connection connection, String schemaName, String table) throws SQLException; /** * Retrieves the unique keys of a specified database table. diff --git a/src/main/java/com/dbmasker/database/Phoenix.java b/src/main/java/com/dbmasker/database/Phoenix.java index be33b79..9a94cfa 100644 --- a/src/main/java/com/dbmasker/database/Phoenix.java +++ b/src/main/java/com/dbmasker/database/Phoenix.java @@ -6,7 +6,9 @@ import java.sql.*; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; +import java.util.Set; /** * Phoenix Database class implements the Database interface for Phoenix databases. @@ -100,4 +102,44 @@ public List getFuncs(Connection connection, String schemaName) throw new SQLFeatureNotSupportedException("Phoenix does not support functions"); } + + /** + * Retrieves the primary keys of a specified table within the given schema. + * + * @param connection A valid database connection. + * @param schemaName The specified schema name. + * @param table The specified table name. + * @return Returns a Set of primary key column names for the specified table. + * @throws SQLException if a database access error occurs + */ + @Override + public Set getPrimaryKeys(Connection connection, String schemaName, String table) throws SQLException { + Set primaryKeys = new HashSet<>(); + + // Use a query to get the primary key column from the SYSTEM.CATALOG table for the given table and schema + String sql = "SELECT COLUMN_NAME " + + "FROM SYSTEM.CATALOG " + + "WHERE TABLE_SCHEM = ? " + + "AND TABLE_NAME = ? " + + "AND COLUMN_FAMILY IS NULL " + // Primary key columns have NULL COLUMN_FAMILY + "AND KEY_SEQ IS NOT NULL " + // Indicates the column is part of the primary key + "ORDER BY KEY_SEQ"; // Order by the key sequence to get the first part of compound primary key if any + + // try-with-resources block ensures that both the PreparedStatement and ResultSet are closed automatically + try (PreparedStatement preparedStatement = connection.prepareStatement(sql)) { + + // Set parameters for the PreparedStatement to prevent SQL injection + preparedStatement.setString(1, schemaName); + preparedStatement.setString(2, table); + + try (ResultSet resultSet = preparedStatement.executeQuery()) { + + // Loop over the resultSet to get all primary key columns + while (resultSet.next()) { + primaryKeys.add(resultSet.getString("COLUMN_NAME")); + } + } + } + return primaryKeys; + } } diff --git a/src/main/java/com/dbmasker/database/gbase/GBase8a.java b/src/main/java/com/dbmasker/database/gbase/GBase8a.java index 8fedad3..d8317a1 100644 --- a/src/main/java/com/dbmasker/database/gbase/GBase8a.java +++ b/src/main/java/com/dbmasker/database/gbase/GBase8a.java @@ -128,11 +128,11 @@ public List getTableAttribute(Connection connection, String sche * @param connection A valid database connection. * @param schemaName The specified schema name. * @param table The specified table name. - * @return Returns a list of primary key column names for the specified table. + * @return Returns a Set of primary key column names for the specified table. * @throws SQLException if a database access error occurs */ @Override - public List getPrimaryKeys(Connection connection, String schemaName, String table) throws SQLException { + public Set getPrimaryKeys(Connection connection, String schemaName, String table) throws SQLException { return getPrimaryKeys(connection, schemaName, "", table); } diff --git a/src/main/java/com/dbmasker/dialect/BaseDialect.java b/src/main/java/com/dbmasker/dialect/BaseDialect.java index 7205811..d18be36 100644 --- a/src/main/java/com/dbmasker/dialect/BaseDialect.java +++ b/src/main/java/com/dbmasker/dialect/BaseDialect.java @@ -6,7 +6,10 @@ import java.sql.Connection; import java.sql.SQLException; +import java.util.HashMap; +import java.util.HashSet; import java.util.Map; +import java.util.Set; /** * BaseDialect class implements the Dialect interface. @@ -101,4 +104,237 @@ protected StringBuilder sqlInit(String schemaName, Map data) { } return sql; } + + /** + * Generates an SQL UPDATE statement for the specified table with the provided conditions. + * + * @param connection The active database connection. + * @param dbType The type of the database (e.g., "MySQL", "PostgreSQL"). + * @param schemaName The name of the schema. + * @param tableName The name of the table for which the SQL update statement is to be generated. + * @param setData The key-value pairs representing columns and their corresponding values to be updated. + * @param condition The conditions that determine which rows will be updated. + * @param filteredByUniqueKey Flag indicating whether to filter the conditions by unique keys. + * @return A string representing the SQL UPDATE statement. + * @throws SQLException If any SQL-related error occurs. + */ + @Override + public String generateUpdateSql(Connection connection, String dbType, String schemaName, String tableName, + Map setData, + Map condition, + boolean filteredByUniqueKey) throws SQLException { + Database database = new DatabaseFactory().getDatabase(dbType); + Map columnTypes = database.getColumnTypes(connection, schemaName, tableName); + // Return null if either setData or condition is empty + if (setData == null || setData.isEmpty() || condition == null || condition.isEmpty()) { + return null; + } + + // If the filteredByUniqueKey flag is set to true, filter the conditions by unique keys. + if (filteredByUniqueKey) { + condition = getFilteredCondition(connection, database, schemaName, tableName, condition); + } + + // Generate and return the SQL UPDATE statement using the given parameters. + return generateUpdateSql(schemaName, tableName, setData, condition, columnTypes); + } + + /** + * Generates an SQL UPDATE statement based on provided schema, table, data sets, conditions, and column types. + * + * @param schemaName The name of the database schema. + * @param tableName The name of the table within the schema. + * @param setData A map containing the columns and values that need to be updated. + * @param condition A map containing the conditions for which rows should be updated. + * @param columnTypes A map specifying the data type of each column. + * @return An SQL UPDATE statement in string format. + */ + @Override + public String generateUpdateSql(String schemaName, String tableName, + Map setData, + Map condition, + Map columnTypes) { + StringBuilder sql = new StringBuilder("UPDATE "); + if (schemaName != null && !schemaName.trim().isEmpty()) { + sql.append(schemaName).append("."); + } + sql.append(tableName).append(" SET "); + + // Return null if either setData or condition is empty + if (setData.isEmpty() || condition.isEmpty()) { + return null; + } + + // Construct the SET part of the SQL query + for (Map.Entry entry : setData.entrySet()) { + String column = entry.getKey().toLowerCase(); + Object data = entry.getValue(); + String type = columnTypes.get(column); + String formattedData = formatData(data, type); + + sql.append(column).append(" = ").append(formattedData).append(", "); + } + + // Remove the trailing comma after the last SET column-value pair + sql.deleteCharAt(sql.length() - 2); + + sql.append(" WHERE "); + + // Construct the WHERE part of the SQL query + sql.append(constructWhereClause(condition, columnTypes)); + + sql.append(";"); + + return sql.toString(); + } + + /** + * Generates a SQL DELETE statement for the given table and conditions. + * + * @param connection The database connection. + * @param dbType The type of the database. + * @param schemaName The name of the schema. + * @param tableName The name of the table. + * @param condition A map representing the conditions for the DELETE operation. + * @param filteredByUniqueKey If true, the conditions are filtered by the unique keys. + * @return The SQL DELETE statement as a string. + * @throws SQLException If any SQL related error occurs. + */ + public String generateDeleteSql(Connection connection, String dbType, String schemaName, String tableName, + Map condition, boolean filteredByUniqueKey) throws SQLException { + Database database = new DatabaseFactory().getDatabase(dbType); + Map columnTypes = database.getColumnTypes(connection, schemaName, tableName); + // Return null if either setData or condition is empty + if (condition == null || condition.isEmpty()) { + return null; + } + + // If the filteredByUniqueKey flag is set to true, filter the conditions by unique keys. + if (filteredByUniqueKey) { + condition = getFilteredCondition(connection, database, schemaName, tableName, condition); + } + + StringBuilder sql = new StringBuilder("DELETE FROM "); + if (schemaName != null && !schemaName.trim().isEmpty()) { + sql.append(schemaName).append("."); + } + + sql.append(tableName) + .append(" WHERE ") + .append(constructWhereClause(condition, columnTypes)) + .append(";"); + + return sql.toString(); + } + + /** + * Constructs the WHERE clause of an SQL query based on the given condition and column types. + * + * @param condition A map representing the condition columns and their respective values. + * @param columnTypes A map representing the column types for the columns in the condition. + * @return A string representing the WHERE clause of an SQL query. + */ + protected String constructWhereClause(Map condition, Map columnTypes) { + StringBuilder whereClause = new StringBuilder(); + + // Iterate through each entry in the condition map + for (Map.Entry entry : condition.entrySet()) { + String column = entry.getKey().toLowerCase(); + Object data = entry.getValue(); + String type = columnTypes.get(column); + String formattedData = formatData(data, type); + + // Check if the value is NULL and handle accordingly + if (data == null || "NULL".equalsIgnoreCase(formattedData)) { + whereClause.append(column).append(" IS NULL AND "); + } else { + whereClause.append(column).append(" = ").append(formattedData).append(" AND "); + } + } + + // Remove the trailing "AND" and return the constructed where clause + return whereClause.substring(0, whereClause.length() - 5); + } + + /** + * Filters the given condition map based on unique keys, primarily using primary keys. + * If the condition remains unchanged after filtering with primary keys, other unique keys are used. + * + * @param connection The database connection. + * @param database The database abstraction object. + * @param schemaName The name of the schema. + * @param tableName The name of the table. + * @param originalCondition The original condition map. + * @return A filtered condition map based on unique keys. + * @throws SQLException If any SQL-related error occurs. + */ + protected Map getFilteredCondition(Connection connection, Database database, String schemaName, + String tableName, Map originalCondition) throws SQLException { + Set> uniqueKeys = new HashSet<>(); + + // Add primary keys to uniqueKeys set + Set primaryKeys = database.getPrimaryKeys(connection, schemaName, tableName); + if (primaryKeys != null && !primaryKeys.isEmpty()) { + uniqueKeys.add(primaryKeys); + } + + Map newCondition = conditionFilter(originalCondition, uniqueKeys); + + // If condition size remains unchanged after filtering with primary keys, then filter with other unique keys. + if (newCondition.size() == originalCondition.size()) { + Map> uniqueKeyMap = database.getUniqueKeys(connection, schemaName, tableName); + uniqueKeys.addAll(uniqueKeyMap.values()); + newCondition = conditionFilter(originalCondition, uniqueKeys); + } + + return newCondition; + } + + /** + * Filters the given condition map to retain only the key-value pairs that form a complete unique key + * from the provided set of unique keys. + * + * @param condition The original conditions as a map of column names to values. + * @param uniqueKeys A set containing sets of column names that form unique keys. + * @return A filtered map containing only the key-value pairs that form a complete unique key, or the original condition + * map if no complete unique key is present. + */ + protected Map conditionFilter(Map condition, Set> uniqueKeys) { + // Map to store the key-value pairs from the condition that match a unique key + Map result = new HashMap<>(); + + // Convert the keys in the condition map to lowercase + Map conditionLower = new HashMap<>(); + for (Map.Entry entry : condition.entrySet()) { + conditionLower.put(entry.getKey().toLowerCase(), entry.getValue()); + } + + // Iterate over each unique key + for (Set uniqueKey : uniqueKeys) { + if (uniqueKey == null || uniqueKey.isEmpty()) { + continue; + } + boolean match = true; + + // Check if all columns in the current unique key are present in the condition + for (String key : uniqueKey) { + if (!conditionLower.containsKey(key.toLowerCase())) { + match = false; + break; + } + } + + // If a complete unique key is found in the condition, add its key-value pairs to the result map + if (match) { + for (String key : uniqueKey) { + result.put(key, conditionLower.get(key.toLowerCase())); + } + return result; + } + } + + // If no complete unique key is found, return the original condition map + return condition; + } + } diff --git a/src/main/java/com/dbmasker/dialect/Dialect.java b/src/main/java/com/dbmasker/dialect/Dialect.java index deded6d..6423ebe 100644 --- a/src/main/java/com/dbmasker/dialect/Dialect.java +++ b/src/main/java/com/dbmasker/dialect/Dialect.java @@ -46,4 +46,50 @@ public interface Dialect { * @throws IllegalArgumentException If the provided data is empty. */ String generateInsertSql(String schemaName, String tableName, Map data, Map columnTypes); + + + /** + * Generates an SQL UPDATE statement for the specified table with the provided conditions. + * + * @param connection The active database connection. + * @param dbType The type of the database (e.g., "MySQL", "PostgreSQL"). + * @param schemaName The name of the schema. + * @param tableName The name of the table for which the SQL update statement is to be generated. + * @param setData The key-value pairs representing columns and their corresponding values to be updated. + * @param condition The conditions that determine which rows will be updated. + * @param filteredByUniqueKey Flag indicating whether to filter the conditions by unique keys. + * @return A string representing the SQL UPDATE statement. + * @throws SQLException If any SQL-related error occurs. + */ + String generateUpdateSql(Connection connection, String dbType, String schemaName, String tableName, + Map setData, + Map condition, + boolean filteredByUniqueKey) throws SQLException; + + /** + * Generates an SQL UPDATE statement based on provided schema, table, data sets, conditions, and column types. + * + * @param schemaName The name of the database schema. + * @param tableName The name of the table within the schema. + * @param setData A map containing the columns and values that need to be updated. + * @param condition A map containing the conditions for which rows should be updated. + * @param columnTypes A map specifying the data type of each column. + * @return An SQL UPDATE statement in string format. + */ + String generateUpdateSql(String schemaName, String tableName, Map setData, Map condition, Map columnTypes); + + /** + * Generates a SQL DELETE statement for the given table and conditions. + * + * @param connection The database connection. + * @param dbType The type of the database. + * @param schemaName The name of the schema. + * @param tableName The name of the table. + * @param condition A map representing the conditions for the DELETE operation. + * @param filteredByUniqueKey If true, the conditions are filtered by the unique keys. + * @return The SQL DELETE statement as a string. + * @throws SQLException If any SQL related error occurs. + */ + String generateDeleteSql(Connection connection, String dbType, String schemaName, String tableName, + Map condition, boolean filteredByUniqueKey) throws SQLException; } \ No newline at end of file diff --git a/src/main/java/com/dbmasker/dialect/PhoenixDialect.java b/src/main/java/com/dbmasker/dialect/PhoenixDialect.java index 0cc8c6e..0944b19 100644 --- a/src/main/java/com/dbmasker/dialect/PhoenixDialect.java +++ b/src/main/java/com/dbmasker/dialect/PhoenixDialect.java @@ -1,5 +1,10 @@ package com.dbmasker.dialect; +import com.dbmasker.database.Database; +import com.dbmasker.database.DatabaseFactory; + +import java.sql.Connection; +import java.sql.SQLException; import java.util.Map; /** @@ -85,4 +90,54 @@ protected StringBuilder sqlInit(String schemaName, Map data) { } return sql; } + + /** + * Generates an SQL UPDATE statement for the specified table with the provided conditions. + * + * @param connection The active database connection. + * @param dbType The type of the database (e.g., "MySQL", "PostgreSQL"). + * @param schemaName The name of the schema. + * @param tableName The name of the table for which the SQL update statement is to be generated. + * @param setData The key-value pairs representing columns and their corresponding values to be updated. + * @param condition The conditions that determine which rows will be updated. + * @param filteredByUniqueKey Flag indicating whether to filter the conditions by unique keys. + * @return A string representing the SQL UPDATE statement. + * @throws SQLException If any SQL-related error occurs. + */ + @Override + public String generateUpdateSql(Connection connection, String dbType, String schemaName, String tableName, + Map setData, + Map condition, + boolean filteredByUniqueKey) throws SQLException { + // Return null if either setData or condition is empty + if (setData == null || setData.isEmpty() || condition == null || condition.isEmpty()) { + return null; + } + Database database = new DatabaseFactory().getDatabase(dbType); + Map columnTypes = database.getColumnTypes(connection, schemaName, tableName); + + condition = getFilteredCondition(connection, database, schemaName, tableName, condition); + + // Generate and return the SQL UPDATE statement using the given parameters. + return generateUpdateSql(schemaName, tableName, setData, condition, columnTypes); + } + + /** + * Generates an SQL UPDATE statement based on provided schema, table, data sets, conditions, and column types. + * + * @param schemaName The name of the database schema. + * @param tableName The name of the table within the schema. + * @param setData A map containing the columns and values that need to be updated. + * @param condition A map containing the conditions for which rows should be updated. + * @param columnTypes A map specifying the data type of each column. + * @return An SQL UPDATE statement in string format. + */ + @Override + public String generateUpdateSql(String schemaName, String tableName, + Map setData, + Map condition, + Map columnTypes) { + setData.putAll(condition); + return generateInsertSql(schemaName, tableName, setData, columnTypes); + } } diff --git a/src/test/java/com/dbmasker/database/dameng/DMAPITests.java b/src/test/java/com/dbmasker/database/dameng/DMAPITests.java index e776a03..0065888 100644 --- a/src/test/java/com/dbmasker/database/dameng/DMAPITests.java +++ b/src/test/java/com/dbmasker/database/dameng/DMAPITests.java @@ -301,10 +301,10 @@ void testGetTableAttribute() throws SQLException { @Test void testGetPrimaryKeys() throws SQLException, ClassNotFoundException { - List tablePrimaryKeys = DBManager.getPrimaryKeys(connection, dbType, "MY_SCHEMA", "EMPLOYEES"); + Set tablePrimaryKeys = DBManager.getPrimaryKeys(connection, dbType, "MY_SCHEMA", "EMPLOYEES"); Assertions.assertEquals(1, tablePrimaryKeys.size()); - List expectPrimaryKeys = new ArrayList<>(); + Set expectPrimaryKeys = new HashSet<>(); expectPrimaryKeys.add("ID"); Assertions.assertEquals(expectPrimaryKeys, tablePrimaryKeys); diff --git a/src/test/java/com/dbmasker/database/dameng/DMDialectAPITests.java b/src/test/java/com/dbmasker/database/dameng/DMDialectAPITests.java index aaaed1d..0df3c2a 100644 --- a/src/test/java/com/dbmasker/database/dameng/DMDialectAPITests.java +++ b/src/test/java/com/dbmasker/database/dameng/DMDialectAPITests.java @@ -48,8 +48,8 @@ class DMDialectAPITests { public void createSchema(Connection connection, String dbType) throws SQLException { String sql = """ - CREATE SCHEMA my_schema; - CREATE TABLE my_schema.mytable ( + CREATE SCHEMA MY_SCHEMA; + CREATE TABLE MY_SCHEMA.mytable ( myint INT, myinteger INTEGER, mysmallint SMALLINT, @@ -77,9 +77,32 @@ myvarbinary VARBINARY(100), DBManager.executeUpdateSQL(connection, dbType, sql); } + public void createSchema1(Connection connection, String dbType) throws SQLException { + String sql = """ + CREATE SCHEMA MY_SCHEMA; + CREATE TABLE MY_SCHEMA.EMPLOYEES ( + id INTEGER PRIMARY KEY, + first_name VARCHAR(255) NOT NULL, + last_name VARCHAR(255) NOT NULL, + email VARCHAR(255) NOT NULL, + age INTEGER, + UNIQUE (first_name, last_name) + ); + """; + DBManager.executeUpdateSQL(connection, dbType, sql); + } + + public void insertData1(Connection connection, String dbType) throws SQLException { + String sql = """ + INSERT INTO MY_SCHEMA.EMPLOYEES (id, first_name, last_name, email, age) + VALUES (1, 'John', 'Doe', 'john.doe@example.com', 30); + """; + DBManager.executeUpdateSQL(connection, dbType, sql); + } + public void insertData(Connection connection, String dbType) throws SQLException { String sql = """ - INSERT INTO my_schema.mytable ( + INSERT INTO MY_SCHEMA.mytable ( myint, -- myint myinteger, -- myinteger mysmallint, -- mysmallint @@ -277,4 +300,204 @@ void testGenerateInsertSql() throws SQLException { Assertions.assertNull(result.get(3).get("MYTIMESTAMP")); } + @Test + void testGenerateUpdateSql() throws SQLException { + createSchema1(connection, dbType); + insertData1(connection, dbType); + + Map setData = new HashMap<>(); + setData.put("age", 100); + Map whereData = new HashMap<>(); + whereData.put("id", 1); + whereData.put("first_name", "John"); + whereData.put("last_name", "Doe"); + String sql = DBDialectManager.generateUpdateSql(connection, dbType, "MY_SCHEMA", "EMPLOYEES", setData, whereData, true); + String expectSQL = "UPDATE MY_SCHEMA.EMPLOYEES SET age = 100 WHERE id = 1;"; + Assertions.assertEquals(expectSQL, sql); + DBManager.executeSQLScript(connection, dbType, sql); + + List> result = DBManager.getTableOrViewData(connection, dbType, "MY_SCHEMA", "EMPLOYEES"); + Assertions.assertEquals(1, result.size()); + Assertions.assertEquals(100, result.get(0).get("AGE")); + Assertions.assertEquals(1, result.get(0).get("ID")); + + setData.put("age", 10); + whereData = new HashMap<>(); + whereData.put("first_name", "John"); + whereData.put("last_name", "Doe"); + whereData.put("email", "john.doe@example.com"); + sql = DBDialectManager.generateUpdateSql(connection, dbType, "MY_SCHEMA", "EMPLOYEES", setData, whereData, true); + expectSQL = "UPDATE MY_SCHEMA.EMPLOYEES SET age = 10 WHERE last_name = 'Doe' AND first_name = 'John';"; + Assertions.assertEquals(expectSQL, sql); + DBManager.executeSQLScript(connection, dbType, sql); + + result = DBManager.getTableOrViewData(connection, dbType, "MY_SCHEMA", "EMPLOYEES"); + Assertions.assertEquals(1, result.size()); + Assertions.assertEquals(10, result.get(0).get("AGE")); + Assertions.assertEquals(1, result.get(0).get("ID")); + + setData.put("age", 99); + whereData = new HashMap<>(); + whereData.put("first_name", "John"); + whereData.put("email", "john.doe@example.com"); + whereData.put("age", 10); + sql = DBDialectManager.generateUpdateSql(connection, dbType, "MY_SCHEMA", "EMPLOYEES", setData, whereData, true); + expectSQL = "UPDATE MY_SCHEMA.EMPLOYEES SET age = 99 WHERE first_name = 'John' AND email = 'john.doe@example.com' AND age = 10;"; + Assertions.assertEquals(expectSQL, sql); + DBManager.executeSQLScript(connection, dbType, sql); + + result = DBManager.getTableOrViewData(connection, dbType, "MY_SCHEMA", "EMPLOYEES"); + Assertions.assertEquals(1, result.size()); + Assertions.assertEquals(99, result.get(0).get("AGE")); + Assertions.assertEquals(1, result.get(0).get("ID")); + + setData.put("age", 98); + sql = DBDialectManager.generateUpdateSql(connection, dbType, "MY_SCHEMA", "EMPLOYEES", setData, whereData, true); + DBManager.executeSQLScript(connection, dbType, sql); + result = DBManager.getTableOrViewData(connection, dbType, "MY_SCHEMA", "EMPLOYEES"); + Assertions.assertEquals(1, result.size()); + Assertions.assertEquals(99, result.get(0).get("AGE")); + + whereData = null; + sql = DBDialectManager.generateUpdateSql(connection, dbType, "MY_SCHEMA", "EMPLOYEES", setData, whereData, true); + Assertions.assertNull(sql); + } + + @Test + void testGenerateUpdateSql1() throws SQLException { + insertData(connection, dbType); + + Map setData = new HashMap<>(); + setData.put("MyInt", 100); + setData.put("MyChar", "char'50'"); + setData.put("MyBlob", "Masker"); + setData.put("MyTimestamp", "2024-01-01 00:00:00"); + setData.put("MyTime", "00:00:00"); + setData.put("MyDate", "2024-01-01"); + setData.put("MyClob", "Masker"); + setData.put("MySmallInt", null); + + Map whereData = new HashMap<>(); + whereData.put("MyInteger", 2); + + String sql = DBDialectManager.generateUpdateSql(connection, dbType, "MY_SCHEMA", "MYTABLE", setData, whereData, true); + DBManager.executeSQLScript(connection, dbType, sql); + List> result = DBManager.getTableOrViewData(connection, dbType, "MY_SCHEMA", "MYTABLE"); + Assertions.assertEquals(1, result.size()); + Assertions.assertEquals(100, result.get(0).get("MYINT")); + Assertions.assertEquals(String.format("%-10s", "char'50'"), result.get(0).get("MYCHAR")); + DmdbBlob blob = (DmdbBlob)result.get(0).get("MYBLOB"); + Assertions.assertEquals("Masker", new String(blob.getBytes(1, (int)blob.length()))); + + Assertions.assertEquals("2024-01-01 00:00:00.0", result.get(0).get("MYTIMESTAMP").toString()); + Assertions.assertEquals("00:00:00", result.get(0).get("MYTIME").toString()); + Assertions.assertEquals("2024-01-01", result.get(0).get("MYDATE").toString()); + DmdbNClob clob = (DmdbNClob)result.get(0).get("MYCLOB"); + Assertions.assertEquals("Masker", clob.getSubString(1, (int)clob.length())); + Assertions.assertNull(result.get(0).get("MYSMALLINT")); + + setData = new HashMap<>(); + setData.put("MyInt", 999); + + whereData = new HashMap<>(); + whereData.put("MyInteger", 2); + whereData.put("MyChar", "char'50'"); + whereData.put("MyTimestamp", "2024-01-01 00:00:00"); + whereData.put("MyTime", "00:00:00"); + whereData.put("MyDate", "2024-01-01"); + whereData.put("MyClob", "Masker"); + whereData.put("MySmallInt", null); + + sql = DBDialectManager.generateUpdateSql(connection, dbType, "MY_SCHEMA", "MYTABLE", setData, whereData, false); + DBManager.executeSQLScript(connection, dbType, sql); + + result = DBManager.getTableOrViewData(connection, dbType, "MY_SCHEMA", "MYTABLE"); + Assertions.assertEquals(1, result.size()); + Assertions.assertEquals(999, result.get(0).get("MYINT")); + } + + @Test + void testGenerateDeleteSql() throws SQLException, ClassNotFoundException { + createSchema1(connection, dbType); + insertData1(connection, dbType); + + Map whereData = new HashMap<>(); + whereData.put("id", 1); + whereData.put("first_name", "John"); + whereData.put("last_name", "Doe"); + String sql = DBDialectManager.generateDeleteSql(connection, dbType, "MY_SCHEMA", "EMPLOYEES", whereData, true); + String expectSQL = "DELETE FROM MY_SCHEMA.EMPLOYEES WHERE id = 1;"; + Assertions.assertEquals(expectSQL, sql); + DBManager.executeSQLScript(connection, dbType, sql); + + List> result = DBManager.getTableOrViewData(connection, dbType, "MY_SCHEMA", "EMPLOYEES"); + Assertions.assertEquals(0, result.size()); + + insertData1(connection, dbType); + result = DBManager.getTableOrViewData(connection, dbType, "MY_SCHEMA", "EMPLOYEES"); + Assertions.assertEquals(1, result.size()); + + whereData = new HashMap<>(); + whereData.put("first_name", "John"); + whereData.put("last_name", "Doe"); + whereData.put("email", "john.doe@example.com"); + + sql = DBDialectManager.generateDeleteSql(connection, dbType, "MY_SCHEMA", "EMPLOYEES", whereData, true); + expectSQL = "DELETE FROM MY_SCHEMA.EMPLOYEES WHERE last_name = 'Doe' AND first_name = 'John';"; + Assertions.assertEquals(expectSQL, sql); + DBManager.executeSQLScript(connection, dbType, sql); + + result = DBManager.getTableOrViewData(connection, dbType, "MY_SCHEMA", "EMPLOYEES"); + Assertions.assertEquals(0, result.size()); + + insertData1(connection, dbType); + result = DBManager.getTableOrViewData(connection, dbType, "MY_SCHEMA", "EMPLOYEES"); + Assertions.assertEquals(1, result.size()); + + whereData = new HashMap<>(); + whereData.put("first_name", "John"); + whereData.put("email", "john.doe@example.com"); + whereData.put("age", 30); + + sql = DBDialectManager.generateDeleteSql(connection, dbType, "MY_SCHEMA", "EMPLOYEES", whereData, true); + expectSQL = "DELETE FROM MY_SCHEMA.EMPLOYEES WHERE first_name = 'John' AND email = 'john.doe@example.com' AND age = 30;"; + Assertions.assertEquals(expectSQL, sql); + DBManager.executeSQLScript(connection, dbType, sql); + + result = DBManager.getTableOrViewData(connection, dbType, "MY_SCHEMA", "EMPLOYEES"); + Assertions.assertEquals(0, result.size()); + + insertData1(connection, dbType); + result = DBManager.getTableOrViewData(connection, dbType, "MY_SCHEMA", "EMPLOYEES"); + Assertions.assertEquals(1, result.size()); + + whereData.put("age", 31); + sql = DBDialectManager.generateDeleteSql(connection, dbType, "MY_SCHEMA", "EMPLOYEES", whereData, true); + DBManager.executeSQLScript(connection, dbType, sql); + result = DBManager.getTableOrViewData(connection, dbType, "MY_SCHEMA", "EMPLOYEES"); + Assertions.assertEquals(1, result.size()); + + whereData = null; + sql = DBDialectManager.generateDeleteSql(connection, dbType, "MY_SCHEMA", "EMPLOYEES", whereData, true); + Assertions.assertNull(sql); + + tearDown(); + setUp(); + insertData(connection, dbType); + + whereData = new HashMap<>(); + whereData.put("MyInteger", 2); + whereData.put("MyChar", "char"); + whereData.put("MyTimestamp", "2023-01-01 13:14:15"); + whereData.put("MyTime", "13:14:15"); + whereData.put("MyDate", "2023-01-01"); + whereData.put("MyClob", "This is CLOB data"); + whereData.put("MySmallInt", 3); + + sql = DBDialectManager.generateDeleteSql(connection, dbType, "MY_SCHEMA", "MYTABLE", whereData, false); + DBManager.executeSQLScript(connection, dbType, sql); + + result = DBManager.getTableOrViewData(connection, dbType, "MY_SCHEMA", "MYTABLE"); + Assertions.assertEquals(0, result.size()); + } } diff --git a/src/test/java/com/dbmasker/database/gbase/Gbase8aAPITests.java b/src/test/java/com/dbmasker/database/gbase/Gbase8aAPITests.java index 3a6cda9..46424e7 100644 --- a/src/test/java/com/dbmasker/database/gbase/Gbase8aAPITests.java +++ b/src/test/java/com/dbmasker/database/gbase/Gbase8aAPITests.java @@ -351,10 +351,10 @@ void testGetTableAttribute() throws SQLException { void testGetPrimaryKeys() throws SQLException, ClassNotFoundException { createSchema(connection, dbType); - List tablePrimaryKeys = DBManager.getPrimaryKeys(connection, dbType, "my_schema", "employees"); + Set tablePrimaryKeys = DBManager.getPrimaryKeys(connection, dbType, "my_schema", "employees"); Assertions.assertEquals(1, tablePrimaryKeys.size()); - List expectPrimaryKeys = new ArrayList<>(); + Set expectPrimaryKeys = new HashSet<>(); expectPrimaryKeys.add("id"); Assertions.assertEquals(expectPrimaryKeys, tablePrimaryKeys); diff --git a/src/test/java/com/dbmasker/database/gbase/Gbase8aDialectAPITests.java b/src/test/java/com/dbmasker/database/gbase/Gbase8aDialectAPITests.java index df2df1b..283f4d4 100644 --- a/src/test/java/com/dbmasker/database/gbase/Gbase8aDialectAPITests.java +++ b/src/test/java/com/dbmasker/database/gbase/Gbase8aDialectAPITests.java @@ -12,6 +12,7 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.sqlite.core.DB; import java.io.InputStream; import java.math.BigDecimal; @@ -68,6 +69,37 @@ mybinary BINARY(50), DBManager.executeUpdateSQLBatch(connection, dbType, sqlList); } + public void createSchema1(Connection connection, String dbType) throws SQLException { + String sql = """ + CREATE SCHEMA IF NOT EXISTS my_schema; + """; + String sql1 = """ + USE my_schema; + """; + String sql2 = """ + CREATE TABLE IF NOT EXISTS my_schema.employees ( + id int PRIMARY KEY, + first_name VARCHAR(255) NOT NULL, + last_name varchar(255) NOT NULL, + email varchar(255) NOT NULL, + age int + ); + """; + List sqlList = new ArrayList<>(); + sqlList.add(sql); + sqlList.add(sql1); + sqlList.add(sql2); + DBManager.executeUpdateSQLBatch(connection, dbType, sqlList); + } + + public void insertData1(Connection connection, String dbType) throws SQLException { + String sql = """ + INSERT INTO my_schema.employees (id, first_name, last_name, email, age) + VALUES (1, 'John', 'Doe', 'john.doe@example.com', 30); + """; + DBManager.executeUpdateSQL(connection, dbType, sql); + } + public void insertData(Connection connection, String dbType) throws SQLException { String sql = """ INSERT INTO my_schema.mytable ( @@ -132,11 +164,15 @@ public void tearDown() throws SQLException { String sql1 = """ DROP TABLE IF EXISTS mytable; """; + String sql2 = """ + DROP TABLE IF EXISTS employees; + """; String sql = """ DROP SCHEMA IF EXISTS my_schema; """; List sqlList = new ArrayList<>(); sqlList.add(sql1); + sqlList.add(sql2); sqlList.add(sql); DBManager.executeUpdateSQLBatch(connection, dbType, sqlList); @@ -250,4 +286,198 @@ void testGenerateInsertSql() throws SQLException { Assertions.assertNull(result.get(3).get("myblob")); } + @Test + void testGenerateUpdateSql() throws SQLException { + createSchema1(connection, dbType); + insertData1(connection, dbType); + + Map setData = new HashMap<>(); + setData.put("age", 100); + Map whereData = new HashMap<>(); + whereData.put("id", 1); + whereData.put("first_name", "John"); + whereData.put("last_name", "Doe"); + String sql = DBDialectManager.generateUpdateSql(connection, dbType, "my_schema", "employees", setData, whereData, true); + String expectSQL = "UPDATE my_schema.employees SET age = 100 WHERE id = 1;"; + Assertions.assertEquals(expectSQL, sql); + DBManager.executeSQLScript(connection, dbType, sql); + + List> result = DBManager.getTableOrViewData(connection, dbType, "my_schema", "employees"); + Assertions.assertEquals(1, result.size()); + Assertions.assertEquals(100, result.get(0).get("age")); + Assertions.assertEquals(1, result.get(0).get("id")); + + setData.put("age", 10); + whereData = new HashMap<>(); + whereData.put("first_name", "John"); + whereData.put("last_name", "Doe"); + sql = DBDialectManager.generateUpdateSql(connection, dbType, "my_schema", "employees", setData, whereData, true); + expectSQL = "UPDATE my_schema.employees SET age = 10 WHERE last_name = 'Doe' AND first_name = 'John';"; + Assertions.assertEquals(expectSQL, sql); + DBManager.executeSQLScript(connection, dbType, sql); + + result = DBManager.getTableOrViewData(connection, dbType, "my_schema", "employees"); + Assertions.assertEquals(1, result.size()); + Assertions.assertEquals(10, result.get(0).get("age")); + Assertions.assertEquals(1, result.get(0).get("id")); + + setData.put("age", 99); + whereData = new HashMap<>(); + whereData.put("first_name", "John"); + whereData.put("email", "john.doe@example.com"); + whereData.put("age", 10); + sql = DBDialectManager.generateUpdateSql(connection, dbType, "my_schema", "employees", setData, whereData, true); + expectSQL = "UPDATE my_schema.employees SET age = 99 WHERE first_name = 'John' AND email = 'john.doe@example.com' AND age = 10;"; + Assertions.assertEquals(expectSQL, sql); + DBManager.executeSQLScript(connection, dbType, sql); + + result = DBManager.getTableOrViewData(connection, dbType, "my_schema", "employees"); + Assertions.assertEquals(1, result.size()); + Assertions.assertEquals(99, result.get(0).get("age")); + Assertions.assertEquals(1, result.get(0).get("id")); + + setData.put("age", 98); + sql = DBDialectManager.generateUpdateSql(connection, dbType, "my_schema", "employees", setData, whereData, true); + DBManager.executeSQLScript(connection, dbType, sql); + result = DBManager.getTableOrViewData(connection, dbType, "my_schema", "employees"); + Assertions.assertEquals(1, result.size()); + Assertions.assertEquals(99, result.get(0).get("age")); + + whereData = null; + sql = DBDialectManager.generateUpdateSql(connection, dbType, "my_schema", "employees", setData, whereData, true); + Assertions.assertNull(sql); + } + + @Test + void testGenerateUpdateSql1() throws SQLException { + createSchema(connection, dbType); + insertData(connection, dbType); + + Map setData = new HashMap<>(); + setData.put("myinteger", 100); + setData.put("myvarchar", "varchar'50'"); + setData.put("mytext", "this is an other text"); + setData.put("mydate", "2024-07-24"); + setData.put("mytimestamp", "2024-07-24 11:12:13"); + setData.put("myboolean", "false"); + setData.put("myblob", "Masker"); + setData.put("mychar", null); + Map whereData = new HashMap<>(); + whereData.put("mysmallint", 10); + + String sql = DBDialectManager.generateUpdateSql(connection, dbType, "my_schema", "mytable", setData, whereData, true); + DBManager.executeSQLScript(connection, dbType, sql); + + List> result = DBManager.getTableOrViewData(connection, dbType, "my_schema", "mytable"); + Assertions.assertEquals(1, result.size()); + Assertions.assertEquals(100, result.get(0).get("myinteger")); + Assertions.assertEquals("varchar'50'", result.get(0).get("myvarchar")); + Assertions.assertEquals("this is an other text", result.get(0).get("mytext")); + Assertions.assertEquals("2024-07-24", result.get(0).get("mydate").toString()); + Assertions.assertEquals("2024-07-24 11:12:13.0", result.get(0).get("mytimestamp").toString()); + Assertions.assertEquals(false, result.get(0).get("myboolean")); + Assertions.assertEquals("Masker", new String((byte[])result.get(0).get("myblob"))); + Assertions.assertNull(result.get(0).get("mychar")); + + setData = new HashMap<>(); + setData.put("myinteger", 999); + whereData = new HashMap<>(); + whereData.put("myinteger", 100); + whereData.put("myvarchar", "varchar'50'"); + whereData.put("mytext", "this is an other text"); + whereData.put("mydate", "2024-07-24"); + whereData.put("mytimestamp", "2024-07-24 11:12:13"); + whereData.put("myboolean", "false"); + whereData.put("mychar", null); + sql = DBDialectManager.generateUpdateSql(connection, dbType, "my_schema", "mytable", setData, whereData, false); + DBManager.executeSQLScript(connection, dbType, sql); + + result = DBManager.getTableOrViewData(connection, dbType, "my_schema", "mytable"); + Assertions.assertEquals(1, result.size()); + Assertions.assertEquals(999, result.get(0).get("myinteger")); + } + + + @Test + void testGenerateDeleteSql() throws SQLException, ClassNotFoundException { + createSchema1(connection, dbType); + insertData1(connection, dbType); + + Map whereData = new HashMap<>(); + whereData.put("id", 1); + whereData.put("first_name", "John"); + whereData.put("last_name", "Doe"); + String sql = DBDialectManager.generateDeleteSql(connection, dbType, "my_schema", "employees", whereData, true); + String expectSQL = "DELETE FROM my_schema.employees WHERE id = 1;"; + Assertions.assertEquals(expectSQL, sql); + DBManager.executeSQLScript(connection, dbType, sql); + + List> result = DBManager.getTableOrViewData(connection, dbType, "my_schema", "employees"); + Assertions.assertEquals(0, result.size()); + + insertData1(connection, dbType); + result = DBManager.getTableOrViewData(connection, dbType, "my_schema", "employees"); + Assertions.assertEquals(1, result.size()); + + whereData = new HashMap<>(); + whereData.put("first_name", "John"); + whereData.put("last_name", "Doe"); + sql = DBDialectManager.generateDeleteSql(connection, dbType, "my_schema", "employees", whereData, true); + expectSQL = "DELETE FROM my_schema.employees WHERE last_name = 'Doe' AND first_name = 'John';"; + Assertions.assertEquals(expectSQL, sql); + DBManager.executeSQLScript(connection, dbType, sql); + + result = DBManager.getTableOrViewData(connection, dbType, "my_schema", "employees"); + Assertions.assertEquals(0, result.size()); + + insertData1(connection, dbType); + result = DBManager.getTableOrViewData(connection, dbType, "my_schema", "employees"); + Assertions.assertEquals(1, result.size()); + + whereData = new HashMap<>(); + whereData.put("first_name", "John"); + whereData.put("email", "john.doe@example.com"); + whereData.put("age", 30); + + sql = DBDialectManager.generateDeleteSql(connection, dbType, "my_schema", "employees", whereData, true); + expectSQL = "DELETE FROM my_schema.employees WHERE first_name = 'John' AND email = 'john.doe@example.com' AND age = 30;"; + Assertions.assertEquals(expectSQL, sql); + DBManager.executeSQLScript(connection, dbType, sql); + + result = DBManager.getTableOrViewData(connection, dbType, "my_schema", "employees"); + Assertions.assertEquals(0, result.size()); + + insertData1(connection, dbType); + result = DBManager.getTableOrViewData(connection, dbType, "my_schema", "employees"); + Assertions.assertEquals(1, result.size()); + + whereData.put("age", 31); + sql = DBDialectManager.generateDeleteSql(connection, dbType, "my_schema", "employees", whereData, true); + DBManager.executeSQLScript(connection, dbType, sql); + result = DBManager.getTableOrViewData(connection, dbType, "my_schema", "employees"); + Assertions.assertEquals(1, result.size()); + + whereData = null; + sql = DBDialectManager.generateDeleteSql(connection, dbType, "my_schema", "employees", whereData, true); + Assertions.assertNull(sql); + + tearDown(); + setUp(); + createSchema(connection, dbType); + insertData(connection, dbType); + + whereData = new HashMap<>(); + whereData.put("myinteger", 20); + whereData.put("myvarchar", "VARCHAR"); + whereData.put("mytext", "This is a text field"); + whereData.put("mydate", "2023-07-24"); + whereData.put("mytimestamp", "2023-07-24 10:11:12"); + whereData.put("myboolean", "true"); + whereData.put("mychar", "CHAR"); + sql = DBDialectManager.generateDeleteSql(connection, dbType, "my_schema", "mytable", whereData, false); + DBManager.executeSQLScript(connection, dbType, sql); + + result = DBManager.getTableOrViewData(connection, dbType, "my_schema", "mytable"); + Assertions.assertEquals(0, result.size()); + } } diff --git a/src/test/java/com/dbmasker/database/gbase/Gbase8sAPITests.java b/src/test/java/com/dbmasker/database/gbase/Gbase8sAPITests.java index 67a2b7b..99b6c50 100644 --- a/src/test/java/com/dbmasker/database/gbase/Gbase8sAPITests.java +++ b/src/test/java/com/dbmasker/database/gbase/Gbase8sAPITests.java @@ -307,10 +307,10 @@ void testGetTableAttribute() throws SQLException { void testGetPrimaryKeys() throws SQLException, ClassNotFoundException { createTable(connection, dbType); - List tablePrimaryKeys = DBManager.getPrimaryKeys(connection, dbType, "", "employees"); + Set tablePrimaryKeys = DBManager.getPrimaryKeys(connection, dbType, "", "employees"); Assertions.assertEquals(1, tablePrimaryKeys.size()); - List expectPrimaryKeys = new ArrayList<>(); + Set expectPrimaryKeys = new HashSet<>(); expectPrimaryKeys.add("id"); Assertions.assertEquals(expectPrimaryKeys, tablePrimaryKeys); diff --git a/src/test/java/com/dbmasker/database/gbase/Gbase8sDialectAPITests.java b/src/test/java/com/dbmasker/database/gbase/Gbase8sDialectAPITests.java index 194d26d..b3cccd0 100644 --- a/src/test/java/com/dbmasker/database/gbase/Gbase8sDialectAPITests.java +++ b/src/test/java/com/dbmasker/database/gbase/Gbase8sDialectAPITests.java @@ -69,6 +69,28 @@ my_serial SERIAL(10) DBManager.executeUpdateSQL(connection, dbType, sql); } + public void createTable1(Connection connection, String dbType) throws SQLException { + String sql = """ + CREATE TABLE IF NOT EXISTS employees ( + id SERIAL PRIMARY KEY, + first_name VARCHAR(255) NOT NULL, + last_name VARCHAR(255) NOT NULL, + email VARCHAR(255) NOT NULL, + age INT, + UNIQUE (email) + ); + """; + DBManager.executeUpdateSQL(connection, dbType, sql); + } + + public void insertData1(Connection connection, String dbType) throws SQLException { + String sql = """ + INSERT INTO employees (first_name, last_name, email, age) + VALUES ('John', 'Doe', 'john.doe@example.com', 30); + """; + DBManager.executeUpdateSQL(connection, dbType, sql); + } + public void insertData(Connection connection, String dbType) throws SQLException { String sql = """ INSERT INTO my_table ( @@ -144,6 +166,10 @@ public void setUp() throws SQLException, ClassNotFoundException { @AfterEach public void tearDown() throws SQLException { + String sql = """ + DROP TABLE IF EXISTS employees; + """; + DBManager.executeUpdateSQL(connection, dbType, sql); String sql2 = """ DROP TABLE IF EXISTS mytable; """; @@ -279,4 +305,197 @@ void testGenerateInsertSql() throws SQLException { Assertions.assertNull(result.get(3).get("my_integer")); Assertions.assertNull(result.get(3).get("my_date")); } + + @Test + void testGenerateUpdateSql() throws SQLException { + createTable1(connection, dbType); + insertData1(connection, dbType); + + Map setData = new HashMap<>(); + setData.put("age", 100); + Map whereData = new HashMap<>(); + whereData.put("id", 1); + whereData.put("first_name", "John"); + whereData.put("last_name", "Doe"); + String sql = DBDialectManager.generateUpdateSql(connection, dbType, "", "employees", setData, whereData, true); + String expectSQL = "UPDATE employees SET age = 100 WHERE id = 1;"; + Assertions.assertEquals(expectSQL, sql); + DBManager.executeSQLScript(connection, dbType, sql); + + List> result = DBManager.getTableOrViewData(connection, dbType, "", "employees"); + Assertions.assertEquals(1, result.size()); + Assertions.assertEquals(100, result.get(0).get("age")); + Assertions.assertEquals(1, result.get(0).get("id")); + + setData.put("age", 10); + whereData = new HashMap<>(); + whereData.put("first_name", "John"); + whereData.put("last_name", "Doe"); + whereData.put("email", "john.doe@example.com"); + sql = DBDialectManager.generateUpdateSql(connection, dbType, "", "employees", setData, whereData, true); + expectSQL = "UPDATE employees SET age = 10 WHERE email = 'john.doe@example.com';"; + Assertions.assertEquals(expectSQL, sql); + DBManager.executeSQLScript(connection, dbType, sql); + + result = DBManager.getTableOrViewData(connection, dbType, "", "employees"); + Assertions.assertEquals(1, result.size()); + Assertions.assertEquals(10, result.get(0).get("age")); + Assertions.assertEquals(1, result.get(0).get("id")); + + setData.put("age", 99); + whereData = new HashMap<>(); + whereData.put("first_name", "John"); + whereData.put("last_name", "Doe"); + whereData.put("age", 10); + sql = DBDialectManager.generateUpdateSql(connection, dbType, "", "employees", setData, whereData, true); + expectSQL = "UPDATE employees SET age = 99 WHERE last_name = 'Doe' AND first_name = 'John' AND age = 10;"; + Assertions.assertEquals(expectSQL, sql); + DBManager.executeSQLScript(connection, dbType, sql); + + result = DBManager.getTableOrViewData(connection, dbType, "", "employees"); + Assertions.assertEquals(1, result.size()); + Assertions.assertEquals(99, result.get(0).get("age")); + Assertions.assertEquals(1, result.get(0).get("id")); + + setData.put("age", 98); + sql = DBDialectManager.generateUpdateSql(connection, dbType, "", "employees", setData, whereData, true); + DBManager.executeSQLScript(connection, dbType, sql); + result = DBManager.getTableOrViewData(connection, dbType, "", "employees"); + Assertions.assertEquals(1, result.size()); + Assertions.assertEquals(99, result.get(0).get("age")); + + whereData = null; + sql = DBDialectManager.generateUpdateSql(connection, dbType, "", "employees", setData, whereData, true); + Assertions.assertNull(sql); + } + + @Test + void testGenerateUpdateSql1() throws SQLException { + createTable(connection, dbType); + insertData(connection, dbType); + + Map setData = new HashMap<>(); + setData.put("my_char", "char'50'"); + setData.put("my_boolean", 0); + setData.put("my_set", "[10, 20, 30]"); + setData.put("my_decimal", 1.1); + setData.put("my_list", "[aa, bb, cc]"); + setData.put("my_date", "2024-01-01"); + setData.put("my_datetime", "2024-01-01 00:00:00"); + setData.put("my_integer", null); + Map whereData = new HashMap<>(); + whereData.put("my_smallint", 1234); + + String sql = DBDialectManager.generateUpdateSql(connection, dbType, "", "my_table", setData, whereData, true); + DBManager.executeSQLScript(connection, dbType, sql); + List> result = DBManager.getTableOrViewData(connection, dbType, "", "my_table"); + Assertions.assertEquals(1, result.size()); + Assertions.assertEquals(String.format("%-10s", "char'50'"), result.get(0).get("my_char")); + Assertions.assertEquals(false, result.get(0).get("my_boolean")); + Assertions.assertEquals("[20, 10, 30]", result.get(0).get("my_set").toString()); + Assertions.assertEquals("1.1", result.get(0).get("my_decimal").toString()); + Assertions.assertEquals("[aa, bb, cc]", result.get(0).get("my_list").toString()); + Assertions.assertEquals("2024-01-01", result.get(0).get("my_date").toString()); + Assertions.assertEquals("2024-01-01 00:00:00.0", result.get(0).get("my_datetime").toString()); + Assertions.assertNull(result.get(0).get("my_integer")); + + setData = new HashMap<>(); + setData.put("my_smallint", 999); + whereData = new HashMap<>(); + whereData.put("my_char", "char'50'"); + whereData.put("my_boolean", 0); + whereData.put("my_set", "[10, 20, 30]"); + whereData.put("my_decimal", 1.1); + whereData.put("my_list", "[aa, bb, cc]"); + whereData.put("my_date", "2024-01-01"); + whereData.put("my_datetime", "2024-01-01 00:00:00"); + whereData.put("my_integer", null); + sql = DBDialectManager.generateUpdateSql(connection, dbType, "", "my_table", setData, whereData, false); + DBManager.executeSQLScript(connection, dbType, sql); + result = DBManager.getTableOrViewData(connection, dbType, "", "my_table"); + Assertions.assertEquals(1, result.size()); + Assertions.assertEquals("999", result.get(0).get("my_smallint").toString()); + } + + @Test + void testGenerateDeleteSql() throws SQLException, ClassNotFoundException { + createTable1(connection, dbType); + insertData1(connection, dbType); + + Map whereData = new HashMap<>(); + whereData.put("id", 1); + whereData.put("first_name", "John"); + whereData.put("last_name", "Doe"); + String sql = DBDialectManager.generateDeleteSql(connection, dbType, "", "employees", whereData, true); + String expectSQL = "DELETE FROM employees WHERE id = 1;"; + Assertions.assertEquals(expectSQL, sql); + DBManager.executeSQLScript(connection, dbType, sql); + + List> result = DBManager.getTableOrViewData(connection, dbType, "", "employees"); + Assertions.assertEquals(0, result.size()); + + insertData1(connection, dbType); + result = DBManager.getTableOrViewData(connection, dbType, "", "employees"); + Assertions.assertEquals(1, result.size()); + + whereData = new HashMap<>(); + whereData.put("first_name", "John"); + whereData.put("last_name", "Doe"); + whereData.put("email", "john.doe@example.com"); + sql = DBDialectManager.generateDeleteSql(connection, dbType, "", "employees", whereData, true); + expectSQL = "DELETE FROM employees WHERE email = 'john.doe@example.com';"; + Assertions.assertEquals(expectSQL, sql); + DBManager.executeSQLScript(connection, dbType, sql); + + result = DBManager.getTableOrViewData(connection, dbType, "", "employees"); + Assertions.assertEquals(0, result.size()); + + insertData1(connection, dbType); + result = DBManager.getTableOrViewData(connection, dbType, "", "employees"); + Assertions.assertEquals(1, result.size()); + + whereData = new HashMap<>(); + whereData.put("first_name", "John"); + whereData.put("last_name", "Doe"); + whereData.put("age", 30); + + sql = DBDialectManager.generateDeleteSql(connection, dbType, "", "employees", whereData, true); + expectSQL = "DELETE FROM employees WHERE last_name = 'Doe' AND first_name = 'John' AND age = 30;"; + Assertions.assertEquals(expectSQL, sql); + DBManager.executeSQLScript(connection, dbType, sql); + + result = DBManager.getTableOrViewData(connection, dbType, "", "employees"); + Assertions.assertEquals(0, result.size()); + + insertData1(connection, dbType); + result = DBManager.getTableOrViewData(connection, dbType, "", "employees"); + Assertions.assertEquals(1, result.size()); + + whereData.put("age", 31); + sql = DBDialectManager.generateDeleteSql(connection, dbType, "", "employees", whereData, true); + DBManager.executeSQLScript(connection, dbType, sql); + result = DBManager.getTableOrViewData(connection, dbType, "", "employees"); + Assertions.assertEquals(1, result.size()); + + whereData = null; + sql = DBDialectManager.generateDeleteSql(connection, dbType, "", "employees", whereData, true); + Assertions.assertNull(sql); + + createTable(connection, dbType); + insertData(connection, dbType); + + whereData = new HashMap<>(); + whereData.put("my_char", "char_data"); + whereData.put("my_boolean", 1); + whereData.put("my_set", "[1, 2, 3]"); + whereData.put("my_decimal", 12345.67); + whereData.put("my_list", "[a, b, c]"); + whereData.put("my_date", "2023-01-01"); + whereData.put("my_datetime", "2023-01-01 01:23:45.67890"); + sql = DBDialectManager.generateDeleteSql(connection, dbType, "", "my_table", whereData, false); + DBManager.executeSQLScript(connection, dbType, sql); + + result = DBManager.getTableOrViewData(connection, dbType, "", "my_table"); + Assertions.assertEquals(0, result.size()); + } } diff --git a/src/test/java/com/dbmasker/database/gbase/Gbase8tAPITests.java b/src/test/java/com/dbmasker/database/gbase/Gbase8tAPITests.java index c504e39..b658bcf 100644 --- a/src/test/java/com/dbmasker/database/gbase/Gbase8tAPITests.java +++ b/src/test/java/com/dbmasker/database/gbase/Gbase8tAPITests.java @@ -304,10 +304,10 @@ void testGetTableAttribute() throws SQLException { void testGetPrimaryKeys() throws SQLException, ClassNotFoundException { createTable(connection, dbType); - List tablePrimaryKeys = DBManager.getPrimaryKeys(connection, dbType, "", "employees"); + Set tablePrimaryKeys = DBManager.getPrimaryKeys(connection, dbType, "", "employees"); Assertions.assertEquals(1, tablePrimaryKeys.size()); - List expectPrimaryKeys = new ArrayList<>(); + Set expectPrimaryKeys = new HashSet<>(); expectPrimaryKeys.add("id"); Assertions.assertEquals(expectPrimaryKeys, tablePrimaryKeys); diff --git a/src/test/java/com/dbmasker/database/gbase/Gbase8tDialectAPITests.java b/src/test/java/com/dbmasker/database/gbase/Gbase8tDialectAPITests.java index 3a8ac23..24cc75e 100644 --- a/src/test/java/com/dbmasker/database/gbase/Gbase8tDialectAPITests.java +++ b/src/test/java/com/dbmasker/database/gbase/Gbase8tDialectAPITests.java @@ -68,6 +68,28 @@ my_serial SERIAL(10) DBManager.executeUpdateSQL(connection, dbType, sql); } + public void createTable1(Connection connection, String dbType) throws SQLException { + String sql = """ + CREATE TABLE IF NOT EXISTS employees ( + id SERIAL PRIMARY KEY, + first_name VARCHAR(255) NOT NULL, + last_name VARCHAR(255) NOT NULL, + email VARCHAR(255) NOT NULL, + age INT, + UNIQUE (email) + ); + """; + DBManager.executeUpdateSQL(connection, dbType, sql); + } + + public void insertData1(Connection connection, String dbType) throws SQLException { + String sql = """ + INSERT INTO employees (first_name, last_name, email, age) + VALUES ('John', 'Doe', 'john.doe@example.com', 30); + """; + DBManager.executeUpdateSQL(connection, dbType, sql); + } + public void insertData(Connection connection, String dbType) throws SQLException { String sql = """ INSERT INTO my_table ( @@ -143,6 +165,10 @@ public void setUp() throws SQLException, ClassNotFoundException { @AfterEach public void tearDown() throws SQLException { + String sql = """ + DROP TABLE IF EXISTS employees; + """; + DBManager.executeUpdateSQL(connection, dbType, sql); String sql3 = """ DROP TABLE IF EXISTS my_table; """; @@ -266,4 +292,197 @@ void testGenerateInsertSql() throws SQLException { Assertions.assertNull(result.get(3).get("my_date")); } + @Test + void testGenerateUpdateSql() throws SQLException { + createTable1(connection, dbType); + insertData1(connection, dbType); + + Map setData = new HashMap<>(); + setData.put("age", 100); + Map whereData = new HashMap<>(); + whereData.put("id", 1); + whereData.put("first_name", "John"); + whereData.put("last_name", "Doe"); + String sql = DBDialectManager.generateUpdateSql(connection, dbType, "", "employees", setData, whereData, true); + String expectSQL = "UPDATE employees SET age = 100 WHERE id = 1;"; + Assertions.assertEquals(expectSQL, sql); + DBManager.executeSQLScript(connection, dbType, sql); + + List> result = DBManager.getTableOrViewData(connection, dbType, "", "employees"); + Assertions.assertEquals(1, result.size()); + Assertions.assertEquals(100, result.get(0).get("age")); + Assertions.assertEquals(1, result.get(0).get("id")); + + setData.put("age", 10); + whereData = new HashMap<>(); + whereData.put("first_name", "John"); + whereData.put("last_name", "Doe"); + whereData.put("email", "john.doe@example.com"); + sql = DBDialectManager.generateUpdateSql(connection, dbType, "", "employees", setData, whereData, true); + expectSQL = "UPDATE employees SET age = 10 WHERE email = 'john.doe@example.com';"; + Assertions.assertEquals(expectSQL, sql); + DBManager.executeSQLScript(connection, dbType, sql); + + result = DBManager.getTableOrViewData(connection, dbType, "", "employees"); + Assertions.assertEquals(1, result.size()); + Assertions.assertEquals(10, result.get(0).get("age")); + Assertions.assertEquals(1, result.get(0).get("id")); + + setData.put("age", 99); + whereData = new HashMap<>(); + whereData.put("first_name", "John"); + whereData.put("last_name", "Doe"); + whereData.put("age", 10); + sql = DBDialectManager.generateUpdateSql(connection, dbType, "", "employees", setData, whereData, true); + expectSQL = "UPDATE employees SET age = 99 WHERE last_name = 'Doe' AND first_name = 'John' AND age = 10;"; + Assertions.assertEquals(expectSQL, sql); + DBManager.executeSQLScript(connection, dbType, sql); + + result = DBManager.getTableOrViewData(connection, dbType, "", "employees"); + Assertions.assertEquals(1, result.size()); + Assertions.assertEquals(99, result.get(0).get("age")); + Assertions.assertEquals(1, result.get(0).get("id")); + + setData.put("age", 98); + sql = DBDialectManager.generateUpdateSql(connection, dbType, "", "employees", setData, whereData, true); + DBManager.executeSQLScript(connection, dbType, sql); + result = DBManager.getTableOrViewData(connection, dbType, "", "employees"); + Assertions.assertEquals(1, result.size()); + Assertions.assertEquals(99, result.get(0).get("age")); + + whereData = null; + sql = DBDialectManager.generateUpdateSql(connection, dbType, "", "employees", setData, whereData, true); + Assertions.assertNull(sql); + } + + @Test + void testGenerateUpdateSql1() throws SQLException { + createTable(connection, dbType); + insertData(connection, dbType); + + Map setData = new HashMap<>(); + setData.put("my_char", "char'50'"); + setData.put("my_boolean", 0); + setData.put("my_set", "[10, 20, 30]"); + setData.put("my_decimal", 1.1); + setData.put("my_list", "[aa, bb, cc]"); + setData.put("my_date", "2024-01-01"); + setData.put("my_datetime", "2024-01-01 00:00:00"); + setData.put("my_integer", null); + Map whereData = new HashMap<>(); + whereData.put("my_smallint", 1234); + + String sql = DBDialectManager.generateUpdateSql(connection, dbType, "", "my_table", setData, whereData, true); + DBManager.executeSQLScript(connection, dbType, sql); + List> result = DBManager.getTableOrViewData(connection, dbType, "", "my_table"); + Assertions.assertEquals(1, result.size()); + Assertions.assertEquals(String.format("%-10s", "char'50'"), result.get(0).get("my_char")); + Assertions.assertEquals(false, result.get(0).get("my_boolean")); + Assertions.assertEquals("[20, 10, 30]", result.get(0).get("my_set").toString()); + Assertions.assertEquals("1.1", result.get(0).get("my_decimal").toString()); + Assertions.assertEquals("[aa, bb, cc]", result.get(0).get("my_list").toString()); + Assertions.assertEquals("2024-01-01", result.get(0).get("my_date").toString()); + Assertions.assertEquals("2024-01-01 00:00:00.0", result.get(0).get("my_datetime").toString()); + Assertions.assertNull(result.get(0).get("my_integer")); + + setData = new HashMap<>(); + setData.put("my_smallint", 999); + whereData = new HashMap<>(); + whereData.put("my_char", "char'50'"); + whereData.put("my_boolean", 0); + whereData.put("my_set", "[10, 20, 30]"); + whereData.put("my_decimal", 1.1); + whereData.put("my_list", "[aa, bb, cc]"); + whereData.put("my_date", "2024-01-01"); + whereData.put("my_datetime", "2024-01-01 00:00:00"); + whereData.put("my_integer", null); + sql = DBDialectManager.generateUpdateSql(connection, dbType, "", "my_table", setData, whereData, false); + DBManager.executeSQLScript(connection, dbType, sql); + result = DBManager.getTableOrViewData(connection, dbType, "", "my_table"); + Assertions.assertEquals(1, result.size()); + Assertions.assertEquals("999", result.get(0).get("my_smallint").toString()); + } + + @Test + void testGenerateDeleteSql() throws SQLException, ClassNotFoundException { + createTable1(connection, dbType); + insertData1(connection, dbType); + + Map whereData = new HashMap<>(); + whereData.put("id", 1); + whereData.put("first_name", "John"); + whereData.put("last_name", "Doe"); + String sql = DBDialectManager.generateDeleteSql(connection, dbType, "", "employees", whereData, true); + String expectSQL = "DELETE FROM employees WHERE id = 1;"; + Assertions.assertEquals(expectSQL, sql); + DBManager.executeSQLScript(connection, dbType, sql); + + List> result = DBManager.getTableOrViewData(connection, dbType, "", "employees"); + Assertions.assertEquals(0, result.size()); + + insertData1(connection, dbType); + result = DBManager.getTableOrViewData(connection, dbType, "", "employees"); + Assertions.assertEquals(1, result.size()); + + whereData = new HashMap<>(); + whereData.put("first_name", "John"); + whereData.put("last_name", "Doe"); + whereData.put("email", "john.doe@example.com"); + sql = DBDialectManager.generateDeleteSql(connection, dbType, "", "employees", whereData, true); + expectSQL = "DELETE FROM employees WHERE email = 'john.doe@example.com';"; + Assertions.assertEquals(expectSQL, sql); + DBManager.executeSQLScript(connection, dbType, sql); + + result = DBManager.getTableOrViewData(connection, dbType, "", "employees"); + Assertions.assertEquals(0, result.size()); + + insertData1(connection, dbType); + result = DBManager.getTableOrViewData(connection, dbType, "", "employees"); + Assertions.assertEquals(1, result.size()); + + whereData = new HashMap<>(); + whereData.put("first_name", "John"); + whereData.put("last_name", "Doe"); + whereData.put("age", 30); + + sql = DBDialectManager.generateDeleteSql(connection, dbType, "", "employees", whereData, true); + expectSQL = "DELETE FROM employees WHERE last_name = 'Doe' AND first_name = 'John' AND age = 30;"; + Assertions.assertEquals(expectSQL, sql); + DBManager.executeSQLScript(connection, dbType, sql); + + result = DBManager.getTableOrViewData(connection, dbType, "", "employees"); + Assertions.assertEquals(0, result.size()); + + insertData1(connection, dbType); + result = DBManager.getTableOrViewData(connection, dbType, "", "employees"); + Assertions.assertEquals(1, result.size()); + + whereData.put("age", 31); + sql = DBDialectManager.generateDeleteSql(connection, dbType, "", "employees", whereData, true); + DBManager.executeSQLScript(connection, dbType, sql); + result = DBManager.getTableOrViewData(connection, dbType, "", "employees"); + Assertions.assertEquals(1, result.size()); + + whereData = null; + sql = DBDialectManager.generateDeleteSql(connection, dbType, "", "employees", whereData, true); + Assertions.assertNull(sql); + + createTable(connection, dbType); + insertData(connection, dbType); + + whereData = new HashMap<>(); + whereData.put("my_char", "char_data"); + whereData.put("my_boolean", 1); + whereData.put("my_set", "[1, 2, 3]"); + whereData.put("my_decimal", 12345.67); + whereData.put("my_list", "[a, b, c]"); + whereData.put("my_date", "2023-01-01"); + whereData.put("my_datetime", "2023-01-01 01:23:45.67890"); + sql = DBDialectManager.generateDeleteSql(connection, dbType, "", "my_table", whereData, false); + DBManager.executeSQLScript(connection, dbType, sql); + + result = DBManager.getTableOrViewData(connection, dbType, "", "my_table"); + Assertions.assertEquals(0, result.size()); + } + } diff --git a/src/test/java/com/dbmasker/database/hbase/PhoenixAPITests.java b/src/test/java/com/dbmasker/database/hbase/PhoenixAPITests.java index e3a3a51..5f59c02 100644 --- a/src/test/java/com/dbmasker/database/hbase/PhoenixAPITests.java +++ b/src/test/java/com/dbmasker/database/hbase/PhoenixAPITests.java @@ -318,6 +318,32 @@ void testGetUniqueKey() { // not support } + @Test + void testGetPrimaryKeys() throws SQLException, ClassNotFoundException { + createSchema(connection, dbType); + + Set tablePrimaryKeys = DBManager.getPrimaryKeys(connection, dbType, "MY_SCHEMA", "EMPLOYEES"); + Assertions.assertEquals(1, tablePrimaryKeys.size()); + + Set expectPrimaryKeys = new HashSet<>(); + expectPrimaryKeys.add("ID"); + + Assertions.assertEquals(expectPrimaryKeys, tablePrimaryKeys); + + // more test cases + Assertions.assertEquals(0, DBManager.getPrimaryKeys(connection, dbType, null, "employees").size()); + Assertions.assertEquals(0, DBManager.getPrimaryKeys(connection, dbType, "fakeSchema", "employees").size()); + + try { + DBManager.getPrimaryKeys(connection, dbType, null, null); + Assertions.fail(); + } catch (IllegalArgumentException e) { + Assertions.assertTrue(e.getMessage().startsWith(ErrorMessages.NULL_TABLE_OR_VIEW_NAME_ERROR)); + } + + Assertions.assertEquals(0, DBManager.getPrimaryKeys(connection, dbType, "my_schema", "fakeTable").size()); + } + @Test void testGetIndex() { // not support diff --git a/src/test/java/com/dbmasker/database/hbase/PhoenixDialectAPITests.java b/src/test/java/com/dbmasker/database/hbase/PhoenixDialectAPITests.java index 90ddfac..a01a18d 100644 --- a/src/test/java/com/dbmasker/database/hbase/PhoenixDialectAPITests.java +++ b/src/test/java/com/dbmasker/database/hbase/PhoenixDialectAPITests.java @@ -73,6 +73,32 @@ my_binary BINARY(10) DBManager.executeUpdateSQLBatch(connection, dbType, sqlList); } + public void createSchema1(Connection connection, String dbType) throws SQLException { + List sqlList = new ArrayList<>(); + String sql1 = "CREATE SCHEMA my_schema"; + + String sql2 = """ + CREATE TABLE my_schema.employees ( + id INTEGER NOT NULL primary key, + first_name VARCHAR(255), + last_name VARCHAR(255), + email VARCHAR(255), + age INTEGER + ) + """; + sqlList.add(sql1); + sqlList.add(sql2); + DBManager.executeUpdateSQLBatch(connection, dbType, sqlList); + } + + public void insertData1(Connection connection, String dbType) throws SQLException { + String sql = """ + upsert into my_schema.employees (id, first_name, last_name, email, age) + values (1, 'John', 'Doe', 'john.doe@example.com', 30) + """; + DBManager.executeUpdateSQL(connection, dbType, sql); + } + public void insertData(Connection connection, String dbType) throws SQLException { String sql = """ UPSERT INTO my_schema.my_table ( @@ -112,8 +138,8 @@ public void insertData(Connection connection, String dbType) throws SQLException 12.0,-- my_unsigned_double 13.0,-- my_decimal TRUE,-- my_boolean - TO_DATE('2023-05-31', 'yyyy-MM-dd'), -- my_time - TO_TIME('12:34:56', 'HH:mm:ss'), -- my_date + TO_TIME('12:34:56', 'HH:mm:ss'), -- my_time + TO_DATE('2023-05-31', 'yyyy-MM-dd'), -- my_date TO_TIMESTAMP('2023-05-31 12:34:56', 'yyyy-MM-dd HH:mm:ss'), -- my_timestamp 'Hello', -- my_varchar 'World', -- my_char @@ -149,6 +175,10 @@ public void tearDown() throws SQLException { DROP TABLE IF EXISTS my_schema.my_table """; DBManager.executeUpdateSQL(connection, dbType, sql); + sql = """ + DROP TABLE IF EXISTS my_schema.employees + """; + DBManager.executeUpdateSQL(connection, dbType, sql); String sql1 = "DROP SCHEMA IF EXISTS my_schema"; DBManager.executeUpdateSQL(connection, dbType, sql1); @@ -260,4 +290,143 @@ void testGenerateInsertSql() throws SQLException { byte[] expected = new byte[10]; Assertions.assertArrayEquals(expected, (byte[]) result.get(3).get("MY_BINARY")); } + + @Test + void testGenerateUpdateSql() throws SQLException { + createSchema1(connection, dbType); + insertData1(connection, dbType); + + Map setData = new HashMap<>(); + setData.put("age", 100); + Map whereData = new HashMap<>(); + whereData.put("id", 1); + whereData.put("first_name", "John"); + whereData.put("last_name", "Doe"); + String sql = DBDialectManager.generateUpdateSql(connection, dbType, "MY_SCHEMA", "EMPLOYEES", setData, whereData, true); + String expectSQL = "UPSERT INTO MY_SCHEMA.EMPLOYEES (ID,age) VALUES\n(1,100);"; + Assertions.assertEquals(expectSQL, sql); + DBManager.executeSQLScript(connection, dbType, sql); + + List> result = DBManager.getTableOrViewData(connection, dbType, "MY_SCHEMA", "EMPLOYEES"); + Assertions.assertEquals(1, result.size()); + Assertions.assertEquals(100, result.get(0).get("AGE")); + Assertions.assertEquals(1, result.get(0).get("ID")); + + whereData = null; + sql = DBDialectManager.generateUpdateSql(connection, dbType, "MY_SCHEMA", "EMPLOYEES", setData, whereData, true); + Assertions.assertNull(sql); + } + + @Test + void testGenerateUpdateSql1() throws SQLException { + createSchema(connection, dbType); + insertData(connection, dbType); + + Map setData = new HashMap<>(); + setData.put("my_bigint", 100L); + setData.put("my_varchar", "Hello, World"); + setData.put("my_boolean", false); + setData.put("my_time", "10:23:54"); + setData.put("my_date", "2024-10-19"); + setData.put("my_timestamp", "2024-10-19 10:23:54"); + Map whereData = new HashMap<>(); + whereData.put("my_integer", 1); + + String sql = DBDialectManager.generateUpdateSql(connection, dbType, "MY_SCHEMA", "MY_TABLE", setData, whereData, true); + DBManager.executeSQLScript(connection, dbType, sql); + List> result = DBManager.getTableOrViewData(connection, dbType, "MY_SCHEMA", "MY_TABLE"); + + Assertions.assertEquals(1, result.size()); + Assertions.assertEquals(100L, result.get(0).get("MY_BIGINT")); + Assertions.assertEquals("Hello, World", result.get(0).get("MY_VARCHAR")); + Assertions.assertEquals(false, result.get(0).get("MY_BOOLEAN")); + Assertions.assertEquals("10:23:54", result.get(0).get("MY_TIME").toString()); + Assertions.assertEquals("2024-10-19", result.get(0).get("MY_DATE").toString()); + Assertions.assertEquals("2024-10-19 10:23:54.0", result.get(0).get("MY_TIMESTAMP").toString()); + } + + @Test + void testGenerateDeleteSql() throws SQLException, ClassNotFoundException { + createSchema1(connection, dbType); + insertData1(connection, dbType); + + Map whereData = new HashMap<>(); + whereData.put("id", 1); + whereData.put("first_name", "John"); + whereData.put("last_name", "Doe"); + String sql = DBDialectManager.generateDeleteSql(connection, dbType, "MY_SCHEMA", "EMPLOYEES", whereData, true); + String expectSQL = "DELETE FROM MY_SCHEMA.EMPLOYEES WHERE id = 1;"; + Assertions.assertEquals(expectSQL, sql); + DBManager.executeSQLScript(connection, dbType, sql); + + List> result = DBManager.getTableOrViewData(connection, dbType, "MY_SCHEMA", "EMPLOYEES"); + Assertions.assertEquals(0, result.size()); + + insertData1(connection, dbType); + result = DBManager.getTableOrViewData(connection, dbType, "MY_SCHEMA", "EMPLOYEES"); + Assertions.assertEquals(1, result.size()); + + whereData = new HashMap<>(); + whereData.put("first_name", "John"); + whereData.put("last_name", "Doe"); + sql = DBDialectManager.generateDeleteSql(connection, dbType, "MY_SCHEMA", "EMPLOYEES", whereData, true); + expectSQL = "DELETE FROM MY_SCHEMA.EMPLOYEES WHERE last_name = 'Doe' AND first_name = 'John';"; + Assertions.assertEquals(expectSQL, sql); + DBManager.executeSQLScript(connection, dbType, sql); + + result = DBManager.getTableOrViewData(connection, dbType, "MY_SCHEMA", "EMPLOYEES"); + Assertions.assertEquals(0, result.size()); + + insertData1(connection, dbType); + result = DBManager.getTableOrViewData(connection, dbType, "MY_SCHEMA", "EMPLOYEES"); + Assertions.assertEquals(1, result.size()); + + whereData = new HashMap<>(); + whereData.put("first_name", "John"); + whereData.put("email", "john.doe@example.com"); + whereData.put("age", 30); + + sql = DBDialectManager.generateDeleteSql(connection, dbType, "MY_SCHEMA", "EMPLOYEES", whereData, true); + expectSQL = "DELETE FROM MY_SCHEMA.EMPLOYEES WHERE first_name = 'John' AND email = 'john.doe@example.com' AND age = 30;"; + Assertions.assertEquals(expectSQL, sql); + DBManager.executeSQLScript(connection, dbType, sql); + + result = DBManager.getTableOrViewData(connection, dbType, "MY_SCHEMA", "EMPLOYEES"); + Assertions.assertEquals(0, result.size()); + + insertData1(connection, dbType); + result = DBManager.getTableOrViewData(connection, dbType, "MY_SCHEMA", "EMPLOYEES"); + Assertions.assertEquals(1, result.size()); + + whereData.put("age", 31); + sql = DBDialectManager.generateDeleteSql(connection, dbType, "MY_SCHEMA", "EMPLOYEES", whereData, true); + DBManager.executeSQLScript(connection, dbType, sql); + result = DBManager.getTableOrViewData(connection, dbType, "MY_SCHEMA", "EMPLOYEES"); + Assertions.assertEquals(1, result.size()); + + whereData = null; + sql = DBDialectManager.generateDeleteSql(connection, dbType, "MY_SCHEMA", "EMPLOYEES", whereData, true); + Assertions.assertNull(sql); + + + tearDown(); + setUp(); + createSchema(connection, dbType); + insertData(connection, dbType); + + whereData = new HashMap<>(); + whereData.put("my_bigint", 3L); + whereData.put("my_varchar", "Hello"); + whereData.put("my_boolean", true); + whereData.put("my_time", "12:34:56"); + whereData.put("my_date", "2023-05-31"); + whereData.put("my_timestamp", "2023-05-31 12:34:56"); + + sql = DBDialectManager.generateDeleteSql(connection, dbType, "MY_SCHEMA", "MY_TABLE", whereData, false); + DBManager.executeSQLScript(connection, dbType, sql); + result = DBManager.getTableOrViewData(connection, dbType, "MY_SCHEMA", "MY_TABLE"); + Assertions.assertEquals(0, result.size()); + + } + } diff --git a/src/test/java/com/dbmasker/database/kingbase/KingBaseAPITests.java b/src/test/java/com/dbmasker/database/kingbase/KingBaseAPITests.java index 8b851c3..61b626e 100644 --- a/src/test/java/com/dbmasker/database/kingbase/KingBaseAPITests.java +++ b/src/test/java/com/dbmasker/database/kingbase/KingBaseAPITests.java @@ -319,10 +319,10 @@ void testGetTableAttribute() throws SQLException { void testGetPrimaryKeys() throws SQLException, ClassNotFoundException { createSchema(connection, dbType); - List tablePrimaryKeys = DBManager.getPrimaryKeys(connection, dbType, "my_schema", "employees"); + Set tablePrimaryKeys = DBManager.getPrimaryKeys(connection, dbType, "my_schema", "employees"); Assertions.assertEquals(1, tablePrimaryKeys.size()); - List expectPrimaryKeys = new ArrayList<>(); + Set expectPrimaryKeys = new HashSet<>(); expectPrimaryKeys.add("id"); Assertions.assertEquals(expectPrimaryKeys, tablePrimaryKeys); diff --git a/src/test/java/com/dbmasker/database/kingbase/KingBaseDialectAPITests.java b/src/test/java/com/dbmasker/database/kingbase/KingBaseDialectAPITests.java index 7ca3c3d..5a679af 100644 --- a/src/test/java/com/dbmasker/database/kingbase/KingBaseDialectAPITests.java +++ b/src/test/java/com/dbmasker/database/kingbase/KingBaseDialectAPITests.java @@ -71,6 +71,29 @@ mycharactervarying CHARACTER VARYING(100), DBManager.executeUpdateSQL(connection, dbType, sql); } + public void createSchema1(Connection connection, String dbType) throws SQLException { + String sql = """ + CREATE SCHEMA my_schema; + CREATE TABLE my_schema.employees ( + id SERIAL PRIMARY KEY, + first_name TEXT NOT NULL, + last_name TEXT NOT NULL, + email TEXT NOT NULL, + age INTEGER, + UNIQUE (first_name, last_name) + ); + """; + DBManager.executeUpdateSQL(connection, dbType, sql); + } + + public void insertData1(Connection connection, String dbType) throws SQLException { + String sql = """ + INSERT INTO my_schema.employees (first_name, last_name, email, age) + VALUES ('John', 'Doe', 'john.doe@example.com', 30); + """; + DBManager.executeUpdateSQL(connection, dbType, sql); + } + public void insertData(Connection connection, String dbType) throws SQLException { String sql = """ INSERT INTO my_schema.mytable ( @@ -249,4 +272,199 @@ void testGenerateInsertSql() throws SQLException { Assertions.assertNull(result.get(3).get("MYINT")); Assertions.assertNull(result.get(3).get("MYTIMESTAMP")); } + + @Test + void testGenerateUpdateSql() throws SQLException { + createSchema1(connection, dbType); + insertData1(connection, dbType); + + Map setData = new HashMap<>(); + setData.put("age", 100); + Map whereData = new HashMap<>(); + whereData.put("id", 1); + whereData.put("first_name", "John"); + whereData.put("last_name", "Doe"); + String sql = DBDialectManager.generateUpdateSql(connection, dbType, "my_schema", "employees", setData, whereData, true); + String expectSQL = "UPDATE my_schema.employees SET age = 100 WHERE id = 1;"; + Assertions.assertEquals(expectSQL, sql); + DBManager.executeSQLScript(connection, dbType, sql); + + List> result = DBManager.getTableOrViewData(connection, dbType, "my_schema", "employees"); + Assertions.assertEquals(1, result.size()); + Assertions.assertEquals(100, result.get(0).get("age")); + Assertions.assertEquals(1, result.get(0).get("id")); + + setData.put("age", 10); + whereData = new HashMap<>(); + whereData.put("first_name", "John"); + whereData.put("last_name", "Doe"); + whereData.put("email", "john.doe@example.com"); + sql = DBDialectManager.generateUpdateSql(connection, dbType, "my_schema", "employees", setData, whereData, true); + expectSQL = "UPDATE my_schema.employees SET age = 10 WHERE last_name = 'Doe' AND first_name = 'John';"; + Assertions.assertEquals(expectSQL, sql); + DBManager.executeSQLScript(connection, dbType, sql); + + result = DBManager.getTableOrViewData(connection, dbType, "my_schema", "employees"); + Assertions.assertEquals(1, result.size()); + Assertions.assertEquals(10, result.get(0).get("age")); + Assertions.assertEquals(1, result.get(0).get("id")); + + setData.put("age", 99); + whereData = new HashMap<>(); + whereData.put("first_name", "John"); + whereData.put("email", "john.doe@example.com"); + whereData.put("age", 10); + sql = DBDialectManager.generateUpdateSql(connection, dbType, "my_schema", "employees", setData, whereData, true); + expectSQL = "UPDATE my_schema.employees SET age = 99 WHERE first_name = 'John' AND email = 'john.doe@example.com' AND age = 10;"; + Assertions.assertEquals(expectSQL, sql); + DBManager.executeSQLScript(connection, dbType, sql); + + result = DBManager.getTableOrViewData(connection, dbType, "my_schema", "employees"); + Assertions.assertEquals(1, result.size()); + Assertions.assertEquals(99, result.get(0).get("age")); + Assertions.assertEquals(1, result.get(0).get("id")); + + setData.put("age", 98); + sql = DBDialectManager.generateUpdateSql(connection, dbType, "my_schema", "employees", setData, whereData, true); + DBManager.executeSQLScript(connection, dbType, sql); + result = DBManager.getTableOrViewData(connection, dbType, "my_schema", "employees"); + Assertions.assertEquals(1, result.size()); + Assertions.assertEquals(99, result.get(0).get("age")); + + whereData = null; + sql = DBDialectManager.generateUpdateSql(connection, dbType, "my_schema", "employees", setData, whereData, true); + Assertions.assertNull(sql); + } + + @Test + void testGenerateUpdateSql1() throws SQLException { + createSchema(connection, dbType); + insertData(connection, dbType); + + Map setData = new HashMap<>(); + setData.put("myint", 100); + setData.put("mycharactervarying", "varchar'000'"); + setData.put("mytimestamp", "2024-01-01 13:14:15.0"); + setData.put("mydate", "2024-01-01"); + setData.put("myBlob", "Masker"); + setData.put("myBoolean", false); + setData.put("myinteger", null); + Map whereData = new HashMap<>(); + whereData.put("mysmallint", 3); + + String sql = DBDialectManager.generateUpdateSql(connection, dbType, "my_schema", "mytable", setData, whereData, true); + DBManager.executeSQLScript(connection, dbType, sql); + + List> result = DBManager.getTableOrViewData(connection, dbType, "my_schema", "mytable"); + Assertions.assertEquals(1, result.size()); + Assertions.assertEquals(100, result.get(0).get("myint")); + Assertions.assertEquals("varchar'000'", result.get(0).get("mycharactervarying")); + Assertions.assertEquals("2024-01-01 13:14:15.0", result.get(0).get("mytimestamp").toString()); + Assertions.assertEquals("2024-01-01 00:00:00.0", result.get(0).get("mydate").toString()); + Assertions.assertEquals("Masker", new String((byte[])result.get(0).get("myblob"))); + Assertions.assertEquals(false, result.get(0).get("myboolean")); + Assertions.assertNull(result.get(0).get("myinteger")); + + setData = new HashMap<>(); + setData.put("mysmallint", 999); + whereData = new HashMap<>(); + whereData.put("myint", 100); + whereData.put("mycharactervarying", "varchar'000'"); + whereData.put("mytimestamp", "2024-01-01 13:14:15.0"); + whereData.put("mydate", "2024-01-01"); + whereData.put("myBlob", "Masker"); + whereData.put("myBoolean", false); + whereData.put("myinteger", null); + sql = DBDialectManager.generateUpdateSql(connection, dbType, "my_schema", "mytable", setData, whereData, false); + DBManager.executeSQLScript(connection, dbType, sql); + + result = DBManager.getTableOrViewData(connection, dbType, "my_schema", "mytable"); + Assertions.assertEquals(1, result.size()); + Assertions.assertEquals(999, result.get(0).get("mysmallint")); + } + + @Test + void testGenerateDeleteSql() throws SQLException, ClassNotFoundException { + createSchema1(connection, dbType); + insertData1(connection, dbType); + + Map whereData = new HashMap<>(); + whereData.put("id", 1); + whereData.put("first_name", "John"); + whereData.put("last_name", "Doe"); + String sql = DBDialectManager.generateDeleteSql(connection, dbType, "my_schema", "employees", whereData, true); + String expectSQL = "DELETE FROM my_schema.employees WHERE id = 1;"; + Assertions.assertEquals(expectSQL, sql); + DBManager.executeSQLScript(connection, dbType, sql); + + List> result = DBManager.getTableOrViewData(connection, dbType, "my_schema", "employees"); + Assertions.assertEquals(0, result.size()); + + insertData1(connection, dbType); + result = DBManager.getTableOrViewData(connection, dbType, "my_schema", "employees"); + Assertions.assertEquals(1, result.size()); + + whereData = new HashMap<>(); + whereData.put("first_name", "John"); + whereData.put("last_name", "Doe"); + whereData.put("email", "john.doe@example.com"); + + sql = DBDialectManager.generateDeleteSql(connection, dbType, "my_schema", "employees", whereData, true); + expectSQL = "DELETE FROM my_schema.employees WHERE last_name = 'Doe' AND first_name = 'John';"; + Assertions.assertEquals(expectSQL, sql); + DBManager.executeSQLScript(connection, dbType, sql); + + result = DBManager.getTableOrViewData(connection, dbType, "my_schema", "employees"); + Assertions.assertEquals(0, result.size()); + + insertData1(connection, dbType); + result = DBManager.getTableOrViewData(connection, dbType, "my_schema", "employees"); + Assertions.assertEquals(1, result.size()); + + whereData = new HashMap<>(); + whereData.put("first_name", "John"); + whereData.put("email", "john.doe@example.com"); + whereData.put("age", 30); + + sql = DBDialectManager.generateDeleteSql(connection, dbType, "my_schema", "employees", whereData, true); + expectSQL = "DELETE FROM my_schema.employees WHERE first_name = 'John' AND email = 'john.doe@example.com' AND age = 30;"; + Assertions.assertEquals(expectSQL, sql); + DBManager.executeSQLScript(connection, dbType, sql); + + result = DBManager.getTableOrViewData(connection, dbType, "my_schema", "employees"); + Assertions.assertEquals(0, result.size()); + + insertData1(connection, dbType); + result = DBManager.getTableOrViewData(connection, dbType, "my_schema", "employees"); + Assertions.assertEquals(1, result.size()); + + whereData.put("age", 31); + sql = DBDialectManager.generateDeleteSql(connection, dbType, "my_schema", "employees", whereData, true); + DBManager.executeSQLScript(connection, dbType, sql); + result = DBManager.getTableOrViewData(connection, dbType, "my_schema", "employees"); + Assertions.assertEquals(1, result.size()); + + whereData = null; + sql = DBDialectManager.generateDeleteSql(connection, dbType, "my_schema", "employees", whereData, true); + Assertions.assertNull(sql); + + tearDown(); + setUp(); + createSchema(connection, dbType); + insertData(connection, dbType); + + whereData = new HashMap<>(); + whereData.put("myint", 1); + whereData.put("mycharactervarying", "VAR100"); + whereData.put("mytimestamp", "2023-07-24 12:34:56"); + whereData.put("mydate", "2023-07-24"); + whereData.put("myBlob", "DBMasker"); + whereData.put("myBoolean", true); + whereData.put("myinteger", 2); + sql = DBDialectManager.generateDeleteSql(connection, dbType, "my_schema", "mytable", whereData, false); + DBManager.executeSQLScript(connection, dbType, sql); + + result = DBManager.getTableOrViewData(connection, dbType, "my_schema", "mytable"); + Assertions.assertEquals(0, result.size()); + } } diff --git a/src/test/java/com/dbmasker/database/mariadb/MariaDBAPITests.java b/src/test/java/com/dbmasker/database/mariadb/MariaDBAPITests.java index 3272541..f780778 100644 --- a/src/test/java/com/dbmasker/database/mariadb/MariaDBAPITests.java +++ b/src/test/java/com/dbmasker/database/mariadb/MariaDBAPITests.java @@ -286,10 +286,10 @@ void testGetTableAttribute() throws SQLException, ClassNotFoundException { void testGetPrimaryKeys() throws SQLException { createTable(connection, dbType); - List tablePrimaryKeys = DBManager.getPrimaryKeys(connection, dbType, "test", "employees"); + Set tablePrimaryKeys = DBManager.getPrimaryKeys(connection, dbType, "test", "employees"); Assertions.assertEquals(1, tablePrimaryKeys.size()); - List expectPrimaryKeys = new ArrayList<>(); + Set expectPrimaryKeys = new HashSet<>(); expectPrimaryKeys.add("id"); Assertions.assertEquals(expectPrimaryKeys, tablePrimaryKeys); diff --git a/src/test/java/com/dbmasker/database/mariadb/MariaDBDialectAPITests.java b/src/test/java/com/dbmasker/database/mariadb/MariaDBDialectAPITests.java index 4dd90fd..84f9db7 100644 --- a/src/test/java/com/dbmasker/database/mariadb/MariaDBDialectAPITests.java +++ b/src/test/java/com/dbmasker/database/mariadb/MariaDBDialectAPITests.java @@ -68,6 +68,20 @@ myset SET('option1', 'option2', 'option3') DBManager.executeUpdateSQL(connection, dbType, sql); } + public void createTable1(Connection connection, String dbType) throws SQLException { + String sql = """ + CREATE TABLE employees ( + id INT PRIMARY KEY, + first_name VARCHAR(255) NOT NULL, + last_name VARCHAR(255) NOT NULL, + email VARCHAR(255) NOT NULL, + age INT, + UNIQUE(last_name, first_name) + ); + """; + DBManager.executeUpdateSQL(connection, dbType, sql); + } + public void insertData(Connection connection, String dbType) throws SQLException { String sql = """ INSERT INTO mytable ( @@ -111,6 +125,14 @@ INSERT INTO mytable ( DBManager.executeUpdateSQL(connection, dbType, sql); } + public void insertData1(Connection connection, String dbType) throws SQLException { + String sql = """ + INSERT INTO employees (id, first_name, last_name, email, age) + VALUES (1, 'John', 'Doe', 'john.doe@example.com', 30); + """; + DBManager.executeUpdateSQL(connection, dbType, sql); + } + public void initConfig() { Properties properties = new Properties(); try (InputStream in = this.getClass().getClassLoader().getResourceAsStream("conf/mariadb.properties")) { @@ -135,6 +157,10 @@ public void tearDown() throws SQLException { DROP TABLE IF EXISTS mytable; """; DBManager.executeUpdateSQL(connection, dbType, sql); + sql = """ + DROP TABLE IF EXISTS employees; + """; + DBManager.executeUpdateSQL(connection, dbType, sql); DBManager.closeConnection(connection); Config.getInstance().setDataSize(DBSecManager.MATCH_DATA_SIZE); @@ -234,9 +260,6 @@ void testGenerateInsertSql() throws SQLException { Assertions.assertEquals("option1", result.get(1).get("myenum").toString()); Assertions.assertEquals("option1,option2", result.get(1).get("myset").toString()); -// java.sql.Date date = (Date) result.get(1).get("myyear"); -// LocalDate localDate = date.toLocalDate(); -// Assertions.assertEquals(2023, localDate.getYear()); Assertions.assertEquals(2023, result.get(1).get("myyear")); @@ -264,4 +287,200 @@ void testGenerateInsertSql() throws SQLException { Assertions.assertNull(result.get(3).get("myint")); Assertions.assertNull(result.get(3).get("myyear")); } + + @Test + void testGenerateUpdateSql() throws SQLException { + createTable1(connection, dbType); + insertData1(connection, dbType); + + Map setData = new HashMap<>(); + setData.put("age", 100); + Map whereData = new HashMap<>(); + whereData.put("id", 1); + whereData.put("first_name", "John"); + whereData.put("last_name", "Doe"); + String sql = DBDialectManager.generateUpdateSql(connection, dbType, "", "employees", setData, whereData, true); + String expectSQL = "UPDATE employees SET age = 100 WHERE id = 1;"; + Assertions.assertEquals(expectSQL, sql); + DBManager.executeSQLScript(connection, dbType, sql); + + List> result = DBManager.getTableOrViewData(connection, dbType, "", "employees"); + Assertions.assertEquals(1, result.size()); + Assertions.assertEquals(100, result.get(0).get("age")); + Assertions.assertEquals(1, result.get(0).get("id")); + + setData.put("age", 10); + whereData = new HashMap<>(); + whereData.put("first_name", "John"); + whereData.put("last_name", "Doe"); + whereData.put("email", "john.doe@example.com"); + sql = DBDialectManager.generateUpdateSql(connection, dbType, "", "employees", setData, whereData, true); + expectSQL = "UPDATE employees SET age = 10 WHERE last_name = 'Doe' AND first_name = 'John';"; + Assertions.assertEquals(expectSQL, sql); + DBManager.executeSQLScript(connection, dbType, sql); + + result = DBManager.getTableOrViewData(connection, dbType, "", "employees"); + Assertions.assertEquals(1, result.size()); + Assertions.assertEquals(10, result.get(0).get("age")); + Assertions.assertEquals(1, result.get(0).get("id")); + + setData.put("age", 99); + whereData = new HashMap<>(); + whereData.put("first_name", "John"); + whereData.put("email", "john.doe@example.com"); + whereData.put("age", 10); + sql = DBDialectManager.generateUpdateSql(connection, dbType, "", "employees", setData, whereData, true); + expectSQL = "UPDATE employees SET age = 99 WHERE first_name = 'John' AND email = 'john.doe@example.com' AND age = 10;"; + Assertions.assertEquals(expectSQL, sql); + DBManager.executeSQLScript(connection, dbType, sql); + + result = DBManager.getTableOrViewData(connection, dbType, "", "employees"); + Assertions.assertEquals(1, result.size()); + Assertions.assertEquals(99, result.get(0).get("age")); + Assertions.assertEquals(1, result.get(0).get("id")); + + setData.put("age", 98); + sql = DBDialectManager.generateUpdateSql(connection, dbType, "", "employees", setData, whereData, true); + DBManager.executeSQLScript(connection, dbType, sql); + result = DBManager.getTableOrViewData(connection, dbType, "", "employees"); + Assertions.assertEquals(1, result.size()); + Assertions.assertEquals(99, result.get(0).get("age")); + + whereData = null; + sql = DBDialectManager.generateUpdateSql(connection, dbType, "", "employees", setData, whereData, true); + Assertions.assertNull(sql); + } + + @Test + void testGenerateUpdateSql1() throws SQLException { + createTable(connection, dbType); + insertData(connection, dbType); + + Map setData = new HashMap<>(); + setData.put("myint", null); + setData.put("myyear", 2024); + setData.put("mychar", "char'51'"); + setData.put("mytinyblob", "tinyblob1".getBytes()); + setData.put("mytimestamp", "2024-01-01 00:00:00"); + setData.put("myfloat", 1.1); + setData.put("myenum", "option2"); + + Map whereData = new HashMap<>(); + whereData.put("mytinyint", 1); + + String sql = DBDialectManager.generateUpdateSql(connection, dbType, "", "mytable", setData, whereData, true); + DBManager.executeSQLScript(connection, dbType, sql); + + List> result = DBManager.getTableOrViewData(connection, dbType, "", "mytable"); + Assertions.assertEquals(1, result.size()); + Assertions.assertNull(result.get(0).get("myint")); + Assertions.assertEquals(2024, result.get(0).get("myyear")); + Assertions.assertEquals("char'51'", result.get(0).get("mychar")); + MariaDbBlob blob = (MariaDbBlob)result.get(0).get("mytinyblob"); + Assertions.assertArrayEquals("tinyblob1".getBytes(), blob.getBytes(1, (int)blob.length())); + + Assertions.assertEquals("2024-01-01 00:00:00.0", result.get(0).get("mytimestamp").toString()); + Assertions.assertEquals("1.1", result.get(0).get("myfloat").toString()); + Assertions.assertEquals("option2", result.get(0).get("myenum")); + + setData = new HashMap<>(); + setData.put("myint", 999); + whereData = new HashMap<>(); + whereData.put("myint", null); + whereData.put("myyear", 2024); + whereData.put("mychar", "char'51'"); + whereData.put("mytinyblob", "tinyblob1".getBytes()); + whereData.put("mytimestamp", "2024-01-01 00:00:00"); + whereData.put("myenum", "option2"); + sql = DBDialectManager.generateUpdateSql(connection, dbType, "", "mytable", setData, whereData, false); + DBManager.executeSQLScript(connection, dbType, sql); + + result = DBManager.getTableOrViewData(connection, dbType, "", "mytable"); + Assertions.assertEquals(1, result.size()); + Assertions.assertEquals(999, result.get(0).get("myint")); + } + + @Test + void testGenerateDeleteSql() throws SQLException, ClassNotFoundException { + createTable1(connection, dbType); + insertData1(connection, dbType); + + Map whereData = new HashMap<>(); + whereData.put("id", 1); + whereData.put("first_name", "John"); + whereData.put("last_name", "Doe"); + String sql = DBDialectManager.generateDeleteSql(connection, dbType, "", "employees", whereData, true); + String expectSQL = "DELETE FROM employees WHERE id = 1;"; + Assertions.assertEquals(expectSQL, sql); + DBManager.executeSQLScript(connection, dbType, sql); + + List> result = DBManager.getTableOrViewData(connection, dbType, "", "employees"); + Assertions.assertEquals(0, result.size()); + + insertData1(connection, dbType); + result = DBManager.getTableOrViewData(connection, dbType, "", "employees"); + Assertions.assertEquals(1, result.size()); + + whereData = new HashMap<>(); + whereData.put("first_name", "John"); + whereData.put("last_name", "Doe"); + whereData.put("email", "john.doe@example.com"); + + sql = DBDialectManager.generateDeleteSql(connection, dbType, "", "employees", whereData, true); + expectSQL = "DELETE FROM employees WHERE last_name = 'Doe' AND first_name = 'John';"; + Assertions.assertEquals(expectSQL, sql); + DBManager.executeSQLScript(connection, dbType, sql); + + result = DBManager.getTableOrViewData(connection, dbType, "", "employees"); + Assertions.assertEquals(0, result.size()); + + insertData1(connection, dbType); + result = DBManager.getTableOrViewData(connection, dbType, "", "employees"); + Assertions.assertEquals(1, result.size()); + + whereData = new HashMap<>(); + whereData.put("first_name", "John"); + whereData.put("email", "john.doe@example.com"); + whereData.put("age", 30); + + sql = DBDialectManager.generateDeleteSql(connection, dbType, "", "employees", whereData, true); + expectSQL = "DELETE FROM employees WHERE first_name = 'John' AND email = 'john.doe@example.com' AND age = 30;"; + Assertions.assertEquals(expectSQL, sql); + DBManager.executeSQLScript(connection, dbType, sql); + + result = DBManager.getTableOrViewData(connection, dbType, "", "employees"); + Assertions.assertEquals(0, result.size()); + + insertData1(connection, dbType); + result = DBManager.getTableOrViewData(connection, dbType, "", "employees"); + Assertions.assertEquals(1, result.size()); + + whereData.put("age", 31); + sql = DBDialectManager.generateDeleteSql(connection, dbType, "", "employees", whereData, true); + DBManager.executeSQLScript(connection, dbType, sql); + result = DBManager.getTableOrViewData(connection, dbType, "", "employees"); + Assertions.assertEquals(1, result.size()); + + whereData = null; + sql = DBDialectManager.generateDeleteSql(connection, dbType, "", "employees", whereData, true); + Assertions.assertNull(sql); + + tearDown(); + setUp(); + createTable(connection, dbType); + insertData(connection, dbType); + + whereData = new HashMap<>(); + whereData.put("myint", 1000); + whereData.put("myyear", 2023); + whereData.put("mychar", "char"); + whereData.put("mytinyblob", "tinyblob".getBytes()); + whereData.put("mydatetime", "2023-07-24 14:00:00"); + whereData.put("myenum", "option1"); + sql = DBDialectManager.generateDeleteSql(connection, dbType, "", "mytable", whereData, false); + DBManager.executeSQLScript(connection, dbType, sql); + + result = DBManager.getTableOrViewData(connection, dbType, "", "mytable"); + Assertions.assertEquals(0, result.size()); + } } diff --git a/src/test/java/com/dbmasker/database/mssql/MsSQLAPITests.java b/src/test/java/com/dbmasker/database/mssql/MsSQLAPITests.java index b5aba57..915b711 100644 --- a/src/test/java/com/dbmasker/database/mssql/MsSQLAPITests.java +++ b/src/test/java/com/dbmasker/database/mssql/MsSQLAPITests.java @@ -316,10 +316,10 @@ void testGetTableAttribute() throws SQLException { @Test void testGetPrimaryKeys() throws SQLException, ClassNotFoundException { - List tablePrimaryKeys = DBManager.getPrimaryKeys(connection, dbType, "my_schema", "employees"); + Set tablePrimaryKeys = DBManager.getPrimaryKeys(connection, dbType, "my_schema", "employees"); Assertions.assertEquals(1, tablePrimaryKeys.size()); - List expectPrimaryKeys = new ArrayList<>(); + Set expectPrimaryKeys = new HashSet<>(); expectPrimaryKeys.add("id"); Assertions.assertEquals(expectPrimaryKeys, tablePrimaryKeys); diff --git a/src/test/java/com/dbmasker/database/mssql/MsSQLDialectAPITests.java b/src/test/java/com/dbmasker/database/mssql/MsSQLDialectAPITests.java index 99859a3..6ed5fd8 100644 --- a/src/test/java/com/dbmasker/database/mssql/MsSQLDialectAPITests.java +++ b/src/test/java/com/dbmasker/database/mssql/MsSQLDialectAPITests.java @@ -67,6 +67,28 @@ MyVarBinary VARBINARY(50), DBManager.executeUpdateSQL(connection, dbType, sql); } + public void createTable1(Connection connection, String dbType) throws SQLException { + String sql = """ + CREATE TABLE my_schema.employees ( + id INT PRIMARY KEY, + first_name NVARCHAR(255) NOT NULL, + last_name NVARCHAR(255) NOT NULL, + email NVARCHAR(255) NOT NULL, + age INT, + UNIQUE (first_name, last_name) + ); + """; + DBManager.executeUpdateSQL(connection, dbType, sql); + } + + public void insertData1(Connection connection, String dbType) throws SQLException { + String sql = """ + INSERT INTO my_schema.employees (id, first_name, last_name, email, age) + VALUES (1, 'John', 'Doe', 'john.doe@example.com', 30); + """; + DBManager.executeUpdateSQL(connection, dbType, sql); + } + public void insertData(Connection connection, String dbType) throws SQLException { String sql = """ INSERT INTO my_schema.MyTable ( @@ -164,6 +186,11 @@ IF OBJECT_ID('my_schema.MyTable', 'U') IS NOT NULL DROP TABLE my_schema.MyTable; """; DBManager.executeUpdateSQL(connection, dbType, sql); + sql = """ + IF OBJECT_ID('my_schema.employees', 'U') IS NOT NULL + DROP TABLE my_schema.employees; + """; + DBManager.executeUpdateSQL(connection, dbType, sql); String sql1 = "DROP SCHEMA my_schema;"; DBManager.executeUpdateSQL(connection, dbType, sql1); @@ -264,4 +291,191 @@ void testGenerateInsertSql() throws SQLException { Assertions.assertNull(result.get(3).get("MyNText")); } + @Test + void testGenerateUpdateSql() throws SQLException { + createTable1(connection, dbType); + insertData1(connection, dbType); + + Map setData = new HashMap<>(); + setData.put("age", 100); + Map whereData = new HashMap<>(); + whereData.put("id", 1); + whereData.put("first_name", "John"); + whereData.put("last_name", "Doe"); + String sql = DBDialectManager.generateUpdateSql(connection, dbType, "my_schema", "employees", setData, whereData, true); + String expectSQL = "UPDATE my_schema.employees SET age = 100 WHERE id = 1;"; + Assertions.assertEquals(expectSQL, sql); + DBManager.executeSQLScript(connection, dbType, sql); + + List> result = DBManager.getTableOrViewData(connection, dbType, "my_schema", "employees"); + Assertions.assertEquals(1, result.size()); + Assertions.assertEquals(100, result.get(0).get("age")); + Assertions.assertEquals(1, result.get(0).get("id")); + + setData.put("age", 10); + whereData = new HashMap<>(); + whereData.put("first_name", "John"); + whereData.put("last_name", "Doe"); + whereData.put("email", "john.doe@example.com"); + sql = DBDialectManager.generateUpdateSql(connection, dbType, "my_schema", "employees", setData, whereData, true); + expectSQL = "UPDATE my_schema.employees SET age = 10 WHERE last_name = N'Doe' AND first_name = N'John';"; + Assertions.assertEquals(expectSQL, sql); + DBManager.executeSQLScript(connection, dbType, sql); + + result = DBManager.getTableOrViewData(connection, dbType, "my_schema", "employees"); + Assertions.assertEquals(1, result.size()); + Assertions.assertEquals(10, result.get(0).get("age")); + Assertions.assertEquals(1, result.get(0).get("id")); + + setData.put("age", 99); + whereData = new HashMap<>(); + whereData.put("first_name", "John"); + whereData.put("email", "john.doe@example.com"); + whereData.put("age", 10); + sql = DBDialectManager.generateUpdateSql(connection, dbType, "my_schema", "employees", setData, whereData, true); + expectSQL = "UPDATE my_schema.employees SET age = 99 WHERE first_name = N'John' AND email = N'john.doe@example.com' AND age = 10;"; + Assertions.assertEquals(expectSQL, sql); + DBManager.executeSQLScript(connection, dbType, sql); + + result = DBManager.getTableOrViewData(connection, dbType, "my_schema", "employees"); + Assertions.assertEquals(1, result.size()); + Assertions.assertEquals(99, result.get(0).get("age")); + Assertions.assertEquals(1, result.get(0).get("id")); + + setData.put("age", 98); + sql = DBDialectManager.generateUpdateSql(connection, dbType, "my_schema", "employees", setData, whereData, true); + DBManager.executeSQLScript(connection, dbType, sql); + result = DBManager.getTableOrViewData(connection, dbType, "my_schema", "employees"); + Assertions.assertEquals(1, result.size()); + Assertions.assertEquals(99, result.get(0).get("age")); + + whereData = null; + sql = DBDialectManager.generateUpdateSql(connection, dbType, "my_schema", "employees", setData, whereData, true); + Assertions.assertNull(sql); + } + + @Test + void testGenerateUpdateSql1() throws SQLException { + insertData(connection, dbType); + + Map setData = new HashMap<>(); + setData.put("MyChar", "char'50'"); + setData.put("MyDatetimeoffset", "2024-10-19 10:23:54 +02:00"); + setData.put("MyVarBinary", "Masker".getBytes()); + setData.put("MyBit", 0); + setData.put("MyMoney", null); + Map whereData = new HashMap<>(); + whereData.put("MyInt", 12345); + + String sql = DBDialectManager.generateUpdateSql(connection, dbType, "my_schema", "mytable", setData, whereData, true); + DBManager.executeSQLScript(connection, dbType, sql); + + List> result = DBManager.getTableOrViewData(connection, dbType, "my_schema", "mytable"); + Assertions.assertEquals(1, result.size()); + Assertions.assertEquals(String.format("%-50s", "char'50'"), result.get(0).get("MyChar")); + Assertions.assertEquals("2024-10-19 10:23:54 +02:00", result.get(0).get("MyDatetimeoffset").toString()); + Assertions.assertEquals(false, result.get(0).get("MyBit")); + Assertions.assertArrayEquals("Masker".getBytes(), (byte[])result.get(0).get("MyVarBinary")); + Assertions.assertNull(result.get(0).get("MyMoney")); + + setData = new HashMap<>(); + setData.put("MyInt", 999); + whereData = new HashMap<>(); + whereData.put("MyInt", 12345); + whereData.put("MyChar", "char'50'"); + whereData.put("MyDatetimeoffset", "2024-10-19 10:23:54 +02:00"); + whereData.put("MyVarBinary", "Masker".getBytes()); + whereData.put("MyBit", 0); + whereData.put("MyMoney", null); + + sql = DBDialectManager.generateUpdateSql(connection, dbType, "my_schema", "mytable", setData, whereData, false); + DBManager.executeSQLScript(connection, dbType, sql); + + result = DBManager.getTableOrViewData(connection, dbType, "my_schema", "mytable"); + Assertions.assertEquals(1, result.size()); + Assertions.assertEquals(999, result.get(0).get("MyInt")); + } + + @Test + void testGenerateDeleteSql() throws SQLException, ClassNotFoundException { + createTable1(connection, dbType); + insertData1(connection, dbType); + + Map whereData = new HashMap<>(); + whereData.put("id", 1); + whereData.put("first_name", "John"); + whereData.put("last_name", "Doe"); + String sql = DBDialectManager.generateDeleteSql(connection, dbType, "my_schema", "employees", whereData, true); + String expectSQL = "DELETE FROM my_schema.employees WHERE id = 1;"; + Assertions.assertEquals(expectSQL, sql); + DBManager.executeSQLScript(connection, dbType, sql); + + List> result = DBManager.getTableOrViewData(connection, dbType, "my_schema", "employees"); + Assertions.assertEquals(0, result.size()); + + insertData1(connection, dbType); + result = DBManager.getTableOrViewData(connection, dbType, "my_schema", "employees"); + Assertions.assertEquals(1, result.size()); + + whereData = new HashMap<>(); + whereData.put("first_name", "John"); + whereData.put("last_name", "Doe"); + whereData.put("email", "john.doe@example.com"); + + sql = DBDialectManager.generateDeleteSql(connection, dbType, "my_schema", "employees", whereData, true); + expectSQL = "DELETE FROM my_schema.employees WHERE last_name = N'Doe' AND first_name = N'John';"; + Assertions.assertEquals(expectSQL, sql); + DBManager.executeSQLScript(connection, dbType, sql); + + result = DBManager.getTableOrViewData(connection, dbType, "my_schema", "employees"); + Assertions.assertEquals(0, result.size()); + + insertData1(connection, dbType); + result = DBManager.getTableOrViewData(connection, dbType, "my_schema", "employees"); + Assertions.assertEquals(1, result.size()); + + whereData = new HashMap<>(); + whereData.put("first_name", "John"); + whereData.put("email", "john.doe@example.com"); + whereData.put("age", 30); + + sql = DBDialectManager.generateDeleteSql(connection, dbType, "my_schema", "employees", whereData, true); + expectSQL = "DELETE FROM my_schema.employees WHERE first_name = N'John' AND email = N'john.doe@example.com' AND age = 30;"; + Assertions.assertEquals(expectSQL, sql); + DBManager.executeSQLScript(connection, dbType, sql); + + result = DBManager.getTableOrViewData(connection, dbType, "my_schema", "employees"); + Assertions.assertEquals(0, result.size()); + + insertData1(connection, dbType); + result = DBManager.getTableOrViewData(connection, dbType, "my_schema", "employees"); + Assertions.assertEquals(1, result.size()); + + whereData.put("age", 31); + sql = DBDialectManager.generateDeleteSql(connection, dbType, "my_schema", "employees", whereData, true); + DBManager.executeSQLScript(connection, dbType, sql); + result = DBManager.getTableOrViewData(connection, dbType, "my_schema", "employees"); + Assertions.assertEquals(1, result.size()); + + whereData = null; + sql = DBDialectManager.generateDeleteSql(connection, dbType, "my_schema", "employees", whereData, true); + Assertions.assertNull(sql); + + insertData(connection, dbType); + + whereData = new HashMap<>(); + whereData.put("MyInt", 12345); + whereData.put("MyChar", "abc"); + whereData.put("MyDatetimeoffset", "2023-01-01 00:00:00 +00:00"); + byte[] byteArray = new byte[] {(byte) 0x01, (byte) 0x23, (byte) 0x45, (byte) 0x67, (byte) 0x89, (byte) 0xAB, (byte) 0xCD, (byte) 0xEF}; + whereData.put("MyVarBinary", byteArray); + whereData.put("MyBit", 1); + whereData.put("MyMoney", 123.45); + sql = DBDialectManager.generateDeleteSql(connection, dbType, "my_schema", "mytable", whereData, false); + DBManager.executeSQLScript(connection, dbType, sql); + + result = DBManager.getTableOrViewData(connection, dbType, "my_schema", "mytable"); + Assertions.assertEquals(0, result.size()); + } + } diff --git a/src/test/java/com/dbmasker/database/mysql/MysqlAPITests.java b/src/test/java/com/dbmasker/database/mysql/MysqlAPITests.java index 1e584f6..d8fc41a 100644 --- a/src/test/java/com/dbmasker/database/mysql/MysqlAPITests.java +++ b/src/test/java/com/dbmasker/database/mysql/MysqlAPITests.java @@ -290,10 +290,10 @@ void testGetTableAttribute() throws SQLException, ClassNotFoundException { void testGetPrimaryKeys() throws SQLException, ClassNotFoundException { createTable(connection, dbType); - List tablePrimaryKeys = DBManager.getPrimaryKeys(connection, dbType, "db_mysql_test", "employees"); + Set tablePrimaryKeys = DBManager.getPrimaryKeys(connection, dbType, "db_mysql_test", "employees"); Assertions.assertEquals(1, tablePrimaryKeys.size()); - List expectPrimaryKeys = new ArrayList<>(); + Set expectPrimaryKeys = new HashSet<>(); expectPrimaryKeys.add("id"); Assertions.assertEquals(expectPrimaryKeys, tablePrimaryKeys); diff --git a/src/test/java/com/dbmasker/database/mysql/MysqlDialectAPITests.java b/src/test/java/com/dbmasker/database/mysql/MysqlDialectAPITests.java index 873b7b6..c367223 100644 --- a/src/test/java/com/dbmasker/database/mysql/MysqlDialectAPITests.java +++ b/src/test/java/com/dbmasker/database/mysql/MysqlDialectAPITests.java @@ -11,6 +11,8 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.mariadb.jdbc.MariaDbBlob; +import org.sqlite.core.DB; import java.io.InputStream; import java.math.BigDecimal; @@ -67,6 +69,20 @@ myset SET('option1', 'option2', 'option3') DBManager.executeUpdateSQL(connection, dbType, sql); } + public void createTable1(Connection connection, String dbType) throws SQLException { + String sql = """ + CREATE TABLE employees ( + id INT PRIMARY KEY, + first_name VARCHAR(255) NOT NULL, + last_name VARCHAR(255) NOT NULL, + email VARCHAR(255) NOT NULL, + age INT, + UNIQUE(last_name, first_name) + ); + """; + DBManager.executeUpdateSQL(connection, dbType, sql); + } + public void insertData(Connection connection, String dbType) throws SQLException { String sql = """ INSERT INTO mytable ( @@ -110,6 +126,13 @@ INSERT INTO mytable ( DBManager.executeUpdateSQL(connection, dbType, sql); } + public void insertData1(Connection connection, String dbType) throws SQLException { + String sql = """ + INSERT INTO employees (id, first_name, last_name, email, age) + VALUES (1, 'John', 'Doe', 'john.doe@example.com', 30); + """; + DBManager.executeUpdateSQL(connection, dbType, sql); + } public void initConfig() { Properties properties = new Properties(); @@ -135,6 +158,10 @@ public void tearDown() throws SQLException { DROP TABLE IF EXISTS mytable; """; DBManager.executeUpdateSQL(connection, dbType, sql); + sql = """ + DROP TABLE IF EXISTS employees; + """; + DBManager.executeUpdateSQL(connection, dbType, sql); DBManager.closeConnection(connection); Config.getInstance().setDataSize(DBSecManager.MATCH_DATA_SIZE); @@ -254,4 +281,199 @@ void testGenerateInsertSql() throws SQLException { Assertions.assertNull(result.get(3).get("myint")); Assertions.assertNull(result.get(3).get("myyear")); } + + @Test + void testGenerateUpdateSql() throws SQLException { + createTable1(connection, dbType); + insertData1(connection, dbType); + + Map setData = new HashMap<>(); + setData.put("age", 100); + Map whereData = new HashMap<>(); + whereData.put("id", 1); + whereData.put("first_name", "John"); + whereData.put("last_name", "Doe"); + String sql = DBDialectManager.generateUpdateSql(connection, dbType, "db_mysql_test", "employees", setData, whereData, true); + String expectSQL = "UPDATE db_mysql_test.employees SET age = 100 WHERE id = 1;"; + Assertions.assertEquals(expectSQL, sql); + DBManager.executeSQLScript(connection, dbType, sql); + + List> result = DBManager.getTableOrViewData(connection, dbType, "db_mysql_test", "employees"); + Assertions.assertEquals(1, result.size()); + Assertions.assertEquals(100, result.get(0).get("age")); + Assertions.assertEquals(1, result.get(0).get("id")); + + setData.put("age", 10); + whereData = new HashMap<>(); + whereData.put("first_name", "John"); + whereData.put("last_name", "Doe"); + whereData.put("email", "john.doe@example.com"); + sql = DBDialectManager.generateUpdateSql(connection, dbType, "db_mysql_test", "employees", setData, whereData, true); + expectSQL = "UPDATE db_mysql_test.employees SET age = 10 WHERE last_name = 'Doe' AND first_name = 'John';"; + Assertions.assertEquals(expectSQL, sql); + DBManager.executeSQLScript(connection, dbType, sql); + + result = DBManager.getTableOrViewData(connection, dbType, "db_mysql_test", "employees"); + Assertions.assertEquals(1, result.size()); + Assertions.assertEquals(10, result.get(0).get("age")); + Assertions.assertEquals(1, result.get(0).get("id")); + + setData.put("age", 99); + whereData = new HashMap<>(); + whereData.put("first_name", "John"); + whereData.put("email", "john.doe@example.com"); + whereData.put("age", 10); + sql = DBDialectManager.generateUpdateSql(connection, dbType, "db_mysql_test", "employees", setData, whereData, true); + expectSQL = "UPDATE db_mysql_test.employees SET age = 99 WHERE first_name = 'John' AND email = 'john.doe@example.com' AND age = 10;"; + Assertions.assertEquals(expectSQL, sql); + DBManager.executeSQLScript(connection, dbType, sql); + + result = DBManager.getTableOrViewData(connection, dbType, "db_mysql_test", "employees"); + Assertions.assertEquals(1, result.size()); + Assertions.assertEquals(99, result.get(0).get("age")); + Assertions.assertEquals(1, result.get(0).get("id")); + + setData.put("age", 98); + sql = DBDialectManager.generateUpdateSql(connection, dbType, "db_mysql_test", "employees", setData, whereData, true); + DBManager.executeSQLScript(connection, dbType, sql); + result = DBManager.getTableOrViewData(connection, dbType, "db_mysql_test", "employees"); + Assertions.assertEquals(1, result.size()); + Assertions.assertEquals(99, result.get(0).get("age")); + + whereData = null; + sql = DBDialectManager.generateUpdateSql(connection, dbType, "db_mysql_test", "employees", setData, whereData, true); + Assertions.assertNull(sql); + } + + @Test + void testGenerateUpdateSql1() throws SQLException { + createTable(connection, dbType); + insertData(connection, dbType); + + Map setData = new HashMap<>(); + setData.put("myint", null); + setData.put("myyear", 2024); + setData.put("mychar", "char'51'"); + setData.put("mytinyblob", "tinyblob1".getBytes()); + setData.put("mytimestamp", "2024-01-01 00:00:00"); + setData.put("myfloat", 1.1); + setData.put("myenum", "option2"); + + Map whereData = new HashMap<>(); + whereData.put("mytinyint", 1); + + String sql = DBDialectManager.generateUpdateSql(connection, dbType, "db_mysql_test", "mytable", setData, whereData, true); + DBManager.executeSQLScript(connection, dbType, sql); + + List> result = DBManager.getTableOrViewData(connection, dbType, "db_mysql_test", "mytable"); + Assertions.assertEquals(1, result.size()); + Assertions.assertNull(result.get(0).get("myint")); + Assertions.assertEquals(2024, result.get(0).get("myyear")); + Assertions.assertEquals("char'51'", result.get(0).get("mychar")); + Assertions.assertArrayEquals("tinyblob1".getBytes(), (byte[])result.get(0).get("mytinyblob")); + + Assertions.assertEquals("2024-01-01 00:00:00.0", result.get(0).get("mytimestamp").toString()); + Assertions.assertEquals("1.1", result.get(0).get("myfloat").toString()); + Assertions.assertEquals("option2", result.get(0).get("myenum")); + + setData = new HashMap<>(); + setData.put("myint", 999); + whereData = new HashMap<>(); + whereData.put("myint", null); + whereData.put("myyear", 2024); + whereData.put("mychar", "char'51'"); + whereData.put("mytinyblob", "tinyblob1".getBytes()); + whereData.put("mytimestamp", "2024-01-01 00:00:00"); + whereData.put("myenum", "option2"); + sql = DBDialectManager.generateUpdateSql(connection, dbType, "db_mysql_test", "mytable", setData, whereData, false); + DBManager.executeSQLScript(connection, dbType, sql); + + result = DBManager.getTableOrViewData(connection, dbType, "db_mysql_test", "mytable"); + Assertions.assertEquals(1, result.size()); + Assertions.assertEquals(999, result.get(0).get("myint")); + } + + @Test + void testGenerateDeleteSql() throws SQLException, ClassNotFoundException { + createTable1(connection, dbType); + insertData1(connection, dbType); + + Map whereData = new HashMap<>(); + whereData.put("id", 1); + whereData.put("first_name", "John"); + whereData.put("last_name", "Doe"); + String sql = DBDialectManager.generateDeleteSql(connection, dbType, "db_mysql_test", "employees", whereData, true); + String expectSQL = "DELETE FROM db_mysql_test.employees WHERE id = 1;"; + Assertions.assertEquals(expectSQL, sql); + DBManager.executeSQLScript(connection, dbType, sql); + + List> result = DBManager.getTableOrViewData(connection, dbType, "db_mysql_test", "employees"); + Assertions.assertEquals(0, result.size()); + + insertData1(connection, dbType); + result = DBManager.getTableOrViewData(connection, dbType, "db_mysql_test", "employees"); + Assertions.assertEquals(1, result.size()); + + whereData = new HashMap<>(); + whereData.put("first_name", "John"); + whereData.put("last_name", "Doe"); + whereData.put("email", "john.doe@example.com"); + + sql = DBDialectManager.generateDeleteSql(connection, dbType, "db_mysql_test", "employees", whereData, true); + expectSQL = "DELETE FROM db_mysql_test.employees WHERE last_name = 'Doe' AND first_name = 'John';"; + Assertions.assertEquals(expectSQL, sql); + DBManager.executeSQLScript(connection, dbType, sql); + + result = DBManager.getTableOrViewData(connection, dbType, "db_mysql_test", "employees"); + Assertions.assertEquals(0, result.size()); + + insertData1(connection, dbType); + result = DBManager.getTableOrViewData(connection, dbType, "db_mysql_test", "employees"); + Assertions.assertEquals(1, result.size()); + + whereData = new HashMap<>(); + whereData.put("first_name", "John"); + whereData.put("email", "john.doe@example.com"); + whereData.put("age", 30); + + sql = DBDialectManager.generateDeleteSql(connection, dbType, "db_mysql_test", "employees", whereData, true); + expectSQL = "DELETE FROM db_mysql_test.employees WHERE first_name = 'John' AND email = 'john.doe@example.com' AND age = 30;"; + Assertions.assertEquals(expectSQL, sql); + DBManager.executeSQLScript(connection, dbType, sql); + + result = DBManager.getTableOrViewData(connection, dbType, "db_mysql_test", "employees"); + Assertions.assertEquals(0, result.size()); + + insertData1(connection, dbType); + result = DBManager.getTableOrViewData(connection, dbType, "db_mysql_test", "employees"); + Assertions.assertEquals(1, result.size()); + + whereData.put("age", 31); + sql = DBDialectManager.generateDeleteSql(connection, dbType, "db_mysql_test", "employees", whereData, true); + DBManager.executeSQLScript(connection, dbType, sql); + result = DBManager.getTableOrViewData(connection, dbType, "db_mysql_test", "employees"); + Assertions.assertEquals(1, result.size()); + + whereData = null; + sql = DBDialectManager.generateDeleteSql(connection, dbType, "db_mysql_test", "employees", whereData, true); + Assertions.assertNull(sql); + + tearDown(); + setUp(); + createTable(connection, dbType); + insertData(connection, dbType); + + whereData = new HashMap<>(); + whereData.put("myint", 1000); + whereData.put("myyear", 2023); + whereData.put("mychar", "char"); + whereData.put("mytinyblob", "tinyblob".getBytes()); + whereData.put("mydatetime", "2023-07-24 14:00:00"); + whereData.put("myenum", "option1"); + sql = DBDialectManager.generateDeleteSql(connection, dbType, "db_mysql_test", "mytable", whereData, false); + DBManager.executeSQLScript(connection, dbType, sql); + + result = DBManager.getTableOrViewData(connection, dbType, "db_mysql_test", "mytable"); + Assertions.assertEquals(0, result.size()); + } } diff --git a/src/test/java/com/dbmasker/database/oracle/OracleAPITests.java b/src/test/java/com/dbmasker/database/oracle/OracleAPITests.java index 8ded2fd..2dc50d0 100644 --- a/src/test/java/com/dbmasker/database/oracle/OracleAPITests.java +++ b/src/test/java/com/dbmasker/database/oracle/OracleAPITests.java @@ -339,10 +339,10 @@ void testGetTableAttribute() throws SQLException, ClassNotFoundException { void testGetPrimaryKeys() throws SQLException, ClassNotFoundException { createTable1(connection, dbType); - List tablePrimaryKeys = DBManager.getPrimaryKeys(connection, dbType, "M", "EMPLOYEES"); + Set tablePrimaryKeys = DBManager.getPrimaryKeys(connection, dbType, "M", "EMPLOYEES"); Assertions.assertEquals(1, tablePrimaryKeys.size()); - List expectPrimaryKeys = new ArrayList<>(); + Set expectPrimaryKeys = new HashSet<>(); expectPrimaryKeys.add("ID"); Assertions.assertEquals(expectPrimaryKeys, tablePrimaryKeys); diff --git a/src/test/java/com/dbmasker/database/oracle/OracleDialectAPITests.java b/src/test/java/com/dbmasker/database/oracle/OracleDialectAPITests.java index 59deb80..8665de3 100644 --- a/src/test/java/com/dbmasker/database/oracle/OracleDialectAPITests.java +++ b/src/test/java/com/dbmasker/database/oracle/OracleDialectAPITests.java @@ -70,6 +70,51 @@ MyUrowid VARCHAR2(200), DBManager.executeUpdateSQL(connection, dbType, sql); } + public void createTable1(Connection connection, String dbType) throws SQLException { + String sql = """ + CREATE TABLE MyTable ( + MyNumber NUMBER, + MyFloat FLOAT, + MyInteger INTEGER, + MySmallint SMALLINT, + MyReal REAL, + MyDoublePrecision DOUBLE PRECISION, + MyDecimal DECIMAL(8, 2), + MyChar CHAR(50), + MyVarchar2 VARCHAR2(50), + MyLong LONG, + MyClob CLOB, + MyRaw RAW(2000), + MyBlob BLOB, + MyBFile BFILE, + MyRowid ROWID, + MyUrowid VARCHAR2(200), + MyXml XMLType, + MyDate DATE, + MyTimestamp TIMESTAMP, + MyIntervalYearToMonth INTERVAL YEAR TO MONTH, + MyIntervalDayToSecond INTERVAL DAY TO SECOND, + PRIMARY KEY (MyInteger) + ) + """; + DBManager.executeUpdateSQL(connection, dbType, sql); + } + + public void createTable2(Connection connection, String dbType) throws SQLException { + String sql = """ + CREATE TABLE EMPLOYEES ( + id INT NOT NULL, + first_name VARCHAR2(255) NOT NULL, + last_name VARCHAR2(255) NOT NULL, + email VARCHAR2(255) NOT NULL, + age INT, + PRIMARY KEY (id), + UNIQUE (first_name, last_name) + ) + """; + DBManager.executeUpdateSQL(connection, dbType, sql); + } + public void insertData(Connection connection, String dbType) throws SQLException { String sql = """ INSERT INTO MyTable ( @@ -104,6 +149,14 @@ INSERT INTO MyTable ( DBManager.executeUpdateSQL(connection, dbType, sql); } + public void insertData2(Connection connection, String dbType) throws SQLException { + String sql = """ + INSERT INTO EMPLOYEES (id, first_name, last_name, email, age) + VALUES (1, 'John', 'Doe', 'john.doe@example.com', 30) + """; + DBManager.executeUpdateSQL(connection, dbType, sql); + } + public void initConfig() { Properties properties = new Properties(); try (InputStream in = this.getClass().getClassLoader().getResourceAsStream("conf/oracle.properties")) { @@ -136,6 +189,18 @@ public void tearDown() throws SQLException { """; DBManager.executeUpdateSQL(connection, dbType, sql); + sql = """ + BEGIN + EXECUTE IMMEDIATE 'DROP TABLE EMPLOYEES'; + EXCEPTION + WHEN OTHERS THEN + IF SQLCODE != -942 THEN + RAISE; + END IF; + END; + """; + DBManager.executeUpdateSQL(connection, dbType, sql); + DBManager.closeConnection(connection); Config.getInstance().setDataSize(DBSecManager.MATCH_DATA_SIZE); } @@ -252,4 +317,218 @@ void testGenerateInsertSql() throws SQLException, IOException { Assertions.assertNull(result.get(3).get("MYINTEGER")); Assertions.assertNull(result.get(3).get("MYINTERVALYEARTOMONTH")); } + + @Test + void testGenerateUpdateSql() throws SQLException { + createTable2(connection, dbType); + insertData2(connection, dbType); + + Map setData = new HashMap<>(); + setData.put("age", 100); + Map whereData = new HashMap<>(); + whereData.put("id", 1); + whereData.put("first_name", "John"); + whereData.put("last_name", "Doe"); + String sql = DBDialectManager.generateUpdateSql(connection, dbType, "M", "EMPLOYEES", setData, whereData, true); + String expectSQL = "UPDATE M.EMPLOYEES SET age = 100 WHERE id = 1;"; + Assertions.assertEquals(expectSQL, sql); + DBManager.executeSQLScript(connection, dbType, sql); + + List> result = DBManager.getTableOrViewData(connection, dbType, "M", "EMPLOYEES"); + Assertions.assertEquals(1, result.size()); + Assertions.assertEquals(new BigDecimal("100"), result.get(0).get("AGE")); + Assertions.assertEquals(new BigDecimal(1), result.get(0).get("ID")); + + setData.put("age", 10); + whereData = new HashMap<>(); + whereData.put("first_name", "John"); + whereData.put("last_name", "Doe"); + whereData.put("email", "john.doe@example.com"); + sql = DBDialectManager.generateUpdateSql(connection, dbType, "M", "EMPLOYEES", setData, whereData, true); + expectSQL = "UPDATE M.EMPLOYEES SET age = 10 WHERE last_name = 'Doe' AND first_name = 'John';"; + Assertions.assertEquals(expectSQL, sql); + DBManager.executeSQLScript(connection, dbType, sql); + + result = DBManager.getTableOrViewData(connection, dbType, "M", "EMPLOYEES"); + Assertions.assertEquals(1, result.size()); + Assertions.assertEquals(new BigDecimal(10), result.get(0).get("AGE")); + Assertions.assertEquals(new BigDecimal(1), result.get(0).get("ID")); + + setData.put("age", 99); + whereData = new HashMap<>(); + whereData.put("first_name", "John"); + whereData.put("email", "john.doe@example.com"); + whereData.put("age", 10); + sql = DBDialectManager.generateUpdateSql(connection, dbType, "M", "EMPLOYEES", setData, whereData, true); + expectSQL = "UPDATE M.EMPLOYEES SET age = 99 WHERE first_name = 'John' AND email = 'john.doe@example.com' AND age = 10;"; + Assertions.assertEquals(expectSQL, sql); + DBManager.executeSQLScript(connection, dbType, sql); + + result = DBManager.getTableOrViewData(connection, dbType, "M", "EMPLOYEES"); + Assertions.assertEquals(1, result.size()); + Assertions.assertEquals(new BigDecimal(99), result.get(0).get("AGE")); + Assertions.assertEquals(new BigDecimal(1), result.get(0).get("ID")); + + setData.put("age", 98); + sql = DBDialectManager.generateUpdateSql(connection, dbType, "M", "EMPLOYEES", setData, whereData, true); + DBManager.executeSQLScript(connection, dbType, sql); + result = DBManager.getTableOrViewData(connection, dbType, "M", "EMPLOYEES"); + Assertions.assertEquals(1, result.size()); + Assertions.assertEquals(new BigDecimal(99), result.get(0).get("AGE")); + + whereData = null; + sql = DBDialectManager.generateUpdateSql(connection, dbType, "M", "EMPLOYEES", setData, whereData, true); + Assertions.assertNull(sql); + } + + @Test + void testGenerateUpdateSql1() throws SQLException, IOException { + createTable1(connection, dbType); + insertData(connection, dbType); + + Map setData = new HashMap<>(); + setData.put("MyDecimal", 321.32); + setData.put("MyChar", "char'50'"); + setData.put("MyBlob", "Masker".getBytes()); + setData.put("MyClob", "This is a big CLOB"); + setData.put("MyDate", "2023-01-01"); + setData.put("MyTimestamp", "2023-08-07 00:00:00"); + setData.put("MyIntervalYearToMonth", "2-6"); + setData.put("MyIntervalDayToSecond", "2 11:00:15"); + setData.put("MyXml", "XMLType_123"); + setData.put("MyReal", null); + + Map whereData = new HashMap<>(); + whereData.put("MyInteger", 123); + whereData.put("MyFloat", 1.11); + + String sql = DBDialectManager.generateUpdateSql(connection, dbType, "M", "MYTABLE", setData, whereData, true); + DBManager.executeSQLScript(connection, dbType, sql); + + List> result = DBManager.getTableOrViewData(connection, dbType, "M", "MYTABLE"); + Assertions.assertEquals(1, result.size()); + Assertions.assertEquals(new BigDecimal("321.32"), result.get(0).get("MYDECIMAL")); + Assertions.assertEquals(String.format("%-50s", "char'50'"), result.get(0).get("MYCHAR")); + Assertions.assertEquals("2023-01-01 00:00:00.0", result.get(0).get("MYDATE").toString()); + Assertions.assertEquals("2023-08-07 00:00:00.0", result.get(0).get("MYTIMESTAMP").toString()); + Assertions.assertEquals("2-6", result.get(0).get("MYINTERVALYEARTOMONTH").toString()); + Assertions.assertEquals("2 11:0:15.0", result.get(0).get("MYINTERVALDAYTOSECOND").toString()); + Assertions.assertEquals("XMLType_123", ((XMLType) result.get(0).get("MYXML")).getString()); + + Blob blob = (Blob)result.get(0).get("MYBLOB"); + InputStream is = blob.getBinaryStream(); + byte[] bytes = is.readAllBytes(); + Assertions.assertArrayEquals("Masker".getBytes(), bytes); + + Clob clob = (Clob)result.get(0).get("MYCLOB"); + Reader reader = clob.getCharacterStream(); + BufferedReader br = new BufferedReader(reader); + Assertions.assertEquals("This is a big CLOB", br.readLine()); + + setData = new HashMap<>(); + setData.put("MyDecimal", 999.99); + whereData = new HashMap<>(); + whereData.put("MyInteger", 123); + whereData.put("MyDecimal", 321.32); + whereData.put("MyChar", "char'50'"); + whereData.put("MyDate", "2023-01-01"); + whereData.put("MyTimestamp", "2023-08-07 00:00:00"); + whereData.put("MyIntervalYearToMonth", "2-6"); + whereData.put("MyIntervalDayToSecond", "2 11:00:15"); + whereData.put("MyReal", null); + + sql = DBDialectManager.generateUpdateSql(connection, dbType, "M", "MYTABLE", setData, whereData, false); + DBManager.executeSQLScript(connection, dbType, sql); + + result = DBManager.getTableOrViewData(connection, dbType, "M", "MYTABLE"); + Assertions.assertEquals(1, result.size()); + Assertions.assertEquals(new BigDecimal("999.99"), result.get(0).get("MYDECIMAL")); + } + + @Test + void testGenerateDeleteSql() throws SQLException, ClassNotFoundException { + createTable2(connection, dbType); + insertData2(connection, dbType); + + Map whereData = new HashMap<>(); + whereData.put("id", 1); + whereData.put("first_name", "John"); + whereData.put("last_name", "Doe"); + String sql = DBDialectManager.generateDeleteSql(connection, dbType, "M", "EMPLOYEES", whereData, true); + String expectSQL = "DELETE FROM M.EMPLOYEES WHERE id = 1;"; + Assertions.assertEquals(expectSQL, sql); + DBManager.executeSQLScript(connection, dbType, sql); + + List> result = DBManager.getTableOrViewData(connection, dbType, "M", "EMPLOYEES"); + Assertions.assertEquals(0, result.size()); + + insertData2(connection, dbType); + result = DBManager.getTableOrViewData(connection, dbType, "M", "EMPLOYEES"); + Assertions.assertEquals(1, result.size()); + + whereData = new HashMap<>(); + whereData.put("first_name", "John"); + whereData.put("last_name", "Doe"); + whereData.put("email", "john.doe@example.com"); + + sql = DBDialectManager.generateDeleteSql(connection, dbType, "M", "EMPLOYEES", whereData, true); + expectSQL = "DELETE FROM M.EMPLOYEES WHERE last_name = 'Doe' AND first_name = 'John';"; + Assertions.assertEquals(expectSQL, sql); + DBManager.executeSQLScript(connection, dbType, sql); + + result = DBManager.getTableOrViewData(connection, dbType, "M", "EMPLOYEES"); + Assertions.assertEquals(0, result.size()); + + insertData2(connection, dbType); + result = DBManager.getTableOrViewData(connection, dbType, "M", "EMPLOYEES"); + Assertions.assertEquals(1, result.size()); + + whereData = new HashMap<>(); + whereData.put("first_name", "John"); + whereData.put("email", "john.doe@example.com"); + whereData.put("age", 30); + + sql = DBDialectManager.generateDeleteSql(connection, dbType, "M", "EMPLOYEES", whereData, true); + expectSQL = "DELETE FROM M.EMPLOYEES WHERE first_name = 'John' AND email = 'john.doe@example.com' AND age = 30;"; + Assertions.assertEquals(expectSQL, sql); + DBManager.executeSQLScript(connection, dbType, sql); + + result = DBManager.getTableOrViewData(connection, dbType, "M", "EMPLOYEES"); + Assertions.assertEquals(0, result.size()); + + insertData2(connection, dbType); + result = DBManager.getTableOrViewData(connection, dbType, "M", "EMPLOYEES"); + Assertions.assertEquals(1, result.size()); + + whereData.put("age", 31); + sql = DBDialectManager.generateDeleteSql(connection, dbType, "M", "EMPLOYEES", whereData, true); + DBManager.executeSQLScript(connection, dbType, sql); + result = DBManager.getTableOrViewData(connection, dbType, "M", "EMPLOYEES"); + Assertions.assertEquals(1, result.size()); + + whereData = null; + sql = DBDialectManager.generateDeleteSql(connection, dbType, "M", "EMPLOYEES", whereData, true); + Assertions.assertNull(sql); + + tearDown(); + setUp(); + createTable1(connection, dbType); + insertData(connection, dbType); + + whereData = new HashMap<>(); + whereData.put("MyInteger", 123); + whereData.put("MyDecimal", 123.45); + whereData.put("MyChar", "CHAR"); + whereData.put("MyDate", "2023-07-07"); + whereData.put("MyTimestamp", "2023-07-07 00:00:00"); + whereData.put("MyIntervalYearToMonth", "2-5"); + whereData.put("MyIntervalDayToSecond", "2 12:30:15"); + whereData.put("MyReal", 123.45); + + sql = DBDialectManager.generateDeleteSql(connection, dbType, "M", "MYTABLE", whereData, false); + DBManager.executeSQLScript(connection, dbType, sql); + + result = DBManager.getTableOrViewData(connection, dbType, "M", "MYTABLE"); + Assertions.assertEquals(0, result.size()); + } } diff --git a/src/test/java/com/dbmasker/database/postgresql/PostgreSQLAPITests.java b/src/test/java/com/dbmasker/database/postgresql/PostgreSQLAPITests.java index baa34be..5a0a981 100644 --- a/src/test/java/com/dbmasker/database/postgresql/PostgreSQLAPITests.java +++ b/src/test/java/com/dbmasker/database/postgresql/PostgreSQLAPITests.java @@ -324,10 +324,10 @@ void testGetTableAttribute() throws SQLException { void testGetPrimaryKeys() throws SQLException, ClassNotFoundException { createSchema(connection, dbType); - List tablePrimaryKeys = DBManager.getPrimaryKeys(connection, dbType, "my_schema", "employees"); + Set tablePrimaryKeys = DBManager.getPrimaryKeys(connection, dbType, "my_schema", "employees"); Assertions.assertEquals(1, tablePrimaryKeys.size()); - List expectPrimaryKeys = new ArrayList<>(); + Set expectPrimaryKeys = new HashSet<>(); expectPrimaryKeys.add("id"); Assertions.assertEquals(expectPrimaryKeys, tablePrimaryKeys); diff --git a/src/test/java/com/dbmasker/database/postgresql/PostgreSQLDialectAPITests.java b/src/test/java/com/dbmasker/database/postgresql/PostgreSQLDialectAPITests.java index cfa0cd3..cdc08fc 100644 --- a/src/test/java/com/dbmasker/database/postgresql/PostgreSQLDialectAPITests.java +++ b/src/test/java/com/dbmasker/database/postgresql/PostgreSQLDialectAPITests.java @@ -58,6 +58,54 @@ MyVarchar VARCHAR(50), DBManager.executeUpdateSQL(connection, dbType, sql); } + public void createSchema2(Connection connection, String dbType) throws SQLException { + String sql = """ + CREATE SCHEMA my_schema; + CREATE SEQUENCE my_schema.employees_id_seq; + + CREATE TABLE my_schema.employees ( + id INTEGER PRIMARY KEY, + first_name VARCHAR(255) NOT NULL, + last_name VARCHAR(255) NOT NULL, + email VARCHAR(255) NOT NULL, + age INTEGER, + UNIQUE(last_name, first_name) + ); + """; + DBManager.executeUpdateSQL(connection, dbType, sql); + } + + public void createSchema3(Connection connection, String dbType) throws SQLException { + String sql = """ + CREATE SCHEMA my_schema; + CREATE TABLE my_schema.MyTable ( + MyBoolean BOOLEAN, + MyInteger INTEGER PRIMARY KEY, + MyInt INT, + MyBigInt BIGINT, + MySmallInt SMALLINT, + MyChar CHAR(50), + MyVarchar VARCHAR(50), + MyText TEXT, + MyReal REAL, + MyBytea BYTEA, + MyDoublePrecision DOUBLE PRECISION, + MyDecimal DECIMAL, + MyNumeric NUMERIC, + MyTimeWithoutTimeZone TIME WITHOUT TIME ZONE, + MyTimeWithTimeZone TIME WITH TIME ZONE, + MyTimestampWithoutTimeZone TIMESTAMP WITHOUT TIME ZONE, + MyTimestampWithTimeZone TIMESTAMP WITH TIME ZONE, + MySerial SERIAL, + MySmallSerial SMALLSERIAL, + MyBigSerial BIGSERIAL, + MyInterval INTERVAL, + MyIntervalYear INTERVAL YEAR + ); + """; + DBManager.executeUpdateSQL(connection, dbType, sql); + } + public void insertData(Connection connection, String dbType) throws SQLException { String sql = """ INSERT INTO my_schema.MyTable ( @@ -111,6 +159,14 @@ public void insertData(Connection connection, String dbType) throws SQLException DBManager.executeUpdateSQL(connection, dbType, sql); } + public void insertData2(Connection connection, String dbType) throws SQLException { + String sql = """ + INSERT INTO my_schema.employees (id, first_name, last_name, email, age) + VALUES (1, 'John', 'Doe', 'john.doe@example.com', 30); + """; + DBManager.executeUpdateSQL(connection, dbType, sql); + } + public void initConfig() { Properties properties = new Properties(); try (InputStream in = this.getClass().getClassLoader().getResourceAsStream("conf/postgreSQL.properties")) { @@ -220,4 +276,191 @@ void testGenerateInsertSql() throws SQLException { Assertions.assertNull(result.get(3).get("myinteger")); Assertions.assertNull(result.get(3).get("myintervalyear")); } + + @Test + void testGenerateUpdateSql() throws SQLException { + createSchema2(connection, dbType); + insertData2(connection, dbType); + + Map setData = new HashMap<>(); + setData.put("age", 100); + Map whereData = new HashMap<>(); + whereData.put("id", 1); + whereData.put("first_name", "John"); + whereData.put("last_name", "Doe"); + String sql = DBDialectManager.generateUpdateSql(connection, dbType, "my_schema", "employees", setData, whereData, true); + String expectSQL = "UPDATE my_schema.employees SET age = 100 WHERE id = 1;"; + Assertions.assertEquals(expectSQL, sql); + DBManager.executeSQLScript(connection, dbType, sql); + + List> result = DBManager.getTableOrViewData(connection, dbType, "my_schema", "employees"); + Assertions.assertEquals(1, result.size()); + Assertions.assertEquals(100, result.get(0).get("age")); + Assertions.assertEquals(1, result.get(0).get("id")); + + setData.put("age", 10); + whereData = new HashMap<>(); + whereData.put("first_name", "John"); + whereData.put("last_name", "Doe"); + whereData.put("email", "john.doe@example.com"); + sql = DBDialectManager.generateUpdateSql(connection, dbType, "my_schema", "employees", setData, whereData, true); + expectSQL = "UPDATE my_schema.employees SET age = 10 WHERE last_name = 'Doe' AND first_name = 'John';"; + Assertions.assertEquals(expectSQL, sql); + DBManager.executeSQLScript(connection, dbType, sql); + + result = DBManager.getTableOrViewData(connection, dbType, "my_schema", "employees"); + Assertions.assertEquals(1, result.size()); + Assertions.assertEquals(10, result.get(0).get("age")); + Assertions.assertEquals(1, result.get(0).get("id")); + + setData.put("age", 99); + whereData = new HashMap<>(); + whereData.put("first_name", "John"); + whereData.put("email", "john.doe@example.com"); + whereData.put("age", 10); + sql = DBDialectManager.generateUpdateSql(connection, dbType, "my_schema", "employees", setData, whereData, true); + expectSQL = "UPDATE my_schema.employees SET age = 99 WHERE first_name = 'John' AND email = 'john.doe@example.com' AND age = 10;"; + Assertions.assertEquals(expectSQL, sql); + DBManager.executeSQLScript(connection, dbType, sql); + + result = DBManager.getTableOrViewData(connection, dbType, "my_schema", "employees"); + Assertions.assertEquals(1, result.size()); + Assertions.assertEquals(99, result.get(0).get("age")); + Assertions.assertEquals(1, result.get(0).get("id")); + + setData.put("age", 98); + sql = DBDialectManager.generateUpdateSql(connection, dbType, "my_schema", "employees", setData, whereData, true); + DBManager.executeSQLScript(connection, dbType, sql); + result = DBManager.getTableOrViewData(connection, dbType, "my_schema", "employees"); + Assertions.assertEquals(1, result.size()); + Assertions.assertEquals(99, result.get(0).get("age")); + + whereData = null; + sql = DBDialectManager.generateUpdateSql(connection, dbType, "my_schema", "employees", setData, whereData, true); + Assertions.assertNull(sql); + } + + @Test + void testGenerateUpdateSql1() throws SQLException { + createSchema3(connection, dbType); + insertData(connection, dbType); + + Map setData = new HashMap<>(); + setData.put("MyBoolean", false); + setData.put("MyChar", "new char"); + setData.put("MyTimestampWithoutTimeZone", "2023-7-19 10:23:54"); + setData.put("MyBytea", "Masker".getBytes()); + setData.put("MyInt", null); + Map whereData = new HashMap<>(); + whereData.put("MyInteger", 10); + whereData.put("MyIntervalYear", "1 year"); + + String sql = DBDialectManager.generateUpdateSql(connection, dbType, "my_schema", "mytable", setData, whereData, true); + DBManager.executeSQLScript(connection, dbType, sql); + + List> result = DBManager.getTableOrViewData(connection, dbType, "my_schema", "mytable"); + Assertions.assertEquals(1, result.size()); + Assertions.assertEquals(String.format("%-50s", "new char"), result.get(0).get("mychar")); + Assertions.assertEquals(false, result.get(0).get("myboolean")); + Assertions.assertEquals("2023-07-19 10:23:54.0", result.get(0).get("mytimestampwithouttimezone").toString()); + Assertions.assertEquals("Masker", new String((byte[]) result.get(0).get("mybytea"))); + + setData = new HashMap<>(); + setData.put("MyInteger", 1); + whereData.put("MyBoolean", false); + whereData.put("MyChar", "new char"); + whereData.put("MyTimestampWithoutTimeZone", "2023-7-19 10:23:54"); + whereData.put("MyBytea", "Masker".getBytes()); + whereData.put("MyInt", null); + sql = DBDialectManager.generateUpdateSql(connection, dbType, "my_schema", "mytable", setData, whereData, false); + DBManager.executeSQLScript(connection, dbType, sql); + + result = DBManager.getTableOrViewData(connection, dbType, "my_schema", "mytable"); + Assertions.assertEquals(1, result.size()); + Assertions.assertEquals(1, result.get(0).get("myinteger")); + } + + @Test + void testGenerateDeleteSql() throws SQLException, ClassNotFoundException { + createSchema2(connection, dbType); + insertData2(connection, dbType); + + Map whereData = new HashMap<>(); + whereData.put("id", 1); + whereData.put("first_name", "John"); + whereData.put("last_name", "Doe"); + String sql = DBDialectManager.generateDeleteSql(connection, dbType, "my_schema", "employees", whereData, true); + String expectSQL = "DELETE FROM my_schema.employees WHERE id = 1;"; + Assertions.assertEquals(expectSQL, sql); + DBManager.executeSQLScript(connection, dbType, sql); + + List> result = DBManager.getTableOrViewData(connection, dbType, "my_schema", "employees"); + Assertions.assertEquals(0, result.size()); + + insertData2(connection, dbType); + result = DBManager.getTableOrViewData(connection, dbType, "my_schema", "employees"); + Assertions.assertEquals(1, result.size()); + + whereData = new HashMap<>(); + whereData.put("first_name", "John"); + whereData.put("last_name", "Doe"); + whereData.put("email", "john.doe@example.com"); + + sql = DBDialectManager.generateDeleteSql(connection, dbType, "my_schema", "employees", whereData, true); + expectSQL = "DELETE FROM my_schema.employees WHERE last_name = 'Doe' AND first_name = 'John';"; + Assertions.assertEquals(expectSQL, sql); + DBManager.executeSQLScript(connection, dbType, sql); + + result = DBManager.getTableOrViewData(connection, dbType, "my_schema", "employees"); + Assertions.assertEquals(0, result.size()); + + insertData2(connection, dbType); + result = DBManager.getTableOrViewData(connection, dbType, "my_schema", "employees"); + Assertions.assertEquals(1, result.size()); + + whereData = new HashMap<>(); + whereData.put("first_name", "John"); + whereData.put("email", "john.doe@example.com"); + whereData.put("age", 30); + + sql = DBDialectManager.generateDeleteSql(connection, dbType, "my_schema", "employees", whereData, true); + expectSQL = "DELETE FROM my_schema.employees WHERE first_name = 'John' AND email = 'john.doe@example.com' AND age = 30;"; + Assertions.assertEquals(expectSQL, sql); + DBManager.executeSQLScript(connection, dbType, sql); + + result = DBManager.getTableOrViewData(connection, dbType, "my_schema", "employees"); + Assertions.assertEquals(0, result.size()); + + insertData2(connection, dbType); + result = DBManager.getTableOrViewData(connection, dbType, "my_schema", "employees"); + Assertions.assertEquals(1, result.size()); + + whereData.put("age", 31); + sql = DBDialectManager.generateDeleteSql(connection, dbType, "my_schema", "employees", whereData, true); + DBManager.executeSQLScript(connection, dbType, sql); + result = DBManager.getTableOrViewData(connection, dbType, "my_schema", "employees"); + Assertions.assertEquals(1, result.size()); + + whereData = null; + sql = DBDialectManager.generateDeleteSql(connection, dbType, "my_schema", "employees", whereData, true); + Assertions.assertNull(sql); + + tearDown(); + setUp(); + createSchema3(connection, dbType); + insertData(connection, dbType); + + whereData = new HashMap<>(); + whereData.put("MyBoolean", true); + whereData.put("MyChar", "char50"); + whereData.put("MyTimestampWithoutTimeZone", "2004-10-19 10:23:54"); + byte[] byteArray = new byte[] {(byte) 0xDE, (byte) 0xAD, (byte) 0xBE, (byte) 0xEF}; + whereData.put("MyBytea", byteArray); + whereData.put("MyInt", 20); + sql = DBDialectManager.generateDeleteSql(connection, dbType, "my_schema", "mytable", whereData, false); + DBManager.executeSQLScript(connection, dbType, sql); + + result = DBManager.getTableOrViewData(connection, dbType, "my_schema", "mytable"); + Assertions.assertEquals(0, result.size()); + } } diff --git a/src/test/java/com/dbmasker/database/sqlite/SQLiteAPITests.java b/src/test/java/com/dbmasker/database/sqlite/SQLiteAPITests.java index 672d176..678baad 100644 --- a/src/test/java/com/dbmasker/database/sqlite/SQLiteAPITests.java +++ b/src/test/java/com/dbmasker/database/sqlite/SQLiteAPITests.java @@ -256,10 +256,10 @@ void testGetPrimaryKeys() throws SQLException, ClassNotFoundException { Connection connection = DBManager.createConnection(driver, url, username, password); createTable(connection, dbType); - List tablePrimaryKeys = DBManager.getPrimaryKeys(connection, dbType, "", "employees"); + Set tablePrimaryKeys = DBManager.getPrimaryKeys(connection, dbType, "", "employees"); Assertions.assertEquals(1, tablePrimaryKeys.size()); - List expectPrimaryKeys = new ArrayList<>(); + Set expectPrimaryKeys = new HashSet<>(); expectPrimaryKeys.add("id"); Assertions.assertEquals(expectPrimaryKeys, tablePrimaryKeys); diff --git a/src/test/java/com/dbmasker/database/sqlite/SQLiteDialectTests.java b/src/test/java/com/dbmasker/database/sqlite/SQLiteDialectTests.java index d5f0f86..2114cc5 100644 --- a/src/test/java/com/dbmasker/database/sqlite/SQLiteDialectTests.java +++ b/src/test/java/com/dbmasker/database/sqlite/SQLiteDialectTests.java @@ -43,6 +43,21 @@ public void createTable(Connection connection, String dbType) throws SQLExceptio DBManager.executeUpdateSQL(connection, dbType, sql); } + public void createTable2(Connection connection, String dbType) throws SQLException { + String sql = """ + CREATE TABLE MyTable + ( + MyInteger INTEGER PRIMARY KEY, + MyDecimal REAL, + MyDateTime TEXT, + MyNull NULL, + MyBlob BLOB NOT NULL, + UNIQUE(MyDateTime, MyBlob) + ); + """; + DBManager.executeUpdateSQL(connection, dbType, sql); + } + public void insertData(Connection connection, String dbType) throws SQLException { String sql = """ INSERT INTO MyTable @@ -144,4 +159,175 @@ void testFormatData() { Assertions.assertEquals("X'44424d61736b6572'", dialect.formatData(str, "BLOB")); } + @Test + void testGenerateUpdateSql() throws SQLException { + createTable2(connection, dbType); + insertData(connection, dbType); + + Map setData = new HashMap<>(); + setData.put("MyDecimal", 123.123); + Map whereData = new HashMap<>(); + whereData.put("MyInteger", 123); + whereData.put("MyDecimal", 1234.56); + whereData.put("MyDateTime", "2023-05-31 12:34:56.789"); + String sql = DBDialectManager.generateUpdateSql(connection, dbType, null, "MyTable", setData, whereData, true); + String expectSQL = "UPDATE MyTable SET mydecimal = 123.123 WHERE myinteger = 123;"; + Assertions.assertEquals(expectSQL, sql); + DBManager.executeSQLScript(connection, dbType, sql); + + List> result = DBManager.getTableOrViewData(connection, dbType, null, "MyTable"); + Assertions.assertEquals(1, result.size()); + Assertions.assertEquals(123, result.get(0).get("MyInteger")); + Assertions.assertEquals(123.123, result.get(0).get("MyDecimal")); + + setData.put("MyDecimal", 111.111); + whereData = new HashMap<>(); + whereData.put("MyBlob", "DBMasker".getBytes()); + whereData.put("MyDecimal", 1234.56); + whereData.put("MyDateTime", "2023-05-31 12:34:56.789"); + sql = DBDialectManager.generateUpdateSql(connection, dbType, null, "MyTable", setData, whereData, true); + expectSQL = "UPDATE MyTable SET mydecimal = 111.111 WHERE mydatetime = '2023-05-31 12:34:56.789' AND myblob = X'44424d61736b6572';"; + Assertions.assertEquals(expectSQL, sql); + DBManager.executeSQLScript(connection, dbType, sql); + + result = DBManager.getTableOrViewData(connection, dbType, null, "MyTable"); + Assertions.assertEquals(1, result.size()); + Assertions.assertEquals(111.111, result.get(0).get("MyDecimal")); + + setData.put("MyDecimal", 222.222); + whereData = new HashMap<>(); + whereData.put("MyDecimal", 111.111); + whereData.put("MyDateTime", "2023-05-31 12:34:56.789"); + whereData.put("MyNull", null); + sql = DBDialectManager.generateUpdateSql(connection, dbType, null, "MyTable", setData, whereData, true); + DBManager.executeSQLScript(connection, dbType, sql); + + result = DBManager.getTableOrViewData(connection, dbType, null, "MyTable"); + Assertions.assertEquals(1, result.size()); + Assertions.assertEquals(222.222, result.get(0).get("MyDecimal")); + + setData.put("MyDecimal", 333.33); + sql = DBDialectManager.generateUpdateSql(connection, dbType, null, "MyTable", setData, whereData, true); + DBManager.executeSQLScript(connection, dbType, sql); + result = DBManager.getTableOrViewData(connection, dbType, null, "MyTable"); + Assertions.assertEquals(1, result.size()); + Assertions.assertEquals(222.222, result.get(0).get("MyDecimal")); + + whereData = null; + sql = DBDialectManager.generateUpdateSql(connection, dbType, null, "MyTable", setData, whereData, true); + Assertions.assertNull(sql); + } + + @Test + void testGenerateUpdateSql1() throws SQLException { + createTable2(connection, dbType); + insertData(connection, dbType); + + Map setData = new HashMap<>(); + setData.put("MyInteger", 234); + setData.put("MyDecimal", 22.123); + setData.put("MyDateTime", "2023-06-31 12:34:56.789"); + setData.put("MyNull", null); + setData.put("MyBlob", "Masker".getBytes()); + Map whereData = new HashMap<>(); + whereData.put("MyInteger", 123); + String sql = DBDialectManager.generateUpdateSql(connection, dbType, null, "MyTable", setData, whereData, true); + DBManager.executeSQLScript(connection, dbType, sql); + + List> result = DBManager.getTableOrViewData(connection, dbType, null, "MyTable"); + Assertions.assertEquals(1, result.size()); + Assertions.assertEquals(234, result.get(0).get("MyInteger")); + Assertions.assertEquals(22.123, result.get(0).get("MyDecimal")); + Assertions.assertEquals("2023-06-31 12:34:56.789", result.get(0).get("MyDateTime").toString()); + Assertions.assertNull(result.get(0).get("MyNull")); + Assertions.assertEquals("Masker", new String((byte[]) result.get(0).get("MyBlob"))); + + setData.put("MyInteger", 345); + whereData = new HashMap<>(); + whereData.put("MyInteger", 234); + whereData.put("MyDecimal", 22.123); + whereData.put("MyDateTime", "2023-06-31 12:34:56.789"); + whereData.put("MyNull", null); + whereData.put("MyBlob", "Masker".getBytes()); + sql = DBDialectManager.generateUpdateSql(connection, dbType, null, "MyTable", setData, whereData, false); + DBManager.executeSQLScript(connection, dbType, sql); + + result = DBManager.getTableOrViewData(connection, dbType, null, "MyTable"); + Assertions.assertEquals(1, result.size()); + Assertions.assertEquals(345, result.get(0).get("MyInteger")); + } + + @Test + void testGenerateDeleteSql() throws SQLException { + createTable2(connection, dbType); + insertData(connection, dbType); + + Map whereData = new HashMap<>(); + whereData.put("MyInteger", 123); + whereData.put("MyDecimal", 1234.56); + whereData.put("MyDateTime", "2023-05-31 12:34:56.789"); + String sql = DBDialectManager.generateDeleteSql(connection, dbType, null, "MyTable", whereData, true); + String expectSQL = "DELETE FROM MyTable WHERE myinteger = 123;"; + Assertions.assertEquals(expectSQL, sql); + DBManager.executeSQLScript(connection, dbType, sql); + + List> result = DBManager.getTableOrViewData(connection, dbType, null, "MyTable"); + Assertions.assertEquals(0, result.size()); + + insertData(connection, dbType); + result = DBManager.getTableOrViewData(connection, dbType, null, "MyTable"); + Assertions.assertEquals(1, result.size()); + + whereData = new HashMap<>(); + whereData.put("MyBlob", "DBMasker".getBytes()); + whereData.put("MyDecimal", 1234.56); + whereData.put("MyDateTime", "2023-05-31 12:34:56.789"); + sql = DBDialectManager.generateDeleteSql(connection, dbType, null, "MyTable", whereData, true); + expectSQL = "DELETE FROM MyTable WHERE mydatetime = '2023-05-31 12:34:56.789' AND myblob = X'44424d61736b6572';"; + Assertions.assertEquals(expectSQL, sql); + DBManager.executeSQLScript(connection, dbType, sql); + + result = DBManager.getTableOrViewData(connection, dbType, null, "MyTable"); + Assertions.assertEquals(0, result.size()); + + insertData(connection, dbType); + result = DBManager.getTableOrViewData(connection, dbType, null, "MyTable"); + Assertions.assertEquals(1, result.size()); + + whereData = new HashMap<>(); + whereData.put("MyDecimal", 1234.56); + whereData.put("MyDateTime", "2023-05-31 12:34:56.789"); + whereData.put("MyNull", null); + sql = DBDialectManager.generateDeleteSql(connection, dbType, null, "MyTable", whereData, true); + DBManager.executeSQLScript(connection, dbType, sql); + + result = DBManager.getTableOrViewData(connection, dbType, null, "MyTable"); + Assertions.assertEquals(0, result.size()); + + insertData(connection, dbType); + result = DBManager.getTableOrViewData(connection, dbType, null, "MyTable"); + Assertions.assertEquals(1, result.size()); + + whereData.put("MyInteger", 1234); + sql = DBDialectManager.generateDeleteSql(connection, dbType, null, "MyTable", whereData, true); + DBManager.executeSQLScript(connection, dbType, sql); + result = DBManager.getTableOrViewData(connection, dbType, null, "MyTable"); + Assertions.assertEquals(1, result.size()); + + whereData = null; + sql = DBDialectManager.generateDeleteSql(connection, dbType, null, "MyTable", whereData, true); + Assertions.assertNull(sql); + + whereData = new HashMap<>(); + whereData.put("MyInteger", 123); + whereData.put("MyDecimal", 1234.56); + whereData.put("MyDateTime", "2023-05-31 12:34:56.789"); + whereData.put("MyNull", null); + whereData.put("MyBlob", "DBMasker".getBytes()); + sql = DBDialectManager.generateDeleteSql(connection, dbType, null, "MyTable", whereData, false); + DBManager.executeSQLScript(connection, dbType, sql); + + result = DBManager.getTableOrViewData(connection, dbType, null, "MyTable"); + Assertions.assertEquals(0, result.size()); + } }