sqlqueries.go 49 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198
  1. // Copyright (C) 2019-2023 Nicola Murino
  2. //
  3. // This program is free software: you can redistribute it and/or modify
  4. // it under the terms of the GNU Affero General Public License as published
  5. // by the Free Software Foundation, version 3.
  6. //
  7. // This program is distributed in the hope that it will be useful,
  8. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. // GNU Affero General Public License for more details.
  11. //
  12. // You should have received a copy of the GNU Affero General Public License
  13. // along with this program. If not, see <https://www.gnu.org/licenses/>.
  14. package dataprovider
  15. import (
  16. "fmt"
  17. "strconv"
  18. "strings"
  19. "github.com/drakkan/sftpgo/v2/internal/vfs"
  20. )
  21. const (
  22. selectUserFields = "u.id,u.username,u.password,u.public_keys,u.home_dir,u.uid,u.gid,u.max_sessions,u.quota_size,u.quota_files," +
  23. "u.permissions,u.used_quota_size,u.used_quota_files,u.last_quota_update,u.upload_bandwidth,u.download_bandwidth," +
  24. "u.expiration_date,u.last_login,u.status,u.filters,u.filesystem,u.additional_info,u.description,u.email,u.created_at," +
  25. "u.updated_at,u.upload_data_transfer,u.download_data_transfer,u.total_data_transfer," +
  26. "u.used_upload_data_transfer,u.used_download_data_transfer,u.deleted_at,u.first_download,u.first_upload,r.name,u.last_password_change"
  27. selectFolderFields = "id,path,used_quota_size,used_quota_files,last_quota_update,name,description,filesystem"
  28. selectAdminFields = "a.id,a.username,a.password,a.status,a.email,a.permissions,a.filters,a.additional_info,a.description,a.created_at,a.updated_at,a.last_login,r.name"
  29. selectAPIKeyFields = "key_id,name,api_key,scope,created_at,updated_at,last_use_at,expires_at,description,user_id,admin_id"
  30. selectShareFields = "s.share_id,s.name,s.description,s.scope,s.paths,u.username,s.created_at,s.updated_at,s.last_use_at," +
  31. "s.expires_at,s.password,s.max_tokens,s.used_tokens,s.allow_from"
  32. selectGroupFields = "id,name,description,created_at,updated_at,user_settings"
  33. selectEventActionFields = "id,name,description,type,options"
  34. selectRoleFields = "id,name,description,created_at,updated_at"
  35. selectIPListEntryFields = "type,ipornet,mode,protocols,description,created_at,updated_at,deleted_at"
  36. selectMinimalFields = "id,name"
  37. )
  38. func getSQLPlaceholders() []string {
  39. var placeholders []string
  40. for i := 1; i <= 50; i++ {
  41. if config.Driver == PGSQLDataProviderName || config.Driver == CockroachDataProviderName {
  42. placeholders = append(placeholders, fmt.Sprintf("$%d", i))
  43. } else {
  44. placeholders = append(placeholders, "?")
  45. }
  46. }
  47. return placeholders
  48. }
  49. func getSQLQuotedName(name string) string {
  50. if config.Driver == MySQLDataProviderName {
  51. return fmt.Sprintf("`%s`", name)
  52. }
  53. return fmt.Sprintf(`"%s"`, name)
  54. }
  55. func getSelectEventRuleFields() string {
  56. if config.Driver == MySQLDataProviderName {
  57. return "id,name,description,created_at,updated_at,`trigger`,conditions,deleted_at,status"
  58. }
  59. return `id,name,description,created_at,updated_at,"trigger",conditions,deleted_at,status`
  60. }
  61. func getCoalesceDefaultForRole(role string) string {
  62. if role != "" {
  63. return "0"
  64. }
  65. return "NULL"
  66. }
  67. func getAddSessionQuery() string {
  68. if config.Driver == MySQLDataProviderName {
  69. return fmt.Sprintf("INSERT INTO %s (`key`,`data`,`type`,`timestamp`) VALUES (%s,%s,%s,%s) "+
  70. "ON DUPLICATE KEY UPDATE `data`=VALUES(`data`), `timestamp`=VALUES(`timestamp`)",
  71. sqlTableSharedSessions, sqlPlaceholders[0], sqlPlaceholders[1], sqlPlaceholders[2], sqlPlaceholders[3])
  72. }
  73. return fmt.Sprintf(`INSERT INTO %s (key,data,type,timestamp) VALUES (%s,%s,%s,%s) ON CONFLICT(key) DO UPDATE SET data=
  74. EXCLUDED.data, timestamp=EXCLUDED.timestamp`,
  75. sqlTableSharedSessions, sqlPlaceholders[0], sqlPlaceholders[1], sqlPlaceholders[2], sqlPlaceholders[3])
  76. }
  77. func getDeleteSessionQuery() string {
  78. if config.Driver == MySQLDataProviderName {
  79. return fmt.Sprintf("DELETE FROM %s WHERE `key` = %s", sqlTableSharedSessions, sqlPlaceholders[0])
  80. }
  81. return fmt.Sprintf(`DELETE FROM %s WHERE key = %s`, sqlTableSharedSessions, sqlPlaceholders[0])
  82. }
  83. func getSessionQuery() string {
  84. if config.Driver == MySQLDataProviderName {
  85. return fmt.Sprintf("SELECT `key`,`data`,`type`,`timestamp` FROM %s WHERE `key` = %s", sqlTableSharedSessions,
  86. sqlPlaceholders[0])
  87. }
  88. return fmt.Sprintf(`SELECT key,data,type,timestamp FROM %s WHERE key = %s`, sqlTableSharedSessions,
  89. sqlPlaceholders[0])
  90. }
  91. func getCleanupSessionsQuery() string {
  92. return fmt.Sprintf(`DELETE from %s WHERE type = %s AND timestamp < %s`,
  93. sqlTableSharedSessions, sqlPlaceholders[0], sqlPlaceholders[1])
  94. }
  95. func getAddDefenderHostQuery() string {
  96. if config.Driver == MySQLDataProviderName {
  97. return fmt.Sprintf("INSERT INTO %s (`ip`,`updated_at`,`ban_time`) VALUES (%s,%s,0) ON DUPLICATE KEY UPDATE `updated_at`=VALUES(`updated_at`)",
  98. sqlTableDefenderHosts, sqlPlaceholders[0], sqlPlaceholders[1])
  99. }
  100. return fmt.Sprintf(`INSERT INTO %s (ip,updated_at,ban_time) VALUES (%s,%s,0) ON CONFLICT (ip) DO UPDATE SET updated_at = EXCLUDED.updated_at RETURNING id`,
  101. sqlTableDefenderHosts, sqlPlaceholders[0], sqlPlaceholders[1])
  102. }
  103. func getAddDefenderEventQuery() string {
  104. return fmt.Sprintf(`INSERT INTO %s (date_time,score,host_id) VALUES (%s,%s,(SELECT id from %s WHERE ip = %s))`,
  105. sqlTableDefenderEvents, sqlPlaceholders[0], sqlPlaceholders[1], sqlTableDefenderHosts, sqlPlaceholders[2])
  106. }
  107. func getDefenderHostsQuery() string {
  108. return fmt.Sprintf(`SELECT id,ip,ban_time FROM %s WHERE updated_at >= %s OR ban_time > 0 ORDER BY updated_at DESC LIMIT %s`,
  109. sqlTableDefenderHosts, sqlPlaceholders[0], sqlPlaceholders[1])
  110. }
  111. func getDefenderHostQuery() string {
  112. return fmt.Sprintf(`SELECT id,ip,ban_time FROM %s WHERE ip = %s AND (updated_at >= %s OR ban_time > 0)`,
  113. sqlTableDefenderHosts, sqlPlaceholders[0], sqlPlaceholders[1])
  114. }
  115. func getDefenderEventsQuery(hostIDS []int64) string {
  116. var sb strings.Builder
  117. for _, hID := range hostIDS {
  118. if sb.Len() == 0 {
  119. sb.WriteString("(")
  120. } else {
  121. sb.WriteString(",")
  122. }
  123. sb.WriteString(strconv.FormatInt(hID, 10))
  124. }
  125. if sb.Len() > 0 {
  126. sb.WriteString(")")
  127. } else {
  128. sb.WriteString("(0)")
  129. }
  130. return fmt.Sprintf(`SELECT host_id,SUM(score) FROM %s WHERE date_time >= %s AND host_id IN %s GROUP BY host_id`,
  131. sqlTableDefenderEvents, sqlPlaceholders[0], sb.String())
  132. }
  133. func getDefenderIsHostBannedQuery() string {
  134. return fmt.Sprintf(`SELECT id FROM %s WHERE ip = %s AND ban_time >= %s`,
  135. sqlTableDefenderHosts, sqlPlaceholders[0], sqlPlaceholders[1])
  136. }
  137. func getDefenderIncrementBanTimeQuery() string {
  138. return fmt.Sprintf(`UPDATE %s SET ban_time = ban_time + %s WHERE ip = %s`,
  139. sqlTableDefenderHosts, sqlPlaceholders[0], sqlPlaceholders[1])
  140. }
  141. func getDefenderSetBanTimeQuery() string {
  142. return fmt.Sprintf(`UPDATE %s SET ban_time = %s WHERE ip = %s`,
  143. sqlTableDefenderHosts, sqlPlaceholders[0], sqlPlaceholders[1])
  144. }
  145. func getDeleteDefenderHostQuery() string {
  146. return fmt.Sprintf(`DELETE FROM %s WHERE ip = %s`, sqlTableDefenderHosts, sqlPlaceholders[0])
  147. }
  148. func getDefenderHostsCleanupQuery() string {
  149. return fmt.Sprintf(`DELETE FROM %s WHERE ban_time < %s AND NOT EXISTS (
  150. SELECT id FROM %s WHERE %s.host_id = %s.id AND %s.date_time > %s)`,
  151. sqlTableDefenderHosts, sqlPlaceholders[0], sqlTableDefenderEvents, sqlTableDefenderEvents, sqlTableDefenderHosts,
  152. sqlTableDefenderEvents, sqlPlaceholders[1])
  153. }
  154. func getDefenderEventsCleanupQuery() string {
  155. return fmt.Sprintf(`DELETE FROM %s WHERE date_time < %s`, sqlTableDefenderEvents, sqlPlaceholders[0])
  156. }
  157. func getIPListEntryQuery() string {
  158. return fmt.Sprintf(`SELECT %s FROM %s WHERE type = %s AND ipornet = %s AND deleted_at = 0`,
  159. selectIPListEntryFields, sqlTableIPLists, sqlPlaceholders[0], sqlPlaceholders[1])
  160. }
  161. func getIPListEntriesQuery(filter, from, order string, limit int) string {
  162. var sb strings.Builder
  163. var idx int
  164. sb.WriteString("SELECT ")
  165. sb.WriteString(selectIPListEntryFields)
  166. sb.WriteString(" FROM ")
  167. sb.WriteString(sqlTableIPLists)
  168. sb.WriteString(" WHERE type = ")
  169. sb.WriteString(sqlPlaceholders[idx])
  170. idx++
  171. if from != "" {
  172. if order == OrderASC {
  173. sb.WriteString(" AND ipornet > ")
  174. } else {
  175. sb.WriteString(" AND ipornet < ")
  176. }
  177. sb.WriteString(sqlPlaceholders[idx])
  178. idx++
  179. }
  180. if filter != "" {
  181. sb.WriteString(" AND ipornet LIKE ")
  182. sb.WriteString(sqlPlaceholders[idx])
  183. idx++
  184. }
  185. sb.WriteString(" AND deleted_at = 0 ")
  186. sb.WriteString(" ORDER BY ipornet ")
  187. sb.WriteString(order)
  188. if limit > 0 {
  189. sb.WriteString(" LIMIT ")
  190. sb.WriteString(sqlPlaceholders[idx])
  191. }
  192. return sb.String()
  193. }
  194. func getCountIPListEntriesQuery() string {
  195. return fmt.Sprintf(`SELECT count(ipornet) FROM %s WHERE type = %s AND deleted_at = 0`, sqlTableIPLists, sqlPlaceholders[0])
  196. }
  197. func getCountAllIPListEntriesQuery() string {
  198. return fmt.Sprintf(`SELECT count(ipornet) FROM %s WHERE deleted_at = 0`, sqlTableIPLists)
  199. }
  200. func getIPListEntriesForIPQueryPg() string {
  201. return fmt.Sprintf(`SELECT %s FROM %s WHERE type = %s AND deleted_at = 0 AND %s::inet BETWEEN first AND last`,
  202. selectIPListEntryFields, sqlTableIPLists, sqlPlaceholders[0], sqlPlaceholders[1])
  203. }
  204. func getIPListEntriesForIPQueryNoPg() string {
  205. return fmt.Sprintf(`SELECT %s FROM %s WHERE type = %s AND deleted_at = 0 AND ip_type = %s AND %s BETWEEN first AND last`,
  206. selectIPListEntryFields, sqlTableIPLists, sqlPlaceholders[0], sqlPlaceholders[1], sqlPlaceholders[2])
  207. }
  208. func getRecentlyUpdatedIPListQuery() string {
  209. return fmt.Sprintf(`SELECT %s FROM %s WHERE updated_at >= %s OR deleted_at > 0`,
  210. selectIPListEntryFields, sqlTableIPLists, sqlPlaceholders[0])
  211. }
  212. func getDumpListEntriesQuery() string {
  213. return fmt.Sprintf(`SELECT %s FROM %s WHERE deleted_at = 0`, selectIPListEntryFields, sqlTableIPLists)
  214. }
  215. func getAddIPListEntryQuery() string {
  216. return fmt.Sprintf(`INSERT INTO %s (type,ipornet,first,last,ip_type,protocols,description,mode,created_at,updated_at,deleted_at)
  217. VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,0)`, sqlTableIPLists, sqlPlaceholders[0], sqlPlaceholders[1],
  218. sqlPlaceholders[2], sqlPlaceholders[3], sqlPlaceholders[4], sqlPlaceholders[5],
  219. sqlPlaceholders[6], sqlPlaceholders[7], sqlPlaceholders[8], sqlPlaceholders[9])
  220. }
  221. func getUpdateIPListEntryQuery() string {
  222. return fmt.Sprintf(`UPDATE %s SET mode=%s,protocols=%s,description=%s,updated_at=%s WHERE type = %s AND ipornet = %s`,
  223. sqlTableIPLists, sqlPlaceholders[0], sqlPlaceholders[1], sqlPlaceholders[2], sqlPlaceholders[3],
  224. sqlPlaceholders[4], sqlPlaceholders[5])
  225. }
  226. func getDeleteIPListEntryQuery(softDelete bool) string {
  227. if softDelete {
  228. return fmt.Sprintf(`UPDATE %s SET updated_at=%s,deleted_at=%s WHERE type = %s AND ipornet = %s`,
  229. sqlTableIPLists, sqlPlaceholders[0], sqlPlaceholders[1], sqlPlaceholders[2], sqlPlaceholders[3])
  230. }
  231. return fmt.Sprintf(`DELETE FROM %s WHERE type = %s AND ipornet = %s`,
  232. sqlTableIPLists, sqlPlaceholders[0], sqlPlaceholders[1])
  233. }
  234. func getRemoveSoftDeletedIPListEntryQuery() string {
  235. return fmt.Sprintf(`DELETE FROM %s WHERE type = %s AND ipornet = %s AND deleted_at > 0`,
  236. sqlTableIPLists, sqlPlaceholders[0], sqlPlaceholders[1])
  237. }
  238. func getConfigsQuery() string {
  239. return fmt.Sprintf(`SELECT configs FROM %s LIMIT 1`, sqlTableConfigs)
  240. }
  241. func getUpdateConfigsQuery() string {
  242. return fmt.Sprintf(`UPDATE %s SET configs = %s`, sqlTableConfigs, sqlPlaceholders[0])
  243. }
  244. func getRoleByNameQuery() string {
  245. return fmt.Sprintf(`SELECT %s FROM %s WHERE name = %s`, selectRoleFields, sqlTableRoles,
  246. sqlPlaceholders[0])
  247. }
  248. func getRolesQuery(order string, minimal bool) string {
  249. var fieldSelection string
  250. if minimal {
  251. fieldSelection = selectMinimalFields
  252. } else {
  253. fieldSelection = selectRoleFields
  254. }
  255. return fmt.Sprintf(`SELECT %s FROM %s ORDER BY name %s LIMIT %s OFFSET %s`, fieldSelection,
  256. sqlTableRoles, order, sqlPlaceholders[0], sqlPlaceholders[1])
  257. }
  258. func getUsersWithRolesQuery(roles []Role) string {
  259. var sb strings.Builder
  260. for _, r := range roles {
  261. if sb.Len() == 0 {
  262. sb.WriteString("(")
  263. } else {
  264. sb.WriteString(",")
  265. }
  266. sb.WriteString(strconv.FormatInt(r.ID, 10))
  267. }
  268. if sb.Len() > 0 {
  269. sb.WriteString(")")
  270. }
  271. return fmt.Sprintf(`SELECT r.id, u.username FROM %s u INNER JOIN %s r ON u.role_id = r.id WHERE u.role_id IN %s`,
  272. sqlTableUsers, sqlTableRoles, sb.String())
  273. }
  274. func getAdminsWithRolesQuery(roles []Role) string {
  275. var sb strings.Builder
  276. for _, r := range roles {
  277. if sb.Len() == 0 {
  278. sb.WriteString("(")
  279. } else {
  280. sb.WriteString(",")
  281. }
  282. sb.WriteString(strconv.FormatInt(r.ID, 10))
  283. }
  284. if sb.Len() > 0 {
  285. sb.WriteString(")")
  286. }
  287. return fmt.Sprintf(`SELECT r.id, a.username FROM %s a INNER JOIN %s r ON a.role_id = r.id WHERE a.role_id IN %s`,
  288. sqlTableAdmins, sqlTableRoles, sb.String())
  289. }
  290. func getDumpRolesQuery() string {
  291. return fmt.Sprintf(`SELECT %s FROM %s`, selectRoleFields, sqlTableRoles)
  292. }
  293. func getAddRoleQuery() string {
  294. return fmt.Sprintf(`INSERT INTO %s (name,description,created_at,updated_at)
  295. VALUES (%s,%s,%s,%s)`, sqlTableRoles, sqlPlaceholders[0], sqlPlaceholders[1],
  296. sqlPlaceholders[2], sqlPlaceholders[3])
  297. }
  298. func getUpdateRoleQuery() string {
  299. return fmt.Sprintf(`UPDATE %s SET description=%s,updated_at=%s
  300. WHERE name = %s`, sqlTableRoles, sqlPlaceholders[0], sqlPlaceholders[1], sqlPlaceholders[2])
  301. }
  302. func getDeleteRoleQuery() string {
  303. return fmt.Sprintf(`DELETE FROM %s WHERE name = %s`, sqlTableRoles, sqlPlaceholders[0])
  304. }
  305. func getGroupByNameQuery() string {
  306. return fmt.Sprintf(`SELECT %s FROM %s WHERE name = %s`, selectGroupFields, getSQLQuotedName(sqlTableGroups),
  307. sqlPlaceholders[0])
  308. }
  309. func getGroupsQuery(order string, minimal bool) string {
  310. var fieldSelection string
  311. if minimal {
  312. fieldSelection = selectMinimalFields
  313. } else {
  314. fieldSelection = selectGroupFields
  315. }
  316. return fmt.Sprintf(`SELECT %s FROM %s ORDER BY name %s LIMIT %s OFFSET %s`, fieldSelection,
  317. getSQLQuotedName(sqlTableGroups), order, sqlPlaceholders[0], sqlPlaceholders[1])
  318. }
  319. func getGroupsWithNamesQuery(numArgs int) string {
  320. var sb strings.Builder
  321. for idx := 0; idx < numArgs; idx++ {
  322. if sb.Len() == 0 {
  323. sb.WriteString("(")
  324. } else {
  325. sb.WriteString(",")
  326. }
  327. sb.WriteString(sqlPlaceholders[idx])
  328. }
  329. if sb.Len() > 0 {
  330. sb.WriteString(")")
  331. } else {
  332. sb.WriteString("('')")
  333. }
  334. return fmt.Sprintf(`SELECT %s FROM %s WHERE name in %s`, selectGroupFields, getSQLQuotedName(sqlTableGroups), sb.String())
  335. }
  336. func getUsersInGroupsQuery(numArgs int) string {
  337. var sb strings.Builder
  338. for idx := 0; idx < numArgs; idx++ {
  339. if sb.Len() == 0 {
  340. sb.WriteString("(")
  341. } else {
  342. sb.WriteString(",")
  343. }
  344. sb.WriteString(sqlPlaceholders[idx])
  345. }
  346. if sb.Len() > 0 {
  347. sb.WriteString(")")
  348. } else {
  349. sb.WriteString("('')")
  350. }
  351. return fmt.Sprintf(`SELECT username FROM %s WHERE id IN (SELECT user_id from %s WHERE group_id IN (SELECT id FROM %s WHERE name IN (%s)))`,
  352. sqlTableUsers, sqlTableUsersGroupsMapping, getSQLQuotedName(sqlTableGroups), sb.String())
  353. }
  354. func getDumpGroupsQuery() string {
  355. return fmt.Sprintf(`SELECT %s FROM %s`, selectGroupFields, getSQLQuotedName(sqlTableGroups))
  356. }
  357. func getAddGroupQuery() string {
  358. return fmt.Sprintf(`INSERT INTO %s (name,description,created_at,updated_at,user_settings)
  359. VALUES (%s,%s,%s,%s,%s)`, getSQLQuotedName(sqlTableGroups), sqlPlaceholders[0], sqlPlaceholders[1],
  360. sqlPlaceholders[2], sqlPlaceholders[3], sqlPlaceholders[4])
  361. }
  362. func getUpdateGroupQuery() string {
  363. return fmt.Sprintf(`UPDATE %s SET description=%s,user_settings=%s,updated_at=%s
  364. WHERE name = %s`, getSQLQuotedName(sqlTableGroups), sqlPlaceholders[0], sqlPlaceholders[1], sqlPlaceholders[2],
  365. sqlPlaceholders[3])
  366. }
  367. func getDeleteGroupQuery() string {
  368. return fmt.Sprintf(`DELETE FROM %s WHERE name = %s`, getSQLQuotedName(sqlTableGroups), sqlPlaceholders[0])
  369. }
  370. func getAdminByUsernameQuery() string {
  371. return fmt.Sprintf(`SELECT %s FROM %s a LEFT JOIN %s r on r.id = a.role_id WHERE a.username = %s`,
  372. selectAdminFields, sqlTableAdmins, sqlTableRoles, sqlPlaceholders[0])
  373. }
  374. func getAdminsQuery(order string) string {
  375. return fmt.Sprintf(`SELECT %s FROM %s a LEFT JOIN %s r on r.id = a.role_id ORDER BY a.username %s LIMIT %s OFFSET %s`,
  376. selectAdminFields, sqlTableAdmins, sqlTableRoles, order, sqlPlaceholders[0], sqlPlaceholders[1])
  377. }
  378. func getDumpAdminsQuery() string {
  379. return fmt.Sprintf(`SELECT %s FROM %s a LEFT JOIN %s r on r.id = a.role_id`,
  380. selectAdminFields, sqlTableAdmins, sqlTableRoles)
  381. }
  382. func getAddAdminQuery(role string) string {
  383. return fmt.Sprintf(`INSERT INTO %s (username,password,status,email,permissions,filters,additional_info,description,created_at,updated_at,last_login,role_id)
  384. VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,0,COALESCE((SELECT id from %s WHERE name = %s),%s))`,
  385. sqlTableAdmins, sqlPlaceholders[0], sqlPlaceholders[1], sqlPlaceholders[2], sqlPlaceholders[3], sqlPlaceholders[4],
  386. sqlPlaceholders[5], sqlPlaceholders[6], sqlPlaceholders[7], sqlPlaceholders[8], sqlPlaceholders[9],
  387. sqlTableRoles, sqlPlaceholders[10], getCoalesceDefaultForRole(role))
  388. }
  389. func getUpdateAdminQuery(role string) string {
  390. return fmt.Sprintf(`UPDATE %s SET password=%s,status=%s,email=%s,permissions=%s,filters=%s,additional_info=%s,description=%s,updated_at=%s,
  391. role_id=COALESCE((SELECT id from %s WHERE name = %s),%s) WHERE username = %s`, sqlTableAdmins, sqlPlaceholders[0],
  392. sqlPlaceholders[1], sqlPlaceholders[2], sqlPlaceholders[3], sqlPlaceholders[4], sqlPlaceholders[5], sqlPlaceholders[6],
  393. sqlPlaceholders[7], sqlTableRoles, sqlPlaceholders[8], getCoalesceDefaultForRole(role), sqlPlaceholders[9])
  394. }
  395. func getDeleteAdminQuery() string {
  396. return fmt.Sprintf(`DELETE FROM %s WHERE username = %s`, sqlTableAdmins, sqlPlaceholders[0])
  397. }
  398. func getShareByIDQuery(filterUser bool) string {
  399. if filterUser {
  400. return fmt.Sprintf(`SELECT %s FROM %s s INNER JOIN %s u ON s.user_id = u.id WHERE s.share_id = %s AND u.username = %s`,
  401. selectShareFields, sqlTableShares, sqlTableUsers, sqlPlaceholders[0], sqlPlaceholders[1])
  402. }
  403. return fmt.Sprintf(`SELECT %s FROM %s s INNER JOIN %s u ON s.user_id = u.id WHERE s.share_id = %s`,
  404. selectShareFields, sqlTableShares, sqlTableUsers, sqlPlaceholders[0])
  405. }
  406. func getSharesQuery(order string) string {
  407. return fmt.Sprintf(`SELECT %s FROM %s s INNER JOIN %s u ON s.user_id = u.id WHERE u.username = %s ORDER BY s.share_id %s LIMIT %s OFFSET %s`,
  408. selectShareFields, sqlTableShares, sqlTableUsers, sqlPlaceholders[0], order, sqlPlaceholders[1], sqlPlaceholders[2])
  409. }
  410. func getDumpSharesQuery() string {
  411. return fmt.Sprintf(`SELECT %s FROM %s s INNER JOIN %s u ON s.user_id = u.id`,
  412. selectShareFields, sqlTableShares, sqlTableUsers)
  413. }
  414. func getAddShareQuery() string {
  415. return fmt.Sprintf(`INSERT INTO %s (share_id,name,description,scope,paths,created_at,updated_at,last_use_at,
  416. expires_at,password,max_tokens,used_tokens,allow_from,user_id) VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)`,
  417. sqlTableShares, sqlPlaceholders[0], sqlPlaceholders[1],
  418. sqlPlaceholders[2], sqlPlaceholders[3], sqlPlaceholders[4], sqlPlaceholders[5], sqlPlaceholders[6],
  419. sqlPlaceholders[7], sqlPlaceholders[8], sqlPlaceholders[9], sqlPlaceholders[10], sqlPlaceholders[11],
  420. sqlPlaceholders[12], sqlPlaceholders[13])
  421. }
  422. func getUpdateShareRestoreQuery() string {
  423. return fmt.Sprintf(`UPDATE %s SET name=%s,description=%s,scope=%s,paths=%s,created_at=%s,updated_at=%s,
  424. last_use_at=%s,expires_at=%s,password=%s,max_tokens=%s,used_tokens=%s,allow_from=%s,user_id=%s WHERE share_id = %s`, sqlTableShares,
  425. sqlPlaceholders[0], sqlPlaceholders[1], sqlPlaceholders[2], sqlPlaceholders[3], sqlPlaceholders[4],
  426. sqlPlaceholders[5], sqlPlaceholders[6], sqlPlaceholders[7], sqlPlaceholders[8], sqlPlaceholders[9],
  427. sqlPlaceholders[10], sqlPlaceholders[11], sqlPlaceholders[12], sqlPlaceholders[13])
  428. }
  429. func getUpdateShareQuery() string {
  430. return fmt.Sprintf(`UPDATE %s SET name=%s,description=%s,scope=%s,paths=%s,updated_at=%s,expires_at=%s,
  431. password=%s,max_tokens=%s,allow_from=%s,user_id=%s WHERE share_id = %s`, sqlTableShares,
  432. sqlPlaceholders[0], sqlPlaceholders[1], sqlPlaceholders[2], sqlPlaceholders[3], sqlPlaceholders[4],
  433. sqlPlaceholders[5], sqlPlaceholders[6], sqlPlaceholders[7], sqlPlaceholders[8], sqlPlaceholders[9],
  434. sqlPlaceholders[10])
  435. }
  436. func getDeleteShareQuery() string {
  437. return fmt.Sprintf(`DELETE FROM %s WHERE share_id = %s`, sqlTableShares, sqlPlaceholders[0])
  438. }
  439. func getAPIKeyByIDQuery() string {
  440. return fmt.Sprintf(`SELECT %s FROM %s WHERE key_id = %s`, selectAPIKeyFields, sqlTableAPIKeys, sqlPlaceholders[0])
  441. }
  442. func getAPIKeysQuery(order string) string {
  443. return fmt.Sprintf(`SELECT %s FROM %s ORDER BY key_id %s LIMIT %s OFFSET %s`, selectAPIKeyFields, sqlTableAPIKeys,
  444. order, sqlPlaceholders[0], sqlPlaceholders[1])
  445. }
  446. func getDumpAPIKeysQuery() string {
  447. return fmt.Sprintf(`SELECT %s FROM %s`, selectAPIKeyFields, sqlTableAPIKeys)
  448. }
  449. func getAddAPIKeyQuery() string {
  450. return fmt.Sprintf(`INSERT INTO %s (key_id,name,api_key,scope,created_at,updated_at,last_use_at,expires_at,description,user_id,admin_id)
  451. VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)`, sqlTableAPIKeys, sqlPlaceholders[0], sqlPlaceholders[1],
  452. sqlPlaceholders[2], sqlPlaceholders[3], sqlPlaceholders[4], sqlPlaceholders[5], sqlPlaceholders[6],
  453. sqlPlaceholders[7], sqlPlaceholders[8], sqlPlaceholders[9], sqlPlaceholders[10])
  454. }
  455. func getUpdateAPIKeyQuery() string {
  456. return fmt.Sprintf(`UPDATE %s SET name=%s,scope=%s,expires_at=%s,user_id=%s,admin_id=%s,description=%s,updated_at=%s
  457. WHERE key_id = %s`, sqlTableAPIKeys, sqlPlaceholders[0], sqlPlaceholders[1], sqlPlaceholders[2],
  458. sqlPlaceholders[3], sqlPlaceholders[4], sqlPlaceholders[5], sqlPlaceholders[6], sqlPlaceholders[7])
  459. }
  460. func getDeleteAPIKeyQuery() string {
  461. return fmt.Sprintf(`DELETE FROM %s WHERE key_id = %s`, sqlTableAPIKeys, sqlPlaceholders[0])
  462. }
  463. func getRelatedUsersForAPIKeysQuery(apiKeys []APIKey) string {
  464. var sb strings.Builder
  465. for _, k := range apiKeys {
  466. if k.userID == 0 {
  467. continue
  468. }
  469. if sb.Len() == 0 {
  470. sb.WriteString("(")
  471. } else {
  472. sb.WriteString(",")
  473. }
  474. sb.WriteString(strconv.FormatInt(k.userID, 10))
  475. }
  476. if sb.Len() > 0 {
  477. sb.WriteString(")")
  478. } else {
  479. sb.WriteString("(0)")
  480. }
  481. return fmt.Sprintf(`SELECT id,username FROM %s WHERE id IN %s`, sqlTableUsers, sb.String())
  482. }
  483. func getRelatedAdminsForAPIKeysQuery(apiKeys []APIKey) string {
  484. var sb strings.Builder
  485. for _, k := range apiKeys {
  486. if k.adminID == 0 {
  487. continue
  488. }
  489. if sb.Len() == 0 {
  490. sb.WriteString("(")
  491. } else {
  492. sb.WriteString(",")
  493. }
  494. sb.WriteString(strconv.FormatInt(k.adminID, 10))
  495. }
  496. if sb.Len() > 0 {
  497. sb.WriteString(")")
  498. } else {
  499. sb.WriteString("(0)")
  500. }
  501. return fmt.Sprintf(`SELECT id,username FROM %s WHERE id IN %s`, sqlTableAdmins, sb.String())
  502. }
  503. func getUserByUsernameQuery(role string) string {
  504. if role == "" {
  505. return fmt.Sprintf(`SELECT %s FROM %s u LEFT JOIN %s r on r.id = u.role_id WHERE u.username = %s AND u.deleted_at = 0`,
  506. selectUserFields, sqlTableUsers, sqlTableRoles, sqlPlaceholders[0])
  507. }
  508. return fmt.Sprintf(`SELECT %s FROM %s u LEFT JOIN %s r on r.id = u.role_id WHERE u.username = %s AND u.deleted_at = 0
  509. AND u.role_id is NOT NULL AND r.name = %s`,
  510. selectUserFields, sqlTableUsers, sqlTableRoles, sqlPlaceholders[0], sqlPlaceholders[1])
  511. }
  512. func getUsersQuery(order, role string) string {
  513. if role == "" {
  514. return fmt.Sprintf(`SELECT %s FROM %s u LEFT JOIN %s r on r.id = u.role_id WHERE
  515. u.deleted_at = 0 ORDER BY u.username %s LIMIT %s OFFSET %s`,
  516. selectUserFields, sqlTableUsers, sqlTableRoles, order, sqlPlaceholders[0], sqlPlaceholders[1])
  517. }
  518. return fmt.Sprintf(`SELECT %s FROM %s u LEFT JOIN %s r on r.id = u.role_id WHERE
  519. u.deleted_at = 0 AND u.role_id is NOT NULL AND r.name = %s ORDER BY u.username %s LIMIT %s OFFSET %s`,
  520. selectUserFields, sqlTableUsers, sqlTableRoles, sqlPlaceholders[0], order, sqlPlaceholders[1], sqlPlaceholders[2])
  521. }
  522. func getUsersForQuotaCheckQuery(numArgs int) string {
  523. var sb strings.Builder
  524. for idx := 0; idx < numArgs; idx++ {
  525. if sb.Len() == 0 {
  526. sb.WriteString("(")
  527. } else {
  528. sb.WriteString(",")
  529. }
  530. sb.WriteString(sqlPlaceholders[idx])
  531. }
  532. if sb.Len() > 0 {
  533. sb.WriteString(")")
  534. }
  535. return fmt.Sprintf(`SELECT id,username,quota_size,used_quota_size,total_data_transfer,upload_data_transfer,
  536. download_data_transfer,used_upload_data_transfer,used_download_data_transfer,filters FROM %s WHERE username IN %s`,
  537. sqlTableUsers, sb.String())
  538. }
  539. func getRecentlyUpdatedUsersQuery() string {
  540. return fmt.Sprintf(`SELECT %s FROM %s u LEFT JOIN %s r on r.id = u.role_id WHERE u.updated_at >= %s OR u.deleted_at > 0`,
  541. selectUserFields, sqlTableUsers, sqlTableRoles, sqlPlaceholders[0])
  542. }
  543. func getDumpUsersQuery() string {
  544. return fmt.Sprintf(`SELECT %s FROM %s u LEFT JOIN %s r on r.id = u.role_id WHERE u.deleted_at = 0`,
  545. selectUserFields, sqlTableUsers, sqlTableRoles)
  546. }
  547. func getDumpFoldersQuery() string {
  548. return fmt.Sprintf(`SELECT %s FROM %s`, selectFolderFields, sqlTableFolders)
  549. }
  550. func getUpdateTransferQuotaQuery(reset bool) string {
  551. if reset {
  552. return fmt.Sprintf(`UPDATE %s SET used_upload_data_transfer = %s,used_download_data_transfer = %s,last_quota_update = %s
  553. WHERE username = %s`, sqlTableUsers, sqlPlaceholders[0], sqlPlaceholders[1], sqlPlaceholders[2], sqlPlaceholders[3])
  554. }
  555. return fmt.Sprintf(`UPDATE %s SET used_upload_data_transfer = used_upload_data_transfer + %s,
  556. used_download_data_transfer = used_download_data_transfer + %s,last_quota_update = %s
  557. WHERE username = %s`, sqlTableUsers, sqlPlaceholders[0], sqlPlaceholders[1], sqlPlaceholders[2], sqlPlaceholders[3])
  558. }
  559. func getUpdateQuotaQuery(reset bool) string {
  560. if reset {
  561. return fmt.Sprintf(`UPDATE %s SET used_quota_size = %s,used_quota_files = %s,last_quota_update = %s
  562. WHERE username = %s`, sqlTableUsers, sqlPlaceholders[0], sqlPlaceholders[1], sqlPlaceholders[2], sqlPlaceholders[3])
  563. }
  564. return fmt.Sprintf(`UPDATE %s SET used_quota_size = used_quota_size + %s,used_quota_files = used_quota_files + %s,last_quota_update = %s
  565. WHERE username = %s`, sqlTableUsers, sqlPlaceholders[0], sqlPlaceholders[1], sqlPlaceholders[2], sqlPlaceholders[3])
  566. }
  567. func getSetUpdateAtQuery() string {
  568. return fmt.Sprintf(`UPDATE %s SET updated_at = %s WHERE username = %s`, sqlTableUsers, sqlPlaceholders[0], sqlPlaceholders[1])
  569. }
  570. func getSetFirstUploadQuery() string {
  571. return fmt.Sprintf(`UPDATE %s SET first_upload = %s WHERE username = %s AND first_upload = 0`,
  572. sqlTableUsers, sqlPlaceholders[0], sqlPlaceholders[1])
  573. }
  574. func getSetFirstDownloadQuery() string {
  575. return fmt.Sprintf(`UPDATE %s SET first_download = %s WHERE username = %s AND first_download = 0`,
  576. sqlTableUsers, sqlPlaceholders[0], sqlPlaceholders[1])
  577. }
  578. func getUpdateLastLoginQuery() string {
  579. return fmt.Sprintf(`UPDATE %s SET last_login = %s WHERE username = %s`, sqlTableUsers, sqlPlaceholders[0], sqlPlaceholders[1])
  580. }
  581. func getUpdateAdminLastLoginQuery() string {
  582. return fmt.Sprintf(`UPDATE %s SET last_login = %s WHERE username = %s`, sqlTableAdmins, sqlPlaceholders[0], sqlPlaceholders[1])
  583. }
  584. func getUpdateAPIKeyLastUseQuery() string {
  585. return fmt.Sprintf(`UPDATE %s SET last_use_at = %s WHERE key_id = %s`, sqlTableAPIKeys, sqlPlaceholders[0], sqlPlaceholders[1])
  586. }
  587. func getUpdateShareLastUseQuery() string {
  588. return fmt.Sprintf(`UPDATE %s SET last_use_at = %s, used_tokens = used_tokens +%s WHERE share_id = %s`,
  589. sqlTableShares, sqlPlaceholders[0], sqlPlaceholders[1], sqlPlaceholders[2])
  590. }
  591. func getQuotaQuery() string {
  592. return fmt.Sprintf(`SELECT used_quota_size,used_quota_files,used_upload_data_transfer,
  593. used_download_data_transfer FROM %s WHERE username = %s`,
  594. sqlTableUsers, sqlPlaceholders[0])
  595. }
  596. func getAddUserQuery(role string) string {
  597. return fmt.Sprintf(`INSERT INTO %s (username,password,public_keys,home_dir,uid,gid,max_sessions,quota_size,quota_files,permissions,
  598. used_quota_size,used_quota_files,last_quota_update,upload_bandwidth,download_bandwidth,status,last_login,expiration_date,filters,
  599. filesystem,additional_info,description,email,created_at,updated_at,upload_data_transfer,download_data_transfer,total_data_transfer,
  600. used_upload_data_transfer,used_download_data_transfer,deleted_at,first_download,first_upload,role_id,last_password_change)
  601. VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,0,0,0,%s,%s,%s,0,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,0,0,0,0,0,
  602. COALESCE((SELECT id from %s WHERE name=%s),%s),%s)`,
  603. sqlTableUsers, sqlPlaceholders[0], sqlPlaceholders[1], sqlPlaceholders[2], sqlPlaceholders[3], sqlPlaceholders[4],
  604. sqlPlaceholders[5], sqlPlaceholders[6], sqlPlaceholders[7], sqlPlaceholders[8], sqlPlaceholders[9],
  605. sqlPlaceholders[10], sqlPlaceholders[11], sqlPlaceholders[12], sqlPlaceholders[13], sqlPlaceholders[14],
  606. sqlPlaceholders[15], sqlPlaceholders[16], sqlPlaceholders[17], sqlPlaceholders[18], sqlPlaceholders[19],
  607. sqlPlaceholders[20], sqlPlaceholders[21], sqlPlaceholders[22], sqlPlaceholders[23], sqlTableRoles,
  608. sqlPlaceholders[24], getCoalesceDefaultForRole(role), sqlPlaceholders[25])
  609. }
  610. func getUpdateUserQuery(role string) string {
  611. return fmt.Sprintf(`UPDATE %s SET password=%s,public_keys=%s,home_dir=%s,uid=%s,gid=%s,max_sessions=%s,quota_size=%s,
  612. quota_files=%s,permissions=%s,upload_bandwidth=%s,download_bandwidth=%s,status=%s,expiration_date=%s,filters=%s,filesystem=%s,
  613. additional_info=%s,description=%s,email=%s,updated_at=%s,upload_data_transfer=%s,download_data_transfer=%s,
  614. total_data_transfer=%s,role_id=COALESCE((SELECT id from %s WHERE name=%s),%s),last_password_change=%s WHERE username = %s`,
  615. sqlTableUsers, sqlPlaceholders[0], sqlPlaceholders[1], sqlPlaceholders[2], sqlPlaceholders[3], sqlPlaceholders[4],
  616. sqlPlaceholders[5], sqlPlaceholders[6], sqlPlaceholders[7], sqlPlaceholders[8], sqlPlaceholders[9],
  617. sqlPlaceholders[10], sqlPlaceholders[11], sqlPlaceholders[12], sqlPlaceholders[13], sqlPlaceholders[14],
  618. sqlPlaceholders[15], sqlPlaceholders[16], sqlPlaceholders[17], sqlPlaceholders[18], sqlPlaceholders[19],
  619. sqlPlaceholders[20], sqlPlaceholders[21], sqlTableRoles, sqlPlaceholders[22], getCoalesceDefaultForRole(role),
  620. sqlPlaceholders[23], sqlPlaceholders[24])
  621. }
  622. func getUpdateUserPasswordQuery() string {
  623. return fmt.Sprintf(`UPDATE %s SET password=%s WHERE username = %s`,
  624. sqlTableUsers, sqlPlaceholders[0], sqlPlaceholders[1])
  625. }
  626. func getDeleteUserQuery(softDelete bool) string {
  627. if softDelete {
  628. return fmt.Sprintf(`UPDATE %s SET updated_at=%s,deleted_at=%s WHERE username = %s`,
  629. sqlTableUsers, sqlPlaceholders[0], sqlPlaceholders[1], sqlPlaceholders[2])
  630. }
  631. return fmt.Sprintf(`DELETE FROM %s WHERE username = %s`, sqlTableUsers, sqlPlaceholders[0])
  632. }
  633. func getRemoveSoftDeletedUserQuery() string {
  634. return fmt.Sprintf(`DELETE FROM %s WHERE username = %s AND deleted_at > 0`, sqlTableUsers, sqlPlaceholders[0])
  635. }
  636. func getFolderByNameQuery() string {
  637. return fmt.Sprintf(`SELECT %s FROM %s WHERE name = %s`, selectFolderFields, sqlTableFolders, sqlPlaceholders[0])
  638. }
  639. func getAddFolderQuery() string {
  640. return fmt.Sprintf(`INSERT INTO %s (path,used_quota_size,used_quota_files,last_quota_update,name,description,filesystem)
  641. VALUES (%s,%s,%s,%s,%s,%s,%s)`, sqlTableFolders, sqlPlaceholders[0], sqlPlaceholders[1], sqlPlaceholders[2],
  642. sqlPlaceholders[3], sqlPlaceholders[4], sqlPlaceholders[5], sqlPlaceholders[6])
  643. }
  644. func getUpdateFolderQuery() string {
  645. return fmt.Sprintf(`UPDATE %s SET path=%s,description=%s,filesystem=%s WHERE name = %s`, sqlTableFolders, sqlPlaceholders[0],
  646. sqlPlaceholders[1], sqlPlaceholders[2], sqlPlaceholders[3])
  647. }
  648. func getDeleteFolderQuery() string {
  649. return fmt.Sprintf(`DELETE FROM %s WHERE name = %s`, sqlTableFolders, sqlPlaceholders[0])
  650. }
  651. func getUpsertFolderQuery() string {
  652. if config.Driver == MySQLDataProviderName {
  653. return fmt.Sprintf("INSERT INTO %s (`path`,`used_quota_size`,`used_quota_files`,`last_quota_update`,`name`,"+
  654. "`description`,`filesystem`) VALUES (%s,%s,%s,%s,%s,%s,%s) ON DUPLICATE KEY UPDATE "+
  655. "`path`=VALUES(`path`),`description`=VALUES(`description`),`filesystem`=VALUES(`filesystem`)",
  656. sqlTableFolders, sqlPlaceholders[0], sqlPlaceholders[1], sqlPlaceholders[2], sqlPlaceholders[3], sqlPlaceholders[4],
  657. sqlPlaceholders[5], sqlPlaceholders[6])
  658. }
  659. return fmt.Sprintf(`INSERT INTO %s (path,used_quota_size,used_quota_files,last_quota_update,name,description,filesystem)
  660. VALUES (%s,%s,%s,%s,%s,%s,%s) ON CONFLICT (name) DO UPDATE SET path = EXCLUDED.path,description=EXCLUDED.description,
  661. filesystem=EXCLUDED.filesystem`, sqlTableFolders, sqlPlaceholders[0], sqlPlaceholders[1], sqlPlaceholders[2],
  662. sqlPlaceholders[3], sqlPlaceholders[4], sqlPlaceholders[5], sqlPlaceholders[6])
  663. }
  664. func getClearUserGroupMappingQuery() string {
  665. return fmt.Sprintf(`DELETE FROM %s WHERE user_id = (SELECT id FROM %s WHERE username = %s)`, sqlTableUsersGroupsMapping,
  666. sqlTableUsers, sqlPlaceholders[0])
  667. }
  668. func getAddUserGroupMappingQuery() string {
  669. return fmt.Sprintf(`INSERT INTO %s (user_id,group_id,group_type) VALUES ((SELECT id FROM %s WHERE username = %s),
  670. (SELECT id FROM %s WHERE name = %s),%s)`,
  671. sqlTableUsersGroupsMapping, sqlTableUsers, sqlPlaceholders[0], getSQLQuotedName(sqlTableGroups),
  672. sqlPlaceholders[1], sqlPlaceholders[2])
  673. }
  674. func getClearAdminGroupMappingQuery() string {
  675. return fmt.Sprintf(`DELETE FROM %s WHERE admin_id = (SELECT id FROM %s WHERE username = %s)`, sqlTableAdminsGroupsMapping,
  676. sqlTableAdmins, sqlPlaceholders[0])
  677. }
  678. func getAddAdminGroupMappingQuery() string {
  679. return fmt.Sprintf(`INSERT INTO %s (admin_id,group_id,options) VALUES ((SELECT id FROM %s WHERE username = %s),
  680. (SELECT id FROM %s WHERE name = %s),%s)`,
  681. sqlTableAdminsGroupsMapping, sqlTableAdmins, sqlPlaceholders[0], getSQLQuotedName(sqlTableGroups),
  682. sqlPlaceholders[1], sqlPlaceholders[2])
  683. }
  684. func getClearGroupFolderMappingQuery() string {
  685. return fmt.Sprintf(`DELETE FROM %s WHERE group_id = (SELECT id FROM %s WHERE name = %s)`, sqlTableGroupsFoldersMapping,
  686. getSQLQuotedName(sqlTableGroups), sqlPlaceholders[0])
  687. }
  688. func getAddGroupFolderMappingQuery() string {
  689. return fmt.Sprintf(`INSERT INTO %s (virtual_path,quota_size,quota_files,folder_id,group_id)
  690. VALUES (%s,%s,%s,(SELECT id FROM %s WHERE name = %s),(SELECT id FROM %s WHERE name = %s))`,
  691. sqlTableGroupsFoldersMapping, sqlPlaceholders[0], sqlPlaceholders[1], sqlPlaceholders[2], sqlTableFolders,
  692. sqlPlaceholders[3], getSQLQuotedName(sqlTableGroups), sqlPlaceholders[4])
  693. }
  694. func getClearUserFolderMappingQuery() string {
  695. return fmt.Sprintf(`DELETE FROM %s WHERE user_id = (SELECT id FROM %s WHERE username = %s)`, sqlTableUsersFoldersMapping,
  696. sqlTableUsers, sqlPlaceholders[0])
  697. }
  698. func getAddUserFolderMappingQuery() string {
  699. return fmt.Sprintf(`INSERT INTO %s (virtual_path,quota_size,quota_files,folder_id,user_id)
  700. VALUES (%s,%s,%s,(SELECT id FROM %s WHERE name = %s),(SELECT id FROM %s WHERE username = %s))`,
  701. sqlTableUsersFoldersMapping, sqlPlaceholders[0], sqlPlaceholders[1], sqlPlaceholders[2], sqlTableFolders,
  702. sqlPlaceholders[3], sqlTableUsers, sqlPlaceholders[4])
  703. }
  704. func getFoldersQuery(order string, minimal bool) string {
  705. var fieldSelection string
  706. if minimal {
  707. fieldSelection = selectMinimalFields
  708. } else {
  709. fieldSelection = selectFolderFields
  710. }
  711. return fmt.Sprintf(`SELECT %s FROM %s ORDER BY name %s LIMIT %s OFFSET %s`, fieldSelection, sqlTableFolders,
  712. order, sqlPlaceholders[0], sqlPlaceholders[1])
  713. }
  714. func getUpdateFolderQuotaQuery(reset bool) string {
  715. if reset {
  716. return fmt.Sprintf(`UPDATE %s SET used_quota_size = %s,used_quota_files = %s,last_quota_update = %s
  717. WHERE name = %s`, sqlTableFolders, sqlPlaceholders[0], sqlPlaceholders[1], sqlPlaceholders[2], sqlPlaceholders[3])
  718. }
  719. return fmt.Sprintf(`UPDATE %s SET used_quota_size = used_quota_size + %s,used_quota_files = used_quota_files + %s,last_quota_update = %s
  720. WHERE name = %s`, sqlTableFolders, sqlPlaceholders[0], sqlPlaceholders[1], sqlPlaceholders[2], sqlPlaceholders[3])
  721. }
  722. func getQuotaFolderQuery() string {
  723. return fmt.Sprintf(`SELECT used_quota_size,used_quota_files FROM %s WHERE name = %s`, sqlTableFolders,
  724. sqlPlaceholders[0])
  725. }
  726. func getRelatedGroupsForUsersQuery(users []User) string {
  727. var sb strings.Builder
  728. for _, u := range users {
  729. if sb.Len() == 0 {
  730. sb.WriteString("(")
  731. } else {
  732. sb.WriteString(",")
  733. }
  734. sb.WriteString(strconv.FormatInt(u.ID, 10))
  735. }
  736. if sb.Len() > 0 {
  737. sb.WriteString(")")
  738. }
  739. return fmt.Sprintf(`SELECT g.name,ug.group_type,ug.user_id FROM %s g INNER JOIN %s ug ON g.id = ug.group_id WHERE
  740. ug.user_id IN %s ORDER BY ug.user_id`, getSQLQuotedName(sqlTableGroups), sqlTableUsersGroupsMapping, sb.String())
  741. }
  742. func getRelatedGroupsForAdminsQuery(admins []Admin) string {
  743. var sb strings.Builder
  744. for _, a := range admins {
  745. if sb.Len() == 0 {
  746. sb.WriteString("(")
  747. } else {
  748. sb.WriteString(",")
  749. }
  750. sb.WriteString(strconv.FormatInt(a.ID, 10))
  751. }
  752. if sb.Len() > 0 {
  753. sb.WriteString(")")
  754. }
  755. return fmt.Sprintf(`SELECT g.name,ag.options,ag.admin_id FROM %s g INNER JOIN %s ag ON g.id = ag.group_id WHERE
  756. ag.admin_id IN %s ORDER BY ag.admin_id`, getSQLQuotedName(sqlTableGroups), sqlTableAdminsGroupsMapping, sb.String())
  757. }
  758. func getRelatedFoldersForUsersQuery(users []User) string {
  759. var sb strings.Builder
  760. for _, u := range users {
  761. if sb.Len() == 0 {
  762. sb.WriteString("(")
  763. } else {
  764. sb.WriteString(",")
  765. }
  766. sb.WriteString(strconv.FormatInt(u.ID, 10))
  767. }
  768. if sb.Len() > 0 {
  769. sb.WriteString(")")
  770. }
  771. return fmt.Sprintf(`SELECT f.id,f.name,f.path,f.used_quota_size,f.used_quota_files,f.last_quota_update,fm.virtual_path,
  772. fm.quota_size,fm.quota_files,fm.user_id,f.filesystem,f.description FROM %s f INNER JOIN %s fm ON f.id = fm.folder_id WHERE
  773. fm.user_id IN %s ORDER BY fm.user_id`, sqlTableFolders, sqlTableUsersFoldersMapping, sb.String())
  774. }
  775. func getRelatedUsersForFoldersQuery(folders []vfs.BaseVirtualFolder) string {
  776. var sb strings.Builder
  777. for _, f := range folders {
  778. if sb.Len() == 0 {
  779. sb.WriteString("(")
  780. } else {
  781. sb.WriteString(",")
  782. }
  783. sb.WriteString(strconv.FormatInt(f.ID, 10))
  784. }
  785. if sb.Len() > 0 {
  786. sb.WriteString(")")
  787. }
  788. return fmt.Sprintf(`SELECT fm.folder_id,u.username FROM %s fm INNER JOIN %s u ON fm.user_id = u.id
  789. WHERE fm.folder_id IN %s ORDER BY fm.folder_id`, sqlTableUsersFoldersMapping, sqlTableUsers, sb.String())
  790. }
  791. func getRelatedGroupsForFoldersQuery(folders []vfs.BaseVirtualFolder) string {
  792. var sb strings.Builder
  793. for _, f := range folders {
  794. if sb.Len() == 0 {
  795. sb.WriteString("(")
  796. } else {
  797. sb.WriteString(",")
  798. }
  799. sb.WriteString(strconv.FormatInt(f.ID, 10))
  800. }
  801. if sb.Len() > 0 {
  802. sb.WriteString(")")
  803. }
  804. return fmt.Sprintf(`SELECT fm.folder_id,g.name FROM %s fm INNER JOIN %s g ON fm.group_id = g.id
  805. WHERE fm.folder_id IN %s ORDER BY fm.folder_id`, sqlTableGroupsFoldersMapping, getSQLQuotedName(sqlTableGroups),
  806. sb.String())
  807. }
  808. func getRelatedUsersForGroupsQuery(groups []Group) string {
  809. var sb strings.Builder
  810. for _, g := range groups {
  811. if sb.Len() == 0 {
  812. sb.WriteString("(")
  813. } else {
  814. sb.WriteString(",")
  815. }
  816. sb.WriteString(strconv.FormatInt(g.ID, 10))
  817. }
  818. if sb.Len() > 0 {
  819. sb.WriteString(")")
  820. }
  821. return fmt.Sprintf(`SELECT um.group_id,u.username FROM %s um INNER JOIN %s u ON um.user_id = u.id
  822. WHERE um.group_id IN %s ORDER BY um.group_id`, sqlTableUsersGroupsMapping, sqlTableUsers, sb.String())
  823. }
  824. func getRelatedAdminsForGroupsQuery(groups []Group) string {
  825. var sb strings.Builder
  826. for _, g := range groups {
  827. if sb.Len() == 0 {
  828. sb.WriteString("(")
  829. } else {
  830. sb.WriteString(",")
  831. }
  832. sb.WriteString(strconv.FormatInt(g.ID, 10))
  833. }
  834. if sb.Len() > 0 {
  835. sb.WriteString(")")
  836. }
  837. return fmt.Sprintf(`SELECT am.group_id,a.username FROM %s am INNER JOIN %s a ON am.admin_id = a.id
  838. WHERE am.group_id IN %s ORDER BY am.group_id`, sqlTableAdminsGroupsMapping, sqlTableAdmins, sb.String())
  839. }
  840. func getRelatedFoldersForGroupsQuery(groups []Group) string {
  841. var sb strings.Builder
  842. for _, g := range groups {
  843. if sb.Len() == 0 {
  844. sb.WriteString("(")
  845. } else {
  846. sb.WriteString(",")
  847. }
  848. sb.WriteString(strconv.FormatInt(g.ID, 10))
  849. }
  850. if sb.Len() > 0 {
  851. sb.WriteString(")")
  852. }
  853. return fmt.Sprintf(`SELECT f.id,f.name,f.path,f.used_quota_size,f.used_quota_files,f.last_quota_update,fm.virtual_path,
  854. fm.quota_size,fm.quota_files,fm.group_id,f.filesystem,f.description FROM %s f INNER JOIN %s fm ON f.id = fm.folder_id WHERE
  855. fm.group_id IN %s ORDER BY fm.group_id`, sqlTableFolders, sqlTableGroupsFoldersMapping, sb.String())
  856. }
  857. func getActiveTransfersQuery() string {
  858. return fmt.Sprintf(`SELECT transfer_id,connection_id,transfer_type,username,folder_name,ip,truncated_size,
  859. current_ul_size,current_dl_size,created_at,updated_at FROM %s WHERE updated_at > %s`,
  860. sqlTableActiveTransfers, sqlPlaceholders[0])
  861. }
  862. func getAddActiveTransferQuery() string {
  863. return fmt.Sprintf(`INSERT INTO %s (transfer_id,connection_id,transfer_type,username,folder_name,ip,truncated_size,
  864. current_ul_size,current_dl_size,created_at,updated_at) VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)`,
  865. sqlTableActiveTransfers, sqlPlaceholders[0], sqlPlaceholders[1], sqlPlaceholders[2], sqlPlaceholders[3],
  866. sqlPlaceholders[4], sqlPlaceholders[5], sqlPlaceholders[6], sqlPlaceholders[7], sqlPlaceholders[8],
  867. sqlPlaceholders[9], sqlPlaceholders[10])
  868. }
  869. func getUpdateActiveTransferSizesQuery() string {
  870. return fmt.Sprintf(`UPDATE %s SET current_ul_size=%s,current_dl_size=%s,updated_at=%s WHERE connection_id = %s AND transfer_id = %s`,
  871. sqlTableActiveTransfers, sqlPlaceholders[0], sqlPlaceholders[1], sqlPlaceholders[2], sqlPlaceholders[3], sqlPlaceholders[4])
  872. }
  873. func getRemoveActiveTransferQuery() string {
  874. return fmt.Sprintf(`DELETE FROM %s WHERE connection_id = %s AND transfer_id = %s`,
  875. sqlTableActiveTransfers, sqlPlaceholders[0], sqlPlaceholders[1])
  876. }
  877. func getCleanupActiveTransfersQuery() string {
  878. return fmt.Sprintf(`DELETE FROM %s WHERE updated_at < %s`, sqlTableActiveTransfers, sqlPlaceholders[0])
  879. }
  880. func getRelatedRulesForActionsQuery(actions []BaseEventAction) string {
  881. var sb strings.Builder
  882. for _, a := range actions {
  883. if sb.Len() == 0 {
  884. sb.WriteString("(")
  885. } else {
  886. sb.WriteString(",")
  887. }
  888. sb.WriteString(strconv.FormatInt(a.ID, 10))
  889. }
  890. if sb.Len() > 0 {
  891. sb.WriteString(")")
  892. }
  893. return fmt.Sprintf(`SELECT am.action_id,r.name FROM %s am INNER JOIN %s r ON am.rule_id = r.id
  894. WHERE am.action_id IN %s ORDER BY r.name ASC`, sqlTableRulesActionsMapping, sqlTableEventsRules, sb.String())
  895. }
  896. func getEventsActionsQuery(order string, minimal bool) string {
  897. var fieldSelection string
  898. if minimal {
  899. fieldSelection = selectMinimalFields
  900. } else {
  901. fieldSelection = selectEventActionFields
  902. }
  903. return fmt.Sprintf(`SELECT %s FROM %s ORDER BY name %s LIMIT %s OFFSET %s`, fieldSelection,
  904. sqlTableEventsActions, order, sqlPlaceholders[0], sqlPlaceholders[1])
  905. }
  906. func getDumpEventActionsQuery() string {
  907. return fmt.Sprintf(`SELECT %s FROM %s`, selectEventActionFields, sqlTableEventsActions)
  908. }
  909. func getEventActionByNameQuery() string {
  910. return fmt.Sprintf(`SELECT %s FROM %s WHERE name = %s`, selectEventActionFields, sqlTableEventsActions,
  911. sqlPlaceholders[0])
  912. }
  913. func getAddEventActionQuery() string {
  914. return fmt.Sprintf(`INSERT INTO %s (name,description,type,options) VALUES (%s,%s,%s,%s)`,
  915. sqlTableEventsActions, sqlPlaceholders[0], sqlPlaceholders[1], sqlPlaceholders[2], sqlPlaceholders[3])
  916. }
  917. func getUpdateEventActionQuery() string {
  918. return fmt.Sprintf(`UPDATE %s SET description=%s,type=%s,options=%s WHERE name = %s`, sqlTableEventsActions,
  919. sqlPlaceholders[0], sqlPlaceholders[1], sqlPlaceholders[2], sqlPlaceholders[3])
  920. }
  921. func getDeleteEventActionQuery() string {
  922. return fmt.Sprintf(`DELETE FROM %s WHERE name = %s`, sqlTableEventsActions, sqlPlaceholders[0])
  923. }
  924. func getEventRulesQuery(order string) string {
  925. return fmt.Sprintf(`SELECT %s FROM %s WHERE deleted_at = 0 ORDER BY name %s LIMIT %s OFFSET %s`,
  926. getSelectEventRuleFields(), sqlTableEventsRules, order, sqlPlaceholders[0], sqlPlaceholders[1])
  927. }
  928. func getDumpEventRulesQuery() string {
  929. return fmt.Sprintf(`SELECT %s FROM %s WHERE deleted_at = 0`, getSelectEventRuleFields(), sqlTableEventsRules)
  930. }
  931. func getRecentlyUpdatedRulesQuery() string {
  932. return fmt.Sprintf(`SELECT %s FROM %s WHERE updated_at >= %s OR deleted_at > 0`, getSelectEventRuleFields(),
  933. sqlTableEventsRules, sqlPlaceholders[0])
  934. }
  935. func getEventRulesByNameQuery() string {
  936. return fmt.Sprintf(`SELECT %s FROM %s WHERE name = %s AND deleted_at = 0`, getSelectEventRuleFields(), sqlTableEventsRules,
  937. sqlPlaceholders[0])
  938. }
  939. func getAddEventRuleQuery() string {
  940. return fmt.Sprintf(`INSERT INTO %s (name,description,created_at,updated_at,%s,conditions,deleted_at,status)
  941. VALUES (%s,%s,%s,%s,%s,%s,0,%s)`,
  942. sqlTableEventsRules, getSQLQuotedName("trigger"), sqlPlaceholders[0], sqlPlaceholders[1], sqlPlaceholders[2],
  943. sqlPlaceholders[3], sqlPlaceholders[4], sqlPlaceholders[5], sqlPlaceholders[6])
  944. }
  945. func getUpdateEventRuleQuery() string {
  946. return fmt.Sprintf(`UPDATE %s SET description=%s,updated_at=%s,%s=%s,conditions=%s,status=%s WHERE name = %s`,
  947. sqlTableEventsRules, sqlPlaceholders[0], sqlPlaceholders[1], getSQLQuotedName("trigger"), sqlPlaceholders[2],
  948. sqlPlaceholders[3], sqlPlaceholders[4], sqlPlaceholders[5])
  949. }
  950. func getDeleteEventRuleQuery(softDelete bool) string {
  951. if softDelete {
  952. return fmt.Sprintf(`UPDATE %s SET updated_at=%s,deleted_at=%s WHERE name = %s`,
  953. sqlTableEventsRules, sqlPlaceholders[0], sqlPlaceholders[1], sqlPlaceholders[2])
  954. }
  955. return fmt.Sprintf(`DELETE FROM %s WHERE name = %s`, sqlTableEventsRules, sqlPlaceholders[0])
  956. }
  957. func getRemoveSoftDeletedRuleQuery() string {
  958. return fmt.Sprintf(`DELETE FROM %s WHERE name = %s AND deleted_at > 0`, sqlTableEventsRules, sqlPlaceholders[0])
  959. }
  960. func getClearRuleActionMappingQuery() string {
  961. return fmt.Sprintf(`DELETE FROM %s WHERE rule_id = (SELECT id FROM %s WHERE name = %s)`, sqlTableRulesActionsMapping,
  962. sqlTableEventsRules, sqlPlaceholders[0])
  963. }
  964. func getUpdateRulesTimestampQuery() string {
  965. return fmt.Sprintf(`UPDATE %s SET updated_at=%s WHERE id IN (SELECT rule_id FROM %s WHERE action_id = (SELECT id from %s WHERE name = %s))`,
  966. sqlTableEventsRules, sqlPlaceholders[0], sqlTableRulesActionsMapping, sqlTableEventsActions, sqlPlaceholders[1])
  967. }
  968. func getRelatedActionsForRulesQuery(rules []EventRule) string {
  969. var sb strings.Builder
  970. for _, r := range rules {
  971. if sb.Len() == 0 {
  972. sb.WriteString("(")
  973. } else {
  974. sb.WriteString(",")
  975. }
  976. sb.WriteString(strconv.FormatInt(r.ID, 10))
  977. }
  978. if sb.Len() > 0 {
  979. sb.WriteString(")")
  980. }
  981. return fmt.Sprintf(`SELECT a.id,a.name,a.description,a.type,a.options,am.options,am.%s,
  982. am.rule_id FROM %s a INNER JOIN %s am ON a.id = am.action_id WHERE am.rule_id IN %s ORDER BY am.%s ASC`,
  983. getSQLQuotedName("order"), sqlTableEventsActions, sqlTableRulesActionsMapping, sb.String(),
  984. getSQLQuotedName("order"))
  985. }
  986. func getAddRuleActionMappingQuery() string {
  987. return fmt.Sprintf(`INSERT INTO %s (rule_id,action_id,%s,options) VALUES ((SELECT id FROM %s WHERE name = %s),
  988. (SELECT id FROM %s WHERE name = %s),%s,%s)`,
  989. sqlTableRulesActionsMapping, getSQLQuotedName("order"), sqlTableEventsRules, sqlPlaceholders[0],
  990. sqlTableEventsActions, sqlPlaceholders[1], sqlPlaceholders[2], sqlPlaceholders[3])
  991. }
  992. func getTaskByNameQuery() string {
  993. return fmt.Sprintf(`SELECT updated_at,version FROM %s WHERE name = %s`, sqlTableTasks, sqlPlaceholders[0])
  994. }
  995. func getAddTaskQuery() string {
  996. return fmt.Sprintf(`INSERT INTO %s (name,updated_at,version) VALUES (%s,%s,0)`,
  997. sqlTableTasks, sqlPlaceholders[0], sqlPlaceholders[1])
  998. }
  999. func getUpdateTaskQuery() string {
  1000. return fmt.Sprintf(`UPDATE %s SET updated_at=%s,version = version + 1 WHERE name = %s AND version = %s`,
  1001. sqlTableTasks, sqlPlaceholders[0], sqlPlaceholders[1], sqlPlaceholders[2])
  1002. }
  1003. func getUpdateTaskTimestampQuery() string {
  1004. return fmt.Sprintf(`UPDATE %s SET updated_at=%s WHERE name = %s`,
  1005. sqlTableTasks, sqlPlaceholders[0], sqlPlaceholders[1])
  1006. }
  1007. func getDeleteTaskQuery() string {
  1008. return fmt.Sprintf(`DELETE FROM %s WHERE name = %s`, sqlTableTasks, sqlPlaceholders[0])
  1009. }
  1010. func getAddNodeQuery() string {
  1011. if config.Driver == MySQLDataProviderName {
  1012. return fmt.Sprintf("INSERT INTO %s (`name`,`data`,created_at,`updated_at`) VALUES (%s,%s,%s,%s) ON DUPLICATE KEY UPDATE "+
  1013. "`data`=VALUES(`data`), `created_at`=VALUES(`created_at`), `updated_at`=VALUES(`updated_at`)",
  1014. sqlTableNodes, sqlPlaceholders[0], sqlPlaceholders[1], sqlPlaceholders[2], sqlPlaceholders[3])
  1015. }
  1016. return fmt.Sprintf(`INSERT INTO %s (name,data,created_at,updated_at) VALUES (%s,%s,%s,%s) ON CONFLICT(name)
  1017. DO UPDATE SET data=EXCLUDED.data, created_at=EXCLUDED.created_at, updated_at=EXCLUDED.updated_at`,
  1018. sqlTableNodes, sqlPlaceholders[0], sqlPlaceholders[1], sqlPlaceholders[2], sqlPlaceholders[3])
  1019. }
  1020. func getUpdateNodeTimestampQuery() string {
  1021. return fmt.Sprintf(`UPDATE %s SET updated_at=%s WHERE name = %s`,
  1022. sqlTableNodes, sqlPlaceholders[0], sqlPlaceholders[1])
  1023. }
  1024. func getNodeByNameQuery() string {
  1025. return fmt.Sprintf(`SELECT name,data,created_at,updated_at FROM %s WHERE name = %s AND updated_at > %s`,
  1026. sqlTableNodes, sqlPlaceholders[0], sqlPlaceholders[1])
  1027. }
  1028. func getNodesQuery() string {
  1029. return fmt.Sprintf(`SELECT name,data,created_at,updated_at FROM %s WHERE name != %s AND updated_at > %s`,
  1030. sqlTableNodes, sqlPlaceholders[0], sqlPlaceholders[1])
  1031. }
  1032. func getCleanupNodesQuery() string {
  1033. return fmt.Sprintf(`DELETE FROM %s WHERE updated_at < %s`, sqlTableNodes, sqlPlaceholders[0])
  1034. }
  1035. func getDatabaseVersionQuery() string {
  1036. return fmt.Sprintf("SELECT version from %s LIMIT 1", sqlTableSchemaVersion)
  1037. }
  1038. func getUpdateDBVersionQuery() string {
  1039. return fmt.Sprintf(`UPDATE %s SET version=%s`, sqlTableSchemaVersion, sqlPlaceholders[0])
  1040. }