Overview
Comment: | Add docs for sqlite-tools.rkt |
---|---|
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA3-256: |
11b31451e33c723422e35c2059939f48 |
User & Date: | joel on 2019-02-23 01:40:46 |
Other Links: | manifest | tags |
Context
2019-02-23
| ||
23:15 | Small fixes and improvements to HTML snippet functions check-in: 95725823 user: joel tags: trunk | |
01:40 | Add docs for sqlite-tools.rkt check-in: 11b31451 user: joel tags: trunk | |
01:39 | Check for existing connection in init-db check-in: bd5c6a94 user: joel tags: trunk | |
Changes
Modified code-docs/main.scrbl from [c017c2f1] to [f7a55451].
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | #lang scribble/manual @; Copyright (c) 2019 Joel Dueck @; @; Copying and distribution of this file, with or without modification, @; are permitted in any medium without royalty provided the copyright @; notice and this notice are preserved. This file is offered as-is, @; without any warranty. @; Scribble source for the main page of the code documents. @title{Local Yarn: source code notes} @author{Joel Dueck} | > > | > > | | | | > > | | > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | #lang scribble/manual @; Copyright (c) 2019 Joel Dueck @; @; Copying and distribution of this file, with or without modification, @; are permitted in any medium without royalty provided the copyright @; notice and this notice are preserved. This file is offered as-is, @; without any warranty. @; Scribble source for the main page of the code documents. @(require "scribble-helpers.rkt") @title{Local Yarn: source code notes} @author{Joel Dueck} These are my notes about the internals of the Local Yarn source code. In other words, a personal reference, rather than a tutorial. These pages concern only the source code itself. Refer to the wiki for anything else. You’ll get the most out of these notes if you have read @other-doc['(lib "pollen/scribblings/pollen.scrbl")], and worked through the tutorials by hand. If you’re viewing these notes on the Fossil repository, note that these pages are heavily interlinked with the central Racket documentation at @tt{docs.racket-lang.org}, which are written and maintained by others. Links on those pages that lead outside of that domain will not work within this repo’s “Code Docs” frame, due to the repository’s @ext-link["https://content-security-policy.com"]{content security policy}. To follow such links, right-click and open the link in a new tab or window. @local-table-of-contents[] @include-section["pollen.scrbl"] @; pollen.rkt @include-section["dust.scrbl"] @; dust.rkt @include-section["sqlite-tools.scrbl"] @; sqlite-tools.rkt |
Added code-docs/sqlite-tools.scrbl version [3bfd95a3].
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 | #lang scribble/manual @; Copyright (c) 2019 Joel Dueck @; @; Copying and distribution of this file, with or without modification, @; are permitted in any medium without royalty provided the copyright @; notice and this notice are preserved. This file is offered as-is, @; without any warranty. @(require "scribble-helpers.rkt" scribble/example) @(require (for-label "../pollen.rkt" "../dust.rkt" racket/base racket/contract db sugar/coerce)) @(define my-eval (make-base-eval)) @(my-eval '(require "sqlite-tools.rkt")) @title{@filepath{sqlite-tools.rkt}} @defmodule["sqlite-tools.rkt" #:packages ()] Provides a very light set of utility functions for managing a single SQLite database. These functions are completely agnostic as to the database schema. It is important to note, these functions are @bold{not safe} for use with data provided by untrusted users! In many places they use @racket[format] to blindly insert table and field names, which is dangerous (see @secref["dbsec-sql-injection" #:doc '(lib "db/scribblings/db.scrbl")]). It’s fine for this project, since its only use of a database is as a disposable cache that can be safely deleted and regenerated at any time, and there are no users except me. @section{Parameters} @defparam[sqltools:dbc con connection? #:value "No DB connection!"] The current database connection. This module assumes a single active connection and stores it in this parameter so you don’t have to pass it to a function every time you execute a query. It’s provided here so you can use it directly with the functions provided by @racketmodname[db]. @defboolparam[sqltools:log-queries? v #:value #f] A kill-switch that determines whether @racket[log-query] does anything. @section{SQL building-blocks} @defproc[(log-query [str string?]) void?] Prints @racket[_str] to standard output with @racket[println], but only if @racket[(sqltools:log-queries?)] is not @code{#f}. This is called by every function in this module that actually executes database queries (i.e., those whose names end in @tt{!}), so if you need to you can see what’s actually being sent to the database. @defproc[(backtick [str stringish?]) string?] Returns @racket[_str] surrounded by backticks. @examples[#:eval my-eval (backtick "field")] @defproc[(list->sql-fields [lst (listof stringish?)]) string?] Given a list of values, returns a single string containing the list elements in order, surrounded by backticks and separated by commas. @examples[#:eval my-eval (list->sql-fields '("id" "name" "address")) (list->sql-fields '(or use symbols))] @defproc[(list->sql-parameters [lst (listof stringish?)]) string?] Given a list of values, return a single string with numbered parameter placeholders, suitable for use in a parameterized SQL query. @examples[#:eval my-eval (list->sql-parameters '(name rank serial))] @deftogether[(@defproc[(bool->int [b any/c]) exact-integer?] @defproc[(int->bool [i exact-integer?]) boolean?])] SQLite has no “boolean” column type (in fact SQLite has no column types, period), so boolean values must be converted to/from the values @code{1} or @code{0}. When converting @emph{from} boolean, @code{#f} becomes @code{0} and any other value becomes @code{1}. When converting integers @emph{to} boolean, @code{0} becomes @code{#f} and any other value becomes @code{#t}. @examples[#:eval my-eval (bool->int #t) (bool->int "") (bool->int #f) (int->bool 1) (int->bool -100) (int->bool 0)] @defproc[(vector->hash [vec vector?] [fields (listof symbolish?)]) hash?] Returns a hash table which uses the values in @racket[_fields] as keys and the vector elements as the values. If @racket[_vec] and @racket[_fields] do not have the same number of elements, the returned hash will have only as many key/value pairs as the one with the fewest elements. The functions in Racket’s @racketmodname[db] module return query results as @seclink["vectors" #:doc '(lib "scribblings/reference/reference.scrbl")]{vectors}, but it is much easier to make use of them as hash tables, with the field names as keys. @examples[#:eval my-eval (vector->hash '#("Yossarian" "Cpt" "Z-247") '(name rank serial)) (code:comment @#,elem{When v and fields are unequal in length:}) (vector->hash '#("a" "b" "c") '(1 2)) (vector->hash '#("a" "b") '(1 2 3))] @section{Tools for making query strings} These functions don’t actually do anything to the database. They just convert lists into various kinds of SQL query strings. This way you can use lists to define what you want from the database instead of writing out the queries by hand. Again, these functions use @racket[format] to build query strings, so they aren’t safe to use with user-supplied data; see the warning at the top of this document. @defproc[(make-table-schema [tablename string?] [fields (listof stringish?)] [#:primary-key-cols pk-cols (listof stringish?) '()]) string?] Given a table name and a list of fields, returns a string containing the SQLite-flavored query that will create that table with those fields. If @racket[_pk-cols] is empty, the first value in @racket[_fields] is designated in the query as the primary key. @examples[#:eval my-eval (make-table-schema "vals" '(a b c)) (make-table-schema "vals" '(a b c) #:primary-key-cols '(a b))] @defproc[(make-insert/replace-query [table stringish?] [fields (listof stringish?)]) string?] Returns a SQLite-flavored query for inserting/updating a record. The list of values to insert is parameterized so it can be used in conjunction with a @racket[list] of values. @examples[#:eval my-eval (make-insert/replace-query 'vals '(a b c))] This query relies on the fact that in SQLite every table contains a @tt{rowid} column by default. For more information on why/how the query works, see @ext-link["https://sqlite.org/lang_insert.html"]{the SQLite docs for @tt{INSERT}}. @defproc[(make-select-query [table stringish?] [fields (listof stringish?)] [#:where where-clause stringish?]) string?] Returns a SQLite query string for selecting rows from the database. @examples[#:eval my-eval (make-select-query 'vals '(a b c) #:where 1)] @section{Query functions} These functions actually execute queries on the currently active database connection stored in the @racket[sqltools:dbc] parameter. @defproc[(init-db! [filename (or/c path-string? 'memory 'temporary)] [query statement?] ...) void?] Initialize the database connection using @racket[sqlite3-connect] with @racket['create] mode. The filename may be followed by any number of queries which will immediately be executed on the database; this can be useful for initializing tables and other setup tasks. The database connection will be stored in the @racket[sqltools:dbc] parameter. If that parameter already holds an active connection, it will be @racket[disconnect]ed and then replaced with the new connection. @defproc[(query! [query-statement statement?] [parameters any/c] ...) void?] Executes a SQL statement using the current connection. @defproc*[([(select-rows! [query statement?] [fieldnames (listof stringish?)]) hash?] [(select-rows! [table stringish?] [fieldnames (listof stringish?)] [where-clause stringish?]) hash?])] Execute a SQL query that returns rows from the database, either using a raw query (first form above), or using a table name, field names, and a @racket[_where-clause] (second form above). Returns a hash table whose keys are the field names supplied. In the first form, @racket[_fieldnames] should list all the fields that will be returned by the query, in order, since this list will be used as the keys for the hash table result. |