Skip to content

Commit

Permalink
allow exposing postgres functions through GraphQL interface (close #333
Browse files Browse the repository at this point in the history
…) (#1073)
  • Loading branch information
rakeshkky authored and 0x777 committed Jan 25, 2019
1 parent e7a42c6 commit 0bf2457
Show file tree
Hide file tree
Showing 101 changed files with 3,886 additions and 331 deletions.
6 changes: 4 additions & 2 deletions cli/commands/migrate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ var ravenVersions = []mt.Version{
}

var testMetadata = map[string][]byte{
"metadata": []byte(`query_templates: []
"metadata": []byte(`functions: []
query_templates: []
remote_schemas: []
tables:
- array_relationships: []
Expand All @@ -40,7 +41,8 @@ tables:
table: test
update_permissions: []
`),
"empty-metadata": []byte(`query_templates: []
"empty-metadata": []byte(`functions: []
query_templates: []
remote_schemas: []
tables: []
`),
Expand Down
68 changes: 68 additions & 0 deletions console/cypress/helpers/dataHelpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,71 @@ export const makeDataAPIOptions = (dataApiUrl, key, body) => ({
body,
failOnStatusCode: false,
});

export const testCustomFunctionDefinition = i => `create function search_posts${'_' +
i} (search text) returns setof post as $$ select * from post where title ilike ('%' || search || '%') or content ilike ('%' || search || '%') $$ language sql stable;
`;

export const getCustomFunctionName = i => `search_posts${'_' + i}`;

export const testCustomFunctionSQL = i => {
return {
type: 'bulk',
args: [
{
type: 'run_sql',
args: {
sql: `CREATE OR REPLACE FUNCTION public.search_posts_${i}(search text)\n RETURNS SETOF post\n LANGUAGE sql\n STABLE\nAS $function$\n select *\n from post\n where\n title ilike ('%' || search || '%') or\n content ilike ('%' || search || '%')\n $function$\n`,
cascade: false,
},
},
{
type: 'track_function',
args: {
name: `search_posts_${i}`,
schema: 'public',
},
},
],
};
};

export const createTable = () => {
return {
type: 'bulk',
args: [
{
type: 'run_sql',
args: {
sql:
'create table post (\n id serial PRIMARY KEY,\n title TEXT,\n content TEXT\n )',
cascade: false,
},
},
{
type: 'add_existing_table_or_view',
args: {
name: 'post',
schema: 'public',
},
},
],
};
};

export const dropTable = () => {
return {
type: 'bulk',
args: [
{
type: 'run_sql',
args: {
sql: 'DROP table post;',
cascade: false,
},
},
],
};
};

export const getSchema = () => 'public';
104 changes: 104 additions & 0 deletions console/cypress/integration/data/functions/spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import {
getElementFromAlias,
baseUrl,
// testCustomFunctionDefinition,
getCustomFunctionName,
getSchema,
testCustomFunctionSQL,
createTable,
dropTable,
} from '../../../helpers/dataHelpers';

import {
dropTableRequest,
dataRequest,
validateCFunc,
validateUntrackedFunc,
} from '../../validators/validators';

export const openRawSQL = () => {
// eslint-disable-line
// Open RawSQL
cy.get('a')
.contains('Data')
.click();
cy.wait(3000);
cy.get(getElementFromAlias('sql-link')).click();
cy.wait(3000);
// Match URL
cy.url().should('eq', `${baseUrl}/data/sql`);
};

export const createCustomFunctionSuccess = () => {
// cy.get('textarea').type(testCustomFunctionDefinition(1), { timeout: 10000, force: true});
// Round about way to create a function
dataRequest(createTable(1), 'success');
cy.wait(5000);
dataRequest(testCustomFunctionSQL(1), 'success');
cy.wait(5000);
// cy.get(getElementFromAlias('run-sql')).click();
// Check if the track checkbox is clicked or not
validateCFunc(getCustomFunctionName(1), getSchema(), 'success');
cy.wait(5000);
};

export const unTrackFunction = () => {
// Are you absolutely sure?\nThis action cannot be undone. This will permanently delete stitched GraphQL schema. Please type "DELETE" (in caps, without quotes) to confirm.\n
cy.visit(`data/schema/public/functions/${getCustomFunctionName(1)}/modify`);
cy.wait(5000);
cy.get(getElementFromAlias('custom-function-edit-untrack-btn')).click();
cy.wait(5000);
validateUntrackedFunc(getCustomFunctionName(1), getSchema(), 'success');
cy.wait(5000);
};

export const trackFunction = () => {
// Are you absolutely sure?\nThis action cannot be undone. This will permanently delete stitched GraphQL schema. Please type "DELETE" (in caps, without quotes) to confirm.\n
/*
cy.visit(
`data/schema/public/functions/${getCustomFunctionName(1)}/modify`,
);
*/
cy.get(
getElementFromAlias(`add-track-function-${getCustomFunctionName(1)}`)
).should('exist');
cy.get(
getElementFromAlias(`add-track-function-${getCustomFunctionName(1)}`)
).click();
cy.wait(5000);
validateCFunc(getCustomFunctionName(1), getSchema(), 'success');
cy.wait(5000);
};

export const verifyPermissionTab = () => {
// Are you absolutely sure?\nThis action cannot be undone. This will permanently delete stitched GraphQL schema. Please type "DELETE" (in caps, without quotes) to confirm.\n
cy.visit(
`data/schema/public/functions/${getCustomFunctionName(1)}/permissions`
);
cy.wait(5000);
cy.get(getElementFromAlias('custom-function-permission-btn')).should('exist');
cy.wait(5000);
};

export const deleteCustomFunction = () => {
// Are you absolutely sure?\nThis action cannot be undone. This will permanently delete stitched GraphQL schema. Please type "DELETE" (in caps, without quotes) to confirm.\n
cy.visit(`data/schema/public/functions/${getCustomFunctionName(1)}/modify`, {
onBeforeLoad(win) {
cy.stub(win, 'prompt').returns('DELETE');
},
});

cy.wait(5000);

cy.get(getElementFromAlias('custom-function-edit-delete-btn')).click();
cy.wait(5000);
cy.window()
.its('prompt')
.should('be.called');
cy.get(getElementFromAlias('delete-confirmation-error')).should('not.exist');
cy.url().should('eq', `${baseUrl}/data/schema/public`);
cy.wait(5000);

dropTableRequest(dropTable(1), 'success');
cy.wait(5000);
};
44 changes: 44 additions & 0 deletions console/cypress/integration/data/functions/test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/* eslint no-unused-vars: 0 */
/* eslint import/prefer-default-export: 0 */
import { testMode } from '../../../helpers/common';
import { setMetaData } from '../../validators/validators';

import {
openRawSQL,
createCustomFunctionSuccess,
deleteCustomFunction,
unTrackFunction,
trackFunction,
verifyPermissionTab,
} from './spec';

const setup = () => {
describe('Setup route', () => {
it('Visit the index route', () => {
// Visit the index route
cy.visit('/data');
cy.wait(5000);
// Get and set validation metadata
setMetaData();
});
});
};

export const runCreateCustomFunctionsTableTests = () => {
describe('Create Custom Function', () => {
// it(
// 'Visit Run SQL page',
// openRawSQL,
// );
it('Create a custom function and track', createCustomFunctionSuccess);
it('Untrack custom function', unTrackFunction);
it('Track custom function', trackFunction);
it('Verify permission tab', verifyPermissionTab);
it('Delete custom function', deleteCustomFunction);
});
};

if (testMode !== 'cli') {
setup();
runCreateCustomFunctionsTableTests();
}
10 changes: 5 additions & 5 deletions console/cypress/integration/data/insert-browse/spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -438,27 +438,27 @@ export const checkViewRelationship = () => {
cy.get(getElementFromAlias('ref-table')).select(getTableName(0, testName));
cy.get(getElementFromAlias('ref-col')).select(getColName(0));
cy.get(getElementFromAlias('save-button')).click();
cy.wait(300);
cy.wait(1000);
// Add relationship
cy.get(getElementFromAlias('add-rel-mod')).click();
cy.get(getElementFromAlias('obj-rel-add-0')).click();
cy.get(getElementFromAlias('suggested-rel-name'))
.clear()
.type('someRel');
cy.get(getElementFromAlias('obj-rel-save-0')).click();
cy.wait(300);
cy.wait(2000);
// Insert a row
cy.get(getElementFromAlias('table-insert-rows')).click();
cy.get(getElementFromAlias('typed-input-1')).type('1');
cy.get(getElementFromAlias('insert-save-button')).click();
cy.wait(300);
cy.wait(1000);
cy.get(getElementFromAlias('table-browse-rows')).click();
cy.wait(300);
cy.wait(1000);
cy.get('a')
.contains('View')
.first()
.click();
cy.wait(300);
cy.wait(1000);
cy.get('a')
.contains('Close')
.first()
Expand Down
6 changes: 4 additions & 2 deletions console/cypress/integration/data/modify/spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ export const passMTAddColumn = () => {
cy.get(getElementFromAlias('column-name')).type(getColName(0));
cy.get(getElementFromAlias('data-type')).select('integer');
cy.get(getElementFromAlias('add-column-button')).click();
cy.wait(2500);
cy.wait(5000);
// cy.get('.notification-success').click();
validateColumn(getTableName(0, testName), [getColName(0)], 'success');
};
Expand All @@ -121,6 +121,7 @@ export const passMCWithRightDefaultValue = () => {
.clear()
.type('1234');
cy.get(getElementFromAlias('save-button')).click();
cy.wait(15000);
};

export const passCreateForeignKey = () => {
Expand All @@ -129,11 +130,12 @@ export const passCreateForeignKey = () => {
cy.get(getElementFromAlias('ref-table')).select(getTableName(0, testName));
cy.get(getElementFromAlias('ref-col')).select(getColName(0));
cy.get(getElementFromAlias('save-button')).click();
cy.wait(500);
cy.wait(15000);
};

export const passRemoveForeignKey = () => {
cy.get(getElementFromAlias('remove-constraint-button')).click();
cy.wait(10000);
};

export const passMTDeleteCol = () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ export const createSimpleRemoteSchema = () => {
.clear()
.type(getRemoteGraphQLURL());
cy.get(getElementFromAlias('add-remote-schema-submit')).click();
cy.wait(10000);
cy.wait(15000);
validateRS(getRemoteSchemaName(1, testName), 'success');
cy.url().should(
'eq',
Expand Down Expand Up @@ -242,7 +242,7 @@ export const passWithEditRemoteSchema = () => {
.type(getRemoteSchemaName(5, testName));

cy.get(getElementFromAlias('remote-schema-edit-save-btn')).click();
cy.wait(5000);
cy.wait(10000);
validateRS(getRemoteSchemaName(5, testName), 'success');

cy.get(getElementFromAlias('remote-schemas-modify')).click();
Expand All @@ -252,7 +252,7 @@ export const passWithEditRemoteSchema = () => {
getRemoteSchemaName(5, testName)
);
cy.get(getElementFromAlias('remote-schema-edit-modify-btn')).should('exist');
cy.wait(5000);
cy.wait(7000);
};

export const deleteRemoteSchema = () => {
Expand Down
Loading

0 comments on commit 0bf2457

Please sign in to comment.