From e2a2ad5aad3c86fcb76c6ba988cbd9ee5966a31f Mon Sep 17 00:00:00 2001 From: YolanFery Date: Thu, 13 Aug 2026 11:32:55 +0200 Subject: [PATCH 1/2] fix: new schema --- openhexa/graphql/schema.generated.graphql | 164 +++++++++++++++++++++- 1 file changed, 159 insertions(+), 5 deletions(-) diff --git a/openhexa/graphql/schema.generated.graphql b/openhexa/graphql/schema.generated.graphql index bf90897f..59addfc4 100644 --- a/openhexa/graphql/schema.generated.graphql +++ b/openhexa/graphql/schema.generated.graphql @@ -477,6 +477,8 @@ registry (`hexa.assistant.agents.all_agent_tool_names`) — a unit test enforces enum AssistantToolName { create_pipeline get_dataset + get_db_schema + get_db_table_schema get_help_or_doc get_pipeline get_static_webapp_file @@ -1169,6 +1171,42 @@ input CreatePipelineVersionInput { zipfile: String } +"""Errors that can occur when creating a saved query.""" +enum CreateSavedQueryError { + PERMISSION_DENIED + WORKSPACE_NOT_FOUND +} + +"""Input for creating a saved query.""" +input CreateSavedQueryInput { + content: String! + description: String + name: String! + workspaceSlug: String! +} + +"""Result of creating a saved query.""" +type CreateSavedQueryResult { + errors: [CreateSavedQueryError!]! + savedQuery: SavedQuery + success: Boolean! +} + +""" +The CreateSelfHostedOrganizationInput type represents the input for the createSelfHostedOrganization mutation. +Used by superusers to provision a subscription-less organization (self-hosted mode). +""" +input CreateSelfHostedOrganizationInput { + """The name of the organization.""" + name: String! + + """ + The short name of the organization (max 5 uppercase letters). + If not provided, it will be auto-generated from the name. + """ + shortName: String +} + """ The CreateTeamError enum represents the possible errors that can occur during the createTeam mutation. """ @@ -1264,7 +1302,7 @@ input CreateWorkspaceInput { description: String loadSampleData: Boolean name: String! - organizationId: UUID + organizationId: UUID! slug: String } @@ -1444,10 +1482,10 @@ type DHIS2QueryResultPage { type Database { credentials: DatabaseCredentials - executeSQL(maxRows: Int, query: String!): ExecuteSQLResult! + executeSQL(maxRows: Int, origin: ExecuteSQLOrigin, query: String!): ExecuteSQLResult! readOnlyCredentials: DatabaseCredentials table(name: String!): DatabaseTable - tables(page: Int, perPage: Int): DatabaseTablePage! + tables(page: Int, perPage: Int, withColumns: Boolean = false, withCounts: Boolean = true): DatabaseTablePage! } type DatabaseCredentials { @@ -2084,6 +2122,23 @@ type DeletePipelineVersionResult { success: Boolean! } +"""Errors that can occur when deleting a saved query.""" +enum DeleteSavedQueryError { + PERMISSION_DENIED + SAVED_QUERY_NOT_FOUND +} + +"""Input for deleting a saved query.""" +input DeleteSavedQueryInput { + id: ID! +} + +"""Result of deleting a saved query.""" +type DeleteSavedQueryResult { + errors: [DeleteSavedQueryError!]! + success: Boolean! +} + """ The DeleteTeamError enum represents the possible errors that can occur during the deleteTeam mutation. """ @@ -2339,6 +2394,17 @@ enum ExecuteSQLError { QUERY_TIMEOUT } +""" +The origin of a SQL query, recorded for auditing and to build a per-user query history. +""" +enum ExecuteSQLOrigin { + """The query originates from the Data Studio frontend.""" + DATA_STUDIO + + """The client did not identify where the query comes from.""" + OTHER +} + """ Represents the result of executing a SQL query against the workspace database. """ @@ -2346,6 +2412,9 @@ type ExecuteSQLResult { """The names of the columns returned by the query.""" columns: [String!] + """The server-side execution time of the query, in milliseconds.""" + durationMs: Int + """The underlying database error message, when the query failed.""" errorMessage: String @@ -2897,7 +2966,6 @@ type MePermissions { """Indicates whether the user has permission to create a team.""" createTeam: Boolean! - createWorkspace: Boolean! manageAccessmodAccessRequests: Boolean! """Indicates whether the user has superuser privileges.""" @@ -3033,6 +3101,10 @@ type Mutation { """Creates a new pipeline template version.""" createPipelineTemplateVersion(input: CreatePipelineTemplateVersionInput!): CreatePipelineTemplateVersionResult! + + """Creates a new saved query in a workspace.""" + createSavedQuery(input: CreateSavedQueryInput!): CreateSavedQueryResult! + createSelfHostedOrganization(input: CreateSelfHostedOrganizationInput!): CreateOrganizationResult! createTeam(input: CreateTeamInput!): CreateTeamResult! createWebapp(input: CreateWebappInput!): CreateWebappResult! createWorkspace(input: CreateWorkspaceInput!): CreateWorkspaceResult! @@ -3074,6 +3146,9 @@ type Mutation { """Deletes a pipeline version.""" deletePipelineVersion(input: DeletePipelineVersionInput!): DeletePipelineVersionResult! + + """Deletes a saved query.""" + deleteSavedQuery(input: DeleteSavedQueryInput!): DeleteSavedQueryResult! deleteTeam(input: DeleteTeamInput!): DeleteTeamResult! """Deletes a template version.""" @@ -3218,6 +3293,9 @@ type Mutation { """Updates a pipeline version.""" updatePipelineVersion(input: UpdatePipelineVersionInput!): UpdatePipelineVersionResult! + + """Updates an existing saved query.""" + updateSavedQuery(input: UpdateSavedQueryInput!): UpdateSavedQueryResult! updateTeam(input: UpdateTeamInput!): UpdateTeamResult! """Updates a template version.""" @@ -4128,6 +4206,11 @@ type Query { """Read the text content of a file from a workspace's bucket.""" readFileContent(endLine: Int, filePath: String!, startLine: Int, workspaceSlug: String!): ReadFileContentResult! readWebappFile(endLine: Int, path: String!, startLine: Int, webappSlug: String!, workspaceSlug: String!): ReadWebappFileResult! + + """ + Retrieves a saved query by its id. When a workspace slug is given, the lookup is scoped to that workspace. + """ + savedQuery(id: ID!, workspaceSlug: String): SavedQuery searchDatabaseTables(organizationId: UUID, page: Int = 1, perPage: Int = 15, query: String!, workspaceSlugs: [String]): DatabaseTableResultPage! searchDatasets(organizationId: UUID, page: Int = 1, perPage: Int = 15, query: String!, workspaceSlugs: [String]): DatasetResultPage! searchFiles(organizationId: UUID, page: Int = 1, perPage: Int = 15, prefix: String, query: String!, workspaceSlugs: [String]): FileResultPage! @@ -4474,6 +4557,47 @@ type S3ObjectPage { totalPages: Int! } +""" +A SQL query saved by a user in the Data Studio. Saved queries belong to a +workspace and are visible to all of its members. +""" +type SavedQuery { + content: String! + createdAt: DateTime! + createdBy: User + description: String + id: ID! + name: String! + permissions: SavedQueryPermissions! + updatedAt: DateTime! + workspace: Workspace! +} + +"""Enum representing the possible orderings for saved queries.""" +enum SavedQueryOrderBy { + NAME_ASC + NAME_DESC + UPDATED_AT_ASC + UPDATED_AT_DESC +} + +"""A page of saved queries.""" +type SavedQueryPage { + items: [SavedQuery!]! + pageNumber: Int! + totalItems: Int! + totalPages: Int! +} + +"""Permissions of a saved query.""" +type SavedQueryPermissions { + """Permission to delete the saved query.""" + delete: Boolean! + + """Permission to edit the saved query.""" + update: Boolean! +} + interface SearchResult { score: Float! } @@ -5336,6 +5460,27 @@ type UpdatePipelineVersionResult { success: Boolean! } +"""Errors that can occur when updating a saved query.""" +enum UpdateSavedQueryError { + PERMISSION_DENIED + SAVED_QUERY_NOT_FOUND +} + +"""Input for updating a saved query.""" +input UpdateSavedQueryInput { + content: String + description: String + id: ID! + name: String +} + +"""Result of updating a saved query.""" +type UpdateSavedQueryResult { + errors: [UpdateSavedQueryError!]! + savedQuery: SavedQuery + success: Boolean! +} + """ The UpdateTeamError enum represents the possible errors that can occur during the updateTeam mutation. """ @@ -5611,6 +5756,9 @@ type UploadPipelineResult { """The User type represents a user in the system.""" type User { + """Whether the user has consented to product analytics tracking.""" + analyticsEnabled: Boolean! + """The avatar of the user.""" avatar: Avatar! @@ -5808,11 +5956,14 @@ type Workspace { invitations(includeAccepted: Boolean, page: Int, perPage: Int): WorkspaceInvitationPage! members(page: Int, perPage: Int): WorkspaceMembershipPage! name: String! - organization: Organization + organization: Organization! permissions: WorkspacePermissions! pipelineLastRunStatuses: [PipelineRunStatus!]! pipelineTags: [String!]! pipelineTemplateTags: [String!]! + + """The saved queries of the workspace.""" + savedQueries(orderBy: SavedQueryOrderBy! = UPDATED_AT_DESC, page: Int = 1, perPage: Int = 15, query: String): SavedQueryPage! shortcuts: [ShortcutItem!]! slug: String! updatedAt: DateTime @@ -5918,6 +6069,9 @@ type WorkspacePermissions { createObject: Boolean! createPipeline: Boolean! createPipelineTemplateVersion: Boolean! + + """Permission to create a saved query in the workspace.""" + createSavedQuery: Boolean! delete: Boolean! deleteDatabaseTable: Boolean! From ed484c71413586eda4b2bf286815c3ad2f64ef38 Mon Sep 17 00:00:00 2001 From: YolanFery Date: Thu, 13 Aug 2026 12:07:10 +0200 Subject: [PATCH 2/2] fix: new schema generation --- openhexa/graphql/graphql_client/__init__.py | 18 ++++++++++++ openhexa/graphql/graphql_client/enums.py | 29 +++++++++++++++++++ .../graphql/graphql_client/input_types.py | 25 +++++++++++++++- 3 files changed, 71 insertions(+), 1 deletion(-) diff --git a/openhexa/graphql/graphql_client/__init__.py b/openhexa/graphql/graphql_client/__init__.py index 2f322b39..42c71c98 100644 --- a/openhexa/graphql/graphql_client/__init__.py +++ b/openhexa/graphql/graphql_client/__init__.py @@ -120,6 +120,7 @@ CreateOrganizationError, CreatePipelineFromTemplateVersionError, CreatePipelineTemplateVersionError, + CreateSavedQueryError, CreateTeamError, CreateTemplateVersionPermissionReason, CreateWebappError, @@ -145,6 +146,7 @@ DeleteOrganizationInvitationError, DeleteOrganizationMemberError, DeletePipelineVersionError, + DeleteSavedQueryError, DeleteTeamError, DeleteTemplateVersionError, DeleteWebappError, @@ -160,6 +162,7 @@ EditWebappFileError, EnableTwoFactorError, ExecuteSQLError, + ExecuteSQLOrigin, FileEncoding, FileSampleStatus, FileType, @@ -212,6 +215,7 @@ ResendWorkspaceInvitationError, ResolveAssistantProposalError, RunDAGError, + SavedQueryOrderBy, SetDAGRunFavoriteError, SetMetadataAttributeError, SetPasswordError, @@ -233,6 +237,7 @@ UpdateOrganizationSubscriptionError, UpdatePipelineError, UpdatePipelineVersionError, + UpdateSavedQueryError, UpdateTeamError, UpdateTemplateError, UpdateTemplateVersionError, @@ -298,6 +303,8 @@ CreatePipelineRecipientInput, CreatePipelineTemplateVersionInput, CreatePipelineVersionInput, + CreateSavedQueryInput, + CreateSelfHostedOrganizationInput, CreateTeamInput, CreateWebappInput, CreateWorkspaceInput, @@ -322,6 +329,7 @@ DeletePipelineRecipientInput, DeletePipelineTemplateInput, DeletePipelineVersionInput, + DeleteSavedQueryInput, DeleteTeamInput, DeleteTemplateVersionInput, DeleteWebappInput, @@ -397,6 +405,7 @@ UpdatePipelineProgressInput, UpdatePipelineRecipientInput, UpdatePipelineVersionInput, + UpdateSavedQueryInput, UpdateTeamInput, UpdateTemplateInput, UpdateTemplateVersionInput, @@ -601,6 +610,9 @@ "CreatePipelineTemplateVersionError", "CreatePipelineTemplateVersionInput", "CreatePipelineVersionInput", + "CreateSavedQueryError", + "CreateSavedQueryInput", + "CreateSelfHostedOrganizationInput", "CreateTeamError", "CreateTeamInput", "CreateTemplateVersionPermissionReason", @@ -683,6 +695,8 @@ "DeletePipelineVersionDeletePipelineVersion", "DeletePipelineVersionError", "DeletePipelineVersionInput", + "DeleteSavedQueryError", + "DeleteSavedQueryInput", "DeleteTeamError", "DeleteTeamInput", "DeleteTemplateVersionError", @@ -708,6 +722,7 @@ "EnableTwoFactorError", "EnableTwoFactorInput", "ExecuteSQLError", + "ExecuteSQLOrigin", "FileEncoding", "FileSampleStatus", "FileType", @@ -852,6 +867,7 @@ "RunDAGError", "RunDAGInput", "RunPipelineInput", + "SavedQueryOrderBy", "SetDAGRunFavoriteError", "SetDAGRunFavoriteInput", "SetMetadataAttributeError", @@ -913,6 +929,8 @@ "UpdatePipelineRecipientInput", "UpdatePipelineVersionError", "UpdatePipelineVersionInput", + "UpdateSavedQueryError", + "UpdateSavedQueryInput", "UpdateTeamError", "UpdateTeamInput", "UpdateTemplateError", diff --git a/openhexa/graphql/graphql_client/enums.py b/openhexa/graphql/graphql_client/enums.py index d33bde63..e4786b70 100644 --- a/openhexa/graphql/graphql_client/enums.py +++ b/openhexa/graphql/graphql_client/enums.py @@ -110,6 +110,8 @@ class ArchiveWorkspaceError(str, Enum): class AssistantToolName(str, Enum): create_pipeline = "create_pipeline" get_dataset = "get_dataset" + get_db_schema = "get_db_schema" + get_db_table_schema = "get_db_table_schema" get_help_or_doc = "get_help_or_doc" get_pipeline = "get_pipeline" get_static_webapp_file = "get_static_webapp_file" @@ -244,6 +246,11 @@ class CreatePipelineTemplateVersionError(str, Enum): WORKSPACE_NOT_FOUND = "WORKSPACE_NOT_FOUND" +class CreateSavedQueryError(str, Enum): + PERMISSION_DENIED = "PERMISSION_DENIED" + WORKSPACE_NOT_FOUND = "WORKSPACE_NOT_FOUND" + + class CreateTeamError(str, Enum): NAME_DUPLICATE = "NAME_DUPLICATE" PERMISSION_DENIED = "PERMISSION_DENIED" @@ -410,6 +417,11 @@ class DeletePipelineVersionError(str, Enum): PIPELINE_VERSION_NOT_FOUND = "PIPELINE_VERSION_NOT_FOUND" +class DeleteSavedQueryError(str, Enum): + PERMISSION_DENIED = "PERMISSION_DENIED" + SAVED_QUERY_NOT_FOUND = "SAVED_QUERY_NOT_FOUND" + + class DeleteTeamError(str, Enum): NOT_FOUND = "NOT_FOUND" PERMISSION_DENIED = "PERMISSION_DENIED" @@ -481,6 +493,11 @@ class ExecuteSQLError(str, Enum): QUERY_TIMEOUT = "QUERY_TIMEOUT" +class ExecuteSQLOrigin(str, Enum): + DATA_STUDIO = "DATA_STUDIO" + OTHER = "OTHER" + + class FileEncoding(str, Enum): BASE64 = "BASE64" TEXT = "TEXT" @@ -830,6 +847,13 @@ class RunDAGError(str, Enum): INVALID_CONFIG = "INVALID_CONFIG" +class SavedQueryOrderBy(str, Enum): + NAME_ASC = "NAME_ASC" + NAME_DESC = "NAME_DESC" + UPDATED_AT_ASC = "UPDATED_AT_ASC" + UPDATED_AT_DESC = "UPDATED_AT_DESC" + + class SetDAGRunFavoriteError(str, Enum): INVALID = "INVALID" MISSING_LABEL = "MISSING_LABEL" @@ -952,6 +976,11 @@ class UpdatePipelineVersionError(str, Enum): PERMISSION_DENIED = "PERMISSION_DENIED" +class UpdateSavedQueryError(str, Enum): + PERMISSION_DENIED = "PERMISSION_DENIED" + SAVED_QUERY_NOT_FOUND = "SAVED_QUERY_NOT_FOUND" + + class UpdateTeamError(str, Enum): NAME_DUPLICATE = "NAME_DUPLICATE" NOT_FOUND = "NOT_FOUND" diff --git a/openhexa/graphql/graphql_client/input_types.py b/openhexa/graphql/graphql_client/input_types.py index fbf02443..56c82d6e 100644 --- a/openhexa/graphql/graphql_client/input_types.py +++ b/openhexa/graphql/graphql_client/input_types.py @@ -222,6 +222,18 @@ class CreatePipelineVersionInput(BaseModel): zipfile: Optional[str] = None +class CreateSavedQueryInput(BaseModel): + content: str + description: Optional[str] = None + name: str + workspace_slug: str = Field(alias="workspaceSlug") + + +class CreateSelfHostedOrganizationInput(BaseModel): + name: str + short_name: Optional[str] = Field(alias="shortName", default=None) + + class CreateTeamInput(BaseModel): name: str @@ -244,7 +256,7 @@ class CreateWorkspaceInput(BaseModel): description: Optional[str] = None load_sample_data: Optional[bool] = Field(alias="loadSampleData", default=None) name: str - organization_id: Optional[Any] = Field(alias="organizationId", default=None) + organization_id: Any = Field(alias="organizationId") slug: Optional[str] = None @@ -337,6 +349,10 @@ class DeletePipelineVersionInput(BaseModel): id: Any +class DeleteSavedQueryInput(BaseModel): + id: str + + class DeleteTeamInput(BaseModel): id: Any @@ -808,6 +824,13 @@ class UpdatePipelineVersionInput(BaseModel): name: Optional[str] = None +class UpdateSavedQueryInput(BaseModel): + content: Optional[str] = None + description: Optional[str] = None + id: str + name: Optional[str] = None + + class UpdateTeamInput(BaseModel): id: Any name: Optional[str] = None