@budibase/server 1.0.80 → 1.0.81-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (322) hide show
  1. package/__mocks__/node-fetch.ts +1 -0
  2. package/builder/assets/{index.c8d1e8f0.css → index.8b1dc06c.css} +2 -2
  3. package/builder/assets/index.e4d4c510.js +1291 -0
  4. package/builder/assets/{vendor.20f80cec.js → vendor.a7c6ad0a.js} +190 -216
  5. package/builder/index.html +3 -3
  6. package/coverage/clover.xml +2531 -2440
  7. package/coverage/coverage-final.json +138 -137
  8. package/coverage/lcov-report/api/controllers/analytics.js.html +6 -6
  9. package/coverage/lcov-report/api/controllers/apikeys.js.html +6 -6
  10. package/coverage/lcov-report/api/controllers/application.js.html +152 -149
  11. package/coverage/lcov-report/api/controllers/auth.js.html +7 -7
  12. package/coverage/lcov-report/api/controllers/automation.js.html +21 -21
  13. package/coverage/lcov-report/api/controllers/backup.js.html +3 -3
  14. package/coverage/lcov-report/api/controllers/cloud.js.html +11 -11
  15. package/coverage/lcov-report/api/controllers/component.js.html +5 -5
  16. package/coverage/lcov-report/api/controllers/datasource.js.html +16 -16
  17. package/coverage/lcov-report/api/controllers/dev.js.html +19 -19
  18. package/coverage/lcov-report/api/controllers/index.html +16 -16
  19. package/coverage/lcov-report/api/controllers/integration.js.html +4 -4
  20. package/coverage/lcov-report/api/controllers/layout.js.html +6 -6
  21. package/coverage/lcov-report/api/controllers/metadata.js.html +9 -9
  22. package/coverage/lcov-report/api/controllers/migrations.js.html +4 -4
  23. package/coverage/lcov-report/api/controllers/permission.js.html +15 -15
  24. package/coverage/lcov-report/api/controllers/query/index.html +1 -1
  25. package/coverage/lcov-report/api/controllers/query/index.js.html +26 -26
  26. package/coverage/lcov-report/api/controllers/query/validation.js.html +10 -10
  27. package/coverage/lcov-report/api/controllers/role.js.html +9 -9
  28. package/coverage/lcov-report/api/controllers/routing.js.html +9 -9
  29. package/coverage/lcov-report/api/controllers/row/external.js.html +86 -23
  30. package/coverage/lcov-report/api/controllers/row/index.html +46 -46
  31. package/coverage/lcov-report/api/controllers/row/index.js.html +76 -49
  32. package/coverage/lcov-report/api/controllers/row/internal.js.html +144 -84
  33. package/coverage/lcov-report/api/controllers/row/internalSearch.js.html +204 -204
  34. package/coverage/lcov-report/api/controllers/row/staticFormula.js.html +24 -24
  35. package/coverage/lcov-report/api/controllers/row/utils.js.html +29 -29
  36. package/coverage/lcov-report/api/controllers/screen.js.html +7 -7
  37. package/coverage/lcov-report/api/controllers/script.js.html +4 -4
  38. package/coverage/lcov-report/api/controllers/table/bulkFormula.js.html +49 -49
  39. package/coverage/lcov-report/api/controllers/table/external.js.html +62 -20
  40. package/coverage/lcov-report/api/controllers/table/index.html +20 -20
  41. package/coverage/lcov-report/api/controllers/table/index.js.html +47 -44
  42. package/coverage/lcov-report/api/controllers/table/internal.js.html +50 -50
  43. package/coverage/lcov-report/api/controllers/table/utils.js.html +80 -80
  44. package/coverage/lcov-report/api/controllers/templates.js.html +5 -5
  45. package/coverage/lcov-report/api/controllers/user.js.html +19 -19
  46. package/coverage/lcov-report/api/controllers/view/exporters.js.html +4 -4
  47. package/coverage/lcov-report/api/controllers/view/index.html +1 -1
  48. package/coverage/lcov-report/api/controllers/view/index.js.html +14 -14
  49. package/coverage/lcov-report/api/controllers/view/utils.js.html +12 -12
  50. package/coverage/lcov-report/api/controllers/view/viewBuilder.js.html +7 -7
  51. package/coverage/lcov-report/api/controllers/webhook.js.html +18 -27
  52. package/coverage/lcov-report/api/index.html +10 -10
  53. package/coverage/lcov-report/api/index.js.html +37 -28
  54. package/coverage/lcov-report/api/routes/analytics.js.html +6 -6
  55. package/coverage/lcov-report/api/routes/apikeys.js.html +8 -8
  56. package/coverage/lcov-report/api/routes/application.js.html +9 -9
  57. package/coverage/lcov-report/api/routes/auth.js.html +6 -6
  58. package/coverage/lcov-report/api/routes/automation.js.html +19 -109
  59. package/coverage/lcov-report/api/routes/backup.js.html +8 -8
  60. package/coverage/lcov-report/api/routes/cloud.js.html +8 -8
  61. package/coverage/lcov-report/api/routes/component.js.html +8 -8
  62. package/coverage/lcov-report/api/routes/datasource.js.html +18 -156
  63. package/coverage/lcov-report/api/routes/deploy.js.html +8 -8
  64. package/coverage/lcov-report/api/routes/dev.js.html +13 -13
  65. package/coverage/lcov-report/api/routes/index.html +35 -35
  66. package/coverage/lcov-report/api/routes/index.js.html +38 -32
  67. package/coverage/lcov-report/api/routes/integration.js.html +8 -8
  68. package/coverage/lcov-report/api/routes/layout.js.html +8 -8
  69. package/coverage/lcov-report/api/routes/metadata.js.html +9 -9
  70. package/coverage/lcov-report/api/routes/migrations.js.html +7 -7
  71. package/coverage/lcov-report/api/routes/permission.js.html +16 -58
  72. package/coverage/lcov-report/api/routes/query.js.html +10 -10
  73. package/coverage/lcov-report/api/routes/role.js.html +15 -78
  74. package/coverage/lcov-report/api/routes/routing.js.html +8 -8
  75. package/coverage/lcov-report/api/routes/row.js.html +80 -14
  76. package/coverage/lcov-report/api/routes/screen.js.html +14 -95
  77. package/coverage/lcov-report/api/routes/script.js.html +1 -1
  78. package/coverage/lcov-report/api/routes/static.js.html +13 -13
  79. package/coverage/lcov-report/api/routes/table.js.html +17 -62
  80. package/coverage/lcov-report/api/routes/templates.js.html +8 -8
  81. package/coverage/lcov-report/api/routes/user.js.html +8 -8
  82. package/coverage/lcov-report/api/routes/utils/index.html +111 -0
  83. package/coverage/lcov-report/api/routes/utils/validators.js.html +737 -0
  84. package/coverage/lcov-report/api/routes/view.js.html +10 -10
  85. package/coverage/lcov-report/api/routes/webhook.js.html +14 -62
  86. package/coverage/lcov-report/automations/actions.js.html +24 -24
  87. package/coverage/lcov-report/automations/automationUtils.js.html +5 -5
  88. package/coverage/lcov-report/automations/bullboard.js.html +16 -16
  89. package/coverage/lcov-report/automations/index.html +1 -1
  90. package/coverage/lcov-report/automations/index.js.html +7 -7
  91. package/coverage/lcov-report/automations/steps/bash.js.html +6 -6
  92. package/coverage/lcov-report/automations/steps/createRow.js.html +7 -7
  93. package/coverage/lcov-report/automations/steps/delay.js.html +4 -4
  94. package/coverage/lcov-report/automations/steps/deleteRow.js.html +7 -7
  95. package/coverage/lcov-report/automations/steps/discord.js.html +7 -7
  96. package/coverage/lcov-report/automations/steps/executeQuery.js.html +6 -6
  97. package/coverage/lcov-report/automations/steps/executeScript.js.html +6 -6
  98. package/coverage/lcov-report/automations/steps/filter.js.html +12 -9
  99. package/coverage/lcov-report/automations/steps/index.html +1 -1
  100. package/coverage/lcov-report/automations/steps/integromat.js.html +5 -5
  101. package/coverage/lcov-report/automations/steps/outgoingWebhook.js.html +8 -8
  102. package/coverage/lcov-report/automations/steps/queryRows.js.html +11 -11
  103. package/coverage/lcov-report/automations/steps/sendSmtpEmail.js.html +5 -5
  104. package/coverage/lcov-report/automations/steps/serverLog.js.html +3 -3
  105. package/coverage/lcov-report/automations/steps/slack.js.html +5 -5
  106. package/coverage/lcov-report/automations/steps/updateRow.js.html +6 -6
  107. package/coverage/lcov-report/automations/steps/utils.js.html +3 -3
  108. package/coverage/lcov-report/automations/steps/zapier.js.html +5 -5
  109. package/coverage/lcov-report/automations/triggerInfo/app.js.html +2 -2
  110. package/coverage/lcov-report/automations/triggerInfo/cron.js.html +2 -2
  111. package/coverage/lcov-report/automations/triggerInfo/index.html +1 -1
  112. package/coverage/lcov-report/automations/triggerInfo/index.js.html +8 -8
  113. package/coverage/lcov-report/automations/triggerInfo/rowDeleted.js.html +2 -2
  114. package/coverage/lcov-report/automations/triggerInfo/rowSaved.js.html +2 -2
  115. package/coverage/lcov-report/automations/triggerInfo/rowUpdated.js.html +2 -2
  116. package/coverage/lcov-report/automations/triggerInfo/webhook.js.html +2 -2
  117. package/coverage/lcov-report/automations/triggers.js.html +26 -26
  118. package/coverage/lcov-report/automations/utils.js.html +35 -35
  119. package/coverage/lcov-report/constants/index.html +5 -5
  120. package/coverage/lcov-report/constants/index.js.html +40 -28
  121. package/coverage/lcov-report/constants/layouts.js.html +5 -5
  122. package/coverage/lcov-report/constants/screens.js.html +4 -4
  123. package/coverage/lcov-report/db/client.js.html +18 -18
  124. package/coverage/lcov-report/db/inMemoryView.js.html +7 -7
  125. package/coverage/lcov-report/db/index.html +15 -15
  126. package/coverage/lcov-report/db/index.js.html +3 -3
  127. package/coverage/lcov-report/db/linkedRows/LinkController.js.html +21 -21
  128. package/coverage/lcov-report/db/linkedRows/index.html +1 -1
  129. package/coverage/lcov-report/db/linkedRows/index.js.html +36 -36
  130. package/coverage/lcov-report/db/linkedRows/linkUtils.js.html +30 -30
  131. package/coverage/lcov-report/db/newid.js.html +4 -4
  132. package/coverage/lcov-report/db/utils.js.html +123 -87
  133. package/coverage/lcov-report/events/AutomationEmitter.js.html +1 -1
  134. package/coverage/lcov-report/events/index.html +1 -1
  135. package/coverage/lcov-report/events/index.js.html +8 -8
  136. package/coverage/lcov-report/events/utils.js.html +18 -18
  137. package/coverage/lcov-report/index.html +91 -76
  138. package/coverage/lcov-report/integrations/tests/TestConfiguration.js.html +1 -1
  139. package/coverage/lcov-report/integrations/tests/index.html +1 -1
  140. package/coverage/lcov-report/middleware/appInfo.js.html +5 -5
  141. package/coverage/lcov-report/middleware/authorized.js.html +29 -29
  142. package/coverage/lcov-report/middleware/builder.js.html +16 -16
  143. package/coverage/lcov-report/middleware/currentapp.js.html +44 -44
  144. package/coverage/lcov-report/middleware/index.html +1 -1
  145. package/coverage/lcov-report/middleware/joi-validator.js.html +14 -14
  146. package/coverage/lcov-report/middleware/resourceId.js.html +29 -29
  147. package/coverage/lcov-report/middleware/selfhost.js.html +1 -1
  148. package/coverage/lcov-report/middleware/usageQuota.js.html +17 -17
  149. package/coverage/lcov-report/middleware/utils.js.html +4 -4
  150. package/coverage/lcov-report/threads/automation.js.html +1 -1
  151. package/coverage/lcov-report/threads/index.html +19 -19
  152. package/coverage/lcov-report/threads/index.js.html +10 -10
  153. package/coverage/lcov-report/threads/query.js.html +123 -39
  154. package/coverage/lcov-report/threads/utils.js.html +14 -14
  155. package/coverage/lcov-report/utilities/bcrypt.js.html +1 -1
  156. package/coverage/lcov-report/utilities/budibaseDir.js.html +7 -7
  157. package/coverage/lcov-report/utilities/centralPath.js.html +4 -4
  158. package/coverage/lcov-report/utilities/csvParser.js.html +6 -6
  159. package/coverage/lcov-report/utilities/global.js.html +28 -28
  160. package/coverage/lcov-report/utilities/index.html +18 -18
  161. package/coverage/lcov-report/utilities/index.js.html +24 -24
  162. package/coverage/lcov-report/utilities/queue/inMemoryQueue.js.html +9 -9
  163. package/coverage/lcov-report/utilities/queue/index.html +1 -1
  164. package/coverage/lcov-report/utilities/routing/index.html +1 -1
  165. package/coverage/lcov-report/utilities/routing/index.js.html +6 -6
  166. package/coverage/lcov-report/utilities/rowProcessor/index.html +1 -1
  167. package/coverage/lcov-report/utilities/rowProcessor/index.js.html +60 -60
  168. package/coverage/lcov-report/utilities/rowProcessor/utils.js.html +13 -13
  169. package/coverage/lcov-report/utilities/scriptRunner.js.html +5 -5
  170. package/coverage/lcov-report/utilities/security.js.html +8 -8
  171. package/coverage/lcov-report/utilities/statusCodes.js.html +1 -1
  172. package/coverage/lcov-report/utilities/usageQuota/index.html +1 -1
  173. package/coverage/lcov-report/utilities/usageQuota/index.js.html +12 -12
  174. package/coverage/lcov-report/utilities/usageQuota/rows.js.html +8 -8
  175. package/coverage/lcov-report/utilities/usageQuota/usageQuoteReset.js.html +1 -1
  176. package/coverage/lcov-report/utilities/users.js.html +5 -5
  177. package/coverage/lcov-report/utilities/workerRequests.js.html +200 -53
  178. package/coverage/lcov.info +3555 -3411
  179. package/dist/api/controllers/application.js +1 -0
  180. package/dist/api/controllers/public/applications.js +94 -0
  181. package/dist/api/controllers/public/mapping/applications.js +29 -0
  182. package/dist/api/controllers/public/mapping/index.js +11 -0
  183. package/dist/api/controllers/public/mapping/queries.js +36 -0
  184. package/dist/api/controllers/public/mapping/rows.js +24 -0
  185. package/dist/api/controllers/public/mapping/tables.js +23 -0
  186. package/dist/api/controllers/public/mapping/types.js +2 -0
  187. package/dist/api/controllers/public/mapping/users.js +29 -0
  188. package/dist/api/controllers/public/queries.js +38 -0
  189. package/dist/api/controllers/public/rows.js +97 -0
  190. package/dist/api/controllers/public/tables.js +75 -0
  191. package/dist/api/controllers/public/users.js +95 -0
  192. package/dist/api/controllers/public/utils.js +49 -0
  193. package/dist/api/controllers/row/external.js +18 -0
  194. package/dist/api/controllers/row/index.js +11 -0
  195. package/dist/api/controllers/row/internal.js +15 -1
  196. package/dist/api/controllers/table/external.js +8 -2
  197. package/dist/api/controllers/table/index.js +2 -1
  198. package/dist/api/controllers/webhook.js +3 -5
  199. package/dist/api/index.js +3 -1
  200. package/dist/api/routes/automation.js +3 -31
  201. package/dist/api/routes/datasource.js +3 -50
  202. package/dist/api/routes/index.js +2 -0
  203. package/dist/api/routes/permission.js +4 -14
  204. package/dist/api/routes/public/applications.js +141 -0
  205. package/dist/api/routes/public/index.js +101 -0
  206. package/dist/api/routes/public/middleware/mapper.js +94 -0
  207. package/dist/api/routes/public/queries.js +77 -0
  208. package/dist/api/routes/public/rows.js +229 -0
  209. package/dist/api/routes/public/tables.js +154 -0
  210. package/dist/api/routes/public/users.js +137 -0
  211. package/dist/api/routes/public/utils/Endpoint.js +36 -0
  212. package/dist/api/routes/role.js +3 -19
  213. package/dist/api/routes/row.js +18 -5
  214. package/dist/api/routes/screen.js +2 -23
  215. package/dist/api/routes/table.js +3 -17
  216. package/dist/api/routes/tests/utilities/index.js +23 -0
  217. package/dist/api/routes/utils/validators.js +200 -0
  218. package/dist/api/routes/webhook.js +2 -17
  219. package/dist/automations/steps/filter.js +2 -2
  220. package/dist/automations/steps/queryRows.js +1 -1
  221. package/dist/automations/utils.js +2 -2
  222. package/dist/constants/index.js +3 -0
  223. package/dist/db/utils.js +11 -0
  224. package/dist/definitions/openapi.js +6 -0
  225. package/dist/environment.js +1 -0
  226. package/dist/integrations/base/sql.js +16 -1
  227. package/dist/integrations/base/sqlTable.js +21 -9
  228. package/dist/integrations/googlesheets.js +3 -0
  229. package/dist/integrations/microsoftSqlServer.js +60 -43
  230. package/dist/integrations/mysql.js +3 -0
  231. package/dist/integrations/oracle.js +14 -19
  232. package/dist/integrations/postgres.js +34 -28
  233. package/dist/integrations/utils.js +32 -15
  234. package/dist/package.json +11 -7
  235. package/dist/tests/utilities/TestConfiguration.js +25 -8
  236. package/dist/threads/query.js +33 -8
  237. package/dist/tsconfig.tsbuildinfo +1 -1
  238. package/dist/utilities/workerRequests.js +50 -15
  239. package/package.json +12 -8
  240. package/scripts/integrations/mssql/data/setup.sql +18 -1
  241. package/scripts/integrations/oracle/oracle.md +2 -2
  242. package/scripts/integrations/postgres/init.sql +11 -3
  243. package/scripts/likeCypress.ts +9 -6
  244. package/specs/generate.js +94 -0
  245. package/specs/openapi.json +2232 -0
  246. package/specs/openapi.yaml +1538 -0
  247. package/specs/parameters.js +59 -0
  248. package/specs/resources/application.js +101 -0
  249. package/specs/resources/index.js +24 -0
  250. package/specs/resources/misc.js +12 -0
  251. package/specs/resources/query.js +189 -0
  252. package/specs/resources/row.js +125 -0
  253. package/specs/resources/table.js +191 -0
  254. package/specs/resources/user.js +126 -0
  255. package/specs/resources/utils/Resource.js +26 -0
  256. package/specs/resources/utils/index.js +11 -0
  257. package/specs/security.js +7 -0
  258. package/src/api/controllers/application.js +1 -0
  259. package/src/api/controllers/public/applications.ts +74 -0
  260. package/src/api/controllers/public/mapping/applications.ts +32 -0
  261. package/src/api/controllers/public/mapping/index.ts +13 -0
  262. package/src/api/controllers/public/mapping/queries.ts +39 -0
  263. package/src/api/controllers/public/mapping/rows.ts +31 -0
  264. package/src/api/controllers/public/mapping/tables.ts +26 -0
  265. package/src/api/controllers/public/mapping/types.ts +13 -0
  266. package/src/api/controllers/public/mapping/users.ts +32 -0
  267. package/src/api/controllers/public/queries.ts +20 -0
  268. package/src/api/controllers/public/rows.ts +77 -0
  269. package/src/api/controllers/public/tables.ts +56 -0
  270. package/src/api/controllers/public/users.ts +82 -0
  271. package/src/api/controllers/public/utils.ts +38 -0
  272. package/src/api/controllers/row/ExternalRequest.ts +1 -1
  273. package/src/api/controllers/row/external.js +21 -0
  274. package/src/api/controllers/row/index.js +9 -0
  275. package/src/api/controllers/row/internal.js +20 -0
  276. package/src/api/controllers/table/external.js +16 -2
  277. package/src/api/controllers/table/index.js +2 -1
  278. package/src/api/controllers/webhook.js +3 -6
  279. package/src/api/index.js +4 -1
  280. package/src/api/routes/automation.js +3 -33
  281. package/src/api/routes/datasource.js +6 -52
  282. package/src/api/routes/index.js +2 -0
  283. package/src/api/routes/permission.js +4 -18
  284. package/src/api/routes/public/applications.ts +156 -0
  285. package/src/api/routes/public/index.ts +118 -0
  286. package/src/api/routes/public/middleware/mapper.ts +81 -0
  287. package/src/api/routes/public/queries.ts +81 -0
  288. package/src/api/routes/public/rows.ts +242 -0
  289. package/src/api/routes/public/tables.ts +169 -0
  290. package/src/api/routes/public/tests/compare.spec.js +184 -0
  291. package/src/api/routes/public/users.ts +144 -0
  292. package/src/api/routes/public/utils/Endpoint.ts +51 -0
  293. package/src/api/routes/role.js +3 -24
  294. package/src/api/routes/row.js +24 -2
  295. package/src/api/routes/screen.js +2 -29
  296. package/src/api/routes/table.js +4 -19
  297. package/src/api/routes/tests/utilities/index.js +24 -0
  298. package/src/api/routes/utils/validators.js +219 -0
  299. package/src/api/routes/webhook.js +2 -18
  300. package/src/automations/steps/filter.js +3 -2
  301. package/src/automations/steps/queryRows.js +1 -1
  302. package/src/automations/utils.js +2 -2
  303. package/src/constants/index.js +4 -0
  304. package/src/db/utils.js +12 -0
  305. package/src/definitions/common.ts +4 -0
  306. package/src/definitions/datasource.ts +7 -0
  307. package/src/definitions/openapi.ts +943 -0
  308. package/src/environment.js +1 -0
  309. package/src/integrations/base/datasourcePlus.ts +3 -0
  310. package/src/integrations/base/sql.ts +16 -1
  311. package/src/integrations/base/sqlTable.ts +35 -13
  312. package/src/integrations/googlesheets.ts +5 -2
  313. package/src/integrations/microsoftSqlServer.ts +86 -61
  314. package/src/integrations/mysql.ts +4 -0
  315. package/src/integrations/oracle.ts +27 -35
  316. package/src/integrations/postgres.ts +33 -26
  317. package/src/integrations/utils.ts +43 -15
  318. package/src/tests/utilities/TestConfiguration.js +23 -2
  319. package/src/threads/query.js +37 -9
  320. package/src/utilities/workerRequests.js +65 -16
  321. package/builder/assets/index.22a39cc9.js +0 -1352
  322. package/scripts/proxy/generateProxyConfig.js +0 -70
@@ -45,6 +45,7 @@ module.exports = {
45
45
  INTERNAL_API_KEY: process.env.INTERNAL_API_KEY,
46
46
  MULTI_TENANCY: process.env.MULTI_TENANCY,
47
47
  HTTP_MIGRATIONS: process.env.HTTP_MIGRATIONS,
48
+ API_REQ_LIMIT_PER_SEC: process.env.API_REQ_LIMIT_PER_SEC,
48
49
  // environment
49
50
  NODE_ENV: process.env.NODE_ENV,
50
51
  JEST_WORKER_ID: process.env.JEST_WORKER_ID,
@@ -5,5 +5,8 @@ export interface DatasourcePlus extends IntegrationBase {
5
5
  tables: Record<string, Table>
6
6
  schemaErrors: Record<string, string>
7
7
 
8
+ // if the datasource supports the use of bindings directly (to protect against SQL injection)
9
+ // this returns the format of the identifier
10
+ getBindingIdentifier(): string
8
11
  buildSchema(datasourceId: string, entities: Record<string, Table>): any
9
12
  }
@@ -249,6 +249,9 @@ class InternalBuilder {
249
249
  create(knex: Knex, json: QueryJson, opts: QueryOptions): KnexQuery {
250
250
  const { endpoint, body } = json
251
251
  let query: KnexQuery = knex(endpoint.entityId)
252
+ if (endpoint.schema) {
253
+ query = query.withSchema(endpoint.schema)
254
+ }
252
255
  const parsedBody = parseBody(body)
253
256
  // make sure no null values in body for creation
254
257
  for (let [key, value] of Object.entries(parsedBody)) {
@@ -267,6 +270,9 @@ class InternalBuilder {
267
270
  bulkCreate(knex: Knex, json: QueryJson): KnexQuery {
268
271
  const { endpoint, body } = json
269
272
  let query: KnexQuery = knex(endpoint.entityId)
273
+ if (endpoint.schema) {
274
+ query = query.withSchema(endpoint.schema)
275
+ }
270
276
  if (!Array.isArray(body)) {
271
277
  return query
272
278
  }
@@ -275,7 +281,7 @@ class InternalBuilder {
275
281
  }
276
282
 
277
283
  read(knex: Knex, json: QueryJson, limit: number): KnexQuery {
278
- let { endpoint, resource, filters, sort, paginate, relationships } = json
284
+ let { endpoint, resource, filters, paginate, relationships } = json
279
285
  const tableName = endpoint.entityId
280
286
  // select all if not specified
281
287
  if (!resource) {
@@ -302,6 +308,9 @@ class InternalBuilder {
302
308
  }
303
309
  // start building the query
304
310
  let query: KnexQuery = knex(tableName).limit(foundLimit)
311
+ if (endpoint.schema) {
312
+ query = query.withSchema(endpoint.schema)
313
+ }
305
314
  if (foundOffset) {
306
315
  query = query.offset(foundOffset)
307
316
  }
@@ -331,6 +340,9 @@ class InternalBuilder {
331
340
  update(knex: Knex, json: QueryJson, opts: QueryOptions): KnexQuery {
332
341
  const { endpoint, body, filters } = json
333
342
  let query: KnexQuery = knex(endpoint.entityId)
343
+ if (endpoint.schema) {
344
+ query = query.withSchema(endpoint.schema)
345
+ }
334
346
  const parsedBody = parseBody(body)
335
347
  query = this.addFilters(query, filters, { tableName: endpoint.entityId })
336
348
  // mysql can't use returning
@@ -344,6 +356,9 @@ class InternalBuilder {
344
356
  delete(knex: Knex, json: QueryJson, opts: QueryOptions): KnexQuery {
345
357
  const { endpoint, filters } = json
346
358
  let query: KnexQuery = knex(endpoint.entityId)
359
+ if (endpoint.schema) {
360
+ query = query.withSchema(endpoint.schema)
361
+ }
347
362
  query = this.addFilters(query, filters, { tableName: endpoint.entityId })
348
363
  // mysql can't use returning
349
364
  if (opts.disableReturning) {
@@ -1,6 +1,10 @@
1
1
  import { Knex, knex } from "knex"
2
2
  import { Table } from "../../definitions/common"
3
- import { Operation, QueryJson } from "../../definitions/datasource"
3
+ import {
4
+ Operation,
5
+ QueryJson,
6
+ RenameColumn,
7
+ } from "../../definitions/datasource"
4
8
  import { breakExternalTableId } from "../utils"
5
9
  import SchemaBuilder = Knex.SchemaBuilder
6
10
  import CreateTableBuilder = Knex.CreateTableBuilder
@@ -10,7 +14,8 @@ function generateSchema(
10
14
  schema: CreateTableBuilder,
11
15
  table: Table,
12
16
  tables: Record<string, Table>,
13
- oldTable: null | Table = null
17
+ oldTable: null | Table = null,
18
+ renamed?: RenameColumn
14
19
  ) {
15
20
  let primaryKey = table && table.primary ? table.primary[0] : null
16
21
  const columns = Object.values(table.schema)
@@ -29,7 +34,11 @@ function generateSchema(
29
34
  for (let [key, column] of Object.entries(table.schema)) {
30
35
  // skip things that are already correct
31
36
  const oldColumn = oldTable ? oldTable.schema[key] : null
32
- if ((oldColumn && oldColumn.type) || (primaryKey === key && !isJunction)) {
37
+ if (
38
+ (oldColumn && oldColumn.type) ||
39
+ (primaryKey === key && !isJunction) ||
40
+ renamed?.updated === key
41
+ ) {
33
42
  continue
34
43
  }
35
44
  switch (column.type) {
@@ -81,6 +90,10 @@ function generateSchema(
81
90
  }
82
91
  }
83
92
 
93
+ if (renamed) {
94
+ schema.renameColumn(renamed.old, renamed.updated)
95
+ }
96
+
84
97
  // need to check if any columns have been deleted
85
98
  if (oldTable) {
86
99
  const deletedColumns = Object.entries(oldTable.schema)
@@ -90,6 +103,9 @@ function generateSchema(
90
103
  )
91
104
  .map(([key]) => key)
92
105
  deletedColumns.forEach(key => {
106
+ if (renamed?.old === key) {
107
+ return
108
+ }
93
109
  if (oldTable.constrained && oldTable.constrained.indexOf(key) !== -1) {
94
110
  schema.dropForeign(key)
95
111
  }
@@ -101,28 +117,29 @@ function generateSchema(
101
117
  }
102
118
 
103
119
  function buildCreateTable(
104
- knex: Knex,
120
+ knex: SchemaBuilder,
105
121
  table: Table,
106
122
  tables: Record<string, Table>
107
123
  ): SchemaBuilder {
108
- return knex.schema.createTable(table.name, schema => {
124
+ return knex.createTable(table.name, schema => {
109
125
  generateSchema(schema, table, tables)
110
126
  })
111
127
  }
112
128
 
113
129
  function buildUpdateTable(
114
- knex: Knex,
130
+ knex: SchemaBuilder,
115
131
  table: Table,
116
132
  tables: Record<string, Table>,
117
- oldTable: Table
133
+ oldTable: Table,
134
+ renamed: RenameColumn
118
135
  ): SchemaBuilder {
119
- return knex.schema.alterTable(table.name, schema => {
120
- generateSchema(schema, table, tables, oldTable)
136
+ return knex.alterTable(table.name, schema => {
137
+ generateSchema(schema, table, tables, oldTable, renamed)
121
138
  })
122
139
  }
123
140
 
124
- function buildDeleteTable(knex: Knex, table: Table): SchemaBuilder {
125
- return knex.schema.dropTable(table.name)
141
+ function buildDeleteTable(knex: SchemaBuilder, table: Table): SchemaBuilder {
142
+ return knex.dropTable(table.name)
126
143
  }
127
144
 
128
145
  class SqlTableQueryBuilder {
@@ -146,7 +163,11 @@ class SqlTableQueryBuilder {
146
163
  }
147
164
 
148
165
  _tableQuery(json: QueryJson): any {
149
- const client = knex({ client: this.sqlClient })
166
+ let client = knex({ client: this.sqlClient }).schema
167
+ if (json?.endpoint?.schema) {
168
+ client = client.withSchema(json.endpoint.schema)
169
+ }
170
+
150
171
  let query
151
172
  if (!json.table || !json.meta || !json.meta.tables) {
152
173
  throw "Cannot execute without table being specified"
@@ -163,7 +184,8 @@ class SqlTableQueryBuilder {
163
184
  client,
164
185
  json.table,
165
186
  json.meta.tables,
166
- json.meta.table
187
+ json.meta.table,
188
+ json.meta.renamed
167
189
  )
168
190
  break
169
191
  case Operation.DELETE_TABLE:
@@ -6,11 +6,10 @@ import {
6
6
  } from "../definitions/datasource"
7
7
  import { OAuth2Client } from "google-auth-library"
8
8
  import { DatasourcePlus } from "./base/datasourcePlus"
9
- import { Row, Table, TableSchema } from "../definitions/common"
9
+ import { Table, TableSchema } from "../definitions/common"
10
10
  import { buildExternalTableId } from "./utils"
11
11
  import { DataSourceOperation, FieldTypes } from "../constants"
12
12
  import { GoogleSpreadsheet } from "google-spreadsheet"
13
- import { table } from "console"
14
13
 
15
14
  module GoogleSheetsModule {
16
15
  const { getGlobalDB } = require("@budibase/backend-core/tenancy")
@@ -112,6 +111,10 @@ module GoogleSheetsModule {
112
111
  this.client = new GoogleSpreadsheet(spreadsheetId)
113
112
  }
114
113
 
114
+ getBindingIdentifier() {
115
+ return ""
116
+ }
117
+
115
118
  /**
116
119
  * Pull the spreadsheet ID out from a valid google sheets URL
117
120
  * @param spreadsheetId - the URL or standard spreadsheetId of the google sheet
@@ -19,6 +19,7 @@ import { Table, TableSchema } from "../definitions/common"
19
19
  module MSSQLModule {
20
20
  const sqlServer = require("mssql")
21
21
  const Sql = require("./base/sql")
22
+ const DEFAULT_SCHEMA = "dbo"
22
23
 
23
24
  interface MSSQLConfig {
24
25
  user: string
@@ -26,9 +27,17 @@ module MSSQLModule {
26
27
  server: string
27
28
  port: number
28
29
  database: string
30
+ schema: string
29
31
  encrypt?: boolean
30
32
  }
31
33
 
34
+ interface TablesResponse {
35
+ TABLE_CATALOG: string
36
+ TABLE_SCHEMA: string
37
+ TABLE_NAME: string
38
+ TABLE_TYPE: string
39
+ }
40
+
32
41
  const SCHEMA: Integration = {
33
42
  docs: "https://github.com/tediousjs/node-mssql",
34
43
  plus: true,
@@ -58,6 +67,10 @@ module MSSQLModule {
58
67
  type: DatasourceFieldTypes.STRING,
59
68
  default: "root",
60
69
  },
70
+ schema: {
71
+ type: DatasourceFieldTypes.STRING,
72
+ default: DEFAULT_SCHEMA,
73
+ },
61
74
  encrypt: {
62
75
  type: DatasourceFieldTypes.BOOLEAN,
63
76
  default: true,
@@ -79,34 +92,9 @@ module MSSQLModule {
79
92
  },
80
93
  }
81
94
 
82
- async function internalQuery(
83
- client: any,
84
- query: SqlQuery,
85
- operation: string | undefined = undefined
86
- ) {
87
- const request = client.request()
88
- try {
89
- if (Array.isArray(query.bindings)) {
90
- let count = 0
91
- for (let binding of query.bindings) {
92
- request.input(`p${count++}`, binding)
93
- }
94
- }
95
- // this is a hack to get the inserted ID back,
96
- // no way to do this with Knex nicely
97
- const sql =
98
- operation === Operation.CREATE
99
- ? `${query.sql}; SELECT SCOPE_IDENTITY() AS id;`
100
- : query.sql
101
- return await request.query(sql)
102
- } catch (err) {
103
- // @ts-ignore
104
- throw new Error(err)
105
- }
106
- }
107
-
108
95
  class SqlServerIntegration extends Sql implements DatasourcePlus {
109
96
  private readonly config: MSSQLConfig
97
+ private index: number = 0
110
98
  static pool: any
111
99
  public tables: Record<string, Table> = {}
112
100
  public schemaErrors: Record<string, string> = {}
@@ -121,6 +109,62 @@ module MSSQLModule {
121
109
  TABLES_SQL =
122
110
  "SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE='BASE TABLE'"
123
111
 
112
+ constructor(config: MSSQLConfig) {
113
+ super(SqlClients.MS_SQL)
114
+ this.config = config
115
+ const clientCfg = {
116
+ ...this.config,
117
+ options: {
118
+ encrypt: this.config.encrypt,
119
+ enableArithAbort: true,
120
+ },
121
+ }
122
+ delete clientCfg.encrypt
123
+ if (!this.pool) {
124
+ this.pool = new sqlServer.ConnectionPool(clientCfg)
125
+ }
126
+ }
127
+
128
+ getBindingIdentifier(): string {
129
+ return `(@p${this.index++})`
130
+ }
131
+
132
+ async connect() {
133
+ try {
134
+ this.client = await this.pool.connect()
135
+ } catch (err) {
136
+ // @ts-ignore
137
+ throw new Error(err)
138
+ }
139
+ }
140
+
141
+ async internalQuery(
142
+ query: SqlQuery,
143
+ operation: string | undefined = undefined
144
+ ) {
145
+ const client = this.client
146
+ const request = client.request()
147
+ this.index = 0
148
+ try {
149
+ if (Array.isArray(query.bindings)) {
150
+ let count = 0
151
+ for (let binding of query.bindings) {
152
+ request.input(`p${count++}`, binding)
153
+ }
154
+ }
155
+ // this is a hack to get the inserted ID back,
156
+ // no way to do this with Knex nicely
157
+ const sql =
158
+ operation === Operation.CREATE
159
+ ? `${query.sql}; SELECT SCOPE_IDENTITY() AS id;`
160
+ : query.sql
161
+ return await request.query(sql)
162
+ } catch (err) {
163
+ // @ts-ignore
164
+ throw new Error(err)
165
+ }
166
+ }
167
+
124
168
  getDefinitionSQL(tableName: string) {
125
169
  return `select *
126
170
  from INFORMATION_SCHEMA.COLUMNS
@@ -149,33 +193,8 @@ module MSSQLModule {
149
193
  WHERE TABLE_NAME='${tableName}'`
150
194
  }
151
195
 
152
- constructor(config: MSSQLConfig) {
153
- super(SqlClients.MS_SQL)
154
- this.config = config
155
- const clientCfg = {
156
- ...this.config,
157
- options: {
158
- encrypt: this.config.encrypt,
159
- enableArithAbort: true,
160
- },
161
- }
162
- delete clientCfg.encrypt
163
- if (!this.pool) {
164
- this.pool = new sqlServer.ConnectionPool(clientCfg)
165
- }
166
- }
167
-
168
- async connect() {
169
- try {
170
- this.client = await this.pool.connect()
171
- } catch (err) {
172
- // @ts-ignore
173
- throw new Error(err)
174
- }
175
- }
176
-
177
196
  async runSQL(sql: string) {
178
- return (await internalQuery(this.client, getSqlQuery(sql))).recordset
197
+ return (await this.internalQuery(getSqlQuery(sql))).recordset
179
198
  }
180
199
 
181
200
  /**
@@ -185,11 +204,14 @@ module MSSQLModule {
185
204
  */
186
205
  async buildSchema(datasourceId: string, entities: Record<string, Table>) {
187
206
  await this.connect()
188
- let tableNames = await this.runSQL(this.TABLES_SQL)
189
- if (tableNames == null || !Array.isArray(tableNames)) {
207
+ let tableInfo: TablesResponse[] = await this.runSQL(this.TABLES_SQL)
208
+ if (tableInfo == null || !Array.isArray(tableInfo)) {
190
209
  throw "Unable to get list of tables in database"
191
210
  }
192
- tableNames = tableNames
211
+
212
+ const schema = this.config.schema || DEFAULT_SCHEMA
213
+ const tableNames = tableInfo
214
+ .filter((record: any) => record.TABLE_SCHEMA === schema)
193
215
  .map((record: any) => record.TABLE_NAME)
194
216
  .filter((name: string) => this.MASTER_TABLES.indexOf(name) === -1)
195
217
 
@@ -238,33 +260,36 @@ module MSSQLModule {
238
260
 
239
261
  async read(query: SqlQuery | string) {
240
262
  await this.connect()
241
- const response = await internalQuery(this.client, getSqlQuery(query))
263
+ const response = await this.internalQuery(getSqlQuery(query))
242
264
  return response.recordset
243
265
  }
244
266
 
245
267
  async create(query: SqlQuery | string) {
246
268
  await this.connect()
247
- const response = await internalQuery(this.client, getSqlQuery(query))
269
+ const response = await this.internalQuery(getSqlQuery(query))
248
270
  return response.recordset || [{ created: true }]
249
271
  }
250
272
 
251
273
  async update(query: SqlQuery | string) {
252
274
  await this.connect()
253
- const response = await internalQuery(this.client, getSqlQuery(query))
275
+ const response = await this.internalQuery(getSqlQuery(query))
254
276
  return response.recordset || [{ updated: true }]
255
277
  }
256
278
 
257
279
  async delete(query: SqlQuery | string) {
258
280
  await this.connect()
259
- const response = await internalQuery(this.client, getSqlQuery(query))
281
+ const response = await this.internalQuery(getSqlQuery(query))
260
282
  return response.recordset || [{ deleted: true }]
261
283
  }
262
284
 
263
285
  async query(json: QueryJson) {
286
+ const schema = this.config.schema
264
287
  await this.connect()
288
+ if (schema && schema !== DEFAULT_SCHEMA && json?.endpoint) {
289
+ json.endpoint.schema = schema
290
+ }
265
291
  const operation = this._operation(json)
266
- const queryFn = (query: any, op: string) =>
267
- internalQuery(this.client, query, op)
292
+ const queryFn = (query: any, op: string) => this.internalQuery(query, op)
268
293
  const processFn = (result: any) =>
269
294
  result.recordset ? result.recordset : [{ [operation]: true }]
270
295
  return this.queryWithReturning(json, queryFn, processFn)
@@ -95,6 +95,10 @@ module MySQLModule {
95
95
  this.config = config
96
96
  }
97
97
 
98
+ getBindingIdentifier(): string {
99
+ return "?"
100
+ }
101
+
98
102
  async connect() {
99
103
  this.client = await mysql.createConnection(this.config)
100
104
  }
@@ -1,24 +1,24 @@
1
1
  import {
2
- Integration,
3
2
  DatasourceFieldTypes,
3
+ Integration,
4
+ Operation,
5
+ QueryJson,
4
6
  QueryTypes,
5
7
  SqlQuery,
6
- QueryJson,
7
- Operation,
8
8
  } from "../definitions/datasource"
9
9
  import {
10
- finaliseExternalTables,
11
- getSqlQuery,
12
10
  buildExternalTableId,
13
11
  convertSqlType,
12
+ finaliseExternalTables,
13
+ getSqlQuery,
14
14
  SqlClients,
15
15
  } from "./utils"
16
16
  import oracledb, {
17
- ExecuteOptions,
18
- Result,
17
+ BindParameters,
19
18
  Connection,
20
19
  ConnectionAttributes,
21
- BindParameters,
20
+ ExecuteOptions,
21
+ Result,
22
22
  } from "oracledb"
23
23
  import Sql from "./base/sql"
24
24
  import { Table } from "../definitions/common"
@@ -137,6 +137,7 @@ module OracleModule {
137
137
 
138
138
  class OracleIntegration extends Sql implements DatasourcePlus {
139
139
  private readonly config: OracleConfig
140
+ private index: number = 1
140
141
 
141
142
  public tables: Record<string, Table> = {}
142
143
  public schemaErrors: Record<string, string> = {}
@@ -174,6 +175,10 @@ module OracleModule {
174
175
  this.config = config
175
176
  }
176
177
 
178
+ getBindingIdentifier(): string {
179
+ return `:${this.index++}`
180
+ }
181
+
177
182
  /**
178
183
  * Map the flat tabular columns and constraints data into a nested object
179
184
  */
@@ -233,20 +238,14 @@ module OracleModule {
233
238
  return oracleTables
234
239
  }
235
240
 
236
- private isSupportedColumn(column: OracleColumn) {
237
- if (UNSUPPORTED_TYPES.includes(column.type)) {
238
- return false
239
- }
240
-
241
- return true
241
+ private static isSupportedColumn(column: OracleColumn) {
242
+ return !UNSUPPORTED_TYPES.includes(column.type)
242
243
  }
243
244
 
244
- private isAutoColumn(column: OracleColumn) {
245
- if (column.default && column.default.toLowerCase().includes("nextval")) {
246
- return true
247
- }
248
-
249
- return false
245
+ private static isAutoColumn(column: OracleColumn) {
246
+ return !!(
247
+ column.default && column.default.toLowerCase().includes("nextval")
248
+ )
250
249
  }
251
250
 
252
251
  /**
@@ -254,7 +253,7 @@ module OracleModule {
254
253
  * This matches the default behaviour for generating DDL used in knex.
255
254
  */
256
255
  private isBooleanType(column: OracleColumn): boolean {
257
- if (
256
+ return (
258
257
  column.type.toLowerCase() === "number" &&
259
258
  Object.values(column.constraints).filter(c => {
260
259
  if (
@@ -273,11 +272,7 @@ module OracleModule {
273
272
  }
274
273
  return false
275
274
  }).length > 0
276
- ) {
277
- return true
278
- }
279
-
280
- return false
275
+ )
281
276
  }
282
277
 
283
278
  private internalConvertType(column: OracleColumn): string {
@@ -317,7 +312,9 @@ module OracleModule {
317
312
  // iterate each column on the table
318
313
  Object.values(oracleTable.columns)
319
314
  // remove columns that we can't read / save
320
- .filter(oracleColumn => this.isSupportedColumn(oracleColumn))
315
+ .filter(oracleColumn =>
316
+ OracleIntegration.isSupportedColumn(oracleColumn)
317
+ )
321
318
  // match the order of the columns in the db
322
319
  .sort((c1, c2) => c1.id - c2.id)
323
320
  .forEach(oracleColumn => {
@@ -325,7 +322,7 @@ module OracleModule {
325
322
  let fieldSchema = table.schema[columnName]
326
323
  if (!fieldSchema) {
327
324
  fieldSchema = {
328
- autocolumn: this.isAutoColumn(oracleColumn),
325
+ autocolumn: OracleIntegration.isAutoColumn(oracleColumn),
329
326
  name: columnName,
330
327
  type: this.internalConvertType(oracleColumn),
331
328
  }
@@ -351,18 +348,13 @@ module OracleModule {
351
348
  private async internalQuery<T>(query: SqlQuery): Promise<Result<T>> {
352
349
  let connection
353
350
  try {
351
+ this.index = 1
354
352
  connection = await this.getConnection()
355
353
 
356
354
  const options: ExecuteOptions = { autoCommit: true }
357
355
  const bindings: BindParameters = query.bindings || []
358
356
 
359
- const result: Result<T> = await connection.execute<T>(
360
- query.sql,
361
- bindings,
362
- options
363
- )
364
-
365
- return result
357
+ return await connection.execute<T>(query.sql, bindings, options)
366
358
  } finally {
367
359
  if (connection) {
368
360
  try {