From 0b90efb8df028dc590e7beb7e2751439734dc322 Mon Sep 17 00:00:00 2001 From: llamousse Date: Sat, 29 Mar 2025 10:20:42 -0700 Subject: [PATCH 1/3] test query progress --- .../helperFunctions/universal.helpers.ts | 8 +++- server/controllers/postgresData.controller.ts | 40 +++++++++++++++++-- server/routes/postgres.router.ts | 8 ++++ src/components/DBDisplay/Sidebar.tsx | 1 + 4 files changed, 53 insertions(+), 4 deletions(-) diff --git a/server/controllers/helperFunctions/universal.helpers.ts b/server/controllers/helperFunctions/universal.helpers.ts index 52e5eba5..f33fd600 100644 --- a/server/controllers/helperFunctions/universal.helpers.ts +++ b/server/controllers/helperFunctions/universal.helpers.ts @@ -12,11 +12,17 @@ interface NewColumn { } //---------------CONNECT TO THE DATABASE----------------------------------------------------------------------------------------- +let dbDataSource: DataSource | null = null; export const dbConnect = async (req: Request) => { + // check if database is already initialized and return if it already is + if (dbDataSource && dbDataSource.isInitialized) { + return dbDataSource; + } + const { db_type, hostname, password, port, username, database_name, service_name } = req.session; - let dbDataSource: DataSource; + // let dbDataSource: DataSource; const commonOptions = { ...(db_type !== 'sqlite' ? { host: hostname as string } : {}), diff --git a/server/controllers/postgresData.controller.ts b/server/controllers/postgresData.controller.ts index 4923cb01..21a15470 100644 --- a/server/controllers/postgresData.controller.ts +++ b/server/controllers/postgresData.controller.ts @@ -23,6 +23,7 @@ const postgresController = { postgresQuery: async (req: Request, res: Response, next: NextFunction) => { const PostgresDataSource = await dbConnect(req); console.log('MADE IT TO postgresQuery MIDDLEWARE'); + /* * Used for storing Primary Key table and column names that are * part of Foreign Keys to adjust IsDestination to be true. @@ -146,19 +147,52 @@ const postgresController = { // Storage of queried results into res.locals res.locals.schema = schema; res.locals.data = tableData; + res.locals.database_link = req.query.database_link; + res.locals.db_connection = PostgresDataSource; // Disconnecting after data has been received - PostgresDataSource.destroy(); - console.log('Database has been disconnected'); + // PostgresDataSource.destroy(); + // console.log('Database has been disconnected'); return next(); } catch (err: unknown) { console.log('Error during Data Source: ', err); - PostgresDataSource.destroy(); + // PostgresDataSource.destroy(); console.log('Database has been disconnected'); return next(err); } }, + //----------Function to gather query metrics from database----------------------------------------------------------------- + postgresGetMetrics: async (req: Request, res: Response, next: NextFunction) => { + // if we pass database_link from FE then we might not need to initialize dbConnect again + // database_link and query can be passed in from FE + // const PostgresGetMetrics = await dbConnect(req); + console.log('dblink check: ', res.locals.database_link); + console.log('REACHED postgresGetMetrics MIDDLEWARE'); + + // const { database_link, queryToRun } = req.query; + // console.log('req.body: ', req); + + // dummy data for now + // db_link + query will be passed from FE, into req.query + const database_link = + 'postgresql://postgres.gcfszuopjvbjtllgmenw:store2025@aws-0-us-east-1.pooler.supabase.com:6543/postgres'; + const sqlString = `SELECT * FROM public.products`; + const queryStr = `EXPLAIN (FORMAT JSON, ANALYZE, VERBOSE, BUFFERS) ${sqlString};`; + + // view result of Explain query + // const result = await PostgresGetMetrics.query(queryStr); + // console.log('result of queryStr: ', result); + // console.log('QUERY PLAN: ', result[0]['QUERY PLAN']); + + // add line to pull execution time from results + // const executionTime = result. + // send date and execution time on response + // res.locals.queryResult = {date: Date.now(), executionTime: executionTime} + + // console.log('done w getMetrics controller'); + }, + //-------------------------------------DATA TABLE ROWS------------------------------------------------- //-------------------ADD NEW ROW----------------------------------------------------------- postgresAddNewRow: async (req: Request, res: Response, next: NextFunction) => { diff --git a/server/routes/postgres.router.ts b/server/routes/postgres.router.ts index 6f4b79f9..44f42a2d 100644 --- a/server/routes/postgres.router.ts +++ b/server/routes/postgres.router.ts @@ -12,6 +12,14 @@ postgresRouter.get( } ); +postgresRouter.post( + '/run-query', + postgresController.postgresGetMetrics, + (_req: Request, res: Response) => { + return res.status(200).json(res.locals); + } +); + //-------------------------------------DATA TABLE ROWS---------------------------------------------------------------------------------------- //-------------------ADD NEW ROW----------------------------------------------------------------------------------------- postgresRouter.post( diff --git a/src/components/DBDisplay/Sidebar.tsx b/src/components/DBDisplay/Sidebar.tsx index 6085f8fe..ee721869 100644 --- a/src/components/DBDisplay/Sidebar.tsx +++ b/src/components/DBDisplay/Sidebar.tsx @@ -92,6 +92,7 @@ const Sidebar = (props: any) => { values.password = internalLinkArray_Postgres[0]; values.port = postgresPort ? postgresPort : '5432'; values.database_name = postgresName; + values.database_link = fullLink; values.db_type = 'postgres'; break; } From fa3f9f006ca5acffa5f6c6498fa2d6da67361d16 Mon Sep 17 00:00:00 2001 From: llamousse Date: Mon, 31 Mar 2025 08:07:42 -0700 Subject: [PATCH 2/3] draft testing BE connection to FE - getMetrics --- .../helperFunctions/universal.helpers.ts | 7 +- server/controllers/postgresData.controller.ts | 32 +++-- src/components/DBDisplay/Sidebar.tsx | 2 +- src/pages/TestNewQuery.tsx | 128 +++++++++++++++--- 4 files changed, 126 insertions(+), 43 deletions(-) diff --git a/server/controllers/helperFunctions/universal.helpers.ts b/server/controllers/helperFunctions/universal.helpers.ts index f33fd600..0c2d4760 100644 --- a/server/controllers/helperFunctions/universal.helpers.ts +++ b/server/controllers/helperFunctions/universal.helpers.ts @@ -15,14 +15,9 @@ interface NewColumn { let dbDataSource: DataSource | null = null; export const dbConnect = async (req: Request) => { - // check if database is already initialized and return if it already is - if (dbDataSource && dbDataSource.isInitialized) { - return dbDataSource; - } - const { db_type, hostname, password, port, username, database_name, service_name } = req.session; - // let dbDataSource: DataSource; + let dbDataSource: DataSource; const commonOptions = { ...(db_type !== 'sqlite' ? { host: hostname as string } : {}), diff --git a/server/controllers/postgresData.controller.ts b/server/controllers/postgresData.controller.ts index 21a15470..be813aa6 100644 --- a/server/controllers/postgresData.controller.ts +++ b/server/controllers/postgresData.controller.ts @@ -22,6 +22,7 @@ const postgresController = { //----------Function to collect all schema and data from database----------------------------------------------------------------- postgresQuery: async (req: Request, res: Response, next: NextFunction) => { const PostgresDataSource = await dbConnect(req); + console.log('postgresQuery REQ: ', req); console.log('MADE IT TO postgresQuery MIDDLEWARE'); /* @@ -147,16 +148,16 @@ const postgresController = { // Storage of queried results into res.locals res.locals.schema = schema; res.locals.data = tableData; - res.locals.database_link = req.query.database_link; - res.locals.db_connection = PostgresDataSource; + // res.locals.database_link = req.query.database_link; + // res.locals.db_connection = PostgresDataSource; // Disconnecting after data has been received - // PostgresDataSource.destroy(); - // console.log('Database has been disconnected'); + PostgresDataSource.destroy(); + console.log('Database has been disconnected'); return next(); } catch (err: unknown) { console.log('Error during Data Source: ', err); - // PostgresDataSource.destroy(); + PostgresDataSource.destroy(); console.log('Database has been disconnected'); return next(err); } @@ -166,20 +167,21 @@ const postgresController = { postgresGetMetrics: async (req: Request, res: Response, next: NextFunction) => { // if we pass database_link from FE then we might not need to initialize dbConnect again // database_link and query can be passed in from FE - // const PostgresGetMetrics = await dbConnect(req); - console.log('dblink check: ', res.locals.database_link); + console.log('reqqq: ', req); + const PostgresGetMetrics = await dbConnect(req); + // console.log('dblink check: ', res.locals.database_link); console.log('REACHED postgresGetMetrics MIDDLEWARE'); - - // const { database_link, queryToRun } = req.query; + console.log('REQ QUERY: ', req.body); + const { query } = req.body; // console.log('req.body: ', req); // dummy data for now // db_link + query will be passed from FE, into req.query - const database_link = - 'postgresql://postgres.gcfszuopjvbjtllgmenw:store2025@aws-0-us-east-1.pooler.supabase.com:6543/postgres'; - const sqlString = `SELECT * FROM public.products`; - const queryStr = `EXPLAIN (FORMAT JSON, ANALYZE, VERBOSE, BUFFERS) ${sqlString};`; - + // const database_link = + // 'postgresql://postgres.gcfszuopjvbjtllgmenw:store2025@aws-0-us-east-1.pooler.supabase.com:6543/postgres'; + // const sqlString = `SELECT * FROM public.products`; + // const queryStr = `EXPLAIN (FORMAT JSON, ANALYZE, VERBOSE, BUFFERS) ${sqlString};`; + const queryStr = `EXPLAIN (FORMAT JSON, ANALYZE, VERBOSE, BUFFERS) ${query};`; // view result of Explain query // const result = await PostgresGetMetrics.query(queryStr); // console.log('result of queryStr: ', result); @@ -190,7 +192,7 @@ const postgresController = { // send date and execution time on response // res.locals.queryResult = {date: Date.now(), executionTime: executionTime} - // console.log('done w getMetrics controller'); + console.log('done w getMetrics controller'); }, //-------------------------------------DATA TABLE ROWS------------------------------------------------- diff --git a/src/components/DBDisplay/Sidebar.tsx b/src/components/DBDisplay/Sidebar.tsx index ee721869..fb9de3f8 100644 --- a/src/components/DBDisplay/Sidebar.tsx +++ b/src/components/DBDisplay/Sidebar.tsx @@ -92,7 +92,7 @@ const Sidebar = (props: any) => { values.password = internalLinkArray_Postgres[0]; values.port = postgresPort ? postgresPort : '5432'; values.database_name = postgresName; - values.database_link = fullLink; + // values.database_link = fullLink; values.db_type = 'postgres'; break; } diff --git a/src/pages/TestNewQuery.tsx b/src/pages/TestNewQuery.tsx index cfc88413..03b8e6a8 100644 --- a/src/pages/TestNewQuery.tsx +++ b/src/pages/TestNewQuery.tsx @@ -1,8 +1,10 @@ //* this will be coming from the sidebar (FeatureTab) import React from 'react'; +import axios from 'axios'; import { useEffect, useState } from 'react'; import FeatureTab from '../components/DBDisplay/FeatureTab'; import { NavLink } from 'react-router-dom'; +import useCredentialsStore from '../store/credentialsStore'; // db selecting from prev connected by user type Database = { @@ -22,6 +24,24 @@ const TestNewQuery: React.FC = () => { const [selectedDb, setSelectedDb] = useState(null); // holds the result of the query after post req const [queryResult, setQueryResult] = useState(null); + // TEMPORARY USE STATE FOR DB TEST LINK + const [databaseLink, setDatabaseLink] = useState(''); + // const [dbTextInput, setDbTextInput] = useState(''); + const setDbCredentials = useCredentialsStore((state) => state.setDbCredentials); + + //form state hooks + const [dbValues, setDbValues] = useState<{ + db_type: string; + database_link?: string; + hostname?: string; + port?: string; + username?: string; + password?: string; + database_name?: string; + service_name?: string; + file_path?: string; + }>({ db_type: 'postgres' }); + //END: STATE DECLARATION // getting req to query / select db user is using useEffect(() => { @@ -51,36 +71,90 @@ const TestNewQuery: React.FC = () => { const sendQuery = async () => { try { // conditional to prevent missing input - if (!textInput || !selectedDb) { - alert('Please enter a query and make sure a database is connected'); - return; - } + // if (!textInput || !selectedDb) { + // alert('Please enter a query and make sure a database is connected'); + // return; + // } // post req //TODO where is it getting sent to?? backend route?? - const response = await fetch('', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ - query: textInput, - databaseId: selectedDb.id, - }), - }); + // const response = await fetch('', { + // method: 'POST', + // headers: { + // 'Content-Type': 'application/json', + // }, + // body: JSON.stringify({ + // query: textInput, + // databaseId: selectedDb.id, + // }), + // }); - // conditional for failed resp - if (!response.ok) { - throw new Error('HTTP error! status: ${response.status}'); + // TEMPORARY BE TEST EFFICIENCY ROUTE /////////////////////////////////////////////////////////////////////////////// + const values: any = dbValues; + if (databaseLink) { + const fullLink = databaseLink; + const splitURI = fullLink.split('/'); + + const postgresName = splitURI[3]; + const postgresPort = splitURI[2].split(':')[2]; + const internalLinkArray_Postgres = splitURI[2].split(':')[1].split('@'); + values.hostname = internalLinkArray_Postgres[1]; + values.username = splitURI[2].split(':')[0]; + values.password = internalLinkArray_Postgres[0]; + values.port = postgresPort ? postgresPort : '5432'; + values.database_name = postgresName; + // values.database_link = fullLink; + values.db_type = 'postgres'; } + setDbCredentials(values); + const dataFromBackend = await axios + .get(`/api/sql/${values.db_type}/run-query`, { params: values }) + .then((res) => { + console.log('metrics from BE: ', res); + return res.data; + }) + .catch((err: ErrorEvent) => console.error('getSchema error', err)); + // TBD this line + setQueryResult(dataFromBackend.result); + + // const testResponse = await fetch( + // 'http://localhost:3000/api/sql/postgres/run-query', + // { + // method: 'POST', + // headers: { + // 'Content-Type': 'application/json', + // }, + // body: JSON.stringify({ + // query: textInput, + // database_link: databaseLink, + // }), + // } + // ) + // .then((res) => { + // if (!res.ok) { + // console.log('error'); + // } + // console.log('metrics from BE: ', res); + // setQueryResult(res); + // }) + // .catch((err) => { + // console.error('Failed to save query results', err); + // }); + // END TEMPORARY BE TEST EFFICIENCY ROUTE /////////////////////////////////////////////////////////////////////////////// + + // conditional for failed resp + // if (!response.ok) { + // throw new Error('HTTP error! status: ${response.status}'); + // } + // parsing and saving the resp (query result) - const result = await response.json(); + // const result = await response.json(); // updates state - setQueryResult(result); + // setQueryResult(result); } catch (error) { console.error('Failed to run query', error); - setQueryResult({ error: 'Something went wrong with running the query' }); + // setQueryResult({ error: 'Something went wrong with running the query' }); } }; @@ -106,7 +180,6 @@ const TestNewQuery: React.FC = () => { result: queryResult, }), }); - // conditional for failed resp if (!response.ok) { throw new Error('HTTP error! status: ${response.status}'); @@ -166,6 +239,19 @@ const TestNewQuery: React.FC = () => { Improve with AI + + {/* TEMPORARY BE - test db + query */} + {/* revas link: + postgresql://postgres.gcfszuopjvbjtllgmenw:store2025@aws-0-us-east-1.pooler.supabase.com:6543/postgres + */} +