Rework loading revision data
These changes were motivated by switching to a mechanism of loading data that isn't dependent on the big advisory lock that prevents more than one revision from being processed at a time. Since INSERT ... RETURNING id; is used, this can block if another transaction inserts the same data, and then cause an error when that transaction commits. The solution is to use ON CONFLICT DO NOTHING, but you have to handle the case when the INSERT doesn't return an id since the other transaction has inserted it. This commit rewrites insert-missing-data-and-return-all-ids to do as described above, as well as being more efficient in how existing data is detected and to use more vectors. Other utilities for inserting data are added as well.
This commit is contained in:
parent
b128e9bd7a
commit
5ed98343d7
25 changed files with 874 additions and 1149 deletions
|
|
@ -846,61 +846,62 @@
|
||||||
conn
|
conn
|
||||||
(inferior-packages->license-id-lists
|
(inferior-packages->license-id-lists
|
||||||
conn
|
conn
|
||||||
;; TODO Don't needlessly convert
|
(assq-ref inferior-packages-data 'license-data)))))
|
||||||
(vector->list
|
|
||||||
(assq-ref inferior-packages-data 'license-data))))))
|
|
||||||
(all-package-metadata-ids
|
(all-package-metadata-ids
|
||||||
new-package-metadata-ids
|
new-package-metadata-ids
|
||||||
(with-time-logging "inserting package metadata entries"
|
(with-time-logging "inserting package metadata entries"
|
||||||
(inferior-packages->package-metadata-ids
|
(inferior-packages->package-metadata-ids
|
||||||
conn
|
conn
|
||||||
;; TODO Don't needlessly convert
|
(assq-ref inferior-packages-data 'metadata)
|
||||||
(vector->list
|
|
||||||
(assq-ref inferior-packages-data 'metadata))
|
|
||||||
package-license-set-ids)))
|
package-license-set-ids)))
|
||||||
(replacement-package-ids
|
(replacement-package-ids
|
||||||
(vector-map
|
(vector-map
|
||||||
(lambda (_ package-index-or-false)
|
(lambda (_ package-index-or-false)
|
||||||
(if package-index-or-false
|
(if package-index-or-false
|
||||||
(first
|
(vector-ref
|
||||||
(inferior-packages->package-ids
|
(inferior-packages->package-ids
|
||||||
conn
|
conn
|
||||||
(list (list (vector-ref names package-index-or-false)
|
(vector
|
||||||
|
(list (vector-ref names package-index-or-false)
|
||||||
(vector-ref versions package-index-or-false)
|
(vector-ref versions package-index-or-false)
|
||||||
(list-ref all-package-metadata-ids
|
(vector-ref all-package-metadata-ids
|
||||||
package-index-or-false)
|
package-index-or-false)
|
||||||
(cons "integer" NULL)))))
|
(cons "integer" NULL))))
|
||||||
|
0)
|
||||||
(cons "integer" NULL)))
|
(cons "integer" NULL)))
|
||||||
(assq-ref inferior-packages-data 'replacements))))
|
(assq-ref inferior-packages-data 'replacements))))
|
||||||
|
|
||||||
(unless (null? new-package-metadata-ids)
|
(unless (= 0 (vector-length new-package-metadata-ids))
|
||||||
(with-time-logging "inserting package metadata tsvector entries"
|
(with-time-logging "inserting package metadata tsvector entries"
|
||||||
(insert-package-metadata-tsvector-entries
|
(insert-package-metadata-tsvector-entries
|
||||||
conn new-package-metadata-ids)))
|
conn new-package-metadata-ids)))
|
||||||
|
|
||||||
(with-time-logging "getting package-ids (without replacements)"
|
(with-time-logging "getting package-ids (without replacements)"
|
||||||
(list->vector
|
|
||||||
(inferior-packages->package-ids
|
(inferior-packages->package-ids
|
||||||
conn
|
conn
|
||||||
;; TODO Do this more efficiently
|
;; Similar to zip, but generating a vector of lists
|
||||||
(zip (vector->list names)
|
(vector-map (lambda (index . vals) vals)
|
||||||
(vector->list versions)
|
names
|
||||||
|
versions
|
||||||
all-package-metadata-ids
|
all-package-metadata-ids
|
||||||
(vector->list replacement-package-ids)))))))
|
replacement-package-ids)))))
|
||||||
|
|
||||||
(define (insert-lint-warnings conn
|
(define (insert-lint-warnings conn
|
||||||
package-ids
|
package-ids
|
||||||
lint-checker-ids
|
lint-checker-ids
|
||||||
lint-warnings-data)
|
lint-warnings-data)
|
||||||
(lint-warnings-data->lint-warning-ids
|
(concatenate!
|
||||||
conn
|
(filter-map
|
||||||
(append-map!
|
|
||||||
(lambda (lint-checker-id warnings-per-package)
|
(lambda (lint-checker-id warnings-per-package)
|
||||||
(if warnings-per-package
|
(if warnings-per-package
|
||||||
(vector-fold
|
(vector-fold
|
||||||
(lambda (_ result package-id warnings)
|
(lambda (_ result package-id warnings)
|
||||||
(append!
|
(if (null? warnings)
|
||||||
result
|
result
|
||||||
|
(cons
|
||||||
|
(lint-warnings-data->lint-warning-ids
|
||||||
|
conn
|
||||||
|
(list->vector
|
||||||
(map
|
(map
|
||||||
(match-lambda
|
(match-lambda
|
||||||
((location-data messages-by-locale)
|
((location-data messages-by-locale)
|
||||||
|
|
@ -916,25 +917,13 @@
|
||||||
package-id
|
package-id
|
||||||
location-id
|
location-id
|
||||||
lint-warning-message-set-id))))
|
lint-warning-message-set-id))))
|
||||||
(fold (lambda (location-and-messages result)
|
warnings)))
|
||||||
;; TODO Sort to delete duplicates, rather than use member
|
result)))
|
||||||
(if (member location-and-messages result)
|
|
||||||
(begin
|
|
||||||
(apply
|
|
||||||
simple-format
|
|
||||||
(current-error-port)
|
|
||||||
"warning: skipping duplicate lint warning ~A ~A\n"
|
|
||||||
location-and-messages)
|
|
||||||
result)
|
|
||||||
(append! result
|
|
||||||
(list location-and-messages))))
|
|
||||||
'()
|
|
||||||
warnings))))
|
|
||||||
'()
|
'()
|
||||||
package-ids
|
package-ids
|
||||||
warnings-per-package)
|
warnings-per-package)
|
||||||
'()))
|
#f))
|
||||||
lint-checker-ids
|
(vector->list lint-checker-ids)
|
||||||
lint-warnings-data)))
|
lint-warnings-data)))
|
||||||
|
|
||||||
(define (update-derivation-ids-hash-table! conn
|
(define (update-derivation-ids-hash-table! conn
|
||||||
|
|
@ -977,30 +966,25 @@
|
||||||
#:key (log-tag "unspecified"))
|
#:key (log-tag "unspecified"))
|
||||||
|
|
||||||
(define (insert-into-derivations conn drvs)
|
(define (insert-into-derivations conn drvs)
|
||||||
(string-append
|
(insert-missing-data-and-return-all-ids
|
||||||
"INSERT INTO derivations "
|
conn
|
||||||
"(file_name, builder, args, env_vars, system_id) VALUES "
|
"derivations"
|
||||||
(string-join
|
'(file_name builder args env_vars system_id)
|
||||||
(map (match-lambda
|
(vector-map (match-lambda*
|
||||||
(($ <derivation> outputs inputs sources
|
((_ ($ <derivation> outputs inputs sources
|
||||||
system builder args env-vars file-name)
|
system builder args env-vars file-name))
|
||||||
(simple-format
|
(list file-name
|
||||||
#f "('~A', '~A', ARRAY[~A]::varchar[], ARRAY[~A], '~A')"
|
|
||||||
file-name
|
|
||||||
builder
|
builder
|
||||||
(string-join (map quote-string args) ",")
|
(cons "varchar[]"
|
||||||
(string-join (map (match-lambda
|
(list->vector args))
|
||||||
|
(cons "varchar[][]"
|
||||||
|
(list->vector
|
||||||
|
(map (match-lambda
|
||||||
((key . value)
|
((key . value)
|
||||||
(string-append
|
(vector key value)))
|
||||||
"['" key '"', $$"
|
env-vars)))
|
||||||
value "$$ ]")))
|
|
||||||
env-vars)
|
|
||||||
",")
|
|
||||||
(system->system-id conn system))))
|
(system->system-id conn system))))
|
||||||
drvs)
|
drvs)))
|
||||||
",")
|
|
||||||
" RETURNING id"
|
|
||||||
";"))
|
|
||||||
|
|
||||||
(define (insert-derivations)
|
(define (insert-derivations)
|
||||||
(with-resource-from-pool postgresql-connection-pool conn
|
(with-resource-from-pool postgresql-connection-pool conn
|
||||||
|
|
@ -1021,6 +1005,7 @@
|
||||||
(let ((derivations
|
(let ((derivations
|
||||||
;; Do this while holding the PostgreSQL connection to
|
;; Do this while holding the PostgreSQL connection to
|
||||||
;; avoid conflicts with other fibers
|
;; avoid conflicts with other fibers
|
||||||
|
(list->vector
|
||||||
(delete-duplicates
|
(delete-duplicates
|
||||||
(filter-map (lambda (derivation)
|
(filter-map (lambda (derivation)
|
||||||
(if (hash-ref derivation-ids-hash-table
|
(if (hash-ref derivation-ids-hash-table
|
||||||
|
|
@ -1028,28 +1013,23 @@
|
||||||
derivation))
|
derivation))
|
||||||
#f
|
#f
|
||||||
derivation))
|
derivation))
|
||||||
unfiltered-derivations))))
|
unfiltered-derivations)))))
|
||||||
(if (null? derivations)
|
(if (= 0 (vector-length derivations))
|
||||||
(values '() '())
|
(values #() #())
|
||||||
(begin
|
(begin
|
||||||
(simple-format
|
(simple-format
|
||||||
(current-error-port)
|
(current-error-port)
|
||||||
"insert-missing-derivations: inserting ~A derivations (~A)\n"
|
"insert-missing-derivations: inserting ~A derivations (~A)\n"
|
||||||
(length derivations)
|
(vector-length derivations)
|
||||||
log-tag)
|
log-tag)
|
||||||
(let ((derivation-ids
|
(let ((derivation-ids
|
||||||
(append-map!
|
(insert-into-derivations conn derivations)))
|
||||||
(lambda (chunk)
|
|
||||||
(map (lambda (result)
|
|
||||||
(string->number (car result)))
|
|
||||||
(exec-query conn (insert-into-derivations conn chunk))))
|
|
||||||
(chunk derivations 500))))
|
|
||||||
|
|
||||||
;; Do this while holding the connection so that other
|
;; Do this while holding the connection so that other
|
||||||
;; fibers don't also try inserting the same derivations
|
;; fibers don't also try inserting the same derivations
|
||||||
(with-time-logging
|
(with-time-logging
|
||||||
(string-append "insert-missing-derivations: updating hash table (" log-tag ")")
|
(string-append "insert-missing-derivations: updating hash table (" log-tag ")")
|
||||||
(for-each (lambda (derivation derivation-id)
|
(vector-for-each (lambda (_ derivation derivation-id)
|
||||||
(hash-set! derivation-ids-hash-table
|
(hash-set! derivation-ids-hash-table
|
||||||
(derivation-file-name derivation)
|
(derivation-file-name derivation)
|
||||||
derivation-id))
|
derivation-id))
|
||||||
|
|
@ -1059,7 +1039,7 @@
|
||||||
(simple-format
|
(simple-format
|
||||||
(current-error-port)
|
(current-error-port)
|
||||||
"insert-missing-derivations: finished inserting ~A derivations (~A)\n"
|
"insert-missing-derivations: finished inserting ~A derivations (~A)\n"
|
||||||
(length derivations)
|
(vector-length derivations)
|
||||||
log-tag)
|
log-tag)
|
||||||
|
|
||||||
(values derivations
|
(values derivations
|
||||||
|
|
@ -1137,10 +1117,10 @@ SELECT 1 FROM derivation_source_file_nars WHERE derivation_source_file_id = $1"
|
||||||
hash
|
hash
|
||||||
compressed-nar-bytevector
|
compressed-nar-bytevector
|
||||||
uncompressed-size))))))))
|
uncompressed-size))))))))
|
||||||
sources-ids
|
(vector->list sources-ids)
|
||||||
sources)))))
|
sources)))))
|
||||||
derivation-ids
|
(vector->list derivation-ids)
|
||||||
derivations)))
|
(vector->list derivations))))
|
||||||
|
|
||||||
(let ((derivations
|
(let ((derivations
|
||||||
derivation-ids
|
derivation-ids
|
||||||
|
|
@ -1154,7 +1134,8 @@ SELECT 1 FROM derivation_source_file_nars WHERE derivation_source_file_id = $1"
|
||||||
(string-append "insert-missing-derivations: inserting outputs ("
|
(string-append "insert-missing-derivations: inserting outputs ("
|
||||||
log-tag ")")
|
log-tag ")")
|
||||||
(with-resource-from-pool postgresql-connection-pool conn
|
(with-resource-from-pool postgresql-connection-pool conn
|
||||||
(for-each (lambda (derivation-id derivation)
|
(vector-for-each
|
||||||
|
(lambda (_ derivation-id derivation)
|
||||||
(insert-derivation-outputs conn
|
(insert-derivation-outputs conn
|
||||||
derivation-id
|
derivation-id
|
||||||
(derivation-outputs derivation)))
|
(derivation-outputs derivation)))
|
||||||
|
|
@ -1169,7 +1150,7 @@ SELECT 1 FROM derivation_source_file_nars WHERE derivation_source_file_id = $1"
|
||||||
(map
|
(map
|
||||||
derivation-input-derivation
|
derivation-input-derivation
|
||||||
(append-map derivation-inputs
|
(append-map derivation-inputs
|
||||||
derivations))))
|
(vector->list derivations)))))
|
||||||
(unless (null? input-derivations)
|
(unless (null? input-derivations)
|
||||||
;; Ensure all the input derivations exist
|
;; Ensure all the input derivations exist
|
||||||
(for-each
|
(for-each
|
||||||
|
|
@ -1182,12 +1163,14 @@ SELECT 1 FROM derivation_source_file_nars WHERE derivation_source_file_id = $1"
|
||||||
#:log-tag log-tag))
|
#:log-tag log-tag))
|
||||||
(chunk! input-derivations 1000))))))
|
(chunk! input-derivations 1000))))))
|
||||||
|
|
||||||
(string-append "insert-missing-derivations: done parallel (" log-tag ")")
|
(simple-format
|
||||||
|
(current-error-port)
|
||||||
|
"debug: insert-missing-derivations: done parallel (~A)\n" log-tag)
|
||||||
(with-resource-from-pool postgresql-connection-pool conn
|
(with-resource-from-pool postgresql-connection-pool conn
|
||||||
(with-time-logging
|
(with-time-logging
|
||||||
(simple-format
|
(simple-format
|
||||||
#f "insert-missing-derivations: inserting inputs for ~A derivations (~A)"
|
#f "insert-missing-derivations: inserting inputs for ~A derivations (~A)"
|
||||||
(length derivations)
|
(vector-length derivations)
|
||||||
log-tag)
|
log-tag)
|
||||||
(insert-derivation-inputs conn
|
(insert-derivation-inputs conn
|
||||||
derivation-ids
|
derivation-ids
|
||||||
|
|
@ -1913,15 +1896,17 @@ SELECT 1 FROM derivation_source_file_nars WHERE derivation_source_file_id = $1"
|
||||||
(define inferior-lint-checkers-data
|
(define inferior-lint-checkers-data
|
||||||
(call-with-inferior
|
(call-with-inferior
|
||||||
(lambda (inferior inferior-store)
|
(lambda (inferior inferior-store)
|
||||||
(inferior-lint-checkers inferior))))
|
(list->vector
|
||||||
|
(inferior-lint-checkers inferior)))))
|
||||||
|
|
||||||
(when inferior-lint-checkers-data
|
(when inferior-lint-checkers-data
|
||||||
(letpar& ((lint-checker-ids
|
(letpar& ((lint-checker-ids
|
||||||
(with-resource-from-pool postgresql-connection-pool conn
|
(with-resource-from-pool postgresql-connection-pool conn
|
||||||
(lint-checkers->lint-checker-ids
|
(lint-checkers->lint-checker-ids
|
||||||
conn
|
conn
|
||||||
(map (match-lambda
|
(vector-map
|
||||||
((name descriptions-by-locale network-dependent)
|
(match-lambda*
|
||||||
|
((_ (name descriptions-by-locale network-dependent))
|
||||||
(list
|
(list
|
||||||
name
|
name
|
||||||
network-dependent
|
network-dependent
|
||||||
|
|
@ -1930,7 +1915,8 @@ SELECT 1 FROM derivation_source_file_nars WHERE derivation_source_file_id = $1"
|
||||||
utility-thread-channel
|
utility-thread-channel
|
||||||
(lambda ()
|
(lambda ()
|
||||||
(lint-checker-description-data->lint-checker-description-set-id
|
(lint-checker-description-data->lint-checker-description-set-id
|
||||||
conn descriptions-by-locale))))))
|
conn
|
||||||
|
descriptions-by-locale))))))
|
||||||
inferior-lint-checkers-data))))
|
inferior-lint-checkers-data))))
|
||||||
(lint-warnings-data
|
(lint-warnings-data
|
||||||
(fibers-map
|
(fibers-map
|
||||||
|
|
@ -1946,7 +1932,8 @@ SELECT 1 FROM derivation_source_file_nars WHERE derivation_source_file_id = $1"
|
||||||
(inferior-lint-warnings inferior
|
(inferior-lint-warnings inferior
|
||||||
inferior-store
|
inferior-store
|
||||||
checker-name)))))))
|
checker-name)))))))
|
||||||
inferior-lint-checkers-data)))
|
(vector->list
|
||||||
|
inferior-lint-checkers-data))))
|
||||||
|
|
||||||
(let ((package-ids (fibers-force package-ids-promise)))
|
(let ((package-ids (fibers-force package-ids-promise)))
|
||||||
(with-resource-from-pool postgresql-connection-pool conn
|
(with-resource-from-pool postgresql-connection-pool conn
|
||||||
|
|
@ -1955,20 +1942,21 @@ SELECT 1 FROM derivation_source_file_nars WHERE derivation_source_file_id = $1"
|
||||||
(fibers-force guix-revision-id-promise)
|
(fibers-force guix-revision-id-promise)
|
||||||
lint-checker-ids)
|
lint-checker-ids)
|
||||||
|
|
||||||
(let ((lint-warning-ids
|
(let ((lint-warning-id-vectors
|
||||||
|
(with-time-logging "inserting lint warnings"
|
||||||
(insert-lint-warnings
|
(insert-lint-warnings
|
||||||
conn
|
conn
|
||||||
package-ids
|
package-ids
|
||||||
lint-checker-ids
|
lint-checker-ids
|
||||||
lint-warnings-data)))
|
lint-warnings-data))))
|
||||||
(chunk-for-each!
|
(with-time-logging "inserting guix revision lint warnings"
|
||||||
(lambda (lint-warning-ids-chunk)
|
(for-each
|
||||||
|
(lambda (lint-warning-ids)
|
||||||
(insert-guix-revision-lint-warnings
|
(insert-guix-revision-lint-warnings
|
||||||
conn
|
conn
|
||||||
(fibers-force guix-revision-id-promise)
|
(fibers-force guix-revision-id-promise)
|
||||||
lint-warning-ids-chunk))
|
lint-warning-ids))
|
||||||
5000
|
lint-warning-id-vectors))))))))
|
||||||
lint-warning-ids)))))))
|
|
||||||
|
|
||||||
(define (extract-and-store-package-derivations)
|
(define (extract-and-store-package-derivations)
|
||||||
(define packages-count
|
(define packages-count
|
||||||
|
|
@ -2113,7 +2101,8 @@ SELECT 1 FROM derivation_source_file_nars WHERE derivation_source_file_id = $1"
|
||||||
guix-revision-id
|
guix-revision-id
|
||||||
package-derivation-ids-chunk)))
|
package-derivation-ids-chunk)))
|
||||||
2000
|
2000
|
||||||
package-derivation-ids)))
|
;; TODO Chunk more efficiently
|
||||||
|
(vector->list package-derivation-ids))))
|
||||||
|
|
||||||
'finished)
|
'finished)
|
||||||
|
|
||||||
|
|
@ -2386,7 +2375,7 @@ SELECT 1 FROM derivation_source_file_nars WHERE derivation_source_file_id = $1"
|
||||||
(with-time-logging "updating builds.derivation_output_details_set_id"
|
(with-time-logging "updating builds.derivation_output_details_set_id"
|
||||||
(update-builds-derivation-output-details-set-id
|
(update-builds-derivation-output-details-set-id
|
||||||
conn
|
conn
|
||||||
(string->number (fibers-force guix-revision-id-promise)))))
|
(fibers-force guix-revision-id-promise))))
|
||||||
(begin
|
(begin
|
||||||
(simple-format #t "Failed to generate store item for ~A\n"
|
(simple-format #t "Failed to generate store item for ~A\n"
|
||||||
commit)
|
commit)
|
||||||
|
|
|
||||||
|
|
@ -510,10 +510,12 @@ WHERE derivations.file_name = $1"
|
||||||
derivation-output-details-lists
|
derivation-output-details-lists
|
||||||
build-server-build-ids)
|
build-server-build-ids)
|
||||||
(let ((build-ids
|
(let ((build-ids
|
||||||
|
(vector->list
|
||||||
(insert-missing-data-and-return-all-ids
|
(insert-missing-data-and-return-all-ids
|
||||||
conn
|
conn
|
||||||
"builds"
|
"builds"
|
||||||
'(build_server_id derivation_file_name build_server_build_id)
|
'(build_server_id derivation_file_name build_server_build_id)
|
||||||
|
(list->vector
|
||||||
(map (lambda (derivation-file-name build-server-build-id)
|
(map (lambda (derivation-file-name build-server-build-id)
|
||||||
(list build-server-id
|
(list build-server-id
|
||||||
derivation-file-name
|
derivation-file-name
|
||||||
|
|
@ -521,8 +523,7 @@ WHERE derivations.file_name = $1"
|
||||||
build-server-build-id
|
build-server-build-id
|
||||||
'())))
|
'())))
|
||||||
derivation-file-names
|
derivation-file-names
|
||||||
build-server-build-ids)
|
build-server-build-ids))))))
|
||||||
#:delete-duplicates? #t)))
|
|
||||||
|
|
||||||
(for-each
|
(for-each
|
||||||
(lambda (build-id derivation-output-details)
|
(lambda (build-id derivation-output-details)
|
||||||
|
|
|
||||||
|
|
@ -76,62 +76,21 @@ SELECT channel_news_entries.commit,
|
||||||
conn
|
conn
|
||||||
"channel_news_entry_text"
|
"channel_news_entry_text"
|
||||||
'(lang text)
|
'(lang text)
|
||||||
|
(list->vector
|
||||||
(map (match-lambda
|
(map (match-lambda
|
||||||
((lang . text)
|
((lang . text)
|
||||||
(list lang text)))
|
(list lang text)))
|
||||||
text)))
|
text))))
|
||||||
|
|
||||||
(define (insert-channel-news-entry conn commit tag)
|
(define (insert-channel-news-entry conn commit tag)
|
||||||
(match (exec-query
|
(insert-and-return-id
|
||||||
conn
|
conn
|
||||||
(string-append
|
"channel_news_entries"
|
||||||
"INSERT INTO channel_news_entries (commit, tag) VALUES ("
|
'(commit tag)
|
||||||
(value->quoted-string-or-null commit)
|
(list (or commit NULL)
|
||||||
","
|
(or tag NULL))))
|
||||||
(value->quoted-string-or-null tag)
|
|
||||||
") RETURNING id"))
|
|
||||||
(((id))
|
|
||||||
(string->number id))))
|
|
||||||
|
|
||||||
(define (insert-channel-news-entries conn channel-news-entries)
|
(define (insert-channel-news-entries conn channel-news-entries)
|
||||||
(define select-channel-news-entries
|
|
||||||
"
|
|
||||||
SELECT channel_news_entries.id,
|
|
||||||
channel_news_entries.commit,
|
|
||||||
channel_news_entries.tag,
|
|
||||||
(
|
|
||||||
SELECT ARRAY_AGG(
|
|
||||||
channel_news_entry_titles.channel_news_entry_text_id
|
|
||||||
ORDER BY channel_news_entry_titles.channel_news_entry_text_id
|
|
||||||
)
|
|
||||||
FROM channel_news_entry_titles
|
|
||||||
WHERE channel_news_entry_id = channel_news_entries.id
|
|
||||||
) AS title_text,
|
|
||||||
(
|
|
||||||
SELECT ARRAY_AGG(
|
|
||||||
channel_news_entry_bodies.channel_news_entry_text_id
|
|
||||||
ORDER BY channel_news_entry_bodies.channel_news_entry_text_id
|
|
||||||
)
|
|
||||||
FROM channel_news_entry_bodies
|
|
||||||
WHERE channel_news_entry_id = channel_news_entries.id
|
|
||||||
) AS body_text
|
|
||||||
FROM channel_news_entries
|
|
||||||
ORDER BY id")
|
|
||||||
|
|
||||||
(define existing
|
|
||||||
(exec-query->vhash conn
|
|
||||||
select-channel-news-entries
|
|
||||||
(match-lambda
|
|
||||||
((_ commit tag title-ids body-ids)
|
|
||||||
(list commit
|
|
||||||
tag
|
|
||||||
(map string->number
|
|
||||||
(parse-postgresql-array-string title-ids))
|
|
||||||
(map string->number
|
|
||||||
(parse-postgresql-array-string body-ids)))))
|
|
||||||
(lambda (result)
|
|
||||||
(string->number (first result)))))
|
|
||||||
|
|
||||||
(map
|
(map
|
||||||
(lambda (entry)
|
(lambda (entry)
|
||||||
(let ((commit (channel-news-entry-commit entry))
|
(let ((commit (channel-news-entry-commit entry))
|
||||||
|
|
@ -145,14 +104,6 @@ ORDER BY id")
|
||||||
conn
|
conn
|
||||||
(channel-news-entry-body entry))
|
(channel-news-entry-body entry))
|
||||||
<)))
|
<)))
|
||||||
(or (and=> (vhash-assoc (list (or commit '())
|
|
||||||
(or tag '())
|
|
||||||
title-ids
|
|
||||||
body-ids)
|
|
||||||
existing)
|
|
||||||
(match-lambda
|
|
||||||
((value . key)
|
|
||||||
key)))
|
|
||||||
(let ((channel-news-entry-id
|
(let ((channel-news-entry-id
|
||||||
(insert-channel-news-entry conn commit tag)))
|
(insert-channel-news-entry conn commit tag)))
|
||||||
(for-each
|
(for-each
|
||||||
|
|
@ -167,14 +118,15 @@ ORDER BY id")
|
||||||
(simple-format #f "(~A, ~A)"
|
(simple-format #f "(~A, ~A)"
|
||||||
channel-news-entry-id
|
channel-news-entry-id
|
||||||
id))
|
id))
|
||||||
ids)
|
(vector->list ids))
|
||||||
", "))))
|
", ")
|
||||||
|
" ON CONFLICT DO NOTHING")))
|
||||||
'("channel_news_entry_titles"
|
'("channel_news_entry_titles"
|
||||||
"channel_news_entry_bodies")
|
"channel_news_entry_bodies")
|
||||||
(list title-ids
|
(list title-ids
|
||||||
body-ids))
|
body-ids))
|
||||||
|
|
||||||
channel-news-entry-id))))
|
channel-news-entry-id)))
|
||||||
channel-news-entries))
|
channel-news-entries))
|
||||||
|
|
||||||
(define (insert-channel-news-entries-for-guix-revision
|
(define (insert-channel-news-entries-for-guix-revision
|
||||||
|
|
@ -194,5 +146,6 @@ ORDER BY id")
|
||||||
(simple-format #f "(~A,~A,~A)" guix-revision-id id index))
|
(simple-format #f "(~A,~A,~A)" guix-revision-id id index))
|
||||||
channel-news-entry-ids
|
channel-news-entry-ids
|
||||||
(iota (length channel-news-entries)))
|
(iota (length channel-news-entries)))
|
||||||
", ")))))
|
", ")
|
||||||
|
" ON CONFLICT DO NOTHING"))))
|
||||||
#t)
|
#t)
|
||||||
|
|
|
||||||
|
|
@ -982,6 +982,7 @@ LOCK TABLE ONLY derivation_output_details
|
||||||
conn
|
conn
|
||||||
"derivation_output_details"
|
"derivation_output_details"
|
||||||
'(path hash_algorithm hash recursive)
|
'(path hash_algorithm hash recursive)
|
||||||
|
(list->vector
|
||||||
(map (lambda (details)
|
(map (lambda (details)
|
||||||
(list (assq-ref details 'path)
|
(list (assq-ref details 'path)
|
||||||
(or (non-empty-string-or-false
|
(or (non-empty-string-or-false
|
||||||
|
|
@ -991,67 +992,20 @@ LOCK TABLE ONLY derivation_output_details
|
||||||
(assq-ref details 'hash))
|
(assq-ref details 'hash))
|
||||||
NULL)
|
NULL)
|
||||||
(assq-ref details 'recursive)))
|
(assq-ref details 'recursive)))
|
||||||
derivation-output-details)))
|
derivation-output-details))))
|
||||||
|
|
||||||
(define (derivation-output-details-ids->derivation-output-details-set-id
|
(define (derivation-output-details-ids->derivation-output-details-set-id
|
||||||
conn
|
conn
|
||||||
derivation-output-details-ids)
|
derivation-output-details-ids)
|
||||||
(define sorted-derivation-output-details-ids
|
(insert-and-return-id
|
||||||
(sort derivation-output-details-ids <))
|
|
||||||
|
|
||||||
(define (select-derivation-output-details-sets-id)
|
|
||||||
(match (exec-query
|
|
||||||
conn
|
conn
|
||||||
(string-append
|
"derivation_output_details_sets"
|
||||||
"
|
'(derivation_output_details_ids)
|
||||||
SELECT id
|
(list (sort derivation-output-details-ids <))))
|
||||||
FROM derivation_output_details_sets
|
|
||||||
WHERE derivation_output_details_ids = ARRAY["
|
|
||||||
(string-join (map number->string
|
|
||||||
sorted-derivation-output-details-ids)
|
|
||||||
",")
|
|
||||||
"]"))
|
|
||||||
(((id))
|
|
||||||
(string->number id))
|
|
||||||
(_ #f)))
|
|
||||||
|
|
||||||
(define (insert-into-derivation-output-details-sets)
|
|
||||||
(match (exec-query
|
|
||||||
conn
|
|
||||||
(string-append
|
|
||||||
"
|
|
||||||
INSERT INTO derivation_output_details_sets (derivation_output_details_ids)
|
|
||||||
VALUES (ARRAY["
|
|
||||||
(string-join (map number->string
|
|
||||||
sorted-derivation-output-details-ids)
|
|
||||||
",")
|
|
||||||
"])
|
|
||||||
RETURNING id"))
|
|
||||||
(((id))
|
|
||||||
(string->number id))))
|
|
||||||
|
|
||||||
(or (select-derivation-output-details-sets-id)
|
|
||||||
(insert-into-derivation-output-details-sets)))
|
|
||||||
|
|
||||||
(define (insert-derivation-outputs conn
|
(define (insert-derivation-outputs conn
|
||||||
derivation-id
|
derivation-id
|
||||||
names-and-derivation-outputs)
|
names-and-derivation-outputs)
|
||||||
(define (insert-into-derivation-outputs output-names
|
|
||||||
derivation-output-details-ids)
|
|
||||||
(string-append "INSERT INTO derivation_outputs "
|
|
||||||
"(derivation_id, name, derivation_output_details_id) VALUES "
|
|
||||||
(string-join
|
|
||||||
(map (lambda (output-name derivation-output-details-id)
|
|
||||||
(simple-format
|
|
||||||
#f "(~A, '~A', ~A)"
|
|
||||||
derivation-id
|
|
||||||
output-name
|
|
||||||
derivation-output-details-id))
|
|
||||||
output-names
|
|
||||||
derivation-output-details-ids)
|
|
||||||
",")
|
|
||||||
";"))
|
|
||||||
|
|
||||||
(define (insert-into-derivations-by-output-details-set
|
(define (insert-into-derivations-by-output-details-set
|
||||||
derivation_output_details_set_id)
|
derivation_output_details_set_id)
|
||||||
(exec-query
|
(exec-query
|
||||||
|
|
@ -1059,12 +1013,15 @@ RETURNING id"))
|
||||||
"
|
"
|
||||||
INSERT INTO derivations_by_output_details_set
|
INSERT INTO derivations_by_output_details_set
|
||||||
(derivation_id, derivation_output_details_set_id)
|
(derivation_id, derivation_output_details_set_id)
|
||||||
VALUES ($1, $2)"
|
VALUES ($1, $2)
|
||||||
|
ON CONFLICT DO NOTHING"
|
||||||
(list (number->string derivation-id)
|
(list (number->string derivation-id)
|
||||||
(number->string derivation_output_details_set_id))))
|
(number->string derivation_output_details_set_id))))
|
||||||
|
|
||||||
(let* ((derivation-outputs (map cdr names-and-derivation-outputs))
|
(let* ((derivation-outputs
|
||||||
(derivation-output-paths (map derivation-output-path
|
(map cdr names-and-derivation-outputs))
|
||||||
|
(derivation-output-paths
|
||||||
|
(map derivation-output-path
|
||||||
derivation-outputs))
|
derivation-outputs))
|
||||||
(derivation-output-names
|
(derivation-output-names
|
||||||
(map car names-and-derivation-outputs))
|
(map car names-and-derivation-outputs))
|
||||||
|
|
@ -1083,10 +1040,17 @@ VALUES ($1, $2)"
|
||||||
(recursive . ,recursive?))))
|
(recursive . ,recursive?))))
|
||||||
derivation-outputs))))
|
derivation-outputs))))
|
||||||
|
|
||||||
(exec-query conn
|
(insert-missing-data
|
||||||
(insert-into-derivation-outputs
|
conn
|
||||||
|
"derivation_outputs"
|
||||||
|
'(derivation_id name derivation_output_details_id)
|
||||||
|
(list->vector
|
||||||
|
(map (lambda (output-name derivation-output-details-id)
|
||||||
|
(list derivation-id
|
||||||
|
output-name
|
||||||
|
derivation-output-details-id))
|
||||||
derivation-output-names
|
derivation-output-names
|
||||||
derivation-output-details-ids))
|
(vector->list derivation-output-details-ids))))
|
||||||
|
|
||||||
(insert-into-derivations-by-output-details-set
|
(insert-into-derivations-by-output-details-set
|
||||||
(derivation-output-details-ids->derivation-output-details-set-id
|
(derivation-output-details-ids->derivation-output-details-set-id
|
||||||
|
|
@ -1434,8 +1398,8 @@ WHERE derivation_source_files.store_path = $1"
|
||||||
"', '" sub-derivation "')"))
|
"', '" sub-derivation "')"))
|
||||||
sub-derivations))))
|
sub-derivations))))
|
||||||
(derivation-inputs derivation)))
|
(derivation-inputs derivation)))
|
||||||
derivation-ids
|
(vector->list derivation-ids)
|
||||||
derivations)))
|
(vector->list derivations))))
|
||||||
|
|
||||||
(chunk-for-each!
|
(chunk-for-each!
|
||||||
(lambda (query-parts-chunk)
|
(lambda (query-parts-chunk)
|
||||||
|
|
@ -1452,18 +1416,11 @@ INNER JOIN derivations
|
||||||
ON derivations.file_name = vals.file_name
|
ON derivations.file_name = vals.file_name
|
||||||
INNER JOIN derivation_outputs
|
INNER JOIN derivation_outputs
|
||||||
ON derivation_outputs.derivation_id = derivations.id
|
ON derivation_outputs.derivation_id = derivations.id
|
||||||
AND vals.output_name = derivation_outputs.name")))
|
AND vals.output_name = derivation_outputs.name
|
||||||
|
ON CONFLICT DO NOTHING")))
|
||||||
1000
|
1000
|
||||||
query-parts)))
|
query-parts)))
|
||||||
|
|
||||||
(define (select-from-derivation-source-files store-paths)
|
|
||||||
(string-append
|
|
||||||
"SELECT id, store_path FROM derivation_source_files "
|
|
||||||
"WHERE store_path IN ("
|
|
||||||
(string-join (map quote-string store-paths)
|
|
||||||
",")
|
|
||||||
");"))
|
|
||||||
|
|
||||||
(define (insert-derivation-sources conn derivation-id sources)
|
(define (insert-derivation-sources conn derivation-id sources)
|
||||||
(define (insert-into-derivation-sources derivation-source-file-ids)
|
(define (insert-into-derivation-sources derivation-source-file-ids)
|
||||||
(string-append
|
(string-append
|
||||||
|
|
@ -1473,16 +1430,17 @@ INNER JOIN derivation_outputs
|
||||||
(map (lambda (derivation-source-file-id)
|
(map (lambda (derivation-source-file-id)
|
||||||
(simple-format
|
(simple-format
|
||||||
#f "(~A, ~A)" derivation-id derivation-source-file-id))
|
#f "(~A, ~A)" derivation-id derivation-source-file-id))
|
||||||
derivation-source-file-ids)
|
(vector->list derivation-source-file-ids))
|
||||||
",")
|
",")
|
||||||
";"))
|
"ON CONFLICT DO NOTHING;"))
|
||||||
|
|
||||||
(let ((sources-ids
|
(let ((sources-ids
|
||||||
(insert-missing-data-and-return-all-ids
|
(insert-missing-data-and-return-all-ids
|
||||||
conn
|
conn
|
||||||
"derivation_source_files"
|
"derivation_source_files"
|
||||||
'(store_path)
|
'(store_path)
|
||||||
(map list sources))))
|
(list->vector
|
||||||
|
(map list sources)))))
|
||||||
|
|
||||||
(exec-query conn
|
(exec-query conn
|
||||||
(insert-into-derivation-sources sources-ids))
|
(insert-into-derivation-sources sources-ids))
|
||||||
|
|
@ -1501,7 +1459,8 @@ INSERT INTO derivation_source_file_nars (
|
||||||
hash,
|
hash,
|
||||||
uncompressed_size,
|
uncompressed_size,
|
||||||
data
|
data
|
||||||
) VALUES ($1, $2, $3, $4, $5, $6)"
|
) VALUES ($1, $2, $3, $4, $5, $6)
|
||||||
|
ON CONFLICT DO NOTHING"
|
||||||
(list (number->string id)
|
(list (number->string id)
|
||||||
"lzip"
|
"lzip"
|
||||||
"sha256"
|
"sha256"
|
||||||
|
|
@ -1520,7 +1479,8 @@ INSERT INTO derivation_source_file_nars (
|
||||||
hash,
|
hash,
|
||||||
uncompressed_size,
|
uncompressed_size,
|
||||||
data
|
data
|
||||||
) VALUES ($1, $2, $3, $4, $5, $6)"
|
) VALUES ($1, $2, $3, $4, $5, $6)
|
||||||
|
ON CONFLICT DO NOTHING"
|
||||||
(list (number->string id)
|
(list (number->string id)
|
||||||
"lzip"
|
"lzip"
|
||||||
"sha256"
|
"sha256"
|
||||||
|
|
|
||||||
|
|
@ -47,16 +47,12 @@ WHERE git_repository_id = $1
|
||||||
(define (insert-git-branch-entry conn
|
(define (insert-git-branch-entry conn
|
||||||
git-repository-id
|
git-repository-id
|
||||||
name)
|
name)
|
||||||
(match (exec-query
|
(insert-and-return-id
|
||||||
conn
|
conn
|
||||||
"
|
"git_branches"
|
||||||
INSERT INTO git_branches (git_repository_id, name)
|
'(git_repository_id name)
|
||||||
VALUES ($1, $2)
|
(list git-repository-id
|
||||||
RETURNING id"
|
name)))
|
||||||
(list (number->string git-repository-id)
|
|
||||||
name))
|
|
||||||
(((id))
|
|
||||||
(string->number id))))
|
|
||||||
|
|
||||||
(define (git-branches-for-commit conn commit)
|
(define (git-branches-for-commit conn commit)
|
||||||
(define query
|
(define query
|
||||||
|
|
|
||||||
|
|
@ -56,8 +56,7 @@ FROM guix_revisions
|
||||||
WHERE commit = $1
|
WHERE commit = $1
|
||||||
AND git_repository_id = $2"
|
AND git_repository_id = $2"
|
||||||
(list commit git-repository-id))
|
(list commit git-repository-id))
|
||||||
(((id))
|
(((id)) (string->number id))
|
||||||
id)
|
|
||||||
(() #f)))
|
(() #f)))
|
||||||
|
|
||||||
(define (insert-guix-revision conn git-repository-id commit)
|
(define (insert-guix-revision conn git-repository-id commit)
|
||||||
|
|
@ -67,7 +66,7 @@ INSERT INTO guix_revisions (git_repository_id, commit)
|
||||||
VALUES ($1, $2) RETURNING id")
|
VALUES ($1, $2) RETURNING id")
|
||||||
|
|
||||||
(match (exec-query conn insert (list git-repository-id commit))
|
(match (exec-query conn insert (list git-repository-id commit))
|
||||||
(((id)) id)))
|
(((id)) (string->number id))))
|
||||||
|
|
||||||
(define (guix-commit-exists? conn commit)
|
(define (guix-commit-exists? conn commit)
|
||||||
(define query
|
(define query
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
(define-module (guix-data-service model license-set)
|
(define-module (guix-data-service model license-set)
|
||||||
#:use-module (srfi srfi-1)
|
#:use-module (srfi srfi-1)
|
||||||
|
#:use-module (srfi srfi-43)
|
||||||
#:use-module (ice-9 vlist)
|
#:use-module (ice-9 vlist)
|
||||||
#:use-module (squee)
|
#:use-module (squee)
|
||||||
#:use-module (guix-data-service utils)
|
#:use-module (guix-data-service utils)
|
||||||
|
|
@ -24,83 +25,12 @@
|
||||||
#:use-module (guix-data-service model license)
|
#:use-module (guix-data-service model license)
|
||||||
#:export (inferior-packages->license-set-ids))
|
#:export (inferior-packages->license-set-ids))
|
||||||
|
|
||||||
(define select-license-sets
|
|
||||||
"
|
|
||||||
SELECT id, license_ids
|
|
||||||
FROM license_sets")
|
|
||||||
|
|
||||||
(define (insert-license-sets license-id-lists)
|
|
||||||
(string-append
|
|
||||||
"INSERT INTO license_sets (license_ids) VALUES "
|
|
||||||
(string-join
|
|
||||||
(map (lambda (license-ids)
|
|
||||||
(string-append
|
|
||||||
"('{"
|
|
||||||
(string-join
|
|
||||||
(map number->string
|
|
||||||
(sort license-ids <))
|
|
||||||
", ")
|
|
||||||
"}')"))
|
|
||||||
license-id-lists)
|
|
||||||
", ")
|
|
||||||
" RETURNING id"))
|
|
||||||
|
|
||||||
(define (inferior-packages->license-set-ids conn license-id-lists)
|
(define (inferior-packages->license-set-ids conn license-id-lists)
|
||||||
(let* ((existing-license-sets
|
(insert-missing-data-and-return-all-ids
|
||||||
(exec-query->vhash conn
|
conn
|
||||||
select-license-sets
|
"license_sets"
|
||||||
(lambda (results)
|
'(license_ids)
|
||||||
(if (string=? (second results) "{}")
|
(vector-map
|
||||||
'()
|
(lambda (_ license-ids)
|
||||||
(map
|
(list (sort license-ids <)))
|
||||||
string->number
|
|
||||||
(string-split
|
|
||||||
(string-drop-right
|
|
||||||
(string-drop (second results) 1)
|
|
||||||
1)
|
|
||||||
#\,))))
|
|
||||||
(lambda (result)
|
|
||||||
(string->number (first result))))) ;; id
|
|
||||||
(missing-license-sets
|
|
||||||
(delete-duplicates/sort!
|
|
||||||
;; Use filter! with list-copy, as filter may return a list that
|
|
||||||
;; shares a portion of the input list, and therefore could be at
|
|
||||||
;; risk of being modified when deleting duplicates
|
|
||||||
(filter! (lambda (license-set-license-ids)
|
|
||||||
(not (vhash-assoc license-set-license-ids
|
|
||||||
existing-license-sets)))
|
|
||||||
(list-copy license-id-lists))
|
|
||||||
(lambda (full-a full-b)
|
|
||||||
(let loop ((a full-a)
|
|
||||||
(b full-b))
|
|
||||||
(cond
|
|
||||||
((null? a) #f)
|
|
||||||
((null? b) #t)
|
|
||||||
(else
|
|
||||||
(let ((a1 (car a))
|
|
||||||
(b1 (car b)))
|
|
||||||
(if (= a1 b1)
|
|
||||||
(loop (cdr a)
|
|
||||||
(cdr b))
|
|
||||||
(< a1 b1)))))))))
|
|
||||||
(new-license-set-entries
|
|
||||||
(if (null? missing-license-sets)
|
|
||||||
'()
|
|
||||||
(map (lambda (result)
|
|
||||||
(string->number (first result)))
|
|
||||||
(exec-query conn
|
|
||||||
(insert-license-sets missing-license-sets)))))
|
|
||||||
(new-entries-id-lookup-vhash
|
|
||||||
(two-lists->vhash missing-license-sets
|
|
||||||
new-license-set-entries)))
|
|
||||||
|
|
||||||
(map (lambda (license-id-list)
|
|
||||||
(cdr
|
|
||||||
(or (vhash-assoc license-id-list
|
|
||||||
existing-license-sets)
|
|
||||||
(vhash-assoc license-id-list
|
|
||||||
new-entries-id-lookup-vhash)
|
|
||||||
(begin
|
|
||||||
(error "missing license set entry"
|
|
||||||
license-id-list)))))
|
|
||||||
license-id-lists)))
|
license-id-lists)))
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
(define-module (guix-data-service model license)
|
(define-module (guix-data-service model license)
|
||||||
#:use-module (srfi srfi-1)
|
#:use-module (srfi srfi-1)
|
||||||
|
#:use-module (srfi srfi-43)
|
||||||
#:use-module (ice-9 vlist)
|
#:use-module (ice-9 vlist)
|
||||||
#:use-module (ice-9 match)
|
#:use-module (ice-9 match)
|
||||||
#:use-module (squee)
|
#:use-module (squee)
|
||||||
|
|
@ -50,7 +51,7 @@
|
||||||
(current-error-port)
|
(current-error-port)
|
||||||
"error: unknown license value ~A for package ~A"
|
"error: unknown license value ~A for package ~A"
|
||||||
x package)
|
x package)
|
||||||
'()))
|
#f))
|
||||||
values))
|
values))
|
||||||
(x
|
(x
|
||||||
(simple-format
|
(simple-format
|
||||||
|
|
@ -70,18 +71,21 @@
|
||||||
;; save non string values as NULL
|
;; save non string values as NULL
|
||||||
NULL))
|
NULL))
|
||||||
|
|
||||||
|
(vector-map
|
||||||
|
(lambda (_ license-tuples)
|
||||||
|
(if (null? license-tuples)
|
||||||
|
#()
|
||||||
(insert-missing-data-and-return-all-ids
|
(insert-missing-data-and-return-all-ids
|
||||||
conn
|
conn
|
||||||
"licenses"
|
"licenses"
|
||||||
`(name uri comment)
|
`(name uri comment)
|
||||||
(map (lambda (license-tuples)
|
(list->vector
|
||||||
(map
|
(filter-map
|
||||||
(match-lambda
|
(match-lambda
|
||||||
((name uri comment)
|
((name uri comment)
|
||||||
(list name
|
(list name
|
||||||
(string-or-null uri)
|
(string-or-null uri)
|
||||||
(string-or-null comment))))
|
(string-or-null comment)))
|
||||||
license-tuples))
|
(#f #f))
|
||||||
license-data)
|
license-tuples)))))
|
||||||
#:delete-duplicates? #t
|
license-data))
|
||||||
#:sets-of-data? #t))
|
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
(define-module (guix-data-service model lint-checker)
|
(define-module (guix-data-service model lint-checker)
|
||||||
#:use-module (srfi srfi-1)
|
#:use-module (srfi srfi-1)
|
||||||
|
#:use-module (srfi srfi-43)
|
||||||
#:use-module (ice-9 match)
|
#:use-module (ice-9 match)
|
||||||
#:use-module (squee)
|
#:use-module (squee)
|
||||||
#:use-module (guix-data-service model utils)
|
#:use-module (guix-data-service model utils)
|
||||||
|
|
@ -24,8 +25,7 @@
|
||||||
lint-warning-count-by-lint-checker-for-revision
|
lint-warning-count-by-lint-checker-for-revision
|
||||||
insert-guix-revision-lint-checkers
|
insert-guix-revision-lint-checkers
|
||||||
lint-checkers-for-revision
|
lint-checkers-for-revision
|
||||||
lint-checker-description-data->lint-checker-description-set-id
|
lint-checker-description-data->lint-checker-description-set-id))
|
||||||
insert-lint-checker-description-set))
|
|
||||||
|
|
||||||
(define (lint-checkers->lint-checker-ids conn lint-checkers-data)
|
(define (lint-checkers->lint-checker-ids conn lint-checkers-data)
|
||||||
(insert-missing-data-and-return-all-ids
|
(insert-missing-data-and-return-all-ids
|
||||||
|
|
@ -40,48 +40,23 @@
|
||||||
conn
|
conn
|
||||||
"lint_checker_descriptions"
|
"lint_checker_descriptions"
|
||||||
'(locale description)
|
'(locale description)
|
||||||
|
(list->vector
|
||||||
(map (match-lambda
|
(map (match-lambda
|
||||||
((locale . description)
|
((locale . description)
|
||||||
(list locale description)))
|
(list locale description)))
|
||||||
descriptions-by-locale)))
|
descriptions-by-locale))))
|
||||||
|
|
||||||
(define (insert-lint-checker-description-set conn lint-description-ids)
|
|
||||||
(let ((query
|
|
||||||
(string-append
|
|
||||||
"INSERT INTO lint_checker_description_sets (description_ids) VALUES "
|
|
||||||
(string-append
|
|
||||||
"('{"
|
|
||||||
(string-join
|
|
||||||
(map number->string
|
|
||||||
(sort lint-description-ids <))
|
|
||||||
", ")
|
|
||||||
"}')")
|
|
||||||
" RETURNING id")))
|
|
||||||
(match (exec-query conn query)
|
|
||||||
(((id)) id))))
|
|
||||||
|
|
||||||
(define (lint-checker-description-data->lint-checker-description-set-id
|
(define (lint-checker-description-data->lint-checker-description-set-id
|
||||||
conn
|
conn
|
||||||
descriptions-by-locale)
|
descriptions-by-locale)
|
||||||
(let* ((lint-checker-description-ids
|
(insert-and-return-id
|
||||||
|
conn
|
||||||
|
"lint_checker_description_sets"
|
||||||
|
'(description_ids)
|
||||||
|
(list
|
||||||
(lint-checker-description-data->lint-checker-description-ids
|
(lint-checker-description-data->lint-checker-description-ids
|
||||||
conn
|
conn
|
||||||
descriptions-by-locale))
|
descriptions-by-locale))))
|
||||||
(lint-checker-description-set-id
|
|
||||||
(exec-query
|
|
||||||
conn
|
|
||||||
(string-append
|
|
||||||
"SELECT id FROM lint_checker_description_sets"
|
|
||||||
" WHERE description_ids = ARRAY["
|
|
||||||
(string-join (map number->string
|
|
||||||
(sort lint-checker-description-ids <)) ", ")
|
|
||||||
"]"))))
|
|
||||||
(string->number
|
|
||||||
(match lint-checker-description-set-id
|
|
||||||
(((id)) id)
|
|
||||||
(()
|
|
||||||
(insert-lint-checker-description-set conn lint-checker-description-ids))))))
|
|
||||||
|
|
||||||
|
|
||||||
(define (lint-warning-count-by-lint-checker-for-revision conn commit-hash)
|
(define (lint-warning-count-by-lint-checker-for-revision conn commit-hash)
|
||||||
(define query
|
(define query
|
||||||
|
|
@ -125,7 +100,7 @@ ORDER BY count DESC")
|
||||||
"(~A, ~A)"
|
"(~A, ~A)"
|
||||||
lint-checker-id
|
lint-checker-id
|
||||||
guix-revision-id))
|
guix-revision-id))
|
||||||
lint-checker-ids)
|
(vector->list lint-checker-ids))
|
||||||
", "))))
|
", "))))
|
||||||
|
|
||||||
(define (lint-checkers-for-revision conn commit-hash)
|
(define (lint-checkers-for-revision conn commit-hash)
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@
|
||||||
;;; <http://www.gnu.org/licenses/>.
|
;;; <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
(define-module (guix-data-service model lint-warning-message)
|
(define-module (guix-data-service model lint-warning-message)
|
||||||
|
#:use-module (srfi srfi-43)
|
||||||
#:use-module (ice-9 match)
|
#:use-module (ice-9 match)
|
||||||
#:use-module (squee)
|
#:use-module (squee)
|
||||||
#:use-module (guix-data-service database)
|
#:use-module (guix-data-service database)
|
||||||
|
|
@ -30,48 +31,24 @@
|
||||||
conn
|
conn
|
||||||
"lint_warning_messages"
|
"lint_warning_messages"
|
||||||
'(locale message)
|
'(locale message)
|
||||||
(map (match-lambda
|
(let ((v (list->vector messages-by-locale)))
|
||||||
|
(vector-map! (lambda (_ data)
|
||||||
|
(match data
|
||||||
((locale . message)
|
((locale . message)
|
||||||
(list locale message)))
|
(list locale message))))
|
||||||
messages-by-locale)))
|
v)
|
||||||
|
v)))
|
||||||
|
|
||||||
(define (lint-warning-message-data->lint-warning-message-set-id
|
(define (lint-warning-message-data->lint-warning-message-set-id
|
||||||
conn
|
conn
|
||||||
messages-by-locale)
|
messages-by-locale)
|
||||||
|
(insert-and-return-id
|
||||||
(let* ((lint-warning-message-ids
|
|
||||||
(lint-warning-message-data->lint-warning-message-ids
|
|
||||||
conn messages-by-locale))
|
|
||||||
(select-query
|
|
||||||
(string-append
|
|
||||||
"SELECT id FROM lint_warning_message_sets "
|
|
||||||
"WHERE message_ids = ARRAY["
|
|
||||||
(string-join (map number->string
|
|
||||||
(sort lint-warning-message-ids <)) ", ")
|
|
||||||
"]")))
|
|
||||||
|
|
||||||
(string->number
|
|
||||||
(match (exec-query conn select-query)
|
|
||||||
(((id)) id)
|
|
||||||
(()
|
|
||||||
(match (exec-query
|
|
||||||
conn
|
conn
|
||||||
(string-append
|
"lint_warning_message_sets"
|
||||||
"
|
'(message_ids)
|
||||||
INSERT INTO lint_warning_message_sets (message_ids) VALUES "
|
(list (lint-warning-message-data->lint-warning-message-ids
|
||||||
(string-append
|
conn
|
||||||
"('{"
|
messages-by-locale))))
|
||||||
(string-join
|
|
||||||
(map number->string
|
|
||||||
(sort lint-warning-message-ids <))
|
|
||||||
", ")
|
|
||||||
"}')") "
|
|
||||||
ON CONFLICT DO NOTHING RETURNING id"))
|
|
||||||
(((id)) id)
|
|
||||||
(()
|
|
||||||
(match (exec-query conn select-query)
|
|
||||||
(((id)) id)))))))))
|
|
||||||
|
|
||||||
|
|
||||||
(define (lint-warning-message-locales-for-revision conn commit-hash)
|
(define (lint-warning-message-locales-for-revision conn commit-hash)
|
||||||
(exec-query
|
(exec-query
|
||||||
|
|
|
||||||
|
|
@ -40,8 +40,7 @@
|
||||||
(define (insert-guix-revision-lint-warnings conn
|
(define (insert-guix-revision-lint-warnings conn
|
||||||
guix-revision-id
|
guix-revision-id
|
||||||
lint-warning-ids)
|
lint-warning-ids)
|
||||||
(if (null? lint-warning-ids)
|
(unless (= 0 (vector-length lint-warning-ids))
|
||||||
'()
|
|
||||||
(exec-query
|
(exec-query
|
||||||
conn
|
conn
|
||||||
(string-append
|
(string-append
|
||||||
|
|
@ -54,8 +53,9 @@
|
||||||
"(~A, ~A)"
|
"(~A, ~A)"
|
||||||
lint-warning-id
|
lint-warning-id
|
||||||
guix-revision-id))
|
guix-revision-id))
|
||||||
lint-warning-ids)
|
(vector->list lint-warning-ids))
|
||||||
", ")))))
|
", ")
|
||||||
|
" ON CONFLICT DO NOTHING"))))
|
||||||
|
|
||||||
(define* (lint-warnings-for-guix-revision conn commit-hash
|
(define* (lint-warnings-for-guix-revision conn commit-hash
|
||||||
#:key
|
#:key
|
||||||
|
|
|
||||||
|
|
@ -23,11 +23,10 @@
|
||||||
#:export (location->location-id))
|
#:export (location->location-id))
|
||||||
|
|
||||||
(define (location->location-id conn location)
|
(define (location->location-id conn location)
|
||||||
(car
|
(insert-and-return-id
|
||||||
(insert-missing-data-and-return-all-ids
|
|
||||||
conn
|
conn
|
||||||
"locations"
|
"locations"
|
||||||
'(file line column_number)
|
'(file line column_number)
|
||||||
(match location
|
(match location
|
||||||
(($ <location> file line column)
|
(($ <location> file line column)
|
||||||
(list (list file line column)))))))
|
(list file line column)))))
|
||||||
|
|
|
||||||
|
|
@ -57,11 +57,12 @@
|
||||||
narinfos))
|
narinfos))
|
||||||
|
|
||||||
(let ((nar-ids
|
(let ((nar-ids
|
||||||
|
(vector->list
|
||||||
(insert-missing-data-and-return-all-ids
|
(insert-missing-data-and-return-all-ids
|
||||||
conn
|
conn
|
||||||
"nars"
|
"nars"
|
||||||
'(store_path hash_algorithm hash size system deriver)
|
'(store_path hash_algorithm hash size system deriver)
|
||||||
data)))
|
(list->vector data)))))
|
||||||
|
|
||||||
(let ((reference-data
|
(let ((reference-data
|
||||||
(concatenate
|
(concatenate
|
||||||
|
|
@ -176,14 +177,12 @@ VALUES ($1, $2)")
|
||||||
#\;)
|
#\;)
|
||||||
((version host-name signature-data)
|
((version host-name signature-data)
|
||||||
|
|
||||||
(first
|
(insert-and-return-id
|
||||||
(insert-missing-data-and-return-all-ids
|
|
||||||
conn
|
conn
|
||||||
"narinfo_signature_data"
|
"narinfo_signature_data"
|
||||||
'(version host_name data_hash data_hash_algorithm
|
'(version host_name data_hash data_hash_algorithm
|
||||||
data_json sig_val_json narinfo_signature_public_key_id
|
data_json sig_val_json narinfo_signature_public_key_id
|
||||||
narinfo_body narinfo_signature_line)
|
narinfo_body narinfo_signature_line)
|
||||||
(list
|
|
||||||
(append (list (string->number version)
|
(append (list (string->number version)
|
||||||
host-name)
|
host-name)
|
||||||
(let* ((data-sexp
|
(let* ((data-sexp
|
||||||
|
|
@ -203,8 +202,7 @@ VALUES ($1, $2)")
|
||||||
(list
|
(list
|
||||||
(bytevector->base16-string hash)
|
(bytevector->base16-string hash)
|
||||||
hash-algorithm
|
hash-algorithm
|
||||||
(cons "jsonb"
|
(sexp->json-string data-sexp)))
|
||||||
(sexp->json-string data-sexp))))
|
|
||||||
(let ((sig-val-sexp
|
(let ((sig-val-sexp
|
||||||
(find (match-lambda
|
(find (match-lambda
|
||||||
((component data ...)
|
((component data ...)
|
||||||
|
|
@ -214,11 +212,10 @@ VALUES ($1, $2)")
|
||||||
(_ #f))
|
(_ #f))
|
||||||
signature-sexp)))
|
signature-sexp)))
|
||||||
(list
|
(list
|
||||||
(cons "jsonb"
|
(sexp->json-string sig-val-sexp)))
|
||||||
(sexp->json-string sig-val-sexp))))
|
|
||||||
(list public-key-id
|
(list public-key-id
|
||||||
body
|
body
|
||||||
signature-line))))))))))))
|
signature-line))))))))))
|
||||||
|
|
||||||
(define (narinfo-signature->public-key-id conn signature)
|
(define (narinfo-signature->public-key-id conn signature)
|
||||||
(let* ((public-key-sexp
|
(let* ((public-key-sexp
|
||||||
|
|
@ -232,13 +229,11 @@ VALUES ($1, $2)")
|
||||||
(public-key-json-string
|
(public-key-json-string
|
||||||
(sexp->json-string public-key-sexp)))
|
(sexp->json-string public-key-sexp)))
|
||||||
|
|
||||||
(first
|
(insert-and-return-id
|
||||||
(insert-missing-data-and-return-all-ids
|
|
||||||
conn
|
conn
|
||||||
"narinfo_signature_public_keys"
|
"narinfo_signature_public_keys"
|
||||||
'(sexp_json)
|
'(sexp_json)
|
||||||
(list (list (cons "jsonb"
|
(list public-key-json-string))))
|
||||||
public-key-json-string)))))))
|
|
||||||
|
|
||||||
(define (select-package-output-availability-for-revision conn revision-commit)
|
(define (select-package-output-availability-for-revision conn revision-commit)
|
||||||
(define query
|
(define query
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@ WHERE git_branch_id = $1 AND
|
||||||
WHERE revision_id = $2
|
WHERE revision_id = $2
|
||||||
)"
|
)"
|
||||||
(list (number->string git-branch-id)
|
(list (number->string git-branch-id)
|
||||||
guix-revision-id)))))
|
(number->string guix-revision-id))))))
|
||||||
|
|
||||||
(define (insert-guix-revision-package-derivation-entries conn
|
(define (insert-guix-revision-package-derivation-entries conn
|
||||||
git-repository-id
|
git-repository-id
|
||||||
|
|
@ -185,7 +185,7 @@ PARTITION OF package_derivations_by_guix_revision_range FOR VALUES IN ("
|
||||||
query
|
query
|
||||||
(list git-repository-id
|
(list git-repository-id
|
||||||
(number->string git-branch-id)
|
(number->string git-branch-id)
|
||||||
guix-revision-id))))
|
(number->string guix-revision-id)))))
|
||||||
|
|
||||||
(define (update-package-derivations-table conn
|
(define (update-package-derivations-table conn
|
||||||
git-repository-id
|
git-repository-id
|
||||||
|
|
|
||||||
|
|
@ -49,12 +49,13 @@
|
||||||
derivation-ids))
|
derivation-ids))
|
||||||
|
|
||||||
(if (null? data-4-tuples)
|
(if (null? data-4-tuples)
|
||||||
'()
|
#()
|
||||||
(insert-missing-data-and-return-all-ids
|
(insert-missing-data-and-return-all-ids
|
||||||
conn
|
conn
|
||||||
"package_derivations"
|
"package_derivations"
|
||||||
'(package_id derivation_id system_id target)
|
'(package_id derivation_id system_id target)
|
||||||
data-4-tuples)))
|
(list->vector
|
||||||
|
data-4-tuples))))
|
||||||
|
|
||||||
(define (count-packages-derivations-in-revision conn commit-hash)
|
(define (count-packages-derivations-in-revision conn commit-hash)
|
||||||
(define query
|
(define query
|
||||||
|
|
|
||||||
|
|
@ -205,27 +205,6 @@ WHERE packages.id IN (
|
||||||
(json-string->scm license-json)))))
|
(json-string->scm license-json)))))
|
||||||
(exec-query conn query (list revision-commit-hash name version locale))))
|
(exec-query conn query (list revision-commit-hash name version locale))))
|
||||||
|
|
||||||
(define (insert-package-metadata metadata-rows)
|
|
||||||
(string-append "INSERT INTO package_metadata "
|
|
||||||
"(synopsis, description, home_page, location_id, license_set_id) "
|
|
||||||
"VALUES "
|
|
||||||
(string-join
|
|
||||||
(map (match-lambda
|
|
||||||
((synopsis description home_page
|
|
||||||
location-id license-set-id)
|
|
||||||
(string-append
|
|
||||||
"("
|
|
||||||
(value->quoted-string-or-null synopsis) ","
|
|
||||||
(value->quoted-string-or-null description) ","
|
|
||||||
(value->quoted-string-or-null home_page) ","
|
|
||||||
location-id ","
|
|
||||||
license-set-id
|
|
||||||
")")))
|
|
||||||
metadata-rows)
|
|
||||||
",")
|
|
||||||
" RETURNING id"
|
|
||||||
";"))
|
|
||||||
|
|
||||||
(define (inferior-packages->translated-package-descriptions-and-synopsis inferior
|
(define (inferior-packages->translated-package-descriptions-and-synopsis inferior
|
||||||
inferior-package)
|
inferior-package)
|
||||||
|
|
||||||
|
|
@ -293,73 +272,12 @@ WHERE packages.id IN (
|
||||||
|
|
||||||
(prevent-inlining-for-tests inferior-packages->translated-package-descriptions-and-synopsis)
|
(prevent-inlining-for-tests inferior-packages->translated-package-descriptions-and-synopsis)
|
||||||
|
|
||||||
(define (insert-package-synopsis-set conn package-synopsis-ids)
|
|
||||||
(let ((query
|
|
||||||
(string-append
|
|
||||||
"INSERT INTO package_synopsis_sets (synopsis_ids) VALUES "
|
|
||||||
(string-append
|
|
||||||
"('{"
|
|
||||||
(string-join
|
|
||||||
(map number->string
|
|
||||||
(sort package-synopsis-ids <))
|
|
||||||
", ")
|
|
||||||
"}')")
|
|
||||||
" RETURNING id")))
|
|
||||||
(match (exec-query conn query)
|
|
||||||
(((id)) id))))
|
|
||||||
|
|
||||||
(define (package-synopsis-data->package-synopsis-set-id
|
|
||||||
conn package-synopsis-ids)
|
|
||||||
(let ((package-synopsis-set-id
|
|
||||||
(exec-query
|
|
||||||
conn
|
|
||||||
(string-append
|
|
||||||
"SELECT id FROM package_synopsis_sets"
|
|
||||||
" WHERE synopsis_ids = ARRAY["
|
|
||||||
(string-join (map number->string
|
|
||||||
(sort package-synopsis-ids <)) ", ")
|
|
||||||
"]"))))
|
|
||||||
(string->number
|
|
||||||
(match package-synopsis-set-id
|
|
||||||
(((id)) id)
|
|
||||||
(()
|
|
||||||
(insert-package-synopsis-set conn package-synopsis-ids))))))
|
|
||||||
|
|
||||||
(define (insert-package-description-set conn package-description-ids)
|
|
||||||
(let ((query
|
|
||||||
(string-append
|
|
||||||
"INSERT INTO package_description_sets (description_ids) VALUES "
|
|
||||||
(string-append
|
|
||||||
"('{"
|
|
||||||
(string-join
|
|
||||||
(map number->string
|
|
||||||
(sort package-description-ids <))
|
|
||||||
", ")
|
|
||||||
"}')")
|
|
||||||
" RETURNING id")))
|
|
||||||
(match (exec-query conn query)
|
|
||||||
(((id)) id))))
|
|
||||||
|
|
||||||
(define (package-description-data->package-description-set-id
|
|
||||||
conn package-description-ids)
|
|
||||||
(let* ((package-description-set-id
|
|
||||||
(exec-query
|
|
||||||
conn
|
|
||||||
(string-append
|
|
||||||
"SELECT id FROM package_description_sets"
|
|
||||||
" WHERE description_ids = ARRAY["
|
|
||||||
(string-join (map number->string
|
|
||||||
(sort package-description-ids <)) ", ")
|
|
||||||
"]"))))
|
|
||||||
(string->number
|
|
||||||
(match package-description-set-id
|
|
||||||
(((id)) id)
|
|
||||||
(()
|
|
||||||
(insert-package-description-set conn package-description-ids))))))
|
|
||||||
|
|
||||||
(define (inferior-packages->package-metadata-ids conn
|
(define (inferior-packages->package-metadata-ids conn
|
||||||
package-metadata
|
package-metadata
|
||||||
license-set-ids)
|
license-set-ids)
|
||||||
|
(define package-metadata-list
|
||||||
|
(vector->list package-metadata))
|
||||||
|
|
||||||
(insert-missing-data-and-return-all-ids
|
(insert-missing-data-and-return-all-ids
|
||||||
conn
|
conn
|
||||||
"package_metadata"
|
"package_metadata"
|
||||||
|
|
@ -369,13 +287,14 @@ WHERE packages.id IN (
|
||||||
package_description_set_id
|
package_description_set_id
|
||||||
package_synopsis_set_id)
|
package_synopsis_set_id)
|
||||||
|
|
||||||
|
(list->vector
|
||||||
(zip
|
(zip
|
||||||
(map (match-lambda
|
(map (match-lambda
|
||||||
((home-page rest ...)
|
((home-page rest ...)
|
||||||
(if (string? home-page)
|
(if (string? home-page)
|
||||||
home-page
|
home-page
|
||||||
NULL)))
|
NULL)))
|
||||||
package-metadata)
|
package-metadata-list)
|
||||||
(with-time-logging "preparing location ids"
|
(with-time-logging "preparing location ids"
|
||||||
(map (match-lambda
|
(map (match-lambda
|
||||||
((_ location rest ...)
|
((_ location rest ...)
|
||||||
|
|
@ -384,53 +303,47 @@ WHERE packages.id IN (
|
||||||
conn
|
conn
|
||||||
location)
|
location)
|
||||||
NULL)))
|
NULL)))
|
||||||
package-metadata))
|
package-metadata-list))
|
||||||
license-set-ids
|
(vector->list license-set-ids)
|
||||||
(with-time-logging "preparing package description set ids"
|
(with-time-logging "preparing package description set ids"
|
||||||
(map (lambda (package-description-ids)
|
(map (lambda (package-description-ids)
|
||||||
(package-description-data->package-description-set-id
|
(insert-and-return-id
|
||||||
conn
|
conn
|
||||||
package-description-ids))
|
"package_description_sets"
|
||||||
|
'(description_ids)
|
||||||
|
(list (sort package-description-ids <))))
|
||||||
(with-time-logging "preparing package description ids"
|
(with-time-logging "preparing package description ids"
|
||||||
|
(map (match-lambda
|
||||||
|
((_ _ package-description-data _)
|
||||||
(insert-missing-data-and-return-all-ids
|
(insert-missing-data-and-return-all-ids
|
||||||
conn
|
conn
|
||||||
"package_descriptions"
|
"package_descriptions"
|
||||||
'(locale description)
|
'(locale description)
|
||||||
(map (match-lambda
|
(list->vector
|
||||||
((_ _ package-description-data _)
|
|
||||||
(map (match-lambda
|
(map (match-lambda
|
||||||
((locale . description)
|
((locale . description)
|
||||||
(list locale description)))
|
(list locale description)))
|
||||||
package-description-data)))
|
package-description-data)))))
|
||||||
package-metadata)
|
package-metadata-list))))
|
||||||
#:delete-duplicates? #t
|
|
||||||
#:sets-of-data? #t))))
|
|
||||||
(with-time-logging "preparing package synopsis set ids"
|
(with-time-logging "preparing package synopsis set ids"
|
||||||
(map (lambda (package-synopsis-ids)
|
(map (lambda (package-synopsis-ids)
|
||||||
(package-synopsis-data->package-synopsis-set-id
|
(insert-and-return-id
|
||||||
conn
|
conn
|
||||||
package-synopsis-ids))
|
"package_synopsis_sets"
|
||||||
|
'(synopsis_ids)
|
||||||
|
(list (sort package-synopsis-ids <))))
|
||||||
|
(map (match-lambda
|
||||||
|
((_ _ _ package-synopsis-data)
|
||||||
(insert-missing-data-and-return-all-ids
|
(insert-missing-data-and-return-all-ids
|
||||||
conn
|
conn
|
||||||
"package_synopsis"
|
"package_synopsis"
|
||||||
'(locale synopsis)
|
'(locale synopsis)
|
||||||
(map (match-lambda
|
(list->vector
|
||||||
((_ _ _ package-synopsis-data)
|
|
||||||
(map (match-lambda
|
(map (match-lambda
|
||||||
((locale . synopsis)
|
((locale . synopsis)
|
||||||
(list locale synopsis)))
|
(list locale synopsis)))
|
||||||
package-synopsis-data)))
|
package-synopsis-data)))))
|
||||||
package-metadata)
|
package-metadata-list)))))))
|
||||||
#:delete-duplicates? #t
|
|
||||||
#:sets-of-data? #t))))
|
|
||||||
;; There can be duplicated entires in package-metadata, for example where
|
|
||||||
;; you have one package definition which interits from another, and just
|
|
||||||
;; overrides the version and the source, the package_metadata entries for
|
|
||||||
;; both definitions will be the same.
|
|
||||||
#:delete-duplicates? #t
|
|
||||||
;; There is so much package metadata that it's worth creating a temporary
|
|
||||||
;; table
|
|
||||||
#:use-temporary-table? #t))
|
|
||||||
|
|
||||||
(define (package-description-and-synopsis-locale-options-guix-revision conn
|
(define (package-description-and-synopsis-locale-options-guix-revision conn
|
||||||
revision-id)
|
revision-id)
|
||||||
|
|
@ -551,8 +464,8 @@ INNER JOIN (
|
||||||
OR translated_package_descriptions.locale = 'en_US.UTF-8')
|
OR translated_package_descriptions.locale = 'en_US.UTF-8')
|
||||||
WHERE package_metadata.id IN ("
|
WHERE package_metadata.id IN ("
|
||||||
(string-join
|
(string-join
|
||||||
(map number->string
|
(map number->string (vector->list package-metadata-ids))
|
||||||
package-metadata-ids) ", ") ")"
|
", ") ")"
|
||||||
"
|
"
|
||||||
ORDER BY package_metadata.id, locale,
|
ORDER BY package_metadata.id, locale,
|
||||||
CASE WHEN translated_package_synopsis.locale =
|
CASE WHEN translated_package_synopsis.locale =
|
||||||
|
|
|
||||||
|
|
@ -250,23 +250,6 @@ WHERE packages.id IN (
|
||||||
|
|
||||||
(exec-query conn query (list commit-hash)))
|
(exec-query conn query (list commit-hash)))
|
||||||
|
|
||||||
(define (insert-into-package-entries package-entries)
|
|
||||||
(string-append
|
|
||||||
"
|
|
||||||
INSERT INTO packages (name, version, package_metadata_id) VALUES "
|
|
||||||
(string-join
|
|
||||||
(map
|
|
||||||
(match-lambda
|
|
||||||
((name version package_metadata_id)
|
|
||||||
(simple-format #f "('~A', '~A', ~A)"
|
|
||||||
name
|
|
||||||
version
|
|
||||||
package_metadata_id)))
|
|
||||||
package-entries)
|
|
||||||
",")
|
|
||||||
"
|
|
||||||
RETURNING id"))
|
|
||||||
|
|
||||||
(define (inferior-packages->package-ids conn package-entries)
|
(define (inferior-packages->package-ids conn package-entries)
|
||||||
(insert-missing-data-and-return-all-ids
|
(insert-missing-data-and-return-all-ids
|
||||||
conn
|
conn
|
||||||
|
|
|
||||||
|
|
@ -34,17 +34,16 @@
|
||||||
(let ((cached-value (hash-ref system->system-id-cache
|
(let ((cached-value (hash-ref system->system-id-cache
|
||||||
system)))
|
system)))
|
||||||
(or cached-value
|
(or cached-value
|
||||||
(match (insert-missing-data-and-return-all-ids
|
(let ((id (insert-and-return-id
|
||||||
conn
|
conn
|
||||||
"systems"
|
"systems"
|
||||||
'(system)
|
'(system)
|
||||||
`((,system)))
|
(list system))))
|
||||||
((id)
|
|
||||||
(hash-set! system->system-id-cache
|
(hash-set! system->system-id-cache
|
||||||
system
|
system
|
||||||
id)
|
id)
|
||||||
(set! systems-cache #f)
|
(set! systems-cache #f)
|
||||||
id)))))
|
id))))
|
||||||
|
|
||||||
(define (lookup-system-id conn system)
|
(define (lookup-system-id conn system)
|
||||||
(let ((cached-value (hash-ref system->system-id-cache
|
(let ((cached-value (hash-ref system->system-id-cache
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
(define-module (guix-data-service model utils)
|
(define-module (guix-data-service model utils)
|
||||||
#:use-module (srfi srfi-1)
|
#:use-module (srfi srfi-1)
|
||||||
|
#:use-module (srfi srfi-43)
|
||||||
#:use-module (ice-9 match)
|
#:use-module (ice-9 match)
|
||||||
#:use-module (ice-9 vlist)
|
#:use-module (ice-9 vlist)
|
||||||
#:use-module (ice-9 receive)
|
#:use-module (ice-9 receive)
|
||||||
|
|
@ -26,14 +27,16 @@
|
||||||
#:export (quote-string
|
#:export (quote-string
|
||||||
value->quoted-string-or-null
|
value->quoted-string-or-null
|
||||||
non-empty-string-or-false
|
non-empty-string-or-false
|
||||||
exec-query->vhash
|
|
||||||
two-lists->vhash
|
|
||||||
parse-postgresql-array-string
|
parse-postgresql-array-string
|
||||||
deduplicate-strings
|
deduplicate-strings
|
||||||
group-list-by-first-n-fields
|
group-list-by-first-n-fields
|
||||||
group-to-alist
|
group-to-alist
|
||||||
group-to-alist/vector
|
group-to-alist/vector
|
||||||
insert-missing-data-and-return-all-ids))
|
insert-missing-data-and-return-all-ids
|
||||||
|
insert-missing-data
|
||||||
|
bulk-select
|
||||||
|
insert-and-return-id
|
||||||
|
prepare-insert-and-return-id))
|
||||||
|
|
||||||
(define (quote-string s)
|
(define (quote-string s)
|
||||||
(string-append "$STR$" s "$STR$"))
|
(string-append "$STR$" s "$STR$"))
|
||||||
|
|
@ -50,22 +53,6 @@
|
||||||
s)
|
s)
|
||||||
#f))
|
#f))
|
||||||
|
|
||||||
(define* (exec-query->vhash conn query field-function value-function
|
|
||||||
#:key (vhash vlist-null))
|
|
||||||
(fold (lambda (row result)
|
|
||||||
(vhash-cons (field-function row)
|
|
||||||
(value-function row)
|
|
||||||
result))
|
|
||||||
vhash
|
|
||||||
(exec-query-with-null-handling conn query)))
|
|
||||||
|
|
||||||
(define (two-lists->vhash l1 l2)
|
|
||||||
(fold (lambda (key value result)
|
|
||||||
(vhash-cons key value result))
|
|
||||||
vlist-null
|
|
||||||
l1
|
|
||||||
l2))
|
|
||||||
|
|
||||||
(define (parse-postgresql-array-string s)
|
(define (parse-postgresql-array-string s)
|
||||||
(if (string=? s "{}")
|
(if (string=? s "{}")
|
||||||
'()
|
'()
|
||||||
|
|
@ -170,18 +157,6 @@ WHERE table_name = $1"
|
||||||
schema-details)
|
schema-details)
|
||||||
(error "error: field-can-be-null?"))))))))
|
(error "error: field-can-be-null?"))))))))
|
||||||
|
|
||||||
(define* (insert-missing-data-and-return-all-ids
|
|
||||||
conn
|
|
||||||
table-name
|
|
||||||
fields
|
|
||||||
data
|
|
||||||
#:key
|
|
||||||
sets-of-data?
|
|
||||||
delete-duplicates?
|
|
||||||
use-temporary-table?)
|
|
||||||
(define field-strings
|
|
||||||
(map symbol->string fields))
|
|
||||||
|
|
||||||
(define value->sql
|
(define value->sql
|
||||||
(match-lambda
|
(match-lambda
|
||||||
((? string? s)
|
((? string? s)
|
||||||
|
|
@ -189,13 +164,14 @@ WHERE table_name = $1"
|
||||||
((? NULL?)
|
((? NULL?)
|
||||||
"NULL")
|
"NULL")
|
||||||
((? symbol? s)
|
((? symbol? s)
|
||||||
(string-append "$STR$"
|
(value->sql (symbol->string s)))
|
||||||
(symbol->string s)
|
|
||||||
"$STR$"))
|
|
||||||
((? number? n)
|
((? number? n)
|
||||||
(number->string n))
|
(number->string n))
|
||||||
((? boolean? b)
|
((? boolean? b)
|
||||||
(if b "TRUE" "FALSE"))
|
(if b "TRUE" "FALSE"))
|
||||||
|
((? vector? v)
|
||||||
|
(string-append
|
||||||
|
"ARRAY[" (string-join (map value->sql (vector->list v)) ",") "]"))
|
||||||
((cast . value)
|
((cast . value)
|
||||||
(string-append
|
(string-append
|
||||||
(value->sql value) "::" cast))
|
(value->sql value) "::" cast))
|
||||||
|
|
@ -203,63 +179,64 @@ WHERE table_name = $1"
|
||||||
(error
|
(error
|
||||||
(simple-format #f "error: unknown type for value: ~A" v)))))
|
(simple-format #f "error: unknown type for value: ~A" v)))))
|
||||||
|
|
||||||
(define (delete-duplicates* data)
|
(define value->sql-literal
|
||||||
(delete-duplicates/sort!
|
(match-lambda
|
||||||
(list-copy data)
|
((? string? s) s)
|
||||||
(lambda (full-a full-b)
|
((? NULL?)
|
||||||
(let loop ((a full-a)
|
"NULL")
|
||||||
(b full-b))
|
((? symbol? s) (symbol->string s))
|
||||||
(if (null? a)
|
((? number? n)
|
||||||
#f
|
(number->string n))
|
||||||
(let ((a-val (match (car a)
|
((? boolean? b)
|
||||||
((_ . val) val)
|
(if b "TRUE" "FALSE"))
|
||||||
((? symbol? val) (symbol->string val))
|
((? vector? v)
|
||||||
(val val)))
|
|
||||||
(b-val (match (car b)
|
|
||||||
((_ . val) val)
|
|
||||||
((? symbol? val) (symbol->string val))
|
|
||||||
(val val))))
|
|
||||||
(cond
|
|
||||||
((NULL? a-val)
|
|
||||||
(if (NULL? b-val)
|
|
||||||
(loop (cdr a) (cdr b))
|
|
||||||
#t))
|
|
||||||
((NULL? b-val)
|
|
||||||
#f)
|
|
||||||
(else
|
|
||||||
(match a-val
|
|
||||||
((? string? v)
|
|
||||||
(if (string=? a-val b-val)
|
|
||||||
(loop (cdr a) (cdr b))
|
|
||||||
(string<? a-val b-val)))
|
|
||||||
((? number? v)
|
|
||||||
(if (= a-val b-val)
|
|
||||||
(loop (cdr a) (cdr b))
|
|
||||||
(< a-val b-val)))
|
|
||||||
((? boolean? v)
|
|
||||||
(if (eq? a-val b-val)
|
|
||||||
(loop (cdr a) (cdr b))
|
|
||||||
a-val)))))))))))
|
|
||||||
|
|
||||||
(define (select-query data)
|
|
||||||
(string-append
|
(string-append
|
||||||
"SELECT id,\n"
|
"{" (string-join (map value->sql-literal (vector->list v)) ",") "}"))
|
||||||
(string-join (map (lambda (field)
|
((cast . value)
|
||||||
(string-append table-name "." field))
|
(string-append
|
||||||
field-strings)
|
(value->sql-literal value) "::" cast))
|
||||||
",\n")
|
(v
|
||||||
" FROM " table-name
|
(error
|
||||||
" JOIN (VALUES "
|
(simple-format #f "error: unknown type for value: ~A" v)))))
|
||||||
|
|
||||||
|
(define* (bulk-select conn
|
||||||
|
table-name
|
||||||
|
fields
|
||||||
|
data
|
||||||
|
#:key (id-proc string->number))
|
||||||
|
(define field-strings
|
||||||
|
(map symbol->string fields))
|
||||||
|
|
||||||
|
(define query
|
||||||
|
(string-append
|
||||||
|
"
|
||||||
|
SELECT vals.bulk_select_index, id
|
||||||
|
FROM " table-name "
|
||||||
|
JOIN (VALUES "
|
||||||
(string-join
|
(string-join
|
||||||
(map
|
(if (vector? data)
|
||||||
(lambda (field-values)
|
(vector-fold
|
||||||
|
(lambda (index result field-values)
|
||||||
|
(cons
|
||||||
(string-append
|
(string-append
|
||||||
"("
|
"("
|
||||||
|
(number->string index) ", "
|
||||||
|
(string-join (map value->sql field-values) ",")
|
||||||
|
")")
|
||||||
|
result))
|
||||||
|
'()
|
||||||
|
data)
|
||||||
|
(map
|
||||||
|
(lambda (index field-values)
|
||||||
|
(string-append
|
||||||
|
"("
|
||||||
|
(number->string index) ", "
|
||||||
(string-join (map value->sql field-values) ",")
|
(string-join (map value->sql field-values) ",")
|
||||||
")"))
|
")"))
|
||||||
data)
|
(iota (length data))
|
||||||
|
data))
|
||||||
", ")
|
", ")
|
||||||
")\n AS vals (" (string-join field-strings ", ") ") "
|
")\n AS vals (bulk_select_index, " (string-join field-strings ", ") ") "
|
||||||
"ON "
|
"ON "
|
||||||
(string-join
|
(string-join
|
||||||
(map (lambda (field)
|
(map (lambda (field)
|
||||||
|
|
@ -275,37 +252,32 @@ WHERE table_name = $1"
|
||||||
field-strings)
|
field-strings)
|
||||||
" AND\n ")))
|
" AND\n ")))
|
||||||
|
|
||||||
(define (temp-table-select-query temp-table-name)
|
(let ((result (make-vector (if (vector? data)
|
||||||
(string-append
|
(vector-length data)
|
||||||
"SELECT " table-name ".id, "
|
(length data))
|
||||||
(string-join (map (lambda (field)
|
#f)))
|
||||||
(string-append table-name "." field))
|
(for-each
|
||||||
field-strings)
|
(match-lambda
|
||||||
", ")
|
((index id)
|
||||||
" FROM " table-name
|
(vector-set! result (string->number index)
|
||||||
" INNER JOIN " temp-table-name
|
(id-proc id))))
|
||||||
" ON "
|
(exec-query conn query))
|
||||||
(string-join
|
|
||||||
(map (lambda (field)
|
|
||||||
(string-concatenate
|
|
||||||
`("("
|
|
||||||
,table-name "." ,field " = " ,temp-table-name "." ,field
|
|
||||||
,@(if (field-can-be-null? conn table-name field)
|
|
||||||
`(" OR ("
|
|
||||||
,table-name "." ,field " IS NULL"
|
|
||||||
" AND "
|
|
||||||
,temp-table-name "." ,field " IS NULL"
|
|
||||||
")")
|
|
||||||
'())
|
|
||||||
")")))
|
|
||||||
field-strings)
|
|
||||||
" AND ")))
|
|
||||||
|
|
||||||
(define* (insert-sql missing-data
|
result))
|
||||||
#:key
|
|
||||||
(table-name table-name))
|
(define* (bulk-insert
|
||||||
|
conn
|
||||||
|
table-name
|
||||||
|
fields
|
||||||
|
data
|
||||||
|
#:key (id-proc string->number))
|
||||||
|
(define field-strings
|
||||||
|
(map symbol->string fields))
|
||||||
|
|
||||||
|
(define query
|
||||||
(string-append
|
(string-append
|
||||||
"INSERT INTO " table-name " (\n"
|
"
|
||||||
|
INSERT INTO " table-name " (\n"
|
||||||
(string-join field-strings ",\n")
|
(string-join field-strings ",\n")
|
||||||
") VALUES "
|
") VALUES "
|
||||||
(string-join
|
(string-join
|
||||||
|
|
@ -318,152 +290,235 @@ WHERE table_name = $1"
|
||||||
field-values)
|
field-values)
|
||||||
", ")
|
", ")
|
||||||
")"))
|
")"))
|
||||||
missing-data)
|
|
||||||
", ")
|
|
||||||
" ON CONFLICT DO NOTHING"))
|
|
||||||
|
|
||||||
(define (format-json json)
|
|
||||||
;; PostgreSQL formats JSON strings differently to guile-json, so use
|
|
||||||
;; PostgreSQL to do the formatting
|
|
||||||
(caar
|
|
||||||
(exec-query
|
|
||||||
conn
|
|
||||||
(string-append
|
|
||||||
"SELECT $STR$" json "$STR$::jsonb"))))
|
|
||||||
|
|
||||||
(define (normalise-values data)
|
|
||||||
(map (match-lambda
|
|
||||||
((? boolean? b)
|
|
||||||
(if b "t" "f"))
|
|
||||||
((? number? n)
|
|
||||||
(number->string n))
|
|
||||||
((? NULL? n) n)
|
|
||||||
((? symbol? s)
|
|
||||||
(symbol->string s))
|
|
||||||
((? string? s)
|
|
||||||
s)
|
|
||||||
((cast . value)
|
|
||||||
(if (string=? cast "jsonb")
|
|
||||||
(format-json value)
|
|
||||||
value))
|
|
||||||
(unknown
|
|
||||||
(error (simple-format #f "normalise-values: error: ~A\n" unknown))))
|
|
||||||
data))
|
|
||||||
|
|
||||||
(let* ((flattened-deduplicated-data
|
|
||||||
(if sets-of-data?
|
|
||||||
(delete-duplicates*
|
|
||||||
(concatenate data))
|
|
||||||
(if delete-duplicates?
|
|
||||||
(delete-duplicates* data)
|
|
||||||
data)))
|
|
||||||
(existing-entries
|
|
||||||
(if use-temporary-table?
|
|
||||||
(let ((temp-table-name
|
|
||||||
(string-append "temp_" table-name)))
|
|
||||||
;; Create a temporary table to store the data
|
|
||||||
(exec-query
|
|
||||||
conn
|
|
||||||
(string-append "CREATE TEMPORARY TABLE "
|
|
||||||
temp-table-name
|
|
||||||
" (LIKE "
|
|
||||||
table-name
|
|
||||||
" INCLUDING ALL)"))
|
|
||||||
(exec-query
|
|
||||||
conn
|
|
||||||
(string-append
|
|
||||||
"ANALYZE " temp-table-name))
|
|
||||||
|
|
||||||
;; Populate the temporary table
|
|
||||||
(unless (null? flattened-deduplicated-data)
|
|
||||||
(with-time-logging (string-append "populating " temp-table-name)
|
|
||||||
(exec-query conn
|
|
||||||
(insert-sql flattened-deduplicated-data
|
|
||||||
#:table-name temp-table-name))))
|
|
||||||
;; Use the temporary table to find the existing values
|
|
||||||
(let ((result
|
|
||||||
(with-time-logging
|
|
||||||
(string-append "querying the " temp-table-name)
|
|
||||||
(exec-query->vhash
|
|
||||||
conn
|
|
||||||
(temp-table-select-query temp-table-name)
|
|
||||||
cdr
|
|
||||||
(lambda (result)
|
|
||||||
(string->number (first result)))))))
|
|
||||||
|
|
||||||
(exec-query conn (string-append "DROP TABLE " temp-table-name))
|
|
||||||
result))
|
|
||||||
|
|
||||||
;; If not using a temporary table, just do a single SELECT query
|
|
||||||
(if (null? flattened-deduplicated-data)
|
|
||||||
'()
|
|
||||||
(fold
|
|
||||||
(lambda (data-chunk result)
|
|
||||||
(exec-query->vhash conn
|
|
||||||
(select-query data-chunk)
|
|
||||||
cdr
|
|
||||||
(lambda (result)
|
|
||||||
(string->number (first result)))
|
|
||||||
#:vhash result))
|
|
||||||
vlist-null
|
|
||||||
(chunk flattened-deduplicated-data
|
|
||||||
3000)))))
|
|
||||||
(missing-entries
|
|
||||||
(let loop ((lst flattened-deduplicated-data)
|
|
||||||
(result '()))
|
|
||||||
(if (null? lst)
|
|
||||||
(if delete-duplicates?
|
|
||||||
(delete-duplicates* result)
|
|
||||||
result)
|
|
||||||
(let ((field-values (car lst)))
|
|
||||||
(if (vhash-assoc
|
|
||||||
;; Normalise at this point, so that the proper value
|
|
||||||
;; to insert is carried forward
|
|
||||||
(normalise-values field-values)
|
|
||||||
existing-entries)
|
|
||||||
(loop (cdr lst)
|
|
||||||
result)
|
|
||||||
(loop (cdr lst)
|
|
||||||
(cons field-values result)))))))
|
|
||||||
(new-entries
|
|
||||||
(if (null? missing-entries)
|
|
||||||
'()
|
|
||||||
(append-map!
|
|
||||||
(lambda (missing-entries-chunk)
|
|
||||||
(exec-query conn
|
|
||||||
(insert-sql missing-entries-chunk))
|
|
||||||
|
|
||||||
(map (lambda (row)
|
|
||||||
(string->number (first row)))
|
|
||||||
(exec-query conn (select-query missing-entries-chunk))))
|
|
||||||
(chunk missing-entries 3000))))
|
|
||||||
|
|
||||||
(new-entries-lookup-vhash
|
|
||||||
(two-lists->vhash missing-entries
|
|
||||||
new-entries))
|
|
||||||
(all-ids
|
|
||||||
(if sets-of-data?
|
|
||||||
(map (lambda (field-value-lists)
|
|
||||||
;; Normalise the result at this point, ensuring that the id's
|
|
||||||
;; in the set are sorted
|
|
||||||
(sort
|
|
||||||
(map (lambda (field-values)
|
|
||||||
(cdr
|
|
||||||
(or (vhash-assoc (normalise-values field-values)
|
|
||||||
existing-entries)
|
|
||||||
(vhash-assoc field-values
|
|
||||||
new-entries-lookup-vhash)
|
|
||||||
(error "missing entry" field-values))))
|
|
||||||
field-value-lists)
|
|
||||||
<))
|
|
||||||
data)
|
data)
|
||||||
(map (lambda (field-values)
|
", ")
|
||||||
(cdr
|
" ON CONFLICT DO NOTHING
|
||||||
(or (vhash-assoc (normalise-values field-values)
|
RETURNING id"))
|
||||||
existing-entries)
|
|
||||||
(vhash-assoc field-values
|
(if (null? data)
|
||||||
new-entries-lookup-vhash)
|
#()
|
||||||
(error "missing entry" field-values))))
|
(let* ((query-result (exec-query conn query))
|
||||||
data))))
|
(expected-ids (length data))
|
||||||
(values all-ids
|
(returned-ids (length query-result)))
|
||||||
(delete-duplicates/sort! new-entries <))))
|
(if (= expected-ids returned-ids)
|
||||||
|
(let ((result
|
||||||
|
(make-vector returned-ids)))
|
||||||
|
(fold
|
||||||
|
(lambda (row index)
|
||||||
|
(match row
|
||||||
|
((id)
|
||||||
|
(vector-set! result index
|
||||||
|
(id-proc id))))
|
||||||
|
(1+ index))
|
||||||
|
0
|
||||||
|
query-result)
|
||||||
|
result)
|
||||||
|
;; Can't match up the ids to the data, so just query for them
|
||||||
|
(bulk-select conn
|
||||||
|
table-name
|
||||||
|
fields
|
||||||
|
data
|
||||||
|
#:id-proc id-proc)))))
|
||||||
|
|
||||||
|
(define* (insert-missing-data
|
||||||
|
conn
|
||||||
|
table-name
|
||||||
|
fields
|
||||||
|
data)
|
||||||
|
(define field-strings
|
||||||
|
(map symbol->string fields))
|
||||||
|
|
||||||
|
(let* ((result
|
||||||
|
(bulk-select
|
||||||
|
conn
|
||||||
|
table-name
|
||||||
|
fields
|
||||||
|
data))
|
||||||
|
(missing-data-indexes
|
||||||
|
(vector-fold
|
||||||
|
(lambda (i missing-data-indexes id-or-f)
|
||||||
|
(if id-or-f
|
||||||
|
missing-data-indexes
|
||||||
|
(cons i missing-data-indexes)))
|
||||||
|
'()
|
||||||
|
result)))
|
||||||
|
|
||||||
|
(bulk-insert
|
||||||
|
conn
|
||||||
|
table-name
|
||||||
|
fields
|
||||||
|
(map (lambda (index)
|
||||||
|
(vector-ref data index))
|
||||||
|
missing-data-indexes))
|
||||||
|
|
||||||
|
*unspecified*))
|
||||||
|
|
||||||
|
(define* (insert-missing-data-and-return-all-ids
|
||||||
|
conn
|
||||||
|
table-name
|
||||||
|
fields
|
||||||
|
data
|
||||||
|
#:key (id-proc string->number))
|
||||||
|
(define field-strings
|
||||||
|
(map symbol->string fields))
|
||||||
|
|
||||||
|
(let* ((result
|
||||||
|
(bulk-select
|
||||||
|
conn
|
||||||
|
table-name
|
||||||
|
fields
|
||||||
|
data
|
||||||
|
#:id-proc id-proc))
|
||||||
|
(missing-data-indexes
|
||||||
|
(vector-fold
|
||||||
|
(lambda (i missing-data-indexes id-or-f)
|
||||||
|
(if id-or-f
|
||||||
|
missing-data-indexes
|
||||||
|
(cons i missing-data-indexes)))
|
||||||
|
'()
|
||||||
|
result))
|
||||||
|
(new-ids
|
||||||
|
(bulk-insert
|
||||||
|
conn
|
||||||
|
table-name
|
||||||
|
fields
|
||||||
|
(map (lambda (index)
|
||||||
|
(vector-ref data index))
|
||||||
|
missing-data-indexes)
|
||||||
|
#:id-proc id-proc)))
|
||||||
|
|
||||||
|
(fold
|
||||||
|
(lambda (missing-data-index index)
|
||||||
|
(let ((new-id (vector-ref new-ids index)))
|
||||||
|
(vector-set! result missing-data-index new-id))
|
||||||
|
(1+ index))
|
||||||
|
0
|
||||||
|
missing-data-indexes)
|
||||||
|
|
||||||
|
(values result new-ids)))
|
||||||
|
|
||||||
|
(define* (insert-and-return-id conn
|
||||||
|
table-name
|
||||||
|
fields
|
||||||
|
field-vals
|
||||||
|
#:key (id-proc string->number))
|
||||||
|
(define field-strings
|
||||||
|
(map symbol->string fields))
|
||||||
|
|
||||||
|
(define select
|
||||||
|
(string-append
|
||||||
|
"
|
||||||
|
SELECT id FROM " table-name "
|
||||||
|
WHERE "
|
||||||
|
(string-join
|
||||||
|
(map (lambda (i field)
|
||||||
|
(string-append
|
||||||
|
"(" field " = $" i
|
||||||
|
(if (field-can-be-null? conn table-name field)
|
||||||
|
(string-append
|
||||||
|
" OR (" field " IS NULL AND $" i " IS NULL)")
|
||||||
|
"")
|
||||||
|
")"))
|
||||||
|
(map number->string
|
||||||
|
(iota (length fields) 1))
|
||||||
|
field-strings)
|
||||||
|
" AND\n ")
|
||||||
|
";"))
|
||||||
|
|
||||||
|
(define insert
|
||||||
|
(string-append
|
||||||
|
"
|
||||||
|
INSERT INTO " table-name " (\n" (string-join field-strings ",\n") ")
|
||||||
|
VALUES (" (string-join
|
||||||
|
(map (lambda (i)
|
||||||
|
(simple-format #f "$~A" i))
|
||||||
|
(iota (length fields) 1))
|
||||||
|
", ") ")
|
||||||
|
ON CONFLICT DO NOTHING
|
||||||
|
RETURNING id;"))
|
||||||
|
|
||||||
|
(let ((sql-field-values
|
||||||
|
(map value->sql-literal field-vals)))
|
||||||
|
(id-proc
|
||||||
|
(match (exec-query
|
||||||
|
conn
|
||||||
|
select
|
||||||
|
sql-field-values)
|
||||||
|
(((id)) id)
|
||||||
|
(()
|
||||||
|
(match (exec-query
|
||||||
|
conn
|
||||||
|
insert
|
||||||
|
sql-field-values)
|
||||||
|
(((id)) id)
|
||||||
|
(()
|
||||||
|
(match (exec-query
|
||||||
|
conn
|
||||||
|
select
|
||||||
|
sql-field-values)
|
||||||
|
(((id)) id)))))))))
|
||||||
|
|
||||||
|
(define (prepare-insert-and-return-id conn
|
||||||
|
table-name
|
||||||
|
fields
|
||||||
|
types)
|
||||||
|
(define field-strings
|
||||||
|
(map symbol->string fields))
|
||||||
|
|
||||||
|
(define prepared-insert-select
|
||||||
|
(string-append
|
||||||
|
"
|
||||||
|
PREPARE " table-name "PreparedInsertSelect
|
||||||
|
(" (string-join (map symbol->string types) ",") ") AS
|
||||||
|
SELECT id FROM " table-name "
|
||||||
|
WHERE "
|
||||||
|
(string-join
|
||||||
|
(map (lambda (i field)
|
||||||
|
(string-append
|
||||||
|
"(" field " = $" i
|
||||||
|
(if (field-can-be-null? conn table-name field)
|
||||||
|
(string-append
|
||||||
|
" OR (" field " IS NULL AND $" i " IS NULL)")
|
||||||
|
"")
|
||||||
|
")"))
|
||||||
|
(map number->string
|
||||||
|
(iota (length fields) 1))
|
||||||
|
field-strings)
|
||||||
|
" AND\n ")
|
||||||
|
";"))
|
||||||
|
|
||||||
|
(define prepared-insert
|
||||||
|
(string-append
|
||||||
|
"
|
||||||
|
PREPARE " table-name "PreparedInsert
|
||||||
|
(" (string-join (map symbol->string types) ",") ") AS
|
||||||
|
INSERT INTO " table-name " (\n" (string-join field-strings ",\n") ")
|
||||||
|
VALUES (" (string-join
|
||||||
|
(map (lambda (i)
|
||||||
|
(simple-format #f "$~A" i))
|
||||||
|
(iota (length fields) 1))
|
||||||
|
", ") ")
|
||||||
|
ON CONFLICT DO NOTHING
|
||||||
|
RETURNING id;"))
|
||||||
|
|
||||||
|
(exec-query conn prepared-insert)
|
||||||
|
(exec-query conn prepared-insert-select)
|
||||||
|
|
||||||
|
(lambda (conn field-vals)
|
||||||
|
(match (exec-query
|
||||||
|
conn
|
||||||
|
(string-append
|
||||||
|
"
|
||||||
|
EXECUTE " table-name "PreparedInsert("
|
||||||
|
(string-join (map value->sql field-vals) ", ")
|
||||||
|
");"))
|
||||||
|
(((id)) id)
|
||||||
|
(()
|
||||||
|
(match (exec-query
|
||||||
|
conn
|
||||||
|
(string-append
|
||||||
|
"
|
||||||
|
EXECUTE " table-name "PreparedInsertSelect("
|
||||||
|
(string-join (map value->sql field-vals) ", ")
|
||||||
|
");"))
|
||||||
|
(((id)) id))))))
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@
|
||||||
(test-begin "test-model-license-set")
|
(test-begin "test-model-license-set")
|
||||||
|
|
||||||
(define license-data
|
(define license-data
|
||||||
'((("License 1"
|
'#((("License 1"
|
||||||
"https://gnu.org/licenses/test-1.html"
|
"https://gnu.org/licenses/test-1.html"
|
||||||
"https://example.com/why-license-1"))
|
"https://example.com/why-license-1"))
|
||||||
(("License 1"
|
(("License 1"
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@
|
||||||
(test-begin "test-model-license")
|
(test-begin "test-model-license")
|
||||||
|
|
||||||
(define license-data
|
(define license-data
|
||||||
'((("License 1"
|
'#((("License 1"
|
||||||
"https://gnu.org/licenses/test-1.html"
|
"https://gnu.org/licenses/test-1.html"
|
||||||
"https://example.com/why-license-1"))
|
"https://example.com/why-license-1"))
|
||||||
(("License 1"
|
(("License 1"
|
||||||
|
|
|
||||||
|
|
@ -16,32 +16,23 @@
|
||||||
conn
|
conn
|
||||||
(lambda (conn)
|
(lambda (conn)
|
||||||
(define data
|
(define data
|
||||||
`((name-1 #t ,(string->number (insert-lint-checker-description-set
|
`#((name-1
|
||||||
conn '(37))))
|
#t
|
||||||
(name-2 #f ,(string->number (insert-lint-checker-description-set
|
,(lint-checker-description-data->lint-checker-description-set-id
|
||||||
conn '(38))))))
|
|
||||||
|
|
||||||
(match (lint-checkers->lint-checker-ids conn data)
|
|
||||||
(((? number? id1) (? number? id2))
|
|
||||||
#t)))
|
|
||||||
#:always-rollback? #t))
|
|
||||||
|
|
||||||
(test-assert "double insert"
|
|
||||||
(with-postgresql-transaction
|
|
||||||
conn
|
conn
|
||||||
(lambda (conn)
|
'(("en_US" . "foo"))))
|
||||||
(define data
|
(name-2
|
||||||
`((name-1 #t ,(string->number (insert-lint-checker-description-set
|
#f
|
||||||
conn '(37))))
|
,(lint-checker-description-data->lint-checker-description-set-id
|
||||||
(name-2 #f ,(string->number (insert-lint-checker-description-set
|
conn
|
||||||
conn '(38))))))
|
'(("en_US" . "bar"))))))
|
||||||
|
|
||||||
(match (lint-checkers->lint-checker-ids conn data)
|
(match (lint-checkers->lint-checker-ids conn data)
|
||||||
(((? number? id1) (? number? id2))
|
(#((? number? id1) (? number? id2))
|
||||||
(match (lint-checkers->lint-checker-ids conn data)
|
(match (lint-checkers->lint-checker-ids conn data)
|
||||||
(((? number? second-id1) (? number? second-id2))
|
(#((? number? second-id1) (? number? second-id2))
|
||||||
(and (eq? id1 second-id1)
|
(and (= id1 second-id1)
|
||||||
(eq? id2 second-id2)))))))
|
(= id2 second-id2)))))))
|
||||||
#:always-rollback? #t))))
|
#:always-rollback? #t))))
|
||||||
|
|
||||||
(test-end)
|
(test-end)
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@
|
||||||
conn
|
conn
|
||||||
(lambda (conn)
|
(lambda (conn)
|
||||||
(match (lint-warning-message-data->lint-warning-message-ids conn data)
|
(match (lint-warning-message-data->lint-warning-message-ids conn data)
|
||||||
(((? number? id1) (? number? id2))
|
(#((? number? id1) (? number? id2))
|
||||||
#t)))
|
#t)))
|
||||||
#:always-rollback? #t))
|
#:always-rollback? #t))
|
||||||
|
|
||||||
|
|
@ -29,11 +29,11 @@
|
||||||
conn
|
conn
|
||||||
(lambda (conn)
|
(lambda (conn)
|
||||||
(match (lint-warning-message-data->lint-warning-message-ids conn data)
|
(match (lint-warning-message-data->lint-warning-message-ids conn data)
|
||||||
(((? number? id1) (? number? id2))
|
(#((? number? id1) (? number? id2))
|
||||||
(match (lint-warning-message-data->lint-warning-message-ids conn data)
|
(match (lint-warning-message-data->lint-warning-message-ids conn data)
|
||||||
(((? number? second-id1) (? number? second-id2))
|
(#((? number? second-id1) (? number? second-id2))
|
||||||
(and (eq? id1 second-id1)
|
(and (= id1 second-id1)
|
||||||
(eq? id2 second-id2)))))))
|
(= id2 second-id2)))))))
|
||||||
#:always-rollback? #t))
|
#:always-rollback? #t))
|
||||||
|
|
||||||
(test-assert "single set insert"
|
(test-assert "single set insert"
|
||||||
|
|
@ -53,7 +53,7 @@
|
||||||
((? number? id)
|
((? number? id)
|
||||||
(match (lint-warning-message-data->lint-warning-message-set-id conn data)
|
(match (lint-warning-message-data->lint-warning-message-set-id conn data)
|
||||||
((? number? second-id)
|
((? number? second-id)
|
||||||
(eq? id second-id))))))
|
(= id second-id))))))
|
||||||
#:always-rollback? #t))))
|
#:always-rollback? #t))))
|
||||||
|
|
||||||
(test-end)
|
(test-end)
|
||||||
|
|
|
||||||
|
|
@ -34,19 +34,20 @@
|
||||||
mock-inferior-package-foo-2))
|
mock-inferior-package-foo-2))
|
||||||
|
|
||||||
(define mock-package-metadata
|
(define mock-package-metadata
|
||||||
|
(list->vector
|
||||||
(map (lambda (mock-inf-pkg)
|
(map (lambda (mock-inf-pkg)
|
||||||
(list
|
(list
|
||||||
(mock-inferior-package-home-page mock-inf-pkg)
|
(mock-inferior-package-home-page mock-inf-pkg)
|
||||||
(mock-inferior-package-location mock-inf-pkg)
|
(mock-inferior-package-location mock-inf-pkg)
|
||||||
`(("en_US.UTF-8" . "Fake synopsis"))
|
`(("en_US.UTF-8" . "Fake synopsis"))
|
||||||
`(("en_US.UTF-8" . "Fake description"))))
|
`(("en_US.UTF-8" . "Fake description"))))
|
||||||
mock-inferior-packages))
|
mock-inferior-packages)))
|
||||||
|
|
||||||
(define (test-license-set-ids conn)
|
(define (test-license-set-ids conn)
|
||||||
(let ((license-id-lists
|
(let ((license-id-lists
|
||||||
(inferior-packages->license-id-lists
|
(inferior-packages->license-id-lists
|
||||||
conn
|
conn
|
||||||
'((("License 1"
|
'#((("License 1"
|
||||||
"https://gnu.org/licenses/test-1.html"
|
"https://gnu.org/licenses/test-1.html"
|
||||||
"https://example.com/why-license-1"))))))
|
"https://example.com/why-license-1"))))))
|
||||||
|
|
||||||
|
|
@ -73,7 +74,7 @@
|
||||||
conn
|
conn
|
||||||
mock-package-metadata
|
mock-package-metadata
|
||||||
(test-license-set-ids conn))
|
(test-license-set-ids conn))
|
||||||
((x) (number? x))))
|
(#(x) (number? x))))
|
||||||
#:always-rollback? #t))
|
#:always-rollback? #t))
|
||||||
|
|
||||||
(with-postgresql-transaction
|
(with-postgresql-transaction
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@
|
||||||
(let ((license-id-lists
|
(let ((license-id-lists
|
||||||
(inferior-packages->license-id-lists
|
(inferior-packages->license-id-lists
|
||||||
conn
|
conn
|
||||||
'((("License 1"
|
'#((("License 1"
|
||||||
"https://gnu.org/licenses/test-1.html"
|
"https://gnu.org/licenses/test-1.html"
|
||||||
"https://example.com/why-license-1"))))))
|
"https://example.com/why-license-1"))))))
|
||||||
|
|
||||||
|
|
@ -47,13 +47,14 @@
|
||||||
mock-inferior-package-foo-2))
|
mock-inferior-package-foo-2))
|
||||||
|
|
||||||
(define mock-package-metadata
|
(define mock-package-metadata
|
||||||
|
(list->vector
|
||||||
(map (lambda (mock-inf-pkg)
|
(map (lambda (mock-inf-pkg)
|
||||||
(list
|
(list
|
||||||
(mock-inferior-package-home-page mock-inf-pkg)
|
(mock-inferior-package-home-page mock-inf-pkg)
|
||||||
(mock-inferior-package-location mock-inf-pkg)
|
(mock-inferior-package-location mock-inf-pkg)
|
||||||
`(("en_US.UTF-8" . "Fake synopsis"))
|
`(("en_US.UTF-8" . "Fake synopsis"))
|
||||||
`(("en_US.UTF-8" . "Fake description"))))
|
`(("en_US.UTF-8" . "Fake description"))))
|
||||||
mock-inferior-packages))
|
mock-inferior-packages)))
|
||||||
|
|
||||||
(with-mock-inferior-packages
|
(with-mock-inferior-packages
|
||||||
(lambda ()
|
(lambda ()
|
||||||
|
|
@ -81,11 +82,12 @@
|
||||||
(cons "integer" NULL))))
|
(cons "integer" NULL))))
|
||||||
(match (inferior-packages->package-ids
|
(match (inferior-packages->package-ids
|
||||||
conn
|
conn
|
||||||
|
(list->vector
|
||||||
(zip (map mock-inferior-package-name mock-inferior-packages)
|
(zip (map mock-inferior-package-name mock-inferior-packages)
|
||||||
(map mock-inferior-package-version mock-inferior-packages)
|
(map mock-inferior-package-version mock-inferior-packages)
|
||||||
package-metadata-ids
|
(vector->list package-metadata-ids)
|
||||||
package-replacement-package-ids))
|
package-replacement-package-ids)))
|
||||||
((x) (number? x))))))
|
(#(x) (number? x))))))
|
||||||
#:always-rollback? #t)
|
#:always-rollback? #t)
|
||||||
|
|
||||||
(with-postgresql-transaction
|
(with-postgresql-transaction
|
||||||
|
|
@ -102,16 +104,18 @@
|
||||||
(test-equal "inferior-packages->package-ids is idempotent"
|
(test-equal "inferior-packages->package-ids is idempotent"
|
||||||
(inferior-packages->package-ids
|
(inferior-packages->package-ids
|
||||||
conn
|
conn
|
||||||
|
(list->vector
|
||||||
(zip (map mock-inferior-package-name mock-inferior-packages)
|
(zip (map mock-inferior-package-name mock-inferior-packages)
|
||||||
(map mock-inferior-package-version mock-inferior-packages)
|
(map mock-inferior-package-version mock-inferior-packages)
|
||||||
package-metadata-ids
|
(vector->list package-metadata-ids)
|
||||||
package-replacement-package-ids))
|
package-replacement-package-ids)))
|
||||||
(inferior-packages->package-ids
|
(inferior-packages->package-ids
|
||||||
conn
|
conn
|
||||||
|
(list->vector
|
||||||
(zip (map mock-inferior-package-name mock-inferior-packages)
|
(zip (map mock-inferior-package-name mock-inferior-packages)
|
||||||
(map mock-inferior-package-version mock-inferior-packages)
|
(map mock-inferior-package-version mock-inferior-packages)
|
||||||
package-metadata-ids
|
(vector->list package-metadata-ids)
|
||||||
package-replacement-package-ids)))))
|
package-replacement-package-ids))))))
|
||||||
#:always-rollback? #t)))))
|
#:always-rollback? #t)))))
|
||||||
|
|
||||||
(test-end)
|
(test-end)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue