• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

TotalTechGeek / pg-swag / 11942733536

20 Nov 2024 10:20PM UTC coverage: 94.749% (-2.2%) from 96.95%
11942733536

push

github

TotalTechGeek
Include the version bump

215 of 243 branches covered (88.48%)

Branch coverage included in aggregate %.

1048 of 1090 relevant lines covered (96.15%)

91594.37 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

88.03
/formatSQL.js
1
import sqlString from 'sqlstring'
3✔
2
import { parseRelative } from './relative.js'
3✔
3
import { toSeconds } from 'iso8601-duration'
3✔
4

3✔
5
/**
3✔
6
 * Sanitizes SQL strings by replacing $1, $2, $3, etc with the corresponding parameter
3✔
7
 *
3✔
8
 * @param {string} key
3✔
9
 * @param {Record<string,any>} params
3✔
10
 * @param {string} dialect
3✔
11
 */
3✔
12
function replace (key, params, dialect) {
3,160,729✔
13
  if (!Array.isArray(params)) throw new Error('Params was not an array')
3,160,729!
14
  if (key === 'data') return ''
3,160,729!
15

3,160,729✔
16
  // check for a :csv or :name or something
3,160,729✔
17
  let modifier = (key.match(/:(\w+)/) || '')[1]
3,160,729✔
18
  if (modifier === 'list') modifier = 'csv'
3,160,729!
19

3,160,729✔
20
  // Extract out the parameter index
3,160,729✔
21
  key = key.replace(/:\w+/, '')
3,160,729✔
22
  key = key.substring(1)
3,160,729✔
23
  key = +key - 1
3,160,729✔
24

3,160,729✔
25
  if (!Number.isInteger(key)) throw new Error('Invalid param index')
3,160,729!
26
  if (Array.isArray(params[key]) && modifier !== 'csv') throw new Error('Param is an array, use :csv to format it')
3,160,729!
27
  if (modifier === 'name') return TableName(params[key], dialect === 'mysql' ? '`' : '"')
3,160,729!
28

2,868,508✔
29
  if (params[key] instanceof Date) {
3,160,729✔
30
    let dateStr = params[key].toISOString()
1,140,270✔
31
    if (dialect === 'sqlite') dateStr = dateStr.replace('T', ' ').replace('Z', '')
1,140,270!
32
    if (dialect === 'mysql') dateStr = dateStr.replace('T', ' ').replace('Z', '+00:00')
1,140,270!
33
    return sqlString.escape(dateStr)
1,140,270✔
34
  }
1,140,270✔
35

1,728,238✔
36
  if (params[key] && typeof params[key] === 'object' && !Array.isArray(params[key])) {
3,160,729✔
37
    if (modifier !== 'json') throw new Error('Invalid object, use :json to stringify it.')
123!
38
    return sqlString.escape(JSON.stringify(params[key])).replace(/\\"/g, '"')
123✔
39
  }
123✔
40

1,728,115✔
41
  if (modifier === 'mysqlInterval') {
3,160,729!
42
    const duration = parseRelative(params[key])
×
43
    // makes a best effort to use months
×
44
    if (duration.months && Object.keys(duration).length === 1) return 'INTERVAL ' + duration.months + ' MONTH'
×
45
    const seconds = toSeconds(duration)
×
46
    return 'INTERVAL ' + seconds + ' SECOND'
×
47
  }
×
48

1,728,115✔
49
  return sqlString.escape(params[key])
1,728,115✔
50
}
3,160,729✔
51

3✔
52
/**
3✔
53
 * @test "select * from jobs where id in ($1:csv)", [1]
3✔
54
 * @test 'select * from $1:name', ['jobs']
3✔
55
 * @test 'select * from jobs where id in ($1:csv)', [[1, 2, 3]]
3✔
56
 * @test '$1:line select 1\n select 2', [true]
3✔
57
 * @test '$1:line select 1\n select 2', [false]
3✔
58
 *
3✔
59
 * Note that this function is a simple implementation, and will break with test cases where '$1' is embedded in a string.
3✔
60
 * Which is an inaccuracy
3✔
61
 *
3✔
62
 * :line will remove the line if the param is not truthy
3✔
63
 * :csv will format an array param into a csv, like '1', '2', '3'
3✔
64
 * :name will format a table name
3✔
65
 *
3✔
66
 * @param {string | string[]} name
3✔
67
 * @param {Record<string,any>} params
3✔
68
 * @param {string} dialect
3✔
69
 */
3✔
70
export function format (sql, params, dialect) {
3✔
71
  const lineRemoval = /\$[0-9]+:line(.*)/g
288,742✔
72
  sql = sql.replace(lineRemoval, (match, k) => {
288,742✔
73
    const key = match.match(/\$[0-9]+/)[0]
285,114✔
74
    const index = +key.substring(1)
285,114✔
75
    if (!params[index - 1]) return ''
285,114✔
76
    return k
285,060✔
77
  })
288,742✔
78
  return sql.replace(/\$([0-9]+)(:\w+)?/g, (match, key) => replace(match, params, dialect))
288,742✔
79
}
288,742✔
80

3✔
81
/**
3✔
82
 * Generates a table name string that is safe to use in SQL queries
3✔
83
 *
3✔
84
 * @test 'jobs'
3✔
85
 * @test 'jobs', '`'
3✔
86
 * @test { name: 'jobs', schema: 'public' }
3✔
87
 * @test { table: 'jobs' }
3✔
88
 * @test {} throws
3✔
89
 */
3✔
90
export function TableName (table, char = '"') {
3✔
91
  let schema = null
292,236✔
92
  if (typeof table !== 'string') {
292,236✔
93
    const tbl = table
292,227✔
94
    if (tbl.name) table = tbl.name
292,227✔
95
    else if (tbl.table) table = tbl.table
292,224✔
96
    else throw new Error('Invalid table name')
3✔
97
    schema = tbl.schema
292,224✔
98
  }
292,224✔
99

292,233✔
100
  if (/"|`|'/.test(table)) throw new Error('Invalid table name, if you hit this, please explain to me why this is necessary.')
292,236!
101
  if (schema) return (sqlString.escapeId(schema) + '.' + sqlString.escapeId(table)).replace(/`/g, char)
292,236✔
102
  return (sqlString.escapeId(table)).replace(/`/g, char)
292,230✔
103
}
292,236✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc