query_generator.js 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. /**
  2. * @fileoverview function used in QBE for DB
  3. * @name Database Operations
  4. *
  5. * @requires jQuery
  6. * @requires jQueryUI
  7. * @requires js/functions.js
  8. *
  9. */
  10. /* global sprintf */ // js/vendor/sprintf.js
  11. $(document).on('change', '.criteria_op', function () {
  12. const op = $(this).val();
  13. const criteria = $(this).closest('.table').find('.rhs_text_val');
  14. isOpWithoutArg(op) ? criteria.hide().val('') : criteria.show();
  15. });
  16. function getFormatsText() {
  17. return {
  18. '=': ' = \'%s\'',
  19. '>': ' > \'%s\'',
  20. '>=': ' >= \'%s\'',
  21. '<': ' < \'%s\'',
  22. '<=': ' <= \'%s\'',
  23. '!=': ' != \'%s\'',
  24. 'LIKE': ' LIKE \'%s\'',
  25. 'LIKE %...%': ' LIKE \'%%%s%%\'',
  26. 'NOT LIKE': ' NOT LIKE \'%s\'',
  27. 'NOT LIKE %...%': ' NOT LIKE \'%%%s%%\'',
  28. 'IN (...)': ' IN (%s)',
  29. 'NOT IN (...)': ' NOT IN (%s)',
  30. 'BETWEEN': ' BETWEEN \'%s\'',
  31. 'NOT BETWEEN': ' NOT BETWEEN \'%s\'',
  32. 'REGEXP': ' REGEXP \'%s\'',
  33. 'REGEXP ^...$': ' REGEXP \'^%s$\'',
  34. 'NOT REGEXP': ' NOT REGEXP \'%s\''
  35. };
  36. }
  37. function opsWithoutArg() {
  38. return ['IS NULL', 'IS NOT NULL'];
  39. }
  40. function isOpWithoutArg(op) {
  41. return opsWithoutArg().includes(op);
  42. }
  43. function generateCondition(criteriaDiv, table) {
  44. const tableName = table.val();
  45. const tableAlias = table.siblings('.table_alias').val();
  46. const criteriaOp = criteriaDiv.find('.criteria_op').first().val();
  47. let criteriaText = criteriaDiv.find('.rhs_text_val').first().val();
  48. let query = '`' + Functions.escapeBacktick(tableAlias === '' ? tableName : tableAlias) + '`.';
  49. query += '`' + Functions.escapeBacktick(table.parent().find('.opColumn').first().val()) + '`';
  50. if (criteriaDiv.find('.criteria_rhs').first().val() === 'text') {
  51. if (isOpWithoutArg(criteriaOp)) {
  52. query += ' ' + criteriaOp;
  53. } else {
  54. const formatsText = getFormatsText();
  55. if (!['IN (...)', 'NOT IN (...)'].includes(criteriaOp)) {
  56. criteriaText = Functions.escapeSingleQuote(criteriaText);
  57. }
  58. query += sprintf(formatsText[criteriaOp], criteriaText);
  59. }
  60. } else {
  61. query += ' ' + criteriaOp;
  62. query += ' `' + Functions.escapeBacktick(criteriaDiv.find('.tableNameSelect').first().val()) + '`.';
  63. query += '`' + Functions.escapeBacktick(criteriaDiv.find('.opColumn').first().val()) + '`';
  64. }
  65. return query;
  66. }
  67. // eslint-disable-next-line no-unused-vars
  68. function generateWhereBlock() {
  69. var count = 0;
  70. var query = '';
  71. $('.tableNameSelect').each(function () {
  72. var criteriaDiv = $(this).siblings('.jsCriteriaOptions').first();
  73. var useCriteria = $(this).siblings('.criteria_col').first();
  74. if ($(this).val() !== '' && useCriteria.prop('checked')) {
  75. if (count > 0) {
  76. criteriaDiv.find('input.logical_op').each(function () {
  77. if ($(this).prop('checked')) {
  78. query += ' ' + $(this).val() + ' ';
  79. }
  80. });
  81. }
  82. query += generateCondition(criteriaDiv, $(this));
  83. count++;
  84. }
  85. });
  86. return query;
  87. }
  88. function generateJoin(newTable, tableAliases, fk) {
  89. var query = '';
  90. query += ' \n\tLEFT JOIN ' + '`' + Functions.escapeBacktick(newTable) + '`';
  91. if (tableAliases[fk.TABLE_NAME][0] !== '') {
  92. query += ' AS `' + Functions.escapeBacktick(tableAliases[newTable][0]) + '`';
  93. query += ' ON `' + Functions.escapeBacktick(tableAliases[fk.TABLE_NAME][0]) + '`';
  94. } else {
  95. query += ' ON `' + Functions.escapeBacktick(fk.TABLE_NAME) + '`';
  96. }
  97. query += '.`' + fk.COLUMN_NAME + '`';
  98. if (tableAliases[fk.REFERENCED_TABLE_NAME][0] !== '') {
  99. query += ' = `' + Functions.escapeBacktick(tableAliases[fk.REFERENCED_TABLE_NAME][0]) + '`';
  100. } else {
  101. query += ' = `' + Functions.escapeBacktick(fk.REFERENCED_TABLE_NAME) + '`';
  102. }
  103. query += '.`' + fk.REFERENCED_COLUMN_NAME + '`';
  104. return query;
  105. }
  106. function existReference(table, fk, usedTables) {
  107. var isReferredBy = fk.TABLE_NAME === table && usedTables.includes(fk.REFERENCED_TABLE_NAME);
  108. var isReferencedBy = fk.REFERENCED_TABLE_NAME === table && usedTables.includes(fk.TABLE_NAME);
  109. return isReferredBy || isReferencedBy;
  110. }
  111. function tryJoinTable(table, tableAliases, usedTables, foreignKeys) {
  112. for (var i = 0; i < foreignKeys.length; i++) {
  113. var fk = foreignKeys[i];
  114. if (existReference(table, fk, usedTables)) {
  115. return generateJoin(table, tableAliases, fk);
  116. }
  117. }
  118. return '';
  119. }
  120. function appendTable(table, tableAliases, usedTables, foreignKeys) {
  121. var query = tryJoinTable(table, tableAliases, usedTables, foreignKeys);
  122. if (query === '') {
  123. if (usedTables.length > 0) {
  124. query += '\n\t, ';
  125. }
  126. query += '`' + Functions.escapeBacktick(table) + '`';
  127. if (tableAliases[table][0] !== '') {
  128. query += ' AS `' + Functions.escapeBacktick(tableAliases[table][0]) + '`';
  129. }
  130. }
  131. usedTables.push(table);
  132. return query;
  133. }
  134. // eslint-disable-next-line no-unused-vars
  135. function generateFromBlock(tableAliases, foreignKeys) {
  136. var usedTables = [];
  137. var query = '';
  138. for (var table in tableAliases) {
  139. if (tableAliases.hasOwnProperty(table)) {
  140. query += appendTable(table, tableAliases, usedTables, foreignKeys);
  141. }
  142. }
  143. return query;
  144. }