]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - server/models/video/sql/video-model-get-query-builder.ts
Use raw SQL for most of video queries
[github/Chocobozzz/PeerTube.git] / server / models / video / sql / video-model-get-query-builder.ts
CommitLineData
d9bf974f 1import { Sequelize, Transaction } from 'sequelize'
d9bf974f 2import { AbstractVideosModelQueryBuilder } from './shared/abstract-videos-model-query-builder'
1d43c3a6
C
3import { VideoFileQueryBuilder } from './shared/video-file-query-builder'
4import { VideoModelBuilder } from './shared/video-model-builder'
17bb4538 5import { VideoTables } from './shared/video-tables'
1d43c3a6
C
6
7/**
8 *
9 * Build a GET SQL query, fetch rows and create the video model
10 *
11 */
d9bf974f
C
12
13export type BuildVideoGetQueryOptions = {
71d4af1e
C
14 id?: number | string
15 url?: string
16
17 type: 'api' | 'full-light' | 'account-blacklist-files' | 'all-files' | 'thumbnails' | 'thumbnails-blacklist' | 'id' | 'blacklist-rights'
18
d9bf974f 19 userId?: number
71d4af1e
C
20 transaction?: Transaction
21
22 logging?: boolean
d9bf974f
C
23}
24
1d43c3a6
C
25export class VideosModelGetQueryBuilder {
26 videoQueryBuilder: VideosModelGetQuerySubBuilder
27 webtorrentFilesQueryBuilder: VideoFileQueryBuilder
28 streamingPlaylistFilesQueryBuilder: VideoFileQueryBuilder
29
30 private readonly videoModelBuilder: VideoModelBuilder
31
32 constructor (protected readonly sequelize: Sequelize) {
33 this.videoQueryBuilder = new VideosModelGetQuerySubBuilder(sequelize)
34 this.webtorrentFilesQueryBuilder = new VideoFileQueryBuilder(sequelize)
35 this.streamingPlaylistFilesQueryBuilder = new VideoFileQueryBuilder(sequelize)
36
17bb4538 37 this.videoModelBuilder = new VideoModelBuilder('get', new VideoTables('get'))
1d43c3a6
C
38 }
39
71d4af1e 40 async queryVideo (options: BuildVideoGetQueryOptions) {
1d43c3a6
C
41 const [ videoRows, webtorrentFilesRows, streamingPlaylistFilesRows ] = await Promise.all([
42 this.videoQueryBuilder.queryVideos(options),
71d4af1e
C
43
44 this.shouldQueryVideoFiles(options)
45 ? this.webtorrentFilesQueryBuilder.queryWebTorrentVideos(options)
46 : Promise.resolve(undefined),
47
48 this.shouldQueryVideoFiles(options)
49 ? this.streamingPlaylistFilesQueryBuilder.queryStreamingPlaylistVideos(options)
50 : Promise.resolve(undefined)
1d43c3a6
C
51 ])
52
53 const videos = this.videoModelBuilder.buildVideosFromRows(videoRows, webtorrentFilesRows, streamingPlaylistFilesRows)
54
55 if (videos.length > 1) {
56 throw new Error('Video results is more than ')
57 }
58
59 if (videos.length === 0) return null
60 return videos[0]
61 }
71d4af1e
C
62
63 private shouldQueryVideoFiles (options: BuildVideoGetQueryOptions) {
64 return [ 'api', 'full-light', 'account-blacklist-files', 'all-files' ].includes(options.type)
65 }
1d43c3a6
C
66}
67
68export class VideosModelGetQuerySubBuilder extends AbstractVideosModelQueryBuilder {
d9bf974f 69 protected attributes: { [key: string]: string }
1d43c3a6
C
70
71 protected webtorrentFilesQuery: string
72 protected streamingPlaylistFilesQuery: string
d9bf974f
C
73
74 constructor (protected readonly sequelize: Sequelize) {
75 super('get')
76 }
77
78 queryVideos (options: BuildVideoGetQueryOptions) {
1d43c3a6 79 this.buildMainGetQuery(options)
d9bf974f 80
71d4af1e 81 return this.runQuery(options)
d9bf974f
C
82 }
83
1d43c3a6 84 private buildMainGetQuery (options: BuildVideoGetQueryOptions) {
d9bf974f
C
85 this.attributes = {
86 '"video".*': ''
87 }
88
71d4af1e
C
89 if (this.shouldIncludeThumbnails(options)) {
90 this.includeThumbnails()
91 }
d9bf974f 92
71d4af1e
C
93 if (this.shouldIncludeBlacklisted(options)) {
94 this.includeBlacklisted()
95 }
d9bf974f 96
71d4af1e
C
97 if (this.shouldIncludeAccount(options)) {
98 this.includeChannels()
99 this.includeAccounts()
100 }
d9bf974f 101
71d4af1e
C
102 if (this.shouldIncludeTags(options)) {
103 this.includeTags()
104 }
d9bf974f 105
71d4af1e
C
106 if (this.shouldIncludeScheduleUpdate(options)) {
107 this.includeScheduleUpdate()
108 }
d9bf974f 109
71d4af1e
C
110 if (this.shouldIncludeLive(options)) {
111 this.includeLive()
112 }
d9bf974f 113
71d4af1e 114 if (options.userId && this.shouldIncludeUserHistory(options)) {
d9bf974f
C
115 this.includeUserHistory(options.userId)
116 }
117
71d4af1e
C
118 if (this.shouldIncludeOwnerUser(options)) {
119 this.includeOwnerUser()
120 }
121
122 if (this.shouldIncludeTrackers(options)) {
d9bf974f 123 this.includeTrackers()
d9bf974f
C
124 }
125
71d4af1e 126 this.whereId(options)
d9bf974f 127
71d4af1e 128 this.query = this.buildQuery(options)
d9bf974f
C
129 }
130
71d4af1e
C
131 private buildQuery (options: BuildVideoGetQueryOptions) {
132 const order = this.shouldIncludeTags(options)
133 ? 'ORDER BY "Tags"."name" ASC'
134 : ''
135
1d43c3a6 136 const from = `SELECT * FROM "video" ${this.where} LIMIT 1`
d9bf974f 137
3c79c2ce 138 return `${this.buildSelect()} FROM (${from}) AS "video" ${this.joins} ${order}`
d9bf974f 139 }
71d4af1e
C
140
141 private shouldIncludeTrackers (options: BuildVideoGetQueryOptions) {
142 return options.type === 'api'
143 }
144
145 private shouldIncludeLive (options: BuildVideoGetQueryOptions) {
146 return [ 'api', 'full-light' ].includes(options.type)
147 }
148
149 private shouldIncludeScheduleUpdate (options: BuildVideoGetQueryOptions) {
150 return [ 'api', 'full-light' ].includes(options.type)
151 }
152
153 private shouldIncludeTags (options: BuildVideoGetQueryOptions) {
154 return [ 'api', 'full-light' ].includes(options.type)
155 }
156
157 private shouldIncludeUserHistory (options: BuildVideoGetQueryOptions) {
158 return [ 'api', 'full-light' ].includes(options.type)
159 }
160
161 private shouldIncludeAccount (options: BuildVideoGetQueryOptions) {
162 return [ 'api', 'full-light', 'account-blacklist-files' ].includes(options.type)
163 }
164
165 private shouldIncludeBlacklisted (options: BuildVideoGetQueryOptions) {
166 return [ 'api', 'full-light', 'account-blacklist-files', 'thumbnails-blacklist', 'blacklist-rights' ].includes(options.type)
167 }
168
169 private shouldIncludeOwnerUser (options: BuildVideoGetQueryOptions) {
170 return options.type === 'blacklist-rights'
171 }
172
173 private shouldIncludeThumbnails (options: BuildVideoGetQueryOptions) {
174 return [ 'api', 'full-light', 'account-blacklist-files', 'thumbnails', 'thumbnails-blacklist' ].includes(options.type)
175 }
d9bf974f 176}