From 80d3c27e620d1767a4a6a3f7c77add07b7c56875 Mon Sep 17 00:00:00 2001 From: LiuLiu Date: Fri, 13 Dec 2024 15:37:57 -0800 Subject: [PATCH 1/4] query multiple --- graphql-server/schema.gql | 1 + graphql-server/src/queryFactory/index.ts | 4 +++- .../src/queryFactory/mysql/index.ts | 18 +++++++++++++-- .../src/queryFactory/postgres/index.ts | 2 +- .../src/sqlSelects/sqlSelect.model.ts | 5 +++++ .../src/sqlSelects/sqlSelect.resolver.ts | 5 +++-- .../components/DataTable/Warnings.tsx | 22 +++++++++++++++++++ .../components/DataTable/index.module.css | 15 ++++++++++++- web/renderer/components/DataTable/index.tsx | 3 +++ .../components/SqlDataTable/index.tsx | 4 ++++ .../components/SqlDataTable/queries.ts | 1 + web/renderer/gen/graphql-types.tsx | 4 +++- 12 files changed, 76 insertions(+), 8 deletions(-) create mode 100644 web/renderer/components/DataTable/Warnings.tsx diff --git a/graphql-server/schema.gql b/graphql-server/schema.gql index c0ae0ea6..7133a8ac 100644 --- a/graphql-server/schema.gql +++ b/graphql-server/schema.gql @@ -249,6 +249,7 @@ type SqlSelect { rows: [Row!]! queryExecutionStatus: QueryExecutionStatus! queryExecutionMessage: String! + warnings: [String!] } enum QueryExecutionStatus { diff --git a/graphql-server/src/queryFactory/index.ts b/graphql-server/src/queryFactory/index.ts index 97cc09a7..32b9f5f8 100644 --- a/graphql-server/src/queryFactory/index.ts +++ b/graphql-server/src/queryFactory/index.ts @@ -70,7 +70,9 @@ export declare class QueryFactory { getTableRows(args: t.TableMaybeSchemaArgs, page: t.TableRowPagination): t.PR; - getSqlSelect(args: t.RefMaybeSchemaArgs & { queryString: string }): t.PR; + getSqlSelect( + args: t.RefMaybeSchemaArgs & { queryString: string }, + ): Promise<{ rows: t.RawRows; warnings: string[] }>; getSchemas( args: t.RefMaybeSchemaArgs, diff --git a/graphql-server/src/queryFactory/mysql/index.ts b/graphql-server/src/queryFactory/mysql/index.ts index c08f0db8..901b1677 100644 --- a/graphql-server/src/queryFactory/mysql/index.ts +++ b/graphql-server/src/queryFactory/mysql/index.ts @@ -142,8 +142,22 @@ export class MySQLQueryFactory ); } - async getSqlSelect(args: t.RefArgs & { queryString: string }): t.PR { - return this.query(args.queryString, [], args.databaseName, args.refName); + async getSqlSelect( + args: t.RefArgs & { queryString: string }, + ): Promise<{ rows: t.RawRows; warnings: string[] }> { + return this.queryMultiple( + async query => { + const rows = await query(args.queryString, [ + args.databaseName, + args.refName, + ]); + const warningsRes = await query("show warnings"); + const warnings = warningsRes.map(w => w.Message); + return { rows, warnings }; + }, + args.databaseName, + args.refName, + ); } async getSchemas(args: t.DBArgs, type?: SchemaType): Promise { diff --git a/graphql-server/src/queryFactory/postgres/index.ts b/graphql-server/src/queryFactory/postgres/index.ts index 78b27bf8..65a8388b 100644 --- a/graphql-server/src/queryFactory/postgres/index.ts +++ b/graphql-server/src/queryFactory/postgres/index.ts @@ -136,7 +136,7 @@ export class PostgresQueryFactory async getSqlSelect( args: t.RefMaybeSchemaArgs & { queryString: string }, - ): t.PR { + ): Promise<{ rows: t.RawRows; warnings: string[] }> { return this.queryQR( async qr => { if (args.schemaName) { diff --git a/graphql-server/src/sqlSelects/sqlSelect.model.ts b/graphql-server/src/sqlSelects/sqlSelect.model.ts index f2238a99..e0bf6b45 100644 --- a/graphql-server/src/sqlSelects/sqlSelect.model.ts +++ b/graphql-server/src/sqlSelects/sqlSelect.model.ts @@ -29,6 +29,9 @@ export class SqlSelect { @Field() queryExecutionMessage: string; + + @Field(_type => [String], { nullable: true }) + warnings?: string[]; } export function fromSqlSelectRow( @@ -36,6 +39,7 @@ export function fromSqlSelectRow( refName: string, doltRows: RawRow | RawRow[], queryString: string, + warnings?: string[], ): SqlSelect { const res = { _id: `/databases/${databaseName}/refs/${refName}/queries/${queryString}`, @@ -46,6 +50,7 @@ export function fromSqlSelectRow( columns: [], queryExecutionStatus: QueryExecutionStatus.Success, queryExecutionMessage: "", + warnings, }; // Some mutation queries do not return an array diff --git a/graphql-server/src/sqlSelects/sqlSelect.resolver.ts b/graphql-server/src/sqlSelects/sqlSelect.resolver.ts index 287c934d..da88ccf4 100644 --- a/graphql-server/src/sqlSelects/sqlSelect.resolver.ts +++ b/graphql-server/src/sqlSelects/sqlSelect.resolver.ts @@ -22,8 +22,9 @@ export class SqlSelectResolver { return fromSqlSelectRow( args.databaseName, args.refName, - res, + res.rows, args.queryString, + res.warnings, ); } @@ -31,7 +32,7 @@ export class SqlSelectResolver { async sqlSelectForCsvDownload(@Args() args: SqlSelectArgs): Promise { const conn = this.conn.connection(); const res = await conn.getSqlSelect(args); - return toCsvString(res); + return toCsvString(res.rows); } } diff --git a/web/renderer/components/DataTable/Warnings.tsx b/web/renderer/components/DataTable/Warnings.tsx new file mode 100644 index 00000000..c29d06bc --- /dev/null +++ b/web/renderer/components/DataTable/Warnings.tsx @@ -0,0 +1,22 @@ +import { IoWarningOutline } from "@react-icons/all-files/io5/IoWarningOutline"; +import css from "./index.module.css"; + +type Props = { + warnings: string[]; +}; + +export default function Warnings({ warnings }: Props) { + const maxNumWarnings = 5; + const warningsToShow = warnings.slice(0, maxNumWarnings); + + return ( +
+ {warningsToShow.map(warning => ( +
+ +

{warning}

+
+ ))} +
+ ); +} diff --git a/web/renderer/components/DataTable/index.module.css b/web/renderer/components/DataTable/index.module.css index 323bbecb..6394a8af 100644 --- a/web/renderer/components/DataTable/index.module.css +++ b/web/renderer/components/DataTable/index.module.css @@ -7,7 +7,7 @@ } .top { - @apply flex justify-start items-center; + @apply flex justify-start flex-col; } .bottom { @@ -28,3 +28,16 @@ .colsButton { @apply ml-4 h-8; } + +.warning { + @apply flex items-center mb-3 mx-6 text-base; + @screen md { + @apply mx-5; + } + svg { + @apply mr-2 text-coral-400 h-5 w-5 flex-shrink-0; + } + p { + @apply text-coral-400; + } +} diff --git a/web/renderer/components/DataTable/index.tsx b/web/renderer/components/DataTable/index.tsx index f545c910..6b888044 100644 --- a/web/renderer/components/DataTable/index.tsx +++ b/web/renderer/components/DataTable/index.tsx @@ -14,6 +14,7 @@ import AddRowsButton from "./AddRowsButton"; import ShowAllColumns from "./ShowAllColumns"; import Table from "./Table"; import css from "./index.module.css"; +import Warnings from "./Warnings"; type Props = { hasMore?: boolean; @@ -23,6 +24,7 @@ type Props = { message?: ReactNode | null; params: RefParams & { tableName?: Maybe; q: string }; error?: ApolloError; + warnings?: Maybe; }; export function Inner({ columns, rows, message = null, ...props }: Props) { @@ -31,6 +33,7 @@ export function Inner({ columns, rows, message = null, ...props }: Props) {
{message}
+ {props.warnings && }
{rows && columns ? ( diff --git a/web/renderer/components/SqlDataTable/index.tsx b/web/renderer/components/SqlDataTable/index.tsx index 52c22d94..23494fab 100644 --- a/web/renderer/components/SqlDataTable/index.tsx +++ b/web/renderer/components/SqlDataTable/index.tsx @@ -15,6 +15,7 @@ import { } from "@gen/graphql-types"; import { SqlQueryParams } from "@lib/params"; import { useState } from "react"; +import { Maybe } from "@dolthub/web-utils"; import SqlMessage from "./SqlMessage"; import { isReadOnlyDatabaseRevisionError } from "./SqlMessage/utils"; import WorkingDiff from "./WorkingDiff"; @@ -32,6 +33,7 @@ type InnerProps = Props & { rows?: RowForDataTableFragment[]; columns?: ColumnForSqlDataTableFragment[]; client: ApolloClient; + warnings?: Maybe; }; function Inner(props: InnerProps) { @@ -46,6 +48,7 @@ function Inner(props: InnerProps) { columns={props.columns} loadMore={async () => {}} message={msg} + warnings={props.warnings} /> {isMut && !isReadOnlyDatabaseRevisionError(props.gqlError) && ( @@ -77,6 +80,7 @@ function Query(props: Props) { columns={data?.sqlSelect.columns} params={props.params} client={client} + warnings={data?.sqlSelect.warnings} /> ); } diff --git a/web/renderer/components/SqlDataTable/queries.ts b/web/renderer/components/SqlDataTable/queries.ts index 8efe50d5..fa0f7de3 100644 --- a/web/renderer/components/SqlDataTable/queries.ts +++ b/web/renderer/components/SqlDataTable/queries.ts @@ -32,6 +32,7 @@ export const SQL_SELECT_QUERY = gql` rows { ...RowForSqlDataTable } + warnings } } `; diff --git a/web/renderer/gen/graphql-types.tsx b/web/renderer/gen/graphql-types.tsx index 6634c25f..944a14e5 100644 --- a/web/renderer/gen/graphql-types.tsx +++ b/web/renderer/gen/graphql-types.tsx @@ -732,6 +732,7 @@ export type SqlSelect = { queryString: Scalars['String']['output']; refName: Scalars['String']['output']; rows: Array; + warnings?: Maybe>; }; export type Status = { @@ -1011,7 +1012,7 @@ export type SqlSelectForSqlDataTableQueryVariables = Exact<{ }>; -export type SqlSelectForSqlDataTableQuery = { __typename?: 'Query', sqlSelect: { __typename?: 'SqlSelect', queryExecutionStatus: QueryExecutionStatus, queryExecutionMessage: string, columns: Array<{ __typename?: 'Column', name: string, isPrimaryKey: boolean, type: string, sourceTable?: string | null }>, rows: Array<{ __typename?: 'Row', columnValues: Array<{ __typename?: 'ColumnValue', displayValue: string }> }> } }; +export type SqlSelectForSqlDataTableQuery = { __typename?: 'Query', sqlSelect: { __typename?: 'SqlSelect', queryExecutionStatus: QueryExecutionStatus, queryExecutionMessage: string, warnings?: Array | null, columns: Array<{ __typename?: 'Column', name: string, isPrimaryKey: boolean, type: string, sourceTable?: string | null }>, rows: Array<{ __typename?: 'Row', columnValues: Array<{ __typename?: 'ColumnValue', displayValue: string }> }> } }; export type StatusFragment = { __typename?: 'Status', _id: string, refName: string, tableName: string, staged: boolean, status: string }; @@ -2685,6 +2686,7 @@ export const SqlSelectForSqlDataTableDocument = gql` rows { ...RowForSqlDataTable } + warnings } } ${ColumnForSqlDataTableFragmentDoc} From 863d683d0c6280ec37e78c8917ab650345ec41f6 Mon Sep 17 00:00:00 2001 From: LiuLiu Date: Mon, 16 Dec 2024 15:20:31 -0800 Subject: [PATCH 2/4] fixes --- graphql-server/src/queryFactory/index.ts | 2 +- graphql-server/src/queryFactory/mysql/index.ts | 2 +- graphql-server/src/queryFactory/postgres/index.ts | 2 +- graphql-server/src/sqlSelects/sqlSelect.model.ts | 5 +++-- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/graphql-server/src/queryFactory/index.ts b/graphql-server/src/queryFactory/index.ts index 32b9f5f8..f35226bd 100644 --- a/graphql-server/src/queryFactory/index.ts +++ b/graphql-server/src/queryFactory/index.ts @@ -72,7 +72,7 @@ export declare class QueryFactory { getSqlSelect( args: t.RefMaybeSchemaArgs & { queryString: string }, - ): Promise<{ rows: t.RawRows; warnings: string[] }>; + ): Promise<{ rows: t.RawRows; warnings?: string[] }>; getSchemas( args: t.RefMaybeSchemaArgs, diff --git a/graphql-server/src/queryFactory/mysql/index.ts b/graphql-server/src/queryFactory/mysql/index.ts index 901b1677..12ace2dd 100644 --- a/graphql-server/src/queryFactory/mysql/index.ts +++ b/graphql-server/src/queryFactory/mysql/index.ts @@ -144,7 +144,7 @@ export class MySQLQueryFactory async getSqlSelect( args: t.RefArgs & { queryString: string }, - ): Promise<{ rows: t.RawRows; warnings: string[] }> { + ): Promise<{ rows: t.RawRows; warnings?: string[] }> { return this.queryMultiple( async query => { const rows = await query(args.queryString, [ diff --git a/graphql-server/src/queryFactory/postgres/index.ts b/graphql-server/src/queryFactory/postgres/index.ts index 65a8388b..653a731d 100644 --- a/graphql-server/src/queryFactory/postgres/index.ts +++ b/graphql-server/src/queryFactory/postgres/index.ts @@ -136,7 +136,7 @@ export class PostgresQueryFactory async getSqlSelect( args: t.RefMaybeSchemaArgs & { queryString: string }, - ): Promise<{ rows: t.RawRows; warnings: string[] }> { + ): Promise<{ rows: t.RawRows; warnings?: string[] }> { return this.queryQR( async qr => { if (args.schemaName) { diff --git a/graphql-server/src/sqlSelects/sqlSelect.model.ts b/graphql-server/src/sqlSelects/sqlSelect.model.ts index e0bf6b45..aff206c0 100644 --- a/graphql-server/src/sqlSelects/sqlSelect.model.ts +++ b/graphql-server/src/sqlSelects/sqlSelect.model.ts @@ -55,12 +55,13 @@ export function fromSqlSelectRow( // Some mutation queries do not return an array if (!Array.isArray(doltRows)) { + console.log("doltRows", doltRows); return { ...res, queryExecutionMessage: `Query OK, ${ - doltRows.affectedRows + doltRows?.affectedRows } rows affected.${ - doltRows.info.length > 0 ? doltRows.info.replace("#", " ") : "" + doltRows?.info.length > 0 ? doltRows.info.replace("#", " ") : "" }`, }; } From e46c9687b9224c772415a8df6333a1dd705c0a07 Mon Sep 17 00:00:00 2001 From: LiuLiu Date: Mon, 16 Dec 2024 15:26:37 -0800 Subject: [PATCH 3/4] lint --- graphql-server/src/sqlSelects/sqlSelect.model.ts | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/graphql-server/src/sqlSelects/sqlSelect.model.ts b/graphql-server/src/sqlSelects/sqlSelect.model.ts index aff206c0..3cbe2b91 100644 --- a/graphql-server/src/sqlSelects/sqlSelect.model.ts +++ b/graphql-server/src/sqlSelects/sqlSelect.model.ts @@ -37,7 +37,7 @@ export class SqlSelect { export function fromSqlSelectRow( databaseName: string, refName: string, - doltRows: RawRow | RawRow[], + doltRows: RawRow | RawRow[] | undefined, queryString: string, warnings?: string[], ): SqlSelect { @@ -55,13 +55,17 @@ export function fromSqlSelectRow( // Some mutation queries do not return an array if (!Array.isArray(doltRows)) { - console.log("doltRows", doltRows); + if (!doltRows) { + return { + ...res, + }; + } return { ...res, queryExecutionMessage: `Query OK, ${ - doltRows?.affectedRows + doltRows.affectedRows } rows affected.${ - doltRows?.info.length > 0 ? doltRows.info.replace("#", " ") : "" + doltRows.info.length > 0 ? doltRows.info.replace("#", " ") : "" }`, }; } From 298434b8001944150189b648e11700c39fbe621a Mon Sep 17 00:00:00 2001 From: LiuLiu Date: Wed, 18 Dec 2024 12:45:37 -0800 Subject: [PATCH 4/4] todo, query --- graphql-server/src/queryFactory/mysql/index.ts | 2 +- graphql-server/src/queryFactory/mysql/queries.ts | 2 ++ graphql-server/src/queryFactory/postgres/index.ts | 1 + graphql-server/src/sqlSelects/sqlSelect.model.ts | 4 +--- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/graphql-server/src/queryFactory/mysql/index.ts b/graphql-server/src/queryFactory/mysql/index.ts index 12ace2dd..235b99ad 100644 --- a/graphql-server/src/queryFactory/mysql/index.ts +++ b/graphql-server/src/queryFactory/mysql/index.ts @@ -151,7 +151,7 @@ export class MySQLQueryFactory args.databaseName, args.refName, ]); - const warningsRes = await query("show warnings"); + const warningsRes = await query(qh.showWarningsQuery); const warnings = warningsRes.map(w => w.Message); return { rows, warnings }; }, diff --git a/graphql-server/src/queryFactory/mysql/queries.ts b/graphql-server/src/queryFactory/mysql/queries.ts index 82ea66ee..46c500ab 100644 --- a/graphql-server/src/queryFactory/mysql/queries.ts +++ b/graphql-server/src/queryFactory/mysql/queries.ts @@ -20,3 +20,5 @@ export const getTriggersQuery = `SHOW TRIGGERS`; export const getEventsQuery = `SHOW EVENTS`; export const proceduresQuery = `SHOW PROCEDURE STATUS WHERE type = "PROCEDURE" AND db = ?`; + +export const showWarningsQuery = `SHOW WARNINGS`; diff --git a/graphql-server/src/queryFactory/postgres/index.ts b/graphql-server/src/queryFactory/postgres/index.ts index 653a731d..695f380c 100644 --- a/graphql-server/src/queryFactory/postgres/index.ts +++ b/graphql-server/src/queryFactory/postgres/index.ts @@ -134,6 +134,7 @@ export class PostgresQueryFactory ); } + // TODO: get warnings for postgres async getSqlSelect( args: t.RefMaybeSchemaArgs & { queryString: string }, ): Promise<{ rows: t.RawRows; warnings?: string[] }> { diff --git a/graphql-server/src/sqlSelects/sqlSelect.model.ts b/graphql-server/src/sqlSelects/sqlSelect.model.ts index 3cbe2b91..828fc4f9 100644 --- a/graphql-server/src/sqlSelects/sqlSelect.model.ts +++ b/graphql-server/src/sqlSelects/sqlSelect.model.ts @@ -56,9 +56,7 @@ export function fromSqlSelectRow( // Some mutation queries do not return an array if (!Array.isArray(doltRows)) { if (!doltRows) { - return { - ...res, - }; + return res; } return { ...res,