2026-04-30 12:36:03 +08:00
//
// Copyright 2026 The InfiniFlow Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
package dao
import (
2026-07-27 15:06:48 +08:00
"context"
2026-04-30 12:36:03 +08:00
"ragflow/internal/entity"
2026-07-27 15:06:48 +08:00
"gorm.io/gorm"
2026-04-30 12:36:03 +08:00
)
// SkillSpaceDAO data access object for skills space
type SkillSpaceDAO struct { }
// NewSkillSpaceDAO creates a new SkillSpaceDAO
func NewSkillSpaceDAO ( ) * SkillSpaceDAO {
return & SkillSpaceDAO { }
}
// Create creates a new skills space
2026-07-27 15:06:48 +08:00
func ( dao * SkillSpaceDAO ) Create ( ctx context . Context , db * gorm . DB , space * entity . SkillSpace ) error {
return db . WithContext ( ctx ) . Create ( space ) . Error
2026-04-30 12:36:03 +08:00
}
// GetByID retrieves a skills space by ID (active only)
2026-07-27 15:06:48 +08:00
func ( dao * SkillSpaceDAO ) GetByID ( ctx context . Context , db * gorm . DB , id string ) ( * entity . SkillSpace , error ) {
2026-04-30 12:36:03 +08:00
var space entity . SkillSpace
2026-07-27 15:06:48 +08:00
err := db . WithContext ( ctx ) . Where ( "id = ? AND status = ?" , id , entity . SpaceStatusActive ) . First ( & space ) . Error
2026-04-30 12:36:03 +08:00
if err != nil {
return nil , err
}
return & space , nil
}
// GetByTenantID retrieves all skills spaces by tenant ID (active only)
2026-07-27 15:06:48 +08:00
func ( dao * SkillSpaceDAO ) GetByTenantID ( ctx context . Context , db * gorm . DB , tenantID string ) ( [ ] * entity . SkillSpace , error ) {
2026-04-30 12:36:03 +08:00
var spaces [ ] * entity . SkillSpace
2026-07-27 15:06:48 +08:00
err := db . WithContext ( ctx ) . Where ( "tenant_id = ? AND status = ?" , tenantID , entity . SpaceStatusActive ) . Order ( "create_time DESC" ) . Find ( & spaces ) . Error
2026-04-30 12:36:03 +08:00
return spaces , err
}
// GetByTenantAndName retrieves a skills space by tenant ID and name (active only)
2026-07-27 15:06:48 +08:00
func ( dao * SkillSpaceDAO ) GetByTenantAndName ( ctx context . Context , db * gorm . DB , tenantID , name string ) ( * entity . SkillSpace , error ) {
2026-04-30 12:36:03 +08:00
var space entity . SkillSpace
2026-07-27 15:06:48 +08:00
err := db . WithContext ( ctx ) . Where ( "tenant_id = ? AND name = ? AND status = ?" , tenantID , name , entity . SpaceStatusActive ) . First ( & space ) . Error
2026-04-30 12:36:03 +08:00
if err != nil {
return nil , err
}
return & space , nil
}
// GetByTenantAndNameAnyStatus retrieves a skills space by tenant ID and name regardless of status
2026-07-27 15:06:48 +08:00
func ( dao * SkillSpaceDAO ) GetByTenantAndNameAnyStatus ( ctx context . Context , db * gorm . DB , tenantID , name string ) ( * entity . SkillSpace , error ) {
2026-04-30 12:36:03 +08:00
var space entity . SkillSpace
2026-07-27 15:06:48 +08:00
err := db . WithContext ( ctx ) . Where ( "tenant_id = ? AND name = ?" , tenantID , name ) . First ( & space ) . Error
2026-04-30 12:36:03 +08:00
if err != nil {
return nil , err
}
return & space , nil
}
// GetByIDAnyStatus retrieves a skills space by ID regardless of status
2026-07-27 15:06:48 +08:00
func ( dao * SkillSpaceDAO ) GetByIDAnyStatus ( ctx context . Context , db * gorm . DB , id string ) ( * entity . SkillSpace , error ) {
2026-04-30 12:36:03 +08:00
var space entity . SkillSpace
2026-07-27 15:06:48 +08:00
err := db . WithContext ( ctx ) . Where ( "id = ?" , id ) . First ( & space ) . Error
2026-04-30 12:36:03 +08:00
if err != nil {
return nil , err
}
return & space , nil
}
// GetByFolderID retrieves a skills space by folder ID (active only)
2026-07-27 15:06:48 +08:00
func ( dao * SkillSpaceDAO ) GetByFolderID ( ctx context . Context , db * gorm . DB , folderID string ) ( * entity . SkillSpace , error ) {
2026-04-30 12:36:03 +08:00
var space entity . SkillSpace
2026-07-27 15:06:48 +08:00
err := db . WithContext ( ctx ) . Where ( "folder_id = ? AND status = ?" , folderID , entity . SpaceStatusActive ) . First ( & space ) . Error
2026-04-30 12:36:03 +08:00
if err != nil {
return nil , err
}
return & space , nil
}
// Update updates a skills space
2026-07-27 15:06:48 +08:00
func ( dao * SkillSpaceDAO ) Update ( ctx context . Context , db * gorm . DB , space * entity . SkillSpace ) error {
return db . WithContext ( ctx ) . Save ( space ) . Error
2026-04-30 12:36:03 +08:00
}
// UpdateByID updates skills space by ID
2026-07-27 15:06:48 +08:00
func ( dao * SkillSpaceDAO ) UpdateByID ( ctx context . Context , db * gorm . DB , id string , updates map [ string ] interface { } ) error {
return db . WithContext ( ctx ) . Model ( & entity . SkillSpace { } ) . Where ( "id = ?" , id ) . Updates ( updates ) . Error
2026-04-30 12:36:03 +08:00
}
// Delete deletes a skills space by ID (soft delete)
2026-07-27 15:06:48 +08:00
func ( dao * SkillSpaceDAO ) Delete ( ctx context . Context , db * gorm . DB , id string ) error {
return db . WithContext ( ctx ) . Model ( & entity . SkillSpace { } ) . Where ( "id = ?" , id ) . Update ( "status" , entity . SpaceStatusDeleted ) . Error
2026-04-30 12:36:03 +08:00
}
// CASStatus performs a compare-and-swap on the space status atomically
// Returns true if the update was applied, false if the current status didn't match expected
2026-07-27 15:06:48 +08:00
func ( dao * SkillSpaceDAO ) CASStatus ( ctx context . Context , db * gorm . DB , id string , expectedStatus , newStatus string ) ( bool , error ) {
result := db . WithContext ( ctx ) . Model ( & entity . SkillSpace { } ) .
2026-04-30 12:36:03 +08:00
Where ( "id = ? AND status = ?" , id , expectedStatus ) .
Update ( "status" , newStatus )
if result . Error != nil {
return false , result . Error
}
return result . RowsAffected > 0 , nil
}
// DeletePermanentByName permanently deletes a skills space by tenant ID and name
// This is used to clean up previously deleted spaces (only deletes status='0' deleted spaces, NOT deleting spaces)
2026-07-27 15:06:48 +08:00
func ( dao * SkillSpaceDAO ) DeletePermanentByName ( ctx context . Context , db * gorm . DB , tenantID , name string ) error {
return db . WithContext ( ctx ) . Unscoped ( ) . Where ( "tenant_id = ? AND name = ? AND status = ?" , tenantID , name , entity . SpaceStatusDeleted ) . Delete ( & entity . SkillSpace { } ) . Error
2026-04-30 12:36:03 +08:00
}
// CountByTenant counts skills spaces by tenant ID
2026-07-27 15:06:48 +08:00
func ( dao * SkillSpaceDAO ) CountByTenant ( ctx context . Context , db * gorm . DB , tenantID string ) ( int64 , error ) {
2026-04-30 12:36:03 +08:00
var count int64
2026-07-27 15:06:48 +08:00
err := db . WithContext ( ctx ) . Model ( & entity . SkillSpace { } ) . Where ( "tenant_id = ? AND status = ?" , tenantID , entity . SpaceStatusActive ) . Count ( & count ) . Error
2026-04-30 12:36:03 +08:00
return count , err
}