diff options
Diffstat (limited to 'server')
6 files changed, 240 insertions, 1 deletions
diff --git a/server/sonar-db-dao/src/schema/schema-sq.ddl b/server/sonar-db-dao/src/schema/schema-sq.ddl index fa3ca75b1e9..27ecbc766e6 100644 --- a/server/sonar-db-dao/src/schema/schema-sq.ddl +++ b/server/sonar-db-dao/src/schema/schema-sq.ddl @@ -800,7 +800,8 @@ CREATE TABLE "PROJECTS"( "NCLOC" BIGINT, "CREATION_METHOD" CHARACTER VARYING(50) NOT NULL, "CONTAINS_AI_CODE" BOOLEAN DEFAULT FALSE NOT NULL, - "AI_CODE_FIX_ENABLED" BOOLEAN DEFAULT FALSE NOT NULL + "AI_CODE_FIX_ENABLED" BOOLEAN DEFAULT FALSE NOT NULL, + "DETECTED_AI_CODE" BOOLEAN DEFAULT FALSE NOT NULL ); ALTER TABLE "PROJECTS" ADD CONSTRAINT "PK_NEW_PROJECTS" PRIMARY KEY("UUID"); CREATE UNIQUE NULLS NOT DISTINCT INDEX "UNIQ_PROJECTS_KEE" ON "PROJECTS"("KEE" NULLS FIRST); @@ -1108,6 +1109,14 @@ CREATE TABLE "TELEMETRY_METRICS_SENT"( ); ALTER TABLE "TELEMETRY_METRICS_SENT" ADD CONSTRAINT "PK_TELEMETRY_METRICS_SENT" PRIMARY KEY("METRIC_KEY", "DIMENSION"); +CREATE TABLE "USER_AI_TOOL_USAGES"( + "UUID" CHARACTER VARYING(40) NOT NULL, + "USER_UUID" CHARACTER VARYING(40) NOT NULL, + "ACTIVATED_AT" BIGINT NOT NULL, + "LAST_ACTIVITY_AT" BIGINT +); +ALTER TABLE "USER_AI_TOOL_USAGES" ADD CONSTRAINT "PK_USER_AI_TOOL_USAGES" PRIMARY KEY("UUID"); + CREATE TABLE "USER_DISMISSED_MESSAGES"( "UUID" CHARACTER VARYING(40) NOT NULL, "USER_UUID" CHARACTER VARYING(255) NOT NULL, diff --git a/server/sonar-db-migration/src/it/java/org/sonar/server/platform/db/migration/version/v202501/CreateUserAIToolUsagesTableIT.java b/server/sonar-db-migration/src/it/java/org/sonar/server/platform/db/migration/version/v202501/CreateUserAIToolUsagesTableIT.java new file mode 100644 index 00000000000..f979ff55593 --- /dev/null +++ b/server/sonar-db-migration/src/it/java/org/sonar/server/platform/db/migration/version/v202501/CreateUserAIToolUsagesTableIT.java @@ -0,0 +1,65 @@ +/* + * SonarQube + * Copyright (C) 2009-2024 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.platform.db.migration.version.v202501; + +import java.sql.SQLException; +import java.sql.Types; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; +import org.sonar.db.MigrationDbTester; +import org.sonar.server.platform.db.migration.step.DdlChange; + +import static org.sonar.server.platform.db.migration.def.VarcharColumnDef.UUID_SIZE; +import static org.sonar.server.platform.db.migration.version.v202501.CreateUserAIToolUsagesTable.COLUMN_ACTIVATED_AT; +import static org.sonar.server.platform.db.migration.version.v202501.CreateUserAIToolUsagesTable.COLUMN_LAST_ACTIVITY_AT; +import static org.sonar.server.platform.db.migration.version.v202501.CreateUserAIToolUsagesTable.COLUMN_USER_UUID; +import static org.sonar.server.platform.db.migration.version.v202501.CreateUserAIToolUsagesTable.COLUMN_UUID; +import static org.sonar.server.platform.db.migration.version.v202501.CreateUserAIToolUsagesTable.USER_AI_TOOLS_USAGES_TABLE_NAME; + +class CreateUserAIToolUsagesTableIT { + + @RegisterExtension + public final MigrationDbTester db = MigrationDbTester.createForMigrationStep(CreateUserAIToolUsagesTable.class); + + private final DdlChange underTest = new CreateUserAIToolUsagesTable(db.database()); + + @Test + void execute_shouldCreateTable() throws SQLException { + db.assertTableDoesNotExist(USER_AI_TOOLS_USAGES_TABLE_NAME); + + underTest.execute(); + + db.assertTableExists(USER_AI_TOOLS_USAGES_TABLE_NAME); + db.assertPrimaryKey(USER_AI_TOOLS_USAGES_TABLE_NAME, "pk_user_ai_tool_usages", COLUMN_UUID); + db.assertColumnDefinition(USER_AI_TOOLS_USAGES_TABLE_NAME, COLUMN_USER_UUID, Types.VARCHAR, UUID_SIZE, false); + db.assertColumnDefinition(USER_AI_TOOLS_USAGES_TABLE_NAME, COLUMN_ACTIVATED_AT, Types.BIGINT, null, false); + db.assertColumnDefinition(USER_AI_TOOLS_USAGES_TABLE_NAME, COLUMN_LAST_ACTIVITY_AT, Types.BIGINT, null, true); + } + + @Test + void execute_shouldBeReentrant() throws SQLException { + db.assertTableDoesNotExist(USER_AI_TOOLS_USAGES_TABLE_NAME); + + underTest.execute(); + underTest.execute(); + + db.assertTableExists(USER_AI_TOOLS_USAGES_TABLE_NAME); + } +} diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v202501/AddDetectedAICodeColumnToProjectsTable.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v202501/AddDetectedAICodeColumnToProjectsTable.java new file mode 100644 index 00000000000..c1a394684b8 --- /dev/null +++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v202501/AddDetectedAICodeColumnToProjectsTable.java @@ -0,0 +1,53 @@ +/* + * SonarQube + * Copyright (C) 2009-2024 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.platform.db.migration.version.v202501; + +import java.sql.SQLException; +import org.sonar.db.Database; +import org.sonar.server.platform.db.migration.def.BooleanColumnDef; +import org.sonar.server.platform.db.migration.sql.AddColumnsBuilder; +import org.sonar.server.platform.db.migration.step.DdlChange; + +import static org.sonar.db.DatabaseUtils.tableColumnExists; + +public class AddDetectedAICodeColumnToProjectsTable extends DdlChange { + static final String PROJECTS_TABLE_NAME = "projects"; + static final String DETECTED_AI_CODE_COLUMN_NAME = "detected_ai_code"; + + public AddDetectedAICodeColumnToProjectsTable(Database db) { + super(db); + } + + @Override + public void execute(Context context) throws SQLException { + try (var connection = getDatabase().getDataSource().getConnection()) { + if (!tableColumnExists(connection, PROJECTS_TABLE_NAME, DETECTED_AI_CODE_COLUMN_NAME)) { + var columnDef = BooleanColumnDef.newBooleanColumnDefBuilder() + .setColumnName(DETECTED_AI_CODE_COLUMN_NAME) + .setIsNullable(false) + .setDefaultValue(false) + .build(); + context.execute(new AddColumnsBuilder(getDialect(), PROJECTS_TABLE_NAME) + .addColumn(columnDef) + .build()); + } + } + } +} diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v202501/CreateUserAIToolUsagesTable.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v202501/CreateUserAIToolUsagesTable.java new file mode 100644 index 00000000000..2f949351403 --- /dev/null +++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v202501/CreateUserAIToolUsagesTable.java @@ -0,0 +1,53 @@ +/* + * SonarQube + * Copyright (C) 2009-2024 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.platform.db.migration.version.v202501; + +import java.sql.SQLException; +import org.sonar.db.Database; +import org.sonar.server.platform.db.migration.sql.CreateTableBuilder; +import org.sonar.server.platform.db.migration.step.CreateTableChange; + +import static org.sonar.server.platform.db.migration.def.BigIntegerColumnDef.newBigIntegerColumnDefBuilder; +import static org.sonar.server.platform.db.migration.def.VarcharColumnDef.UUID_SIZE; +import static org.sonar.server.platform.db.migration.def.VarcharColumnDef.newVarcharColumnDefBuilder; + +public class CreateUserAIToolUsagesTable extends CreateTableChange { + + static final String USER_AI_TOOLS_USAGES_TABLE_NAME = "user_ai_tool_usages"; + static final String COLUMN_UUID = "uuid"; + static final String COLUMN_USER_UUID = "user_uuid"; + static final String COLUMN_ACTIVATED_AT = "activated_at"; + static final String COLUMN_LAST_ACTIVITY_AT = "last_activity_at"; + + + protected CreateUserAIToolUsagesTable(Database db) { + super(db, USER_AI_TOOLS_USAGES_TABLE_NAME); + } + + @Override + public void execute(Context context, String tableName) throws SQLException { + context.execute(new CreateTableBuilder(getDialect(), tableName) + .addPkColumn(newVarcharColumnDefBuilder().setColumnName(COLUMN_UUID).setIsNullable(false).setLimit(UUID_SIZE).build()) + .addColumn(newVarcharColumnDefBuilder().setColumnName(COLUMN_USER_UUID).setIsNullable(false).setLimit(UUID_SIZE).build()) + .addColumn(newBigIntegerColumnDefBuilder().setColumnName(COLUMN_ACTIVATED_AT).setIsNullable(false).build()) + .addColumn(newBigIntegerColumnDefBuilder().setColumnName(COLUMN_LAST_ACTIVITY_AT).setIsNullable(true).build()) + .build()); + } +} diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v202501/DbVersion202501.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v202501/DbVersion202501.java index 0ecc76cac19..82f284c6634 100644 --- a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v202501/DbVersion202501.java +++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v202501/DbVersion202501.java @@ -42,6 +42,8 @@ public class DbVersion202501 implements DbVersion { .add(2025_01_002, "Delete removed complexity metrics from 'metrics' table", DeleteRemovedComplexityMetrics.class) .add(2025_01_003, "Create index on 'rule_tags' table", CreateIndexOnRuleTagsTable.class) .add(2025_01_004, "Rename 'Sonar Way' without 0 new issues condition to 'Sonar Way(legacy)'", RenameOldSonarWayToLegacy.class) + .add(2025_01_005, "Create 'user_ai_tool_usages' table", CreateUserAIToolUsagesTable.class) + .add(2025_01_006, "Add 'detected_ai_code' column to 'projects' table", AddDetectedAICodeColumnToProjectsTable.class) ; } } diff --git a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v202501/AddDetectedAICodeColumnToProjectsTableTest.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v202501/AddDetectedAICodeColumnToProjectsTableTest.java new file mode 100644 index 00000000000..07e7d0bb2ad --- /dev/null +++ b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v202501/AddDetectedAICodeColumnToProjectsTableTest.java @@ -0,0 +1,57 @@ +/* + * SonarQube + * Copyright (C) 2009-2024 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.platform.db.migration.version.v202501; + +import java.sql.SQLException; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; +import org.sonar.db.MigrationDbTester; + +import static java.sql.Types.BOOLEAN; +import static org.assertj.core.api.AssertionsForClassTypes.assertThatCode; +import static org.sonar.server.platform.db.migration.version.v202501.AddDetectedAICodeColumnToProjectsTable.DETECTED_AI_CODE_COLUMN_NAME; +import static org.sonar.server.platform.db.migration.version.v202501.AddDetectedAICodeColumnToProjectsTable.PROJECTS_TABLE_NAME; + +class AddDetectedAICodeColumnToProjectsTableTest { + + @RegisterExtension + public final MigrationDbTester db = MigrationDbTester.createForMigrationStep(AddDetectedAICodeColumnToProjectsTable.class); + + private final AddDetectedAICodeColumnToProjectsTable underTest = new AddDetectedAICodeColumnToProjectsTable(db.database()); + + @Test + void execute_whenColumnDoesNotExist_shouldCreateColumn() throws SQLException { + db.assertColumnDoesNotExist(PROJECTS_TABLE_NAME, DETECTED_AI_CODE_COLUMN_NAME); + underTest.execute(); + assertColumnExists(); + } + + @Test + void execute_whenColumnsAlreadyExists_shouldNotFail() throws SQLException { + underTest.execute(); + assertColumnExists(); + assertThatCode(underTest::execute).doesNotThrowAnyException(); + } + + private void assertColumnExists() { + db.assertColumnDefinition(PROJECTS_TABLE_NAME, DETECTED_AI_CODE_COLUMN_NAME, BOOLEAN, null, false); + } + +} |