Skip to content
Snippets Groups Projects
Commit 2ce80bfc authored by Kirill Stytsenko's avatar Kirill Stytsenko
Browse files

buildQuery fn on backend w/ tests

Former-commit-id: c3dafd54
parent 0282b8a4
No related branches found
No related tags found
1 merge request!23Sprint results
...@@ -123,7 +123,7 @@ test-backend-table: ...@@ -123,7 +123,7 @@ test-backend-table:
test-frontend: test-frontend:
stage: test stage: test
script: script:
- "echo \"todo\"" - "cd fda-ui && yarn test"
deploy-all: deploy-all:
stage: deploy stage: deploy
......
<template> <template>
<div>QB</div> <div>
<div>
QB
</div>
<v-btn @click="buildQuery">Build</v-btn>
</div>
</template> </template>
<script> <script>
...@@ -11,6 +16,12 @@ export default { ...@@ -11,6 +16,12 @@ export default {
mounted () { mounted () {
}, },
methods: { methods: {
async buildQuery () {
const url = '/server-middleware/query/build'
const data = {}
const res = await this.$axios.post(url, data)
console.log(res)
}
} }
} }
</script> </script>
......
...@@ -10,11 +10,22 @@ ...@@ -10,11 +10,22 @@
"generate": "nuxt generate", "generate": "nuxt generate",
"ver": "nuxt --version", "ver": "nuxt --version",
"lint:js": "eslint --ext .js,.vue --ignore-path .gitignore .", "lint:js": "eslint --ext .js,.vue --ignore-path .gitignore .",
"lint": "yarn lint:js" "lint": "yarn lint:js",
"test": "ava --verbose",
"test:watch": "ava --watch"
},
"ava": {
"require": [
"./test/setup.js",
"@babel/polyfill"
],
"files": [
"test/unit/**/*",
"test/e2e/**/*"
]
}, },
"dependencies": { "dependencies": {
"@babel/plugin-transform-runtime": "^7.13.9", "@babel/plugin-transform-runtime": "^7.13.9",
"@babel/preset-env": "^7.13.9",
"@mdi/js": "^5.8.55", "@mdi/js": "^5.8.55",
"@nuxtjs/axios": "^5.12.2", "@nuxtjs/axios": "^5.12.2",
"@nuxtjs/proxy": "^2.1.0", "@nuxtjs/proxy": "^2.1.0",
...@@ -22,6 +33,7 @@ ...@@ -22,6 +33,7 @@
"core-js": "^3.6.5", "core-js": "^3.6.5",
"date-fns": "^2.16.1", "date-fns": "^2.16.1",
"is-docker": "^2.2.1", "is-docker": "^2.2.1",
"knex": "^0.95.6",
"multer": "^1.4.2", "multer": "^1.4.2",
"node-fetch": "^2.6.1", "node-fetch": "^2.6.1",
"nuxt": "^2.12.2", "nuxt": "^2.12.2",
...@@ -30,6 +42,11 @@ ...@@ -30,6 +42,11 @@
"vuex-persist": "^3.1.3" "vuex-persist": "^3.1.3"
}, },
"devDependencies": { "devDependencies": {
"ava": "^3.15.0",
"@babel/core": "^7.14.3",
"@babel/polyfill": "^7.12.1",
"@babel/preset-env": "^7.14.2",
"@babel/register": "^7.13.16",
"@nuxtjs/dotenv": "^1.4.1", "@nuxtjs/dotenv": "^1.4.1",
"@nuxtjs/eslint-config": "^3.1.0", "@nuxtjs/eslint-config": "^3.1.0",
"@nuxtjs/eslint-module": "^2.0.0", "@nuxtjs/eslint-module": "^2.0.0",
......
...@@ -3,6 +3,7 @@ const app = require('express')() ...@@ -3,6 +3,7 @@ const app = require('express')()
const multer = require('multer') const multer = require('multer')
const upload = multer({ dest: '/tmp' }) const upload = multer({ dest: '/tmp' })
const fetch = require('node-fetch') const fetch = require('node-fetch')
const { buildQuery } = require('./query')
// TODO extend me // TODO extend me
const colTypeMap = { const colTypeMap = {
...@@ -45,4 +46,8 @@ app.post('/table_from_csv', upload.single('file'), async (req, res) => { ...@@ -45,4 +46,8 @@ app.post('/table_from_csv', upload.single('file'), async (req, res) => {
res.json({ success: true, file, columns: entries }) res.json({ success: true, file, columns: entries })
}) })
app.post('/query/build', (req, res) => {
return res.json(buildQuery(req.body))
})
module.exports = app module.exports = app
const knex = require('knex')({ client: 'pg' })
// just for information: allowed operators
// eslint-disable-next-line
const operators = [
'=',
'<',
'>',
'<=',
'>=',
'<>',
'!=',
'like',
'not like',
'between',
'not between',
'ilike',
'not ilike',
'exists',
'not exist',
'rlike',
'not rlike',
'regexp',
'not regexp',
'match',
'&',
'|',
'^',
'<<',
'>>',
'~',
'~=',
'~*',
'!~',
'!~*',
'#',
'&&',
'@>',
'<@',
'||',
'&<',
'&>',
'-|-',
'@@',
'!!'
]
export function buildQuery ({ table, select, clauses }) {
const builder = knex(table)
clauses = clauses || []
select = select || []
builder.select(...select)
for (let i = 0; i < clauses.length; i++) {
const clause = clauses[i]
const cmd = builder[clause.type]
if (typeof cmd === 'function') {
builder[clause.type].apply(builder, clause.params)
}
}
let sql
try {
sql = builder.toQuery()
} catch (e) {
return {
error: e.message
}
}
return {
table,
statements: builder._statements,
sql
}
}
require('@babel/register')({
babelrc: false,
presets: ['@babel/preset-env']
})
const test = require('ava')
const { buildQuery } = require('../../server-middleware/query')
// for e2e nuxt see https://soshace.com/writing-end-to-end-tests-for-nuxt-apps-using-jsdom-and-ava/
test('simple select', (t) => {
const r = buildQuery({
table: 'Table'
})
t.is(r.sql, 'select * from "Table"')
})
test('select some columns', (t) => {
const r = buildQuery({
table: 'Table',
select: ['aaa', 'bbb']
})
t.is(r.sql, 'select "aaa", "bbb" from "Table"')
})
test('simple where clause', (t) => {
const r = buildQuery({
table: 'Table',
clauses: [
{ type: 'where', params: ['foo', '=', 42] }
]
})
t.is(r.sql, 'select * from "Table" where "foo" = 42')
})
test('using unallowed operator', (t) => {
const r = buildQuery({
table: 'Table',
clauses: [
{ type: 'where', params: ['foo', 'UNKNOWN', 42] }
]
})
t.is(r.sql, undefined)
t.is(r.error, 'The operator "UNKNOWN" is not permitted')
})
test('where clause with explicit "and"', (t) => {
const r = buildQuery({
table: 'Table',
clauses: [
{ type: 'where', params: ['foo', '=', 42] },
{ type: 'and' }, // here, unlike below
{ type: 'where', params: ['bar', '=', 42] }
]
})
t.is(r.sql, 'select * from "Table" where "foo" = 42 and "bar" = 42')
})
test('where clause with implicit "and"', (t) => {
const r = buildQuery({
table: 'Table',
clauses: [
{ type: 'where', params: ['foo', '=', 42] },
// not here, unlike above
{ type: 'where', params: ['bar', '=', 42] }
]
})
t.is(r.sql, 'select * from "Table" where "foo" = 42 and "bar" = 42')
})
test('where clause with "or"', (t) => {
const r = buildQuery({
table: 'Table',
clauses: [
{ type: 'where', params: ['foo', '=', 42] },
{ type: 'or' },
{ type: 'where', params: ['bar', '=', 42] }
]
})
t.is(r.sql, 'select * from "Table" where "foo" = 42 or "bar" = 42')
})
This diff is collapsed.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment