├── .gitattributes
├── LICENSE
├── README.md
├── db_nimternalsql.nimble
├── htmldocs
├── db_nimternalsql.html
├── db_nimternalsql.idx
├── db_nimternalsql
│ ├── duprem.html
│ ├── duprem.idx
│ ├── join.html
│ ├── join.idx
│ ├── like.html
│ ├── like.idx
│ ├── nqcommon.html
│ ├── nqcommon.idx
│ ├── nqtables.html
│ ├── nqtables.idx
│ ├── snapshot.html
│ ├── snapshot.idx
│ ├── sorter.html
│ ├── sorter.idx
│ ├── sqlparser.html
│ ├── sqlparser.idx
│ ├── sqlscanner.html
│ ├── sqlscanner.idx
│ ├── tx.html
│ ├── tx.idx
│ ├── union.html
│ └── union.idx
├── dochack.js
├── nimdoc.out.css
└── theindex.html
├── src
├── db_nimternalsql.nim
└── db_nimternalsql
│ ├── duprem.nim
│ ├── groupby.nim
│ ├── intersect.nim
│ ├── join.nim
│ ├── like.nim
│ ├── nqcommon.nim
│ ├── nqexcept.nim
│ ├── nqtables.nim
│ ├── snapshot.nim
│ ├── sorter.nim
│ ├── sqlparser.nim
│ ├── sqlscanner.nim
│ ├── tx.nim
│ └── union.nim
└── tests
├── alltests.nim
├── autoinc.nim
├── autoinc_txlog.nim
├── binary.nim
├── boolean.nim
├── cast.nim
├── char.nim
├── commit.nim
├── datetime.nim
├── default.nim
├── delete.nim
├── distinct.nim
├── except.nim
├── expjoin.nim
├── group.nim
├── impjoin.nim
├── insert_select.nim
├── intersect.nim
├── key.nim
├── leftjoin.nim
├── like.nim
├── nim.cfg
├── null.nim
├── numeric.nim
├── order.nim
├── prepared.nim
├── rollback.nim
├── snapshots.nim
├── subqueries.nim
├── txlog.nim
├── txlog_snapshot.nim
├── union.nim
├── update.nim
├── where.nim
└── with.nim
/.gitattributes:
--------------------------------------------------------------------------------
1 | * linguist-vendored
2 | *.nim linguist-vendored=false
3 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Rene Hartmann
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # NimternalSQL, an in-memory SQL database for Nim
2 |
3 | NimternalSQL is a Nim library providing an in-memory SQL database.
4 | It uses the same interface as the Nim db_*.nim database wrappers.
5 |
6 | Tables are implemented using hash tables, so specifying a key using PRIMARY KEY is mandatory.
7 | Compound keys are supported.
8 |
9 | ## Data types
10 |
11 | The following data types are supported:
12 |
13 | * INTEGER
14 | * TEXT
15 | * CHAR
16 | * VARCHAR
17 | * DECIMAL
18 | * NUMERIC
19 | * REAL
20 | * DOUBLE PRECISION
21 | * BIGINT
22 | * BOOLEAN
23 | * BINARY
24 | * VARBINARY
25 | * LONGVARBINARY
26 | * RAW
27 | * BYTEA
28 | * TIME
29 | * DATE
30 | * TIMESTAMP
31 |
32 | DECIMAL and NUMERIC are internally represented as 64-bit integers. The maximum number of digits is 18.
33 |
34 | AUTOINCREMENT is supported on INTEGER and BIGINT columns. It is not restricted to key columns.
35 |
36 | ## Scalar operators
37 |
38 | Besides the usual arithmetic, comparison, and logical operators, NimternalSQL supports the following scalar operators:
39 |
40 | * || (string concatenation)
41 | * CASE
42 | * CAST
43 | * CHAR_LENGTH
44 | * CURRENT_DATE
45 | * CURRENT_TIME
46 | * CURRENT_TIMESTAMP
47 | * LENGTH
48 | * LOWER
49 | * UPPER
50 | * LIKE
51 | * OCTET_LENGTH
52 | * POSITION
53 | * SUBSTR
54 | * TRIM
55 |
56 | ## Persistence
57 |
58 | Persistence is supported through snapshots or (optionally) a transaction
59 | log.
60 |
61 | ## Transactions
62 |
63 | By default, NimternalSQL is in autocommit mode. Autocommit mode can be
64 | enabled or disabled using DbConn.setAutocommit().
65 |
66 | ## Unimplemented SQL features
67 |
68 | A number of SQL features is not implemented, most notably:
69 |
70 | OUTER JOIN (JOIN .. ON, CROSS JOIN, and LEFT JOIN are supported)
71 |
72 | HAVING (GROUP BY is supported)
73 |
74 | RECURSIVE (WITH without RECURSIVE is supported)
75 |
76 | ALTER TABLE
77 |
78 | Views
79 |
--------------------------------------------------------------------------------
/db_nimternalsql.nimble:
--------------------------------------------------------------------------------
1 | # Package
2 |
3 | version = "1.3.2"
4 | author = "Rene Hartmann"
5 | description = "An in-memory SQL database library"
6 | license = "MIT"
7 | srcDir = "src"
8 |
9 | # Deps
10 |
11 | requires "nim >= 1.6.0"
12 |
13 | task test, "Runs all the tests":
14 | cd "tests"
15 | exec "nim c -r alltests.nim"
16 |
--------------------------------------------------------------------------------
/htmldocs/db_nimternalsql.idx:
--------------------------------------------------------------------------------
1 | DbConn db_nimternalsql.html#DbConn db_nimternalsql: DbConn
2 | Row db_nimternalsql.html#Row db_nimternalsql: Row
3 | open db_nimternalsql.html#open,string,string,string,string db_nimternalsql: open(connection, user, password, database: string): DbConn
4 | close db_nimternalsql.html#close,DbConn db_nimternalsql: close(db: DbConn)
5 | setAutocommit db_nimternalsql.html#setAutocommit,DbConn,bool db_nimternalsql: setAutocommit(db: DbConn; ac: bool)
6 | dbError db_nimternalsql.html#dbError,DbConn db_nimternalsql: dbError(db: DbConn)
7 | sqlState db_nimternalsql.html#sqlState,ref.DbError db_nimternalsql: sqlState(err: ref DbError): string
8 | exec db_nimternalsql.html#exec,DbConn,SqlQuery,varargs[string,] db_nimternalsql: exec(conn: DbConn; sql: SqlQuery; args: varargs[string, `$`])
9 | exec db_nimternalsql.html#exec,DbConn,SqlPrepared,varargs[string,] db_nimternalsql: exec(conn: DbConn; stmt: SqlPrepared; args: varargs[string, `$`])
10 | tryExec db_nimternalsql.html#tryExec,DbConn,SqlQuery,varargs[string,] db_nimternalsql: tryExec(db: DbConn; query: SqlQuery; args: varargs[string, `$`]): bool
11 | tryExec db_nimternalsql.html#tryExec,DbConn,SqlPrepared,varargs[string,] db_nimternalsql: tryExec(db: DbConn; stmt: SqlPrepared; args: varargs[string, `$`]): bool
12 | execAffectedRows db_nimternalsql.html#execAffectedRows,DbConn,SqlQuery,varargs[string,] db_nimternalsql: execAffectedRows(conn: DbConn; sql: SqlQuery; args: varargs[string, `$`]): int64
13 | execAffectedRows db_nimternalsql.html#execAffectedRows,DbConn,SqlPrepared,varargs[string,] db_nimternalsql: execAffectedRows(conn: DbConn; stmt: SqlPrepared; args: varargs[string, `$`]): int64
14 | instantRows db_nimternalsql.html#instantRows.i,DbConn,SqlQuery,varargs[string,] db_nimternalsql: instantRows(conn: DbConn; sql: SqlQuery; args: varargs[string, `$`]): InstantRow
15 | instantRows db_nimternalsql.html#instantRows.i,DbConn,DbColumns,SqlQuery,varargs[string,] db_nimternalsql: instantRows(conn: DbConn; columns: var DbColumns; sql: SqlQuery;\n args: varargs[string, `$`]): InstantRow
16 | prepare db_nimternalsql.html#prepare,DbConn,SqlQuery db_nimternalsql: prepare(conn: DbConn; sql: SqlQuery): SqlPrepared
17 | instantRows db_nimternalsql.html#instantRows.i,DbConn,SqlPrepared,varargs[string,] db_nimternalsql: instantRows(conn: DbConn; sql: SqlPrepared; args: varargs[string, `$`]): InstantRow
18 | `[]` db_nimternalsql.html#[],InstantRow,int db_nimternalsql: `[]`(row: InstantRow; col: int): string
19 | len db_nimternalsql.html#len,InstantRow db_nimternalsql: len(row: InstantRow): int
20 | rows db_nimternalsql.html#rows.i,DbConn,SqlQuery,varargs[string,] db_nimternalsql: rows(db: DbConn; query: SqlQuery; args: varargs[string, `$`]): Row
21 | rows db_nimternalsql.html#rows.i,DbConn,SqlPrepared,varargs[string,] db_nimternalsql: rows(db: DbConn; stmt: SqlPrepared; args: varargs[string, `$`]): Row
22 | getAllRows db_nimternalsql.html#getAllRows,DbConn,SqlQuery,varargs[string,] db_nimternalsql: getAllRows(db: DbConn; query: SqlQuery; args: varargs[string, `$`]): seq[Row]
23 | getAllRows db_nimternalsql.html#getAllRows,DbConn,SqlPrepared,varargs[string,] db_nimternalsql: getAllRows(db: DbConn; stmt: SqlPrepared; args: varargs[string, `$`]): seq[Row]
24 | getRow db_nimternalsql.html#getRow,DbConn,SqlQuery,varargs[string,] db_nimternalsql: getRow(conn: DbConn; query: SqlQuery; args: varargs[string, `$`]): Row
25 | getRow db_nimternalsql.html#getRow,DbConn,SqlPrepared,varargs[string,] db_nimternalsql: getRow(conn: DbConn; stmt: SqlPrepared; args: varargs[string, `$`]): Row
26 | getValue db_nimternalsql.html#getValue,DbConn,SqlQuery,varargs[string,] db_nimternalsql: getValue(conn: DbConn; query: SqlQuery; args: varargs[string, `$`]): string
27 | getValue db_nimternalsql.html#getValue,DbConn,SqlPrepared,varargs[string,] db_nimternalsql: getValue(conn: DbConn; stmt: SqlPrepared; args: varargs[string, `$`]): string
28 | save db_nimternalsql.html#save,DbConn,string db_nimternalsql: save(conn: DbConn; filename: string)
29 | save db_nimternalsql.html#save,DbConn db_nimternalsql: save(conn: DbConn)
30 | restore db_nimternalsql.html#restore,DbConn,string db_nimternalsql: restore(conn: DbConn; filename: string)
31 | Examples db_nimternalsql.html#examples Examples
32 | Opening a connection to a database db_nimternalsql.html#examples-opening-a-connection-to-a-database Opening a connection to a database
33 | Creating a table db_nimternalsql.html#examples-creating-a-table Creating a table
34 | Inserting data db_nimternalsql.html#examples-inserting-data Inserting data
35 |
--------------------------------------------------------------------------------
/htmldocs/db_nimternalsql/duprem.html:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 | src/db_nimternalsql/duprem
21 |
22 |
23 |
24 |
25 |
67 |
68 |
69 |
70 |
71 |
72 |
src/db_nimternalsql/duprem
73 |
74 |
75 |
76 |
80 |
Dark Mode
81 |
82 |
83 |
84 | -
85 | Index
86 |
87 |
88 |
89 |
90 | Search:
92 |
93 |
94 | Group by:
95 |
99 |
100 |
101 | -
102 | Imports
103 |
106 |
107 | -
108 | Types
109 |
115 |
116 | -
117 | Procs
118 |
126 |
127 | -
128 | Methods
129 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
152 |
153 |
154 |
155 |
165 |
166 |
167 |
168 |
169 |
170 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
method getColumns(table: DupRemTable): DbColumns {....raises: [SqlError], tags: [].}
185 |
-
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 | Made with Nim. Generated: 2022-04-30 16:41:59 UTC
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
--------------------------------------------------------------------------------
/htmldocs/db_nimternalsql/duprem.idx:
--------------------------------------------------------------------------------
1 | DupRemTable db_nimternalsql/duprem.html#DupRemTable duprem: DupRemTable
2 | newDupRemTable db_nimternalsql/duprem.html#newDupRemTable,VTable duprem: newDupRemTable(child: VTable): VTable
3 | getColumns db_nimternalsql/duprem.html#getColumns.e,DupRemTable duprem: getColumns(table: DupRemTable): DbColumns
4 |
--------------------------------------------------------------------------------
/htmldocs/db_nimternalsql/join.html:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 | src/db_nimternalsql/join
21 |
22 |
23 |
24 |
25 |
67 |
68 |
69 |
70 |
71 |
72 |
src/db_nimternalsql/join
73 |
74 |
75 |
76 |
80 |
Dark Mode
81 |
82 |
83 |
84 | -
85 | Index
86 |
87 |
88 |
89 |
90 | Search:
92 |
93 |
94 | Group by:
95 |
99 |
100 |
101 | -
102 | Imports
103 |
106 |
107 | -
108 | Types
109 |
117 |
118 | -
119 | Procs
120 |
130 |
131 | -
132 | Methods
133 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
156 |
157 |
158 |
159 |
160 |
JoinTable = ref object of VTable
161 | children: array[2, VTable]
162 | exp*: Expression
163 | leftOuter*: bool
164 |
165 |
-
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
method getColumns(table: JoinTable): DbColumns {....raises: [SqlError], tags: [].}
192 |
-
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 | Made with Nim. Generated: 2022-04-30 16:41:59 UTC
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
--------------------------------------------------------------------------------
/htmldocs/db_nimternalsql/join.idx:
--------------------------------------------------------------------------------
1 | JoinTable db_nimternalsql/join.html#JoinTable join: JoinTable
2 | newJoinTable db_nimternalsql/join.html#newJoinTable,VTable,VTable,bool,Expression join: newJoinTable(lchild: VTable; rchild: VTable; leftOuter: bool = false;\n exp: Expression = nil): VTable
3 | getColumns db_nimternalsql/join.html#getColumns.e,JoinTable join: getColumns(table: JoinTable): DbColumns
4 |
--------------------------------------------------------------------------------
/htmldocs/db_nimternalsql/like.html:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 | src/db_nimternalsql/like
21 |
22 |
23 |
24 |
25 |
67 |
68 |
69 |
70 |
71 |
72 |
src/db_nimternalsql/like
73 |
74 |
75 |
76 |
80 |
Dark Mode
81 |
82 |
83 |
84 | -
85 | Index
86 |
87 |
88 |
89 |
90 | Search:
92 |
93 |
94 | Group by:
95 |
99 |
100 |
101 | -
102 | Procs
103 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
Unicode LIKE matching
123 |
124 |
125 |
126 |
127 |
func matchesLike(s: seq[Rune]; pattern: seq[Rune]; startAt: Natural = 0): bool {.
128 | ...raises: [], tags: [].}
129 |
-
130 |
131 |
132 |
133 |
134 |
135 |
136 |
func matchesLike(s: string; pattern: string): bool {....raises: [], tags: [].}
137 |
-
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 | Made with Nim. Generated: 2022-04-30 16:41:59 UTC
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
--------------------------------------------------------------------------------
/htmldocs/db_nimternalsql/like.idx:
--------------------------------------------------------------------------------
1 | matchesLike db_nimternalsql/like.html#matchesLike,seq[Rune],seq[Rune],Natural like: matchesLike(s: seq[Rune]; pattern: seq[Rune]; startAt: Natural = 0): bool
2 | matchesLike db_nimternalsql/like.html#matchesLike,string,string like: matchesLike(s: string; pattern: string): bool
3 |
--------------------------------------------------------------------------------
/htmldocs/db_nimternalsql/nqcommon.idx:
--------------------------------------------------------------------------------
1 | defaultDumpName db_nimternalsql/nqcommon.html#defaultDumpName nqcommon: defaultDumpName
2 | tooManyRowsReturnedBySubquery db_nimternalsql/nqcommon.html#tooManyRowsReturnedBySubquery nqcommon: tooManyRowsReturnedBySubquery
3 | stringTooLong db_nimternalsql/nqcommon.html#stringTooLong nqcommon: stringTooLong
4 | valueOutOfRange db_nimternalsql/nqcommon.html#valueOutOfRange nqcommon: valueOutOfRange
5 | invalidDatetimeValue db_nimternalsql/nqcommon.html#invalidDatetimeValue nqcommon: invalidDatetimeValue
6 | invalidParameterValue db_nimternalsql/nqcommon.html#invalidParameterValue nqcommon: invalidParameterValue
7 | columnNotNullable db_nimternalsql/nqcommon.html#columnNotNullable nqcommon: columnNotNullable
8 | uniqueConstraintViolation db_nimternalsql/nqcommon.html#uniqueConstraintViolation nqcommon: uniqueConstraintViolation
9 | syntaxError db_nimternalsql/nqcommon.html#syntaxError nqcommon: syntaxError
10 | columnRefAmbiguous db_nimternalsql/nqcommon.html#columnRefAmbiguous nqcommon: columnRefAmbiguous
11 | undefinedColumnName db_nimternalsql/nqcommon.html#undefinedColumnName nqcommon: undefinedColumnName
12 | undefinedObjectName db_nimternalsql/nqcommon.html#undefinedObjectName nqcommon: undefinedObjectName
13 | invalidGrouping db_nimternalsql/nqcommon.html#invalidGrouping nqcommon: invalidGrouping
14 | typeMismatch db_nimternalsql/nqcommon.html#typeMismatch nqcommon: typeMismatch
15 | undefinedFunction db_nimternalsql/nqcommon.html#undefinedFunction nqcommon: undefinedFunction
16 | tableExists db_nimternalsql/nqcommon.html#tableExists nqcommon: tableExists
17 | generalError db_nimternalsql/nqcommon.html#generalError nqcommon: generalError
18 | internalError db_nimternalsql/nqcommon.html#internalError nqcommon: internalError
19 | fileIoError db_nimternalsql/nqcommon.html#fileIoError nqcommon: fileIoError
20 | fileNotValid db_nimternalsql/nqcommon.html#fileNotValid nqcommon: fileNotValid
21 | notADirectory db_nimternalsql/nqcommon.html#notADirectory nqcommon: notADirectory
22 | restoreNotSupported db_nimternalsql/nqcommon.html#restoreNotSupported nqcommon: restoreNotSupported
23 | ColumnDef db_nimternalsql/nqcommon.html#ColumnDef nqcommon: ColumnDef
24 | TypeDef db_nimternalsql/nqcommon.html#TypeDef nqcommon: TypeDef
25 | Expression db_nimternalsql/nqcommon.html#Expression nqcommon: Expression
26 | ScalarLit db_nimternalsql/nqcommon.html#ScalarLit nqcommon: ScalarLit
27 | StringLit db_nimternalsql/nqcommon.html#StringLit nqcommon: StringLit
28 | NumericLit db_nimternalsql/nqcommon.html#NumericLit nqcommon: NumericLit
29 | BoolLit db_nimternalsql/nqcommon.html#BoolLit nqcommon: BoolLit
30 | TimeLit db_nimternalsql/nqcommon.html#TimeLit nqcommon: TimeLit
31 | TimestampLit db_nimternalsql/nqcommon.html#TimestampLit nqcommon: TimestampLit
32 | DateLit db_nimternalsql/nqcommon.html#DateLit nqcommon: DateLit
33 | NullLit db_nimternalsql/nqcommon.html#NullLit nqcommon: NullLit
34 | ScalarOpExp db_nimternalsql/nqcommon.html#ScalarOpExp nqcommon: ScalarOpExp
35 | QVarExp db_nimternalsql/nqcommon.html#QVarExp nqcommon: QVarExp
36 | ListExp db_nimternalsql/nqcommon.html#ListExp nqcommon: ListExp
37 | CaseExp db_nimternalsql/nqcommon.html#CaseExp nqcommon: CaseExp
38 | CastExp db_nimternalsql/nqcommon.html#CastExp nqcommon: CastExp
39 | SelectElement db_nimternalsql/nqcommon.html#SelectElement nqcommon: SelectElement
40 | SqlError db_nimternalsql/nqcommon.html#SqlError nqcommon: SqlError
41 | raiseDbError db_nimternalsql/nqcommon.html#raiseDbError,string,string nqcommon: raiseDbError(msg: string; sqlstate: string)
42 | newStringLit db_nimternalsql/nqcommon.html#newStringLit,string nqcommon: newStringLit(v: string): Expression
43 | newNumericLit db_nimternalsql/nqcommon.html#newNumericLit,string nqcommon: newNumericLit(v: string): Expression
44 | newTimeLit db_nimternalsql/nqcommon.html#newTimeLit,string nqcommon: newTimeLit(v: string): Expression
45 | newTimestampLit db_nimternalsql/nqcommon.html#newTimestampLit,string nqcommon: newTimestampLit(v: string): Expression
46 | newDateLit db_nimternalsql/nqcommon.html#newDateLit,string nqcommon: newDateLit(v: string): Expression
47 | newBoolLit db_nimternalsql/nqcommon.html#newBoolLit,bool nqcommon: newBoolLit(v: bool): Expression
48 | newNullLit db_nimternalsql/nqcommon.html#newNullLit nqcommon: newNullLit(): Expression
49 | newListExp db_nimternalsql/nqcommon.html#newListExp,seq[Expression] nqcommon: newListExp(v: seq[Expression]): Expression
50 | newScalarOpExp db_nimternalsql/nqcommon.html#newScalarOpExp,string,varargs[Expression] nqcommon: newScalarOpExp(name: string; args: varargs[Expression]): Expression
51 | newQVarExp db_nimternalsql/nqcommon.html#newQVarExp,string,string nqcommon: newQVarExp(name: string; tableName: string = ""): QVarExp
52 | newCaseExp db_nimternalsql/nqcommon.html#newCaseExp,Expression,seq[tuple[Expression,Expression]],Expression nqcommon: newCaseExp(exp: Expression;\n whens: seq[tuple[cond: Expression, exp: Expression]];\n elseExp: Expression): Expression
53 | newCastExp db_nimternalsql/nqcommon.html#newCastExp,Expression,TypeDef nqcommon: newCastExp(exp: Expression; typ: TypeDef): Expression
54 | `$` db_nimternalsql/nqcommon.html#$.e,Expression nqcommon: `$`(exp: Expression): string
55 |
--------------------------------------------------------------------------------
/htmldocs/db_nimternalsql/nqtables.idx:
--------------------------------------------------------------------------------
1 | maxPrecision db_nimternalsql/nqtables.html#maxPrecision nqtables: maxPrecision
2 | XColumnDef db_nimternalsql/nqtables.html#XColumnDef nqtables: XColumnDef
3 | BaseTable db_nimternalsql/nqtables.html#BaseTable nqtables: BaseTable
4 | Database db_nimternalsql/nqtables.html#Database nqtables: Database
5 | Record db_nimternalsql/nqtables.html#Record nqtables: Record
6 | kInt db_nimternalsql/nqtables.html#kInt MatValueKind.kInt
7 | kNumeric db_nimternalsql/nqtables.html#kNumeric MatValueKind.kNumeric
8 | kFloat db_nimternalsql/nqtables.html#kFloat MatValueKind.kFloat
9 | kString db_nimternalsql/nqtables.html#kString MatValueKind.kString
10 | kBool db_nimternalsql/nqtables.html#kBool MatValueKind.kBool
11 | kNull db_nimternalsql/nqtables.html#kNull MatValueKind.kNull
12 | kBigint db_nimternalsql/nqtables.html#kBigint MatValueKind.kBigint
13 | kTime db_nimternalsql/nqtables.html#kTime MatValueKind.kTime
14 | kDate db_nimternalsql/nqtables.html#kDate MatValueKind.kDate
15 | MatValueKind db_nimternalsql/nqtables.html#MatValueKind nqtables: MatValueKind
16 | MatValue db_nimternalsql/nqtables.html#MatValue nqtables: MatValue
17 | HashBaseTable db_nimternalsql/nqtables.html#HashBaseTable nqtables: HashBaseTable
18 | nqkNull db_nimternalsql/nqtables.html#nqkNull NqValueKind.nqkNull
19 | nqkInt db_nimternalsql/nqtables.html#nqkInt NqValueKind.nqkInt
20 | nqkNumeric db_nimternalsql/nqtables.html#nqkNumeric NqValueKind.nqkNumeric
21 | nqkFloat db_nimternalsql/nqtables.html#nqkFloat NqValueKind.nqkFloat
22 | nqkString db_nimternalsql/nqtables.html#nqkString NqValueKind.nqkString
23 | nqkBool db_nimternalsql/nqtables.html#nqkBool NqValueKind.nqkBool
24 | nqkList db_nimternalsql/nqtables.html#nqkList NqValueKind.nqkList
25 | nqkBigint db_nimternalsql/nqtables.html#nqkBigint NqValueKind.nqkBigint
26 | nqkTime db_nimternalsql/nqtables.html#nqkTime NqValueKind.nqkTime
27 | nqkDate db_nimternalsql/nqtables.html#nqkDate NqValueKind.nqkDate
28 | nqkTimestamp db_nimternalsql/nqtables.html#nqkTimestamp NqValueKind.nqkTimestamp
29 | NqValueKind db_nimternalsql/nqtables.html#NqValueKind nqtables: NqValueKind
30 | NqValue db_nimternalsql/nqtables.html#NqValue nqtables: NqValue
31 | VarResolver db_nimternalsql/nqtables.html#VarResolver nqtables: VarResolver
32 | VTable db_nimternalsql/nqtables.html#VTable nqtables: VTable
33 | BaseTableRef db_nimternalsql/nqtables.html#BaseTableRef nqtables: BaseTableRef
34 | WhereTable db_nimternalsql/nqtables.html#WhereTable nqtables: WhereTable
35 | ProjectTable db_nimternalsql/nqtables.html#ProjectTable nqtables: ProjectTable
36 | ColumnAssignment db_nimternalsql/nqtables.html#ColumnAssignment nqtables: ColumnAssignment
37 | InstantRow db_nimternalsql/nqtables.html#InstantRow nqtables: InstantRow
38 | Cursor db_nimternalsql/nqtables.html#Cursor nqtables: Cursor
39 | newInstantRow db_nimternalsql/nqtables.html#newInstantRow,VTable,seq[NqValue] nqtables: newInstantRow(table: VTable; vals: seq[NqValue]): InstantRow
40 | newMatInstantRow db_nimternalsql/nqtables.html#newMatInstantRow,VTable,Record[MatValue] nqtables: newMatInstantRow(table: VTable; key: Record[MatValue]): InstantRow
41 | newWhereTable db_nimternalsql/nqtables.html#newWhereTable,VTable,Expression nqtables: newWhereTable(child: VTable; whereExp: Expression): VTable
42 | newProjectTable db_nimternalsql/nqtables.html#newProjectTable,VTable,seq[SelectElement] nqtables: newProjectTable(child: VTable; columns: seq[SelectElement]): VTable
43 | columnNo db_nimternalsql/nqtables.html#columnNo.e,VTable,string,string nqtables: columnNo(rtable: VTable; name: string; tableName: string): int
44 | isQVarExp db_nimternalsql/nqtables.html#isQVarExp,Expression nqtables: isQVarExp(exp: Expression): bool
45 | hash db_nimternalsql/nqtables.html#hash,NqValue nqtables: hash(v: NqValue): Hash
46 | toNum db_nimternalsql/nqtables.html#toNum,NqValue nqtables: toNum(v: NqValue): NqValue
47 | toNumeric db_nimternalsql/nqtables.html#toNumeric,NqValue nqtables: toNumeric(v: NqValue): NqValue
48 | toFloat db_nimternalsql/nqtables.html#toFloat,NqValue nqtables: toFloat(v: NqValue): float
49 | adjustScale db_nimternalsql/nqtables.html#adjustScale,NqValue,NqValue nqtables: adjustScale(a: var NqValue; b: var NqValue)
50 | toNqValue db_nimternalsql/nqtables.html#toNqValue,MatValue,ColumnDef nqtables: toNqValue(v: MatValue; colDef: ColumnDef): NqValue
51 | checkType db_nimternalsql/nqtables.html#checkType,ColumnDef nqtables: checkType(def: ColumnDef)
52 | setScale db_nimternalsql/nqtables.html#setScale,NqValue,Natural nqtables: setScale(v: NqValue; scale: Natural): NqValue
53 | toMatValue db_nimternalsql/nqtables.html#toMatValue,NqValue,ColumnDef nqtables: toMatValue(v: NqValue; colDef: ColumnDef): MatValue
54 | `==` db_nimternalsql/nqtables.html#==,seq,seq nqtables: `==`(r1: seq; r2: seq): bool
55 | newHashBaseTable db_nimternalsql/nqtables.html#newHashBaseTable,string,openArray[ColumnDef],seq[string] nqtables: newHashBaseTable(name: string; columns: openArray[ColumnDef]; key: seq[string]): HashBaseTable
56 | newDatabase db_nimternalsql/nqtables.html#newDatabase nqtables: newDatabase(): Database
57 | keyIndex db_nimternalsql/nqtables.html#keyIndex,BaseTable,int nqtables: keyIndex(table: BaseTable; col: int): int
58 | isKey db_nimternalsql/nqtables.html#isKey,BaseTable,int nqtables: isKey(table: BaseTable; col: int): bool
59 | getTable db_nimternalsql/nqtables.html#getTable,Database,string nqtables: getTable(db: Database; tableName: string): BaseTable
60 | eval db_nimternalsql/nqtables.html#eval.e,Expression,VarResolver,AggrResolver nqtables: eval(exp: Expression; varResolver: VarResolver; aggrResolver: AggrResolver = proc (\n exp: ScalarOpExp): NqValue = raiseDbError(exp.opName & " not supported",\n undefinedFunction)): NqValue
61 | eval db_nimternalsql/nqtables.html#eval.e,StringLit,VarResolver,AggrResolver nqtables: eval(exp: StringLit; varResolver: VarResolver; aggrResolver: AggrResolver): NqValue
62 | eval db_nimternalsql/nqtables.html#eval.e,NumericLit,VarResolver,AggrResolver nqtables: eval(exp: NumericLit; varResolver: VarResolver; aggrResolver: AggrResolver): NqValue
63 | eval db_nimternalsql/nqtables.html#eval.e,TimeLit,VarResolver,AggrResolver nqtables: eval(exp: TimeLit; varResolver: VarResolver; aggrResolver: AggrResolver): NqValue
64 | eval db_nimternalsql/nqtables.html#eval.e,TimestampLit,VarResolver,AggrResolver nqtables: eval(exp: TimestampLit; varResolver: VarResolver; aggrResolver: AggrResolver): NqValue
65 | eval db_nimternalsql/nqtables.html#eval.e,DateLit,VarResolver,AggrResolver nqtables: eval(exp: DateLit; varResolver: VarResolver; aggrResolver: AggrResolver): NqValue
66 | eval db_nimternalsql/nqtables.html#eval.e,BoolLit,VarResolver,AggrResolver nqtables: eval(exp: BoolLit; varResolver: VarResolver; aggrResolver: AggrResolver): NqValue
67 | eval db_nimternalsql/nqtables.html#eval.e,NullLit,VarResolver,AggrResolver nqtables: eval(exp: NullLit; varResolver: VarResolver; aggrResolver: AggrResolver): NqValue
68 | `+` db_nimternalsql/nqtables.html#+,NqValue,NqValue nqtables: `+`(a: NqValue; b: NqValue): NqValue
69 | newCursor db_nimternalsql/nqtables.html#newCursor.e,VTable,openArray[string] nqtables: newCursor(table: VTable; args: openArray[string]): Cursor
70 | next db_nimternalsql/nqtables.html#next.e,Cursor,InstantRow,VarResolver nqtables: next(cursor: Cursor; row: var InstantRow; varResolver: VarResolver = nil): bool
71 | instantRows db_nimternalsql/nqtables.html#instantRows.i,VTable,varargs[string],VarResolver nqtables: instantRows(rtable: VTable; args: varargs[string]; varResolver: VarResolver): InstantRow
72 | columnCount db_nimternalsql/nqtables.html#columnCount.e,VTable nqtables: columnCount(table: VTable): Natural
73 | columnCount db_nimternalsql/nqtables.html#columnCount,InstantRow nqtables: columnCount(row: InstantRow): int
74 | eval db_nimternalsql/nqtables.html#eval.e,ScalarOpExp,VarResolver,AggrResolver nqtables: eval(exp: ScalarOpExp; varResolver: VarResolver; aggrResolver: AggrResolver): NqValue
75 | getAggrs db_nimternalsql/nqtables.html#getAggrs,seq[SelectElement] nqtables: getAggrs(sels: seq[SelectElement]): seq[Expression]
76 | eval db_nimternalsql/nqtables.html#eval.e,QVarExp,VarResolver,AggrResolver nqtables: eval(exp: QVarExp; varResolver: VarResolver; aggrResolver: AggrResolver): NqValue
77 | eval db_nimternalsql/nqtables.html#eval.e,ListExp,VarResolver,AggrResolver nqtables: eval(exp: ListExp; varResolver: VarResolver; aggrResolver: AggrResolver): NqValue
78 | eval db_nimternalsql/nqtables.html#eval.e,VTable,VarResolver,AggrResolver nqtables: eval(exp: VTable; varResolver: VarResolver; aggrResolver: AggrResolver): NqValue
79 | eval db_nimternalsql/nqtables.html#eval.e,CaseExp,VarResolver,AggrResolver nqtables: eval(exp: CaseExp; varResolver: VarResolver; aggrResolver: AggrResolver): NqValue
80 | `$` db_nimternalsql/nqtables.html#$,NqValue nqtables: `$`(val: NqValue): string
81 | eval db_nimternalsql/nqtables.html#eval.e,CastExp,VarResolver,AggrResolver nqtables: eval(exp: CastExp; varResolver: VarResolver; aggrResolver: AggrResolver): NqValue
82 | columnNo db_nimternalsql/nqtables.html#columnNo.e,BaseTable,string nqtables: columnNo(rtable: BaseTable; name: string): int
83 | columnValueAt db_nimternalsql/nqtables.html#columnValueAt,InstantRow,Natural nqtables: columnValueAt(row: InstantRow; col: Natural): NqValue
84 | getColumns db_nimternalsql/nqtables.html#getColumns.e,VTable nqtables: getColumns(table: VTable): DbColumns
85 | getColumns db_nimternalsql/nqtables.html#getColumns.e,BaseTableRef nqtables: getColumns(table: BaseTableRef): DbColumns
86 | getColumns db_nimternalsql/nqtables.html#getColumns.e,WhereTable nqtables: getColumns(table: WhereTable): DbColumns
87 | columnNo db_nimternalsql/nqtables.html#columnNo,VTable,QVarExp nqtables: columnNo(table: VTable; colRef: QVarExp): int
88 | getColumns db_nimternalsql/nqtables.html#getColumns.e,ProjectTable nqtables: getColumns(table: ProjectTable): DbColumns
89 | setColumnValueAt db_nimternalsql/nqtables.html#setColumnValueAt,HashBaseTable,Record[MatValue],Natural,MatValue nqtables: setColumnValueAt(table: HashBaseTable; keyRecord: var Record[MatValue];\n col: Natural; val: MatValue)
90 | setColumnValueAt db_nimternalsql/nqtables.html#setColumnValueAt,InstantRow,Natural,NqValue nqtables: setColumnValueAt(row: var InstantRow; col: Natural; val: NqValue)
91 | instantRows db_nimternalsql/nqtables.html#instantRows.i,BaseTableRef nqtables: instantRows(tableRef: BaseTableRef): InstantRow
92 | isConst db_nimternalsql/nqtables.html#isConst,Expression nqtables: isConst(exp: Expression): bool
93 | expKeyCols db_nimternalsql/nqtables.html#expKeyCols,Expression,BaseTableRef,proc(Expression),openArray[string] nqtables: expKeyCols(exp: Expression; tableRef: BaseTableRef;\n isConstProc: proc (exp: Expression): bool; args: openArray[string]): seq[\n tuple[colNo: Natural, exp: Expression]]
94 | isKeyUpdate db_nimternalsql/nqtables.html#isKeyUpdate,BaseTable,seq[ColumnAssignment] nqtables: isKeyUpdate(table: BaseTable; assignments: seq[ColumnAssignment]): bool
95 | contains db_nimternalsql/nqtables.html#contains.e,VTable,InstantRow nqtables: contains(table: VTable; row: InstantRow): bool
96 | contains db_nimternalsql/nqtables.html#contains.e,BaseTableRef,InstantRow nqtables: contains(table: BaseTableRef; row: InstantRow): bool
97 |
--------------------------------------------------------------------------------
/htmldocs/db_nimternalsql/snapshot.idx:
--------------------------------------------------------------------------------
1 | writeError db_nimternalsql/snapshot.html#writeError snapshot: writeError
2 | readErrorMissingData db_nimternalsql/snapshot.html#readErrorMissingData snapshot: readErrorMissingData
3 | writeValue db_nimternalsql/snapshot.html#writeValue,File,MatValue snapshot: writeValue(f: File; val: MatValue)
4 | writeRecord db_nimternalsql/snapshot.html#writeRecord,File,Record snapshot: writeRecord(f: File; rec: Record)
5 | writeName db_nimternalsql/snapshot.html#writeName,File,string snapshot: writeName(f: File; name: string)
6 | writeTableDef db_nimternalsql/snapshot.html#writeTableDef,File,BaseTable snapshot: writeTableDef(f: File; table: BaseTable)
7 | save db_nimternalsql/snapshot.html#save,Database,string snapshot: save(db: Database; filename: string)
8 | readValue db_nimternalsql/snapshot.html#readValue,File snapshot: readValue(f: File): MatValue
9 | readRecord db_nimternalsql/snapshot.html#readRecord,File snapshot: readRecord(f: File): Record[MatValue]
10 | readName db_nimternalsql/snapshot.html#readName,File snapshot: readName(f: File): string
11 | readTableDef db_nimternalsql/snapshot.html#readTableDef,File,BaseTable snapshot: readTableDef(f: File; table: BaseTable)
12 | restore db_nimternalsql/snapshot.html#restore,Database,string snapshot: restore(db: Database; filename: string)
13 |
--------------------------------------------------------------------------------
/htmldocs/db_nimternalsql/sorter.html:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 | src/db_nimternalsql/sorter
21 |
22 |
23 |
24 |
25 |
67 |
68 |
69 |
70 |
71 |
72 |
src/db_nimternalsql/sorter
73 |
74 |
75 |
76 |
80 |
Dark Mode
81 |
82 |
83 |
84 | -
85 | Index
86 |
87 |
88 |
89 |
90 | Search:
92 |
93 |
94 | Group by:
95 |
99 |
100 |
101 | -
102 | Imports
103 |
106 |
107 | -
108 | Procs
109 |
124 |
125 | -
126 | Methods
127 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
150 |
151 |
152 |
153 |
154 |
proc cmp(v1: NqValue; v2: NqValue): int {....raises: [SqlError], tags: [].}
155 |
-
156 |
157 |
158 |
159 |
160 |
161 |
162 |
func newSortedTable(child: VTable; order: seq[tuple[col: Natural, asc: bool]];
163 | removeDuplicates: bool = false): VTable {....raises: [],
164 | tags: [].}
165 |
-
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
method getColumns(table: SortedTable): DbColumns {....raises: [SqlError], tags: [].}
178 |
-
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 | Made with Nim. Generated: 2022-04-30 16:41:59 UTC
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
--------------------------------------------------------------------------------
/htmldocs/db_nimternalsql/sorter.idx:
--------------------------------------------------------------------------------
1 | newSortedTable db_nimternalsql/sorter.html#newSortedTable,VTable,seq[tuple[Natural,bool]],bool sorter: newSortedTable(child: VTable; order: seq[tuple[col: Natural, asc: bool]];\n removeDuplicates: bool = false): VTable
2 | cmp db_nimternalsql/sorter.html#cmp,NqValue,NqValue sorter: cmp(v1: NqValue; v2: NqValue): int
3 | getColumns db_nimternalsql/sorter.html#getColumns.e,SortedTable sorter: getColumns(table: SortedTable): DbColumns
4 |
--------------------------------------------------------------------------------
/htmldocs/db_nimternalsql/sqlparser.idx:
--------------------------------------------------------------------------------
1 | trkSimpleTableRef db_nimternalsql/sqlparser.html#trkSimpleTableRef SqlTableRefKind.trkSimpleTableRef
2 | trkRelOp db_nimternalsql/sqlparser.html#trkRelOp SqlTableRefKind.trkRelOp
3 | SqlTableRefKind db_nimternalsql/sqlparser.html#SqlTableRefKind sqlparser: SqlTableRefKind
4 | SqlTableRef db_nimternalsql/sqlparser.html#SqlTableRef sqlparser: SqlTableRef
5 | SqlStatement db_nimternalsql/sqlparser.html#SqlStatement sqlparser: SqlStatement
6 | SqlSelect db_nimternalsql/sqlparser.html#SqlSelect sqlparser: SqlSelect
7 | SqlCreateTable db_nimternalsql/sqlparser.html#SqlCreateTable sqlparser: SqlCreateTable
8 | SqlDropTable db_nimternalsql/sqlparser.html#SqlDropTable sqlparser: SqlDropTable
9 | ikValues db_nimternalsql/sqlparser.html#ikValues SqlInsertKind.ikValues
10 | ikSelect db_nimternalsql/sqlparser.html#ikSelect SqlInsertKind.ikSelect
11 | SqlInsertKind db_nimternalsql/sqlparser.html#SqlInsertKind sqlparser: SqlInsertKind
12 | SqlInsert db_nimternalsql/sqlparser.html#SqlInsert sqlparser: SqlInsert
13 | UpdateAssignment db_nimternalsql/sqlparser.html#UpdateAssignment sqlparser: UpdateAssignment
14 | SqlUpdate db_nimternalsql/sqlparser.html#SqlUpdate sqlparser: SqlUpdate
15 | SqlDelete db_nimternalsql/sqlparser.html#SqlDelete sqlparser: SqlDelete
16 | SqlCommit db_nimternalsql/sqlparser.html#SqlCommit sqlparser: SqlCommit
17 | SqlRollback db_nimternalsql/sqlparser.html#SqlRollback sqlparser: SqlRollback
18 | OrderByElement db_nimternalsql/sqlparser.html#OrderByElement sqlparser: OrderByElement
19 | tekSelect db_nimternalsql/sqlparser.html#tekSelect TableExpKind.tekSelect
20 | tekUnion db_nimternalsql/sqlparser.html#tekUnion TableExpKind.tekUnion
21 | tekExcept db_nimternalsql/sqlparser.html#tekExcept TableExpKind.tekExcept
22 | tekIntersect db_nimternalsql/sqlparser.html#tekIntersect TableExpKind.tekIntersect
23 | TableExpKind db_nimternalsql/sqlparser.html#TableExpKind sqlparser: TableExpKind
24 | TableExp db_nimternalsql/sqlparser.html#TableExp sqlparser: TableExp
25 | NamedTableExp db_nimternalsql/sqlparser.html#NamedTableExp sqlparser: NamedTableExp
26 | QueryExp db_nimternalsql/sqlparser.html#QueryExp sqlparser: QueryExp
27 | parseStatement db_nimternalsql/sqlparser.html#parseStatement,Reader sqlparser: parseStatement(reader: Reader): SqlStatement
28 |
--------------------------------------------------------------------------------
/htmldocs/db_nimternalsql/sqlscanner.idx:
--------------------------------------------------------------------------------
1 | tokAll db_nimternalsql/sqlscanner.html#tokAll TokenKind.tokAll
2 | tokAnd db_nimternalsql/sqlscanner.html#tokAnd TokenKind.tokAnd
3 | tokAny db_nimternalsql/sqlscanner.html#tokAny TokenKind.tokAny
4 | tokAs db_nimternalsql/sqlscanner.html#tokAs TokenKind.tokAs
5 | tokAsc db_nimternalsql/sqlscanner.html#tokAsc TokenKind.tokAsc
6 | tokAutoincrement db_nimternalsql/sqlscanner.html#tokAutoincrement TokenKind.tokAutoincrement
7 | tokBy db_nimternalsql/sqlscanner.html#tokBy TokenKind.tokBy
8 | tokChar db_nimternalsql/sqlscanner.html#tokChar TokenKind.tokChar
9 | tokDefault db_nimternalsql/sqlscanner.html#tokDefault TokenKind.tokDefault
10 | tokDrop db_nimternalsql/sqlscanner.html#tokDrop TokenKind.tokDrop
11 | tokVarchar db_nimternalsql/sqlscanner.html#tokVarchar TokenKind.tokVarchar
12 | tokNumeric db_nimternalsql/sqlscanner.html#tokNumeric TokenKind.tokNumeric
13 | tokCase db_nimternalsql/sqlscanner.html#tokCase TokenKind.tokCase
14 | tokCast db_nimternalsql/sqlscanner.html#tokCast TokenKind.tokCast
15 | tokWhen db_nimternalsql/sqlscanner.html#tokWhen TokenKind.tokWhen
16 | tokThen db_nimternalsql/sqlscanner.html#tokThen TokenKind.tokThen
17 | tokElse db_nimternalsql/sqlscanner.html#tokElse TokenKind.tokElse
18 | tokEnd db_nimternalsql/sqlscanner.html#tokEnd TokenKind.tokEnd
19 | tokCommit db_nimternalsql/sqlscanner.html#tokCommit TokenKind.tokCommit
20 | tokRollback db_nimternalsql/sqlscanner.html#tokRollback TokenKind.tokRollback
21 | tokCreate db_nimternalsql/sqlscanner.html#tokCreate TokenKind.tokCreate
22 | tokCross db_nimternalsql/sqlscanner.html#tokCross TokenKind.tokCross
23 | tokCount db_nimternalsql/sqlscanner.html#tokCount TokenKind.tokCount
24 | tokDecimal db_nimternalsql/sqlscanner.html#tokDecimal TokenKind.tokDecimal
25 | tokDelete db_nimternalsql/sqlscanner.html#tokDelete TokenKind.tokDelete
26 | tokDesc db_nimternalsql/sqlscanner.html#tokDesc TokenKind.tokDesc
27 | tokDistinct db_nimternalsql/sqlscanner.html#tokDistinct TokenKind.tokDistinct
28 | tokDouble db_nimternalsql/sqlscanner.html#tokDouble TokenKind.tokDouble
29 | tokTime db_nimternalsql/sqlscanner.html#tokTime TokenKind.tokTime
30 | tokTimestamp db_nimternalsql/sqlscanner.html#tokTimestamp TokenKind.tokTimestamp
31 | tokTrim db_nimternalsql/sqlscanner.html#tokTrim TokenKind.tokTrim
32 | tokLeading db_nimternalsql/sqlscanner.html#tokLeading TokenKind.tokLeading
33 | tokTrailing db_nimternalsql/sqlscanner.html#tokTrailing TokenKind.tokTrailing
34 | tokBoth db_nimternalsql/sqlscanner.html#tokBoth TokenKind.tokBoth
35 | tokPrecision db_nimternalsql/sqlscanner.html#tokPrecision TokenKind.tokPrecision
36 | tokExists db_nimternalsql/sqlscanner.html#tokExists TokenKind.tokExists
37 | tokFrom db_nimternalsql/sqlscanner.html#tokFrom TokenKind.tokFrom
38 | tokGroup db_nimternalsql/sqlscanner.html#tokGroup TokenKind.tokGroup
39 | tokIf db_nimternalsql/sqlscanner.html#tokIf TokenKind.tokIf
40 | tokInsert db_nimternalsql/sqlscanner.html#tokInsert TokenKind.tokInsert
41 | tokUpdate db_nimternalsql/sqlscanner.html#tokUpdate TokenKind.tokUpdate
42 | tokSet db_nimternalsql/sqlscanner.html#tokSet TokenKind.tokSet
43 | tokIn db_nimternalsql/sqlscanner.html#tokIn TokenKind.tokIn
44 | tokIs db_nimternalsql/sqlscanner.html#tokIs TokenKind.tokIs
45 | tokInto db_nimternalsql/sqlscanner.html#tokInto TokenKind.tokInto
46 | tokJoin db_nimternalsql/sqlscanner.html#tokJoin TokenKind.tokJoin
47 | tokKey db_nimternalsql/sqlscanner.html#tokKey TokenKind.tokKey
48 | tokLike db_nimternalsql/sqlscanner.html#tokLike TokenKind.tokLike
49 | tokNot db_nimternalsql/sqlscanner.html#tokNot TokenKind.tokNot
50 | tokOn db_nimternalsql/sqlscanner.html#tokOn TokenKind.tokOn
51 | tokOr db_nimternalsql/sqlscanner.html#tokOr TokenKind.tokOr
52 | tokOrder db_nimternalsql/sqlscanner.html#tokOrder TokenKind.tokOrder
53 | tokPrimary db_nimternalsql/sqlscanner.html#tokPrimary TokenKind.tokPrimary
54 | tokSelect db_nimternalsql/sqlscanner.html#tokSelect TokenKind.tokSelect
55 | tokTable db_nimternalsql/sqlscanner.html#tokTable TokenKind.tokTable
56 | tokUnion db_nimternalsql/sqlscanner.html#tokUnion TokenKind.tokUnion
57 | tokIntersect db_nimternalsql/sqlscanner.html#tokIntersect TokenKind.tokIntersect
58 | tokExcept db_nimternalsql/sqlscanner.html#tokExcept TokenKind.tokExcept
59 | tokValues db_nimternalsql/sqlscanner.html#tokValues TokenKind.tokValues
60 | tokWhere db_nimternalsql/sqlscanner.html#tokWhere TokenKind.tokWhere
61 | tokWith db_nimternalsql/sqlscanner.html#tokWith TokenKind.tokWith
62 | tokLeft db_nimternalsql/sqlscanner.html#tokLeft TokenKind.tokLeft
63 | tokInner db_nimternalsql/sqlscanner.html#tokInner TokenKind.tokInner
64 | tokOuter db_nimternalsql/sqlscanner.html#tokOuter TokenKind.tokOuter
65 | tokPosition db_nimternalsql/sqlscanner.html#tokPosition TokenKind.tokPosition
66 | tokAsterisk db_nimternalsql/sqlscanner.html#tokAsterisk TokenKind.tokAsterisk
67 | tokDiv db_nimternalsql/sqlscanner.html#tokDiv TokenKind.tokDiv
68 | tokPlus db_nimternalsql/sqlscanner.html#tokPlus TokenKind.tokPlus
69 | tokNull db_nimternalsql/sqlscanner.html#tokNull TokenKind.tokNull
70 | tokMinus db_nimternalsql/sqlscanner.html#tokMinus TokenKind.tokMinus
71 | tokRightParen db_nimternalsql/sqlscanner.html#tokRightParen TokenKind.tokRightParen
72 | tokLeftParen db_nimternalsql/sqlscanner.html#tokLeftParen TokenKind.tokLeftParen
73 | tokComma db_nimternalsql/sqlscanner.html#tokComma TokenKind.tokComma
74 | tokDot db_nimternalsql/sqlscanner.html#tokDot TokenKind.tokDot
75 | tokEq db_nimternalsql/sqlscanner.html#tokEq TokenKind.tokEq
76 | tokNeq db_nimternalsql/sqlscanner.html#tokNeq TokenKind.tokNeq
77 | tokLt db_nimternalsql/sqlscanner.html#tokLt TokenKind.tokLt
78 | tokLe db_nimternalsql/sqlscanner.html#tokLe TokenKind.tokLe
79 | tokGt db_nimternalsql/sqlscanner.html#tokGt TokenKind.tokGt
80 | tokGe db_nimternalsql/sqlscanner.html#tokGe TokenKind.tokGe
81 | tokConcat db_nimternalsql/sqlscanner.html#tokConcat TokenKind.tokConcat
82 | tokIdentifier db_nimternalsql/sqlscanner.html#tokIdentifier TokenKind.tokIdentifier
83 | tokString db_nimternalsql/sqlscanner.html#tokString TokenKind.tokString
84 | tokInt db_nimternalsql/sqlscanner.html#tokInt TokenKind.tokInt
85 | tokRat db_nimternalsql/sqlscanner.html#tokRat TokenKind.tokRat
86 | tokTrue db_nimternalsql/sqlscanner.html#tokTrue TokenKind.tokTrue
87 | tokFalse db_nimternalsql/sqlscanner.html#tokFalse TokenKind.tokFalse
88 | tokPlaceholder db_nimternalsql/sqlscanner.html#tokPlaceholder TokenKind.tokPlaceholder
89 | tokNumPlaceholder db_nimternalsql/sqlscanner.html#tokNumPlaceholder TokenKind.tokNumPlaceholder
90 | tokEndOfInput db_nimternalsql/sqlscanner.html#tokEndOfInput TokenKind.tokEndOfInput
91 | TokenKind db_nimternalsql/sqlscanner.html#TokenKind sqlscanner: TokenKind
92 | Token db_nimternalsql/sqlscanner.html#Token sqlscanner: Token
93 | Reader db_nimternalsql/sqlscanner.html#Reader sqlscanner: Reader
94 | FileReader db_nimternalsql/sqlscanner.html#FileReader sqlscanner: FileReader
95 | StringReader db_nimternalsql/sqlscanner.html#StringReader sqlscanner: StringReader
96 | Scanner db_nimternalsql/sqlscanner.html#Scanner sqlscanner: Scanner
97 | newStringReader db_nimternalsql/sqlscanner.html#newStringReader,string sqlscanner: newStringReader(s: string): StringReader
98 | newFileReader db_nimternalsql/sqlscanner.html#newFileReader,File sqlscanner: newFileReader(f: File): FileReader
99 | newScanner db_nimternalsql/sqlscanner.html#newScanner,Reader sqlscanner: newScanner(r: Reader): Scanner
100 | currentToken db_nimternalsql/sqlscanner.html#currentToken,Scanner sqlscanner: currentToken(s: Scanner): Token
101 | nextToken db_nimternalsql/sqlscanner.html#nextToken,Scanner sqlscanner: nextToken(s: Scanner): Token
102 | isValidTime db_nimternalsql/sqlscanner.html#isValidTime,string sqlscanner: isValidTime(str: string): bool
103 | isValidTimestamp db_nimternalsql/sqlscanner.html#isValidTimestamp,string sqlscanner: isValidTimestamp(str: string): bool
104 | isValidDate db_nimternalsql/sqlscanner.html#isValidDate,string sqlscanner: isValidDate(str: string): bool
105 |
--------------------------------------------------------------------------------
/htmldocs/db_nimternalsql/tx.idx:
--------------------------------------------------------------------------------
1 | Tx db_nimternalsql/tx.html#Tx tx: Tx
2 | newTx db_nimternalsql/tx.html#newTx,string,File tx: newTx(logPath: string; file: File): Tx
3 | createBaseTable db_nimternalsql/tx.html#createBaseTable,Tx,Database,string,openArray[ColumnDef],seq[string] tx: createBaseTable(tx: Tx; db: Database; name: string;\n columns: openArray[ColumnDef]; key: seq[string]): BaseTable
4 | dropBaseTable db_nimternalsql/tx.html#dropBaseTable,Tx,Database,string tx: dropBaseTable(tx: Tx; db: Database; name: string)
5 | insert db_nimternalsql/tx.html#insert,Tx,BaseTable,seq[NqValue] tx: insert(tx: Tx; table: BaseTable; values: seq[NqValue])
6 | delete db_nimternalsql/tx.html#delete,Tx,BaseTable,Expression,openArray[string] tx: delete(tx: Tx; table: BaseTable; whereExp: Expression; args: openArray[string]): int64
7 | update db_nimternalsql/tx.html#update,Tx,BaseTable,seq[ColumnAssignment],Expression,openArray[string] tx: update(tx: Tx; table: BaseTable; assignments: seq[ColumnAssignment];\n whereExp: Expression; args: openArray[string]): int64
8 | commit db_nimternalsql/tx.html#commit,Tx tx: commit(tx: Tx)
9 | rollback db_nimternalsql/tx.html#rollback,Tx,Database tx: rollback(tx: Tx; db: Database)
10 | openLog db_nimternalsql/tx.html#openLog,string,Database tx: openLog(logdir: string; db: Database): File
11 | closeLog db_nimternalsql/tx.html#closeLog,Tx tx: closeLog(tx: Tx)
12 | logIsActive db_nimternalsql/tx.html#logIsActive,Tx tx: logIsActive(tx: Tx): bool
13 | truncateLog db_nimternalsql/tx.html#truncateLog,Tx tx: truncateLog(tx: Tx)
14 |
--------------------------------------------------------------------------------
/htmldocs/db_nimternalsql/union.html:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 | src/db_nimternalsql/union
21 |
22 |
23 |
24 |
25 |
67 |
68 |
69 |
70 |
71 |
72 |
src/db_nimternalsql/union
73 |
74 |
75 |
76 |
80 |
Dark Mode
81 |
82 |
83 |
84 | -
85 | Index
86 |
87 |
88 |
89 |
90 | Search:
92 |
93 |
94 | Group by:
95 |
99 |
100 |
101 | -
102 | Imports
103 |
106 |
107 | -
108 | Procs
109 |
117 |
118 | -
119 | Methods
120 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
148 |
149 |
150 |
151 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
method columnNo(table: UnionTable; name: string; tableName: string): int {.
167 | ...raises: [SqlError], tags: [].}
168 |
-
169 |
170 |
171 |
172 |
173 |
174 |
175 |
method getColumns(table: UnionTable): DbColumns {....raises: [SqlError], tags: [].}
176 |
-
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 | Made with Nim. Generated: 2022-04-30 16:41:59 UTC
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
--------------------------------------------------------------------------------
/htmldocs/db_nimternalsql/union.idx:
--------------------------------------------------------------------------------
1 | newUnionTable db_nimternalsql/union.html#newUnionTable,VTable,VTable union: newUnionTable(lchild: VTable; rchild: VTable): VTable
2 | columnNo db_nimternalsql/union.html#columnNo.e,UnionTable,string,string union: columnNo(table: UnionTable; name: string; tableName: string): int
3 | getColumns db_nimternalsql/union.html#getColumns.e,UnionTable union: getColumns(table: UnionTable): DbColumns
4 |
--------------------------------------------------------------------------------
/src/db_nimternalsql/duprem.nim:
--------------------------------------------------------------------------------
1 | import nqtables
2 | import db_common
3 | import sets
4 |
5 | type
6 | DupRemTable* = ref object of VTable
7 | child*: VTable
8 | DupRemTableCursor = ref object of Cursor
9 | table: DupRemTable
10 | iter: iterator(cursor: DupRemTableCursor): InstantRow
11 | rows: HashSet[seq[NqValue]]
12 |
13 | func newDupRemTable*(child: VTable): VTable =
14 | result = DupRemTable(child: child)
15 |
16 | method columnCount(table: DupRemTable): Natural =
17 | result = columnCount(table.child)
18 |
19 | method columnNo(table: DupRemTable, name: string, tableName: string): int =
20 | return table.child.columnNo(name, tableName)
21 |
22 | iterator instantRows(cursor: DupRemTableCursor): InstantRow {.closure.} =
23 | for r in cursor.rows.items:
24 | yield newInstantRow(cursor.table.child, r)
25 |
26 | method newCursor(table: DupRemTable, args: openArray[string]): Cursor =
27 | let childCursor = newCursor(table.child, args)
28 | let columnCount = columnCount(table)
29 | var row: InstantRow
30 | var rows: seq[seq[NqValue]]
31 | while childCursor.next(row):
32 | var destRow: seq[NqValue]
33 | for i in 0.. 0
20 | rightMatch: bool # true if a row from the right was returned
21 | # which matched the current row of the left table
22 |
23 | func newJoinTable*(lchild: VTable, rchild: VTable,
24 | leftOuter: bool = false,
25 | exp: Expression = nil): VTable =
26 | result = JoinTable(children: [lchild, rchild],
27 | leftOuter: leftOuter, exp: exp)
28 |
29 | method columnCount(table: JoinTable): Natural =
30 | result = columnCount(table.children[0]) + columnCount(table.children[1])
31 |
32 | method columnNo(table: JoinTable, name: string, tableName: string): int =
33 | let col1 = table.children[0].columnNo(name, tableName)
34 | let col2 = table.children[1].columnNo(name, tableName);
35 |
36 | if col1 == -1 and col2 == -1:
37 | return -1;
38 | if col1 != -1 and col2 != -1:
39 | raiseDbError("column reference \"" & (if tableName != "": tableName & "." else: "") &
40 | name & "\" is ambiguous", columnRefAmbiguous)
41 | result = if col1 != -1: col1 else: columnCount(table.children[0]) + col2
42 |
43 | func join(row1: InstantRow, row2: InstantRow, table: VTable): InstantRow =
44 | var vals = seq[NqValue](@[])
45 | for i in 0.. 0:
140 | return nextByKey(cursor, row, varResolver)
141 | var rrow: InstantRow
142 | while true:
143 | if cursor.advanceLeft:
144 | cursor.advanceLeft = false
145 | if not cursor.childCursors[0].next(cursor.row, varResolver):
146 | return false
147 | cursor.rightMatch = false
148 | if cursor.childCursors[1].next(rrow):
149 | row = join(cursor.row, rrow, cursor.table)
150 | if evalJoinCond(cursor, row):
151 | cursor.rightMatch = true
152 | return true
153 | else:
154 | continue
155 | if cursor.table.leftOuter and not cursor.rightMatch:
156 | row = join(cursor.row,
157 | newInstantRow(cursor.table.children[1],
158 | repeat(NqValue(kind: nqkNull),
159 | cursor.table.children[1].columnCount)),
160 | cursor.table)
161 | cursor.advanceLeft = true
162 | return true
163 | if not cursor.childCursors[0].next(cursor.row, varResolver):
164 | return false
165 | cursor.childCursors[1] = newCursor(cursor.table.children[1], cursor.args)
166 | cursor.rightMatch = false
167 | if cursor.childCursors[1].next(rrow, varResolver):
168 | row = join(cursor.row, rrow, cursor.table)
169 | if evalJoinCond(cursor, row):
170 | cursor.rightMatch = true
171 | return true
172 | result = false
173 |
174 | method getColumns*(table: JoinTable): DbColumns =
175 | for i in 0..1:
176 | var cols = table.children[i].getColumns()
177 | for j in 0..= pattern.len:
13 | return false
14 | case pattern[patIdx]:
15 | of matchSingle:
16 | idx += 1
17 | patIdx += 1
18 | of matchMany:
19 | for i in idx..s.len:
20 | if matchesLike(s, pattern[patIdx + 1..pattern.high], i):
21 | return true
22 | return false
23 | else:
24 | if s[idx] != pattern[patIdx]:
25 | return false
26 | idx += 1
27 | patIdx += 1
28 | for c in pattern[patIdx..pattern.high]:
29 | if c != matchMany:
30 | return false
31 | result = true
32 |
33 | func matchesLike*(s: string, pattern: string): bool =
34 | result = matchesLike(toRunes(s), toRunes(pattern))
35 |
--------------------------------------------------------------------------------
/src/db_nimternalsql/nqcommon.nim:
--------------------------------------------------------------------------------
1 | #
2 | # Copyright (c) 2020, 2022 Rene Hartmann
3 | #
4 | # See the file LICENSE for details about the copyright.
5 | #
6 | import db_common
7 |
8 | const
9 | defaultDumpName* = "dump.ndb"
10 |
11 | tooManyRowsReturnedBySubquery* = "21000"
12 | stringTooLong* = "22001"
13 | valueOutOfRange* = "22003"
14 | invalidDatetimeValue* = "22007"
15 | invalidParameterValue* = "22023"
16 | columnNotNullable* = "23502"
17 | uniqueConstraintViolation* = "23505"
18 | syntaxError* = "42601"
19 | columnRefAmbiguous* = "42702"
20 | undefinedColumnName* = "42703"
21 | undefinedObjectName* = "42704"
22 | invalidGrouping* = "42803"
23 | typeMismatch* = "42804"
24 | undefinedFunction* = "42883"
25 | tableExists* = "42N01"
26 | generalError* = "HY000"
27 | internalError* = "N0000"
28 | fileIoError* = "N0001"
29 | fileNotValid* = "N0002"
30 | notADirectory* = "N0003"
31 | restoreNotSupported* = "NS004"
32 |
33 | type
34 | ColumnDef* = object of RootObj
35 | name*: string
36 | typ*: string
37 | size*: Natural
38 | precision*: Natural
39 | scale*: Natural
40 | notNull*: bool
41 | defaultValue*: Expression
42 | primaryKey*: bool # unused in BaseTable
43 | autoincrement*: bool
44 | TypeDef* = object
45 | typ*: string
46 | size*: Natural
47 | precision*: Natural
48 | scale*: Natural
49 |
50 | Expression* = ref object of RootObj
51 | ScalarLit* = ref object of Expression
52 | val*: string
53 | StringLit* {.final.} = ref object of ScalarLit
54 | NumericLit* {.final.} = ref object of ScalarLit
55 | BoolLit* {.final.} = ref object of ScalarLit
56 | TimeLit* {.final.} = ref object of ScalarLit
57 | TimestampLit* {.final.} = ref object of ScalarLit
58 | DateLit* {.final.} = ref object of ScalarLit
59 | NullLit* {.final.} = ref object of Expression
60 | ScalarOpExp* {.acyclic.} = ref object of Expression
61 | opName*: string
62 | args*: seq[Expression]
63 | QVarExp* = ref object of Expression
64 | name*: string
65 | tableName*: string
66 | ListExp* {.acyclic.} = ref object of Expression
67 | exps*: seq[Expression]
68 | CaseExp* {.acyclic.} = ref object of Expression
69 | exp*: Expression
70 | whens*: seq[tuple[cond: Expression, exp: Expression]]
71 | elseExp*: Expression
72 | CastExp* {.acyclic.} = ref object of Expression
73 | exp*: Expression
74 | typeDef*: TypeDef
75 | SelectElement* {.acyclic.} = object
76 | colName*: string
77 | exp*: Expression
78 |
79 | SqlError* = object of DbError
80 | sqlState*: string
81 |
82 | proc raiseDbError*(msg: string, sqlstate: string) {.noreturn.} =
83 | var
84 | e: ref SqlError
85 | new(e)
86 | e.msg = msg
87 | e.sqlState = sqlstate
88 | raise e
89 |
90 | func newStringLit*(v: string): Expression =
91 | result = StringLit(val: v)
92 |
93 | func newNumericLit*(v: string): Expression =
94 | result = NumericLit(val: v)
95 |
96 | func newTimeLit*(v: string): Expression =
97 | result = TimeLit(val: v)
98 |
99 | func newTimestampLit*(v: string): Expression =
100 | result = TimestampLit(val: v)
101 |
102 | func newDateLit*(v: string): Expression =
103 | result = DateLit(val: v)
104 |
105 | func newBoolLit*(v: bool): Expression =
106 | result = BoolLit(val: if v: "TRUE" else: "FALSE")
107 |
108 | func newNullLit*(): Expression =
109 | result = NullLit()
110 |
111 | func newListExp*(v: seq[Expression]): Expression =
112 | result = ListExp(exps: v)
113 |
114 | func newScalarOpExp*(name: string, args: varargs[Expression]): Expression =
115 | result = ScalarOpExp(opName: name, args: @args)
116 |
117 | func newQVarExp*(name: string, tableName: string = ""): QVarExp =
118 | result = QVarExp(name: name, tableName: tableName)
119 |
120 | func newCaseExp*(exp: Expression,
121 | whens: seq[tuple[cond: Expression, exp: Expression]],
122 | elseExp: Expression): Expression =
123 | result = CaseExp(exp: exp, whens: whens, elseExp: elseExp)
124 |
125 | func newCastExp*(exp: Expression, typ: TypeDef): Expression =
126 | result = CastExp(exp: exp, typedef: typ)
127 |
128 | method `$`*(exp: Expression): string {.base.} = nil
129 |
130 | method `$`(exp: ScalarLit): string =
131 | result = exp.val
132 |
133 | method `$`(exp: ScalarOpExp): string =
134 | result = exp.opName & '('
135 | for i in 0..= cursor.rows.len:
69 | return false
70 | row = newInstantRow(cursor.table, cursor.rows[cursor.nextRow])
71 | cursor.nextRow += 1
72 | if not cursor.table.removeDuplicates or
73 | cursor.nextRow < 2 or cursor.rows[cursor.nextRow - 1] != cursor.rows[cursor.nextRow - 2]:
74 | return true
75 |
76 | method getColumns*(table: SortedTable): DbColumns =
77 | result = table.child.getColumns()
78 |
--------------------------------------------------------------------------------
/src/db_nimternalsql/sqlscanner.nim:
--------------------------------------------------------------------------------
1 | #
2 | # Copyright (c) 2020, 2022 Rene Hartmann
3 | #
4 | # See the file LICENSE for details about the copyright.
5 | #
6 | import strutils
7 | import nqcommon
8 | import times
9 |
10 | type
11 | TokenKind* = enum
12 | tokAll, tokAnd, tokAny, tokAs, tokAsc, tokAutoincrement,
13 | tokBy, tokChar, tokDefault,
14 | tokDrop, tokVarchar, tokNumeric, tokCase, tokCast, tokWhen,
15 | tokThen, tokElse, tokEnd, tokCommit, tokRollback, tokCreate,
16 | tokCross, tokCount, tokDecimal,
17 | tokDelete, tokDesc, tokDistinct, tokDouble, tokTime, tokTimestamp,
18 | tokTrim, tokLeading, tokTrailing, tokBoth,
19 | tokPrecision, tokExists,
20 | tokFrom, tokGroup, tokIf, tokInsert, tokUpdate, tokSet, tokIn, tokIs,
21 | tokInto, tokJoin, tokKey, tokLike, tokNot, tokOn, tokOr, tokOrder,
22 | tokPrimary, tokSelect, tokTable, tokUnion, tokIntersect, tokExcept,
23 | tokValues, tokWhere, tokWith,
24 | tokLeft, tokInner, tokOuter, tokPosition,
25 | tokAsterisk, tokDiv, tokPlus, tokNull, tokMinus, tokRightParen,
26 | tokLeftParen, tokComma, tokDot, tokEq, tokNeq, tokLt, tokLe, tokGt, tokGe,
27 | tokConcat, tokIdentifier, tokString, tokInt, tokRat, tokTrue, tokFalse,
28 | tokPlaceholder, tokNumPlaceholder, tokEndOfInput
29 | Token* = object
30 | case kind*: TokenKind
31 | of tokIdentifier:
32 | identifier*: string
33 | of tokString, tokInt, tokRat:
34 | value*: string
35 | else: discard
36 |
37 | Reader* = ref object of RootObj
38 | FileReader* = ref object of Reader
39 | file: File
40 | nextChar: char
41 | eof: bool
42 | StringReader* = ref object of Reader
43 | buf: string
44 | current: int
45 |
46 | Scanner* = ref object
47 | reader: Reader
48 | current: Token
49 |
50 | method read(reader: Reader): char {.base.} = nil
51 | method peek(reader: Reader): char {.base.} = nil
52 |
53 | proc newStringReader*(s: string): StringReader =
54 | result = StringReader(buf: s, current: 0)
55 |
56 | method read(reader: StringReader): char =
57 | if reader.current >= reader.buf.len():
58 | raise newException(EOFError, "end of input string")
59 | result = reader.buf[reader.current]
60 | reader.current += 1
61 |
62 | method peek(reader: StringReader): char =
63 | if reader.current < reader.buf.len():
64 | result = reader.buf[reader.current]
65 | else:
66 | result = '\0'
67 |
68 | proc newFileReader*(f: File): FileReader =
69 | result = FileReader(file: f, eof: false)
70 | try:
71 | result.nextChar = f.readChar()
72 | except EOFError:
73 | result.eof = true
74 |
75 | method read(reader: FileReader): char =
76 | if reader.eof:
77 | raise newException(EOFError, "end of input file")
78 | result = reader.nextChar
79 | try:
80 | reader.nextChar = reader.file.readChar()
81 | except EOFError:
82 | reader.eof = true
83 |
84 | method peek(reader: FileReader): char =
85 | if reader.eof:
86 | result = '\0'
87 | else:
88 | result = reader.nextChar
89 |
90 | proc newScanner*(r: Reader): Scanner =
91 | result = Scanner(reader: r)
92 |
93 | proc toToken(s: string): Token =
94 | case toUpperAscii(s):
95 | of "ALL":
96 | return Token(kind: tokAll)
97 | of "AND":
98 | return Token(kind: tokAnd)
99 | of "ANY":
100 | return Token(kind: tokAny)
101 | of "AS":
102 | return Token(kind: tokAs)
103 | of "ASC":
104 | return Token(kind: tokAsc)
105 | of "AUTOINCREMENT", "AUTO_INCREMENT":
106 | return Token(kind: tokAutoincrement)
107 | of "BOTH":
108 | return Token(kind: tokBoth)
109 | of "BY":
110 | return Token(kind: tokBy)
111 | of "CASE":
112 | return Token(kind: tokCase)
113 | of "CAST":
114 | return Token(kind: tokCast)
115 | of "COMMIT":
116 | return Token(kind: tokCommit)
117 | of "COUNT":
118 | return Token(kind: tokCount)
119 | of "CHARACTER", "CHAR":
120 | return Token(kind: tokChar)
121 | of "CREATE":
122 | return Token(kind: tokCreate)
123 | of "CROSS":
124 | return Token(kind: tokCross)
125 | of "DEC", "DECIMAL":
126 | return Token(kind: tokDecimal)
127 | of "DELETE":
128 | return Token(kind: tokDelete)
129 | of "DEFAULT":
130 | return Token(kind: tokDefault)
131 | of "DESC":
132 | return Token(kind: tokDesc)
133 | of "DISTINCT":
134 | return Token(kind: tokDistinct)
135 | of "DOUBLE":
136 | return Token(kind: tokDouble)
137 | of "DROP":
138 | return Token(kind: tokDrop)
139 | of "ELSE":
140 | return Token(kind: tokElse)
141 | of "END":
142 | return Token(kind: tokEnd)
143 | of "EXCEPT":
144 | return Token(kind: tokExcept)
145 | of "EXISTS":
146 | return Token(kind: tokExists)
147 | of "FALSE":
148 | return Token(kind: tokFalse)
149 | of "GROUP":
150 | return Token(kind: tokGroup)
151 | of "TIME":
152 | return Token(kind: tokTime)
153 | of "TIMESTAMP":
154 | return Token(kind: tokTimestamp)
155 | of "THEN":
156 | return Token(kind: tokThen)
157 | of "TRUE":
158 | return Token(kind: tokTrue)
159 | of "FROM":
160 | return Token(kind: tokFrom)
161 | of "IF":
162 | return Token(kind: tokIf)
163 | of "INNER":
164 | return Token(kind: tokInner)
165 | of "INSERT":
166 | return Token(kind: tokInsert)
167 | of "IN":
168 | return Token(kind: tokIn)
169 | of "INTERSECT":
170 | return Token(kind: tokIntersect)
171 | of "INTO":
172 | return Token(kind: tokInto)
173 | of "IS":
174 | return Token(kind: tokIs)
175 | of "JOIN":
176 | return Token(kind: tokJoin)
177 | of "KEY":
178 | return Token(kind: tokKey)
179 | of "LEADING":
180 | return Token(kind: tokLeading)
181 | of "LEFT":
182 | return Token(kind: tokLeft)
183 | of "LIKE":
184 | return Token(kind: tokLike)
185 | of "NOT":
186 | return Token(kind: tokNot)
187 | of "NULL":
188 | return Token(kind: tokNull)
189 | of "NUMERIC":
190 | return Token(kind: tokNumeric)
191 | of "ON":
192 | return Token(kind: tokOn)
193 | of "OR":
194 | return Token(kind: tokOr)
195 | of "ORDER":
196 | return Token(kind: tokOrder)
197 | of "OUTER":
198 | return Token(kind: tokOuter)
199 | of "POSITION":
200 | return Token(kind: tokPosition)
201 | of "PRIMARY":
202 | return Token(kind: tokPrimary)
203 | of "PRECISION":
204 | return Token(kind: tokPrecision)
205 | of "TABLE":
206 | return Token(kind: tokTable)
207 | of "TRAILING":
208 | return Token(kind: tokTrailing)
209 | of "TRIM":
210 | return Token(kind: tokTrim)
211 | of "ROLLBACK":
212 | return Token(kind: tokRollback)
213 | of "SELECT":
214 | return Token(kind: tokSelect)
215 | of "SET":
216 | return Token(kind: tokSet)
217 | of "SOME":
218 | return Token(kind: tokAny)
219 | of "UNION":
220 | return Token(kind: tokUnion)
221 | of "UPDATE":
222 | return Token(kind: tokUpdate)
223 | of "VALUES":
224 | return Token(kind: tokValues)
225 | of "VARCHAR":
226 | return Token(kind: tokVarchar)
227 | of "WHEN":
228 | return Token(kind: tokWhen)
229 | of "WHERE":
230 | return Token(kind: tokWhere)
231 | of "WITH":
232 | return Token(kind: tokWith)
233 | result = Token(kind: tokIdentifier, identifier: toUpperAscii(s))
234 |
235 | proc currentToken*(s: Scanner): Token =
236 | result = s.current
237 |
238 | func isAlphaNumericUnderscore(c: char): bool =
239 | result = isAlphaNumeric(c) or c == '_'
240 |
241 | proc readNextToken(s: Scanner): Token =
242 | var c: char
243 | try:
244 | c = s.reader.read()
245 | while isSpaceAscii(c):
246 | c = s.reader.read()
247 | except EOFError:
248 | return Token(kind: tokEndOfInput)
249 | if isAlphaAscii(c):
250 | var id = $c
251 | try:
252 | while isAlphaNumericUnderscore(s.reader.peek()):
253 | id &= s.reader.read()
254 | except EOFError:
255 | discard
256 | return toToken(id)
257 | if isDigit(c):
258 | var numStr = $c
259 | try:
260 | while isDigit(s.reader.peek()):
261 | numStr &= s.reader.read()
262 | if s.reader.peek() == '.':
263 | numStr &= "."
264 | discard s.reader.read()
265 | while isDigit(s.reader.peek()):
266 | numStr &= s.reader.read()
267 | if toUpperAscii(s.reader.peek()) == 'E':
268 | numStr &= 'E'
269 | discard s.reader.read()
270 | let sc = s.reader.peek()
271 | if sc == '+' or sc == '-':
272 | numStr &= sc
273 | discard s.reader.read()
274 | while isDigit(s.reader.peek()):
275 | numStr &= s.reader.read()
276 | except EOFError:
277 | discard
278 | return if find(numStr, ".") >= 0: Token(kind: tokRat, value: numStr)
279 | else: Token(kind: tokInt, value: numStr)
280 | case c:
281 | of '*':
282 | return Token(kind: tokAsterisk)
283 | of '/':
284 | return Token(kind: tokDiv)
285 | of '+':
286 | return Token(kind: tokPlus)
287 | of '-':
288 | return Token(kind: tokMinus)
289 | of '(':
290 | return Token(kind: tokLeftParen)
291 | of ')':
292 | return Token(kind: tokRightParen)
293 | of ',':
294 | return Token(kind: tokComma)
295 | of '.':
296 | return Token(kind: tokDot)
297 | of '=':
298 | return Token(kind: tokEq)
299 | of '<':
300 | if s.reader.peek() == '>':
301 | discard s.reader.read()
302 | return Token(kind: tokNeq)
303 | elif s.reader.peek() == '=':
304 | discard s.reader.read()
305 | return Token(kind: tokLe)
306 | return Token(kind: tokLt)
307 | of '>':
308 | if s.reader.peek() == '=':
309 | discard s.reader.read()
310 | return Token(kind: tokGe)
311 | return Token(kind: tokGt)
312 | of '|':
313 | if s.reader.read() != '|':
314 | raiseDbError("invalid operator: |", syntaxError)
315 | return Token(kind: tokConcat)
316 | of '\'':
317 | var str = ""
318 | while true:
319 | c = s.reader.read()
320 | if c == '\'':
321 | if s.reader.peek() == '\'':
322 | discard s.reader.read()
323 | str &= '\''
324 | else:
325 | break
326 | else:
327 | str &= c
328 | return Token(kind: tokString, value: str)
329 | of '?':
330 | return Token(kind: tokPlaceholder)
331 | of '$':
332 | return Token(kind: tokNumPlaceholder)
333 | else:
334 | raiseDbError("Invalid character: " & c, syntaxError)
335 |
336 | proc nextToken*(s: Scanner): Token =
337 | s.current = readNextToken(s)
338 | result = s.current
339 |
340 | proc isValidTime*(str: string): bool =
341 | if str.len > 15:
342 | return false
343 | try:
344 | discard parse(str.substr(0, 7), "hh:mm:ss")
345 | except:
346 | return false
347 | if str.len > 8:
348 | if str[8] != '.':
349 | return false
350 | for i in 9.. 26:
357 | return false
358 | try:
359 | discard parse(str.substr(0, 18), "yyyy-MM-dd HH:mm:ss", utc())
360 | except:
361 | return false
362 | if str.len > 19:
363 | if str[19] != '.':
364 | return false
365 | for i in 20..= rcols[i].typ.maxReprLen: lcols[i].typ.maxReprLen
65 | else: rcols[i].typ.maxReprLen,
66 | precision: if lcols[i].typ.precision >= rcols[i].typ.precision: lcols[i].typ.precision
67 | else: rcols[i].typ.precision,
68 | scale: if lcols[i].typ.scale >= rcols[i].typ.scale: lcols[i].typ.scale
69 | else: rcols[i].typ.scale,
70 | min: if lcols[i].typ.min <= rcols[i].typ.min: lcols[i].typ.min
71 | else: rcols[i].typ.min,
72 | max: if lcols[i].typ.min >= rcols[i].typ.min: lcols[i].typ.max
73 | else: rcols[i].typ.max,
74 | validValues: @[])
75 | result.add(DbColumn(name: if lcols[i].name == rcols[i].name: lcols[i].name else: "",
76 | tableName: "", typ: typ, primaryKey: false, foreignKey: false))
77 |
--------------------------------------------------------------------------------
/tests/alltests.nim:
--------------------------------------------------------------------------------
1 | import osproc
2 |
3 | var failedTests: seq[string]
4 |
5 | proc execTest(testFile: string) =
6 | if execCmd("nim c -r " & testFile) != 0:
7 | failedTests.add(testFile)
8 |
9 | execTest("binary.nim")
10 | execTest("boolean.nim")
11 | execTest("char.nim")
12 | execTest("commit.nim")
13 | execTest("default.nim")
14 | execTest("distinct.nim")
15 | execTest("expjoin.nim")
16 | execTest("group.nim")
17 | execTest("impjoin.nim")
18 | execTest("leftjoin.nim")
19 | execTest("key.nim")
20 | execTest("like.nim")
21 | execTest("null.nim")
22 | execTest("numeric.nim")
23 | execTest("order.nim")
24 | execTest("prepared.nim")
25 | execTest("rollback.nim")
26 | execTest("snapshots.nim")
27 | execTest("subqueries.nim")
28 | execTest("union.nim")
29 | execTest("update.nim")
30 | execTest("where.nim")
31 | execTest("txlog.nim")
32 | execTest("txlog_snapshot.nim")
33 | execTest("datetime.nim")
34 | execTest("cast.nim")
35 | execTest("autoinc.nim")
36 | execTest("autoinc_txlog.nim")
37 | execTest("except.nim")
38 | execTest("intersect.nim")
39 | execTest("with.nim")
40 | execTest("insert_select.nim")
41 |
42 | if failedTests.len > 0:
43 | echo "FAILURE: tests failed: " & $failedTests
44 |
--------------------------------------------------------------------------------
/tests/autoinc.nim:
--------------------------------------------------------------------------------
1 | import db_nimternalsql
2 |
3 | var db = open("", "", "", "")
4 | exec(db, sql"""CREATE TABLE tst
5 | (k integer primary key autoincrement, n numeric, s text, i bigint not null autoincrement)""")
6 |
7 | doAssert execAffectedRows(db, sql"INSERT INTO tst (n, s) VALUES (2, 'Yo')") == 1
8 | doAssert execAffectedRows(db, sql"INSERT INTO tst (n, s) VALUES (5, 'Yaa')") == 1
9 |
10 | var res = getAllRows(db, sql"SELECT * FROM tst ORDER BY k")
11 |
12 | doAssert res.len == 2
13 | doAssert res[0][0] == "1"
14 | doAssert res[0][1] == "2"
15 | doAssert res[0][2] == "Yo"
16 | doAssert res[0][3] == "1"
17 | doAssert res[1][0] == "2"
18 | doAssert res[1][1] == "5"
19 | doAssert res[1][2] == "Yaa"
20 | doAssert res[1][3] == "2"
21 |
22 | save(db, "snapshot.dump")
23 |
24 | db = open("", "", "", "")
25 | restore(db, "snapshot.dump")
26 |
27 | doAssert execAffectedRows(db, sql"INSERT INTO tst (n, s) VALUES (6, 'Ji')") == 1
28 |
29 | exec(db, sql"CREATE TABLE tst2 (n numeric primary key, t text)")
30 | exec(db, sql"INSERT INTO tst2 VALUES (10, 'Ba')")
31 | exec(db, sql"INSERT INTO tst2 VALUES (11, 'Bbo')")
32 |
33 | exec(db, sql"INSERT INTO tst (n, s) SELECT * FROM tst2")
34 |
35 | res = getAllRows(db, sql"SELECT * FROM tst ORDER BY k")
36 |
37 | doAssert res.len == 5
38 | doAssert res[0][0] == "1"
39 | doAssert res[0][1] == "2"
40 | doAssert res[0][2] == "Yo"
41 | doAssert res[0][3] == "1"
42 | doAssert res[1][0] == "2"
43 | doAssert res[1][1] == "5"
44 | doAssert res[1][2] == "Yaa"
45 | doAssert res[1][3] == "2"
46 | doAssert res[2][0] == "3"
47 | doAssert res[2][1] == "6"
48 | doAssert res[2][2] == "Ji"
49 | doAssert res[2][3] == "3"
50 | doAssert res[3][0] == "4"
51 | doAssert res[3][1] == "10"
52 | doAssert res[3][2] == "Ba"
53 | doAssert res[3][3] == "4"
54 | doAssert res[4][0] == "5"
55 | doAssert res[4][1] == "11"
56 | doAssert res[4][2] == "Bbo"
57 | doAssert res[4][3] == "5"
58 |
59 | close(db)
60 |
--------------------------------------------------------------------------------
/tests/autoinc_txlog.nim:
--------------------------------------------------------------------------------
1 | import db_nimternalsql
2 | import os
3 |
4 | removeDir("db")
5 |
6 | var db = open("db", "", "", "")
7 | exec(db, sql"""CREATE TABLE tst
8 | (n numeric, k bigint primary key autoincrement, s text, i int autoincrement)""")
9 |
10 | doAssert execAffectedRows(db, sql"INSERT INTO tst (n, s) VALUES (2, 'Yo')") == 1
11 | doAssert execAffectedRows(db, sql"INSERT INTO tst (n, s) VALUES (5, 'Yaa')") == 1
12 |
13 | var res = getAllRows(db, sql"SELECT * FROM tst ORDER BY k")
14 |
15 | doAssert res.len == 2
16 | doAssert res[0][0] == "2"
17 | doAssert res[0][1] == "1"
18 | doAssert res[0][2] == "Yo"
19 | doAssert res[0][3] == "1"
20 | doAssert res[1][0] == "5"
21 | doAssert res[1][1] == "2"
22 | doAssert res[1][2] == "Yaa"
23 | doAssert res[1][3] == "2"
24 |
25 | close(db)
26 |
27 | db = open("db", "", "", "")
28 |
29 | doAssert execAffectedRows(db, sql"INSERT INTO tst (n, s) VALUES (6, 'Ji')") == 1
30 | doAssert execAffectedRows(db, sql"INSERT INTO tst (n, s) VALUES (7, 'Yj')") == 1
31 |
32 | res = getAllRows(db, sql"SELECT * FROM tst ORDER BY k")
33 |
34 | doAssert res.len == 4
35 | doAssert res[0][0] == "2"
36 | doAssert res[0][1] == "1"
37 | doAssert res[0][2] == "Yo"
38 | doAssert res[0][3] == "1"
39 | doAssert res[1][0] == "5"
40 | doAssert res[1][1] == "2"
41 | doAssert res[1][2] == "Yaa"
42 | doAssert res[1][3] == "2"
43 | doAssert res[2][0] == "6"
44 | doAssert res[2][1] == "3"
45 | doAssert res[2][2] == "Ji"
46 | doAssert res[2][3] == "3"
47 | doAssert res[3][0] == "7"
48 | doAssert res[3][1] == "4"
49 | doAssert res[3][2] == "Yj"
50 | doAssert res[3][3] == "4"
51 |
52 | close(db)
53 |
--------------------------------------------------------------------------------
/tests/binary.nim:
--------------------------------------------------------------------------------
1 | import db_nimternalsql
2 |
3 | let db = open("", "", "", "")
4 | exec(db, sql"CREATE TABLE tst (a binary primary key, b bytea, c varbinary, d longvarbinary, e raw)")
5 |
6 | let s1 = "\x01\x02AB\xFE\xFF"
7 | let s2 = "\x01\x02\x00AB\xFE\xFF"
8 | let s3 = "\x00ab"
9 | let s4 = "xX\x00\x08\x09"
10 | let s5 = "\n\r\""
11 | exec(db, sql"INSERT INTO tst VALUES (?, ?, ?, ?, ?)", s1, s2, s3, s4, s5)
12 |
13 | let row = getRow(db, sql"SELECT a, b, c, d, e FROM tst")
14 |
15 | doAssert row[0] == s1
16 | doAssert row[1] == s2
17 | doAssert row[1].len == 7
18 | doAssert row[2] == s3
19 | doAssert row[3] == s4
20 | doAssert row[4] == s5
21 |
22 | doAssert getValue(db,
23 | sql"""SELECT COUNT(*)
24 | FROM tst
25 | WHERE a = ?""",
26 | s1) == "1"
27 |
28 | close(db)
29 |
--------------------------------------------------------------------------------
/tests/boolean.nim:
--------------------------------------------------------------------------------
1 | import db_nimternalsql
2 | import strutils
3 |
4 | let db = open("", "", "", "")
5 | exec(db, sql"""CREATE TABLE tst
6 | (a int primary key, b boolean, c boolean)""")
7 |
8 | doAssert execAffectedRows(db, sql"INSERT INTO tst VALUES (1, TRUE, false)") == 1
9 |
10 | var rows = getAllRows(db, sql"SELECT b, c, b AND c, b OR c FROM tst")
11 |
12 | doAssert rows.len == 1
13 | doAssert rows[0][0] == "TRUE"
14 | doAssert rows[0][1] == "FALSE"
15 | doAssert rows[0][2] == "FALSE"
16 | doAssert rows[0][3] == "TRUE"
17 |
--------------------------------------------------------------------------------
/tests/cast.nim:
--------------------------------------------------------------------------------
1 | import db_nimternalsql
2 | import db_common
3 |
4 | let db = open("", "", "", "")
5 | exec(db, sql"""CREATE TABLE tst
6 | (k int PRIMARY KEY, n numeric(10, 1), s text)""")
7 | exec(db, sql"""INSERT INTO tst VALUES(1, 5.5, 'T')""")
8 |
9 | doAssert getValue(db, sql"""SELECT k + CAST ('2' AS INT) FROM tst""") == "3"
10 | doAssert getValue(db, sql"""SELECT k + CAST ('2' AS REAL) FROM tst""") == "3.0"
11 | doAssert getValue(db, sql"""SELECT k + CAST ('2' AS DOUBLE PRECISION) FROM tst""") == "3.0"
12 | doAssert getValue(db, sql"""SELECT k + CAST ('2' AS BIGINT) FROM tst""") == "3"
13 | doAssert getValue(db, sql"""SELECT CAST (n AS NUMERIC(4,2)) FROM tst""") == "5.50"
14 | doAssert getValue(db, sql"""SELECT ':' || CAST (n as TEXT) FROM tst""") == ":5.5"
15 | doAssert getValue(db, sql"""SELECT CAST (s || 'RUE' AS BOOLEAN) FROM tst""") == "TRUE"
16 |
17 | var cols: DbColumns
18 | var val: string
19 | for r in instantRows(db, cols, sql"""SELECT CAST(s || 'TX' AS CHAR(3)) FROM tst"""):
20 | val = r[0]
21 |
22 | doAssert val == "TTX"
23 | doAssert cols[0].typ.kind == dbFixedChar
24 |
25 | try:
26 | echo getValue(db, sql"""SELECT CAST(500 + n AS NUMERIC(1, 1)) FROM tst""")
27 | raiseAssert("CAST with insufficient precision succeeded")
28 | except DbError as e:
29 | doAssert sqlState(e) == "22003"
30 | try:
31 | echo getValue(db, sql"""SELECT CAST(s || 'TX' AS CHAR(2)) FROM tst""")
32 | raiseAssert("CAST with insufficient size succeeded")
33 | except DbError as e:
34 | doAssert sqlState(e) == "22001"
35 |
36 | exec(db, sql"""INSERT INTO tst VALUES(2, 5.5, '05:')""")
37 |
38 | var row = getRow(db, sql"""SELECT CAST(s || '10:12' AS TIME),
39 | CAST('2002-12-02' AS DATE),
40 | CAST('1902-02-03 ' || s || '01:03.223344' AS TIMESTAMP)
41 | FROM tst""")
42 | doAssert row[0] == "05:10:12"
43 | doAssert row[1] == "2002-12-02"
44 | doAssert row[2] == "1902-02-03 05:01:03.223344"
45 |
46 | row = getRow(db, sql"""SELECT CAST(s || '10:12.345' AS TIME(2)),
47 | CAST('2002-12-02' AS DATE),
48 | CAST('1902-02-03 ' || s || '01:03.223344' AS TIMESTAMP(5))
49 | FROM tst""")
50 | doAssert row[0] == "05:10:12.34"
51 | doAssert row[1] == "2002-12-02"
52 | doAssert row[2] == "1902-02-03 05:01:03.22334"
53 |
54 | close(db)
55 |
--------------------------------------------------------------------------------
/tests/char.nim:
--------------------------------------------------------------------------------
1 | import db_nimternalsql
2 | import db_common
3 |
4 | let db = open("", "", "", "")
5 | exec(db, sql"CREATE TABLE tst (a char(3) primary key, b char, c varchar(5), d text)")
6 |
7 | try:
8 | exec(db, sql"INSERT INTO tst (a, c) VALUES (?, ?)", "t", "123456")
9 | raiseAssert("value exceeding column length was excepted")
10 | except DbError:
11 | discard
12 |
13 | exec(db, sql"INSERT INTO tst VALUES (?, 'f', 'Don''t ', ? || UPPER(?) || LOWER(?))",
14 | "yo", "Yo", "Yo", "Yo")
15 |
16 | var res: seq[seq[string]]
17 |
18 | var cols: DbColumns
19 | for r in instantRows(db, cols, sql"SELECT * FROM tst"):
20 | res.add(@[r[0], r[1], r[2], r[3]])
21 |
22 | doAssert cols.len == 4
23 | doAssert cols[0].name == "A"
24 | doAssert cols[0].typ.kind == dbFixedChar
25 | doAssert cols[0].primaryKey
26 | doAssert cols[1].name == "B"
27 | doAssert cols[1].typ.kind == dbFixedChar
28 | doAssert not cols[1].primaryKey
29 | doAssert cols[2].name == "C"
30 | doAssert cols[2].typ.kind == dbVarchar
31 | doAssert not cols[2].primaryKey
32 | doAssert cols[3].name == "D"
33 | doAssert cols[3].typ.kind == dbVarchar
34 | doAssert not cols[3].primaryKey
35 |
36 | doAssert res.len == 1
37 | doAssert res[0][0] == "yo "
38 | doAssert res[0][1] == "f"
39 | doAssert res[0][2] == "Don't "
40 | doAssert res[0][3] == "YoYOyo"
41 |
42 | doAssert getValue(db, sql"SELECT SUBSTR(d, 2, 2) FROM tst") == "oY"
43 | doAssert getValue(db, sql"SELECT SUBSTR(d, ?) FROM tst", "2") == "oYOyo"
44 | doAssert getValue(db, sql"SELECT SUBSTR(d, -1, 1) FROM tst") == "o"
45 | doAssert getValue(db, sql"SELECT SUBSTR(d, -2 * 1) FROM tst") == "yo"
46 |
47 | doAssert getValue(db, sql"SELECT POSITION('Oy' IN d) FROM tst") == "4"
48 | doAssert getValue(db, sql"SELECT POSITION('' IN d) FROM tst") == "1"
49 | doAssert getValue(db, sql"SELECT POSITION('Bab' IN d) FROM tst") == "0"
50 | doAssert getValue(db, sql"SELECT POSITION('h' IN 'Äh') FROM tst") == "2"
51 |
52 | res = @[]
53 | for r in instantRows(db, sql"SELECT * FROM tst WHERE b IN (?)", "f"):
54 | res.add(@[r[0], r[1], r[2], r[3]])
55 |
56 | doAssert res.len == 1
57 | doAssert res[0][0] == "yo "
58 | doAssert res[0][1] == "f"
59 | doAssert res[0][2] == "Don't "
60 | doAssert res[0][3] == "YoYOyo"
61 |
62 | doAssert getValue(db, sql"SELECT b FROM tst WHERE b >= ?", "f") == "f"
63 |
64 | exec(db, sql"UPDATE tst SET b = '', c = 'Do', d = d || d")
65 |
66 | res = @[]
67 | for r in instantRows(db, sql"SELECT * FROM tst"):
68 | res.add(@[r[0], r[1], r[2], r[3]])
69 |
70 | doAssert res.len == 1
71 | doAssert res[0][0] == "yo "
72 | doAssert res[0][1] == " "
73 | doAssert res[0][2] == "Do"
74 | doAssert res[0][3] == "YoYOyoYoYOyo"
75 |
76 | doAssert getValue(db, sql"SELECT COUNT(*) FROM tst WHERE c >= 'Do'") == "1"
77 |
78 | doAssert getValue(db, sql"SELECT COUNT(*) FROM tst WHERE c > 'Do'") == "0"
79 |
80 | try:
81 | echo getValue(db, sql"SELECT COUNT(*) FROM tst WHERE c >= 3")
82 | raiseAssert("comparing character column with number succeeded")
83 | except DbError:
84 | discard
85 |
86 | doAssert getValue(db, sql"SELECT OCTET_LENGTH(c) FROM tst WHERE a = 'yo '") == "2"
87 | doAssert getValue(db, sql"SELECT LENGTH(c) FROM tst WHERE a = 'yo '") == "2"
88 | doAssert getValue(db, sql"SELECT CHAR_LENGTH(c) FROM tst WHERE a = 'yo '") == "2"
89 |
90 | doAssert getValue(db, sql"SELECT TRIM(a) FROM tst WHERE TRIM(a) = 'yo'") == "yo"
91 | doAssert getValue(db, sql"SELECT TRIM(LEADING FROM ' ' || a) FROM tst WHERE a = 'yo '") == "yo "
92 | doAssert getValue(db, sql"SELECT TRIM(TRAILING FROM ' ' || a) FROM tst WHERE a = 'yo '") == " yo"
93 | doAssert getValue(db, sql"SELECT TRIM(BOTH FROM ' ' || a) FROM tst WHERE a = 'yo '") == "yo"
94 | doAssert getValue(db, sql"SELECT TRIM('x' FROM 'xofx') FROM tst WHERE a = 'yo '") == "of"
95 | doAssert getValue(db, sql"SELECT TRIM(LEADING 'x' FROM 'xofx') FROM tst WHERE a = 'yo '") == "ofx"
96 | doAssert getValue(db, sql"SELECT TRIM(TRAILING 'x' FROM 'xofx') FROM tst WHERE a = 'yo '") == "xof"
97 | doAssert getValue(db, sql"SELECT TRIM(BOTH 'x' FROM 'xofx') FROM tst WHERE a = 'yo '") == "of"
98 |
99 | exec(db, sql"UPDATE tst SET c = '2' WHERE a = 'yo '")
100 |
101 | doAssert getValue(db, sql"SELECT COUNT(*) FROM tst WHERE c > ?", "10") == "1"
102 |
103 | exec(db, sql"DROP TABLE tst")
104 |
105 | try:
106 | for r in instantRows(db, sql"SELECT * FROM tst"):
107 | discard
108 | raiseAssert("tst is still accessible after DROP table")
109 | except DbError:
110 | doAssert sqlState((ref DbError)(getCurrentException())) == "42704"
111 |
112 | exec(db, sql"DROP TABLE IF EXISTS tst")
113 |
--------------------------------------------------------------------------------
/tests/commit.nim:
--------------------------------------------------------------------------------
1 | import db_nimternalsql
2 |
3 | let db = open("", "", "", "")
4 | exec(db, sql"CREATE TABLE tst (a int primary key, b int, c text)")
5 | exec(db, sql"INSERT INTO tst VALUES (1, 2, 'yo')")
6 | exec(db, sql"INSERT INTO tst VALUES (2, 3, 'ya')")
7 |
8 | db.setAutocommit(false)
9 | exec(db, sql"INSERT INTO tst VALUES (3, 3, 'yai')")
10 |
11 | exec(db, sql"UPDATE tst SET a = a + 10 WHERE b = 3")
12 | exec(db, sql"UPDATE tst SET c = 'yi' WHERE a = 1")
13 |
14 | exec(db, sql"DELETE FROM tst WHERE a = 12");
15 | exec(db, sql"COMMIT")
16 |
17 | var rows = getAllRows(db, sql"SELECT * FROM tst ORDER BY a")
18 | doAssert rows.len == 2
19 | doAssert rows[0][0] == "1"
20 | doAssert rows[0][1] == "2"
21 | doAssert rows[0][2] == "yi"
22 | doAssert rows[1][0] == "13"
23 | doAssert rows[1][1] == "3"
24 | doAssert rows[1][2] == "yai"
25 |
26 | db.close()
27 |
--------------------------------------------------------------------------------
/tests/datetime.nim:
--------------------------------------------------------------------------------
1 | import times
2 | import db_nimternalsql
3 |
4 | let db = open("", "", "", "")
5 |
6 | exec(db, sql"""CREATE TABLE dt (n int primary key, t time, t6 time(6), d date,
7 | ts timestamp, ts0 timestamp(0))""")
8 |
9 | exec(db, sql"""INSERT INTO dt VALUES(1, '09:01:02', '11:12:13.123456', '2021-12-23',
10 | '1993-06-13 22:59:59.123456', '2003-06-13 22:59:59')""")
11 |
12 | doAssert getValue(db, sql"""SELECT t FROM dt WHERE n = 1""") == "09:01:02"
13 |
14 | doAssert getValue(db, sql"""SELECT t6 FROM dt WHERE n = 1""") == "11:12:13.123456"
15 |
16 | doAssert getValue(db, sql"""SELECT d FROM dt WHERE n = 1""") == "2021-12-23"
17 |
18 | doAssert getValue(db, sql"""SELECT ts FROM dt WHERE n = 1""") == "1993-06-13 22:59:59.123456"
19 |
20 | doAssert getValue(db, sql"""SELECT ts0 FROM dt WHERE n = 1""") == "2003-06-13 22:59:59"
21 |
22 | doAssert getValue(db, sql"""SELECT t FROM dt WHERE t >= t""") == "09:01:02"
23 | doAssert getValue(db, sql"""SELECT t FROM dt WHERE t >= '09:01:02'""") == "09:01:02"
24 | doAssert getValue(db, sql"""SELECT t FROM dt WHERE '09:01:02' <= t""") == "09:01:02"
25 | doAssert getValue(db, sql"""SELECT t FROM dt WHERE t = t""") == "09:01:02"
26 | doAssert getValue(db, sql"""SELECT t FROM dt WHERE t = '09:01:02'""") == "09:01:02"
27 | doAssert getValue(db, sql"""SELECT t FROM dt WHERE '09:01:02' = t""") == "09:01:02"
28 |
29 | doAssert getValue(db, sql"""SELECT d FROM dt WHERE d >= d""") == "2021-12-23"
30 | doAssert getValue(db, sql"""SELECT d FROM dt WHERE d >= '2021-12-23'""") == "2021-12-23"
31 | doAssert getValue(db, sql"""SELECT d FROM dt WHERE '2021-12-23' <= d""") == "2021-12-23"
32 | doAssert getValue(db, sql"""SELECT d FROM dt WHERE d = d""") == "2021-12-23"
33 | doAssert getValue(db, sql"""SELECT d FROM dt WHERE d = '2021-12-23'""") == "2021-12-23"
34 | doAssert getValue(db, sql"""SELECT d FROM dt WHERE '2021-12-23' = d""") == "2021-12-23"
35 |
36 | doAssert getValue(db, sql"""SELECT ts FROM dt WHERE ts >= ts""") == "1993-06-13 22:59:59.123456"
37 | doAssert getValue(db, sql"""SELECT ts FROM dt WHERE ts <= ts""") == "1993-06-13 22:59:59.123456"
38 | doAssert getValue(db, sql"""SELECT ts FROM dt WHERE ts > ts""") == ""
39 | doAssert getValue(db, sql"""SELECT ts FROM dt WHERE ts < ts""") == ""
40 | doAssert getValue(db, sql"""SELECT ts FROM dt WHERE ts >= '1993-06-13 22:59:59.123456'""") == "1993-06-13 22:59:59.123456"
41 | doAssert getValue(db, sql"""SELECT ts FROM dt WHERE '1993-06-13 22:59:59.123456' >= ts """) == "1993-06-13 22:59:59.123456"
42 | doAssert getValue(db, sql"""SELECT ts FROM dt WHERE ts = ts""") == "1993-06-13 22:59:59.123456"
43 | doAssert getValue(db, sql"""SELECT ts FROM dt WHERE ts = '1993-06-13 22:59:59.123456'""") == "1993-06-13 22:59:59.123456"
44 | doAssert getValue(db, sql"""SELECT ts FROM dt WHERE '1993-06-13 22:59:59.123456' = ts """) == "1993-06-13 22:59:59.123456"
45 |
46 | exec(db, sql"INSERT INTO dt (n, t, d, ts) VALUES(2, current_time, current_date, current_timestamp)")
47 |
48 | discard parse(getValue(db, sql"""SELECT t FROM dt WHERE n = 2"""), "HH:mm:ss")
49 |
50 | var datestr = getValue(db, sql"""SELECT d FROM dt WHERE n = 2""")
51 | var dt = parse(datestr, "yyyy-MM-dd", utc())
52 | doAssert dt.year == now().year
53 | doAssert dt.month == now().month
54 | doAssert dt.monthday == now().monthday
55 |
56 | datestr = getValue(db, sql"""SELECT ts FROM dt WHERE n = 2""")
57 | dt = parse(datestr, "yyyy-MM-dd HH:mm:ss'.'ffffff", utc())
58 | doAssert dt.year == now().year
59 | doAssert dt.month == now().month
60 | doAssert dt.monthday == now().utc.monthday
61 |
62 | exec(db, sql"""CREATE TABLE dt2 (n int primary key, t time(3), ts timestamp(2))""")
63 |
64 | exec(db, sql"""INSERT INTO dt2 VALUES(1, '01:02:03.123456', '1993-06-13 20:21:22.123456')""")
65 |
66 | doAssert getValue(db, sql"""SELECT t FROM dt2""") == "01:02:03.123"
67 |
68 | doAssert getValue(db, sql"""SELECT t FROM dt2 WHERE t = '01:02:03.123'""") == "01:02:03.123"
69 |
70 | doAssert getValue(db, sql"""SELECT ts FROM dt2""") == "1993-06-13 20:21:22.12"
71 |
72 | doAssert getValue(db, sql"""SELECT ts FROM dt2 WHERE ts = '1993-06-13 20:21:22.12'""") == "1993-06-13 20:21:22.12"
73 |
74 | try:
75 | exec(db, sql"INSERT INTO dt (n, t) VALUES(3, TIME '05:06:7')")
76 | raiseAssert("invalid time literal accepted")
77 | except DbError as e:
78 | doAssert e.sqlState() == "22007"
79 | try:
80 | exec(db, sql"INSERT INTO dt (n, t) VALUES(3, TIME '05:06:07.f')")
81 | raiseAssert("invalid time literal accepted")
82 | except DbError as e:
83 | doAssert e.sqlState() == "22007"
84 | exec(db, sql"""INSERT INTO dt (n, t, ts, d)
85 | VALUES(3, TIME '05:06:08', TIMESTAMP '2000-01-02 05:04:06.123456',
86 | DATE '2003-02-01')""")
87 |
88 | let row = getRow(db, sql"SELECT t, ts, d FROM dt WHERE n = 3")
89 | doAssert row[0] == "05:06:08"
90 | doAssert row[1] == "2000-01-02 05:04:06.123456"
91 | doAssert row[2] == "2003-02-01"
92 |
93 | close(db)
94 |
--------------------------------------------------------------------------------
/tests/default.nim:
--------------------------------------------------------------------------------
1 | import db_nimternalsql
2 |
3 | let db = open("", "", "", "")
4 | exec(db, sql"""CREATE TABLE tst (
5 | a char(3) DEFAULT 'nix' PRIMARY KEY,
6 | b char DEFAULT 'x' not null,
7 | c varchar(5))""")
8 |
9 | # Error
10 | try:
11 | exec(db, sql"INSERT INTO tst (a) VALUES('yay', 'Yo')")
12 | raiseAssert("INSERT succeeded although # of values differed from # of columns")
13 | except DbError as e:
14 | doAssert e.sqlState() == "42601"
15 |
16 | exec(db, sql"INSERT INTO tst (a, c) VALUES('yay', 'Yo')")
17 | exec(db, sql"INSERT INTO tst DEFAULT VALUES")
18 |
19 | var res: seq[seq[string]]
20 |
21 | for r in instantRows(db, sql"SELECT * FROM tst ORDER BY a"):
22 | res.add(@[r[0], r[1], r[2]])
23 |
24 | doAssert res.len == 2
25 | doAssert res[0][0] == "nix"
26 | doAssert res[0][1] == "x"
27 | doAssert res[0][2] == ""
28 | doAssert res[1][0] == "yay"
29 | doAssert res[1][1] == "x"
30 | doAssert res[1][2] == "Yo"
31 |
--------------------------------------------------------------------------------
/tests/delete.nim:
--------------------------------------------------------------------------------
1 | import db_nimternalsql
2 |
3 | let db = open("", "", "", "")
4 | exec(db, sql"CREATE TABLE tst (a int primary key, b int, c text)")
5 | exec(db, sql"INSERT INTO tst VALUES (1, 2, 'yo')")
6 | exec(db, sql"INSERT INTO tst VALUES (2, 3, 'ya')")
7 | exec(db, sql"INSERT INTO tst VALUES (3, 3, 'yayo')")
8 | exec(db, sql"INSERT INTO tst VALUES (4, 10, 'yo')")
9 |
10 | doAssert execAffectedRows(db, sql"DELETE FROM tst WHERE a = 1") == 1
11 |
12 | var res: seq[seq[string]]
13 | for r in instantRows(db, sql"SELECT * FROM tst ORDER BY a"):
14 | res.add(@[r[0], r[1], r[2]])
15 |
16 | doAssert res.len == 3
17 | doAssert res[0][0] == "2"
18 | doAssert res[0][1] == "3"
19 | doAssert res[0][2] == "ya"
20 | doAssert res[1][0] == "3"
21 | doAssert res[1][1] == "3"
22 | doAssert res[1][2] == "yayo"
23 | doAssert res[2][0] == "4"
24 | doAssert res[2][1] == "10"
25 | doAssert res[2][2] == "yo"
26 |
27 | doAssert execAffectedRows(db, sql"DELETE FROM tst WHERE c='yo'") == 1
28 |
29 | res = @[]
30 | for r in instantRows(db, sql"SELECT * FROM tst ORDER BY a"):
31 | res.add(@[r[0], r[1], r[2]])
32 | doAssert res.len == 2
33 | doAssert res[0][0] == "2"
34 | doAssert res[0][1] == "3"
35 | doAssert res[0][2] == "ya"
36 | doAssert res[1][0] == "3"
37 | doAssert res[1][1] == "3"
38 | doAssert res[1][2] == "yayo"
39 |
40 | doAssert execAffectedRows(db, sql"DELETE FROM tst") == 2
41 |
42 | doAssert getValue(db, sql"SELECT COUNT(*) FROM tst") == "0"
43 |
--------------------------------------------------------------------------------
/tests/distinct.nim:
--------------------------------------------------------------------------------
1 | import db_nimternalsql
2 | import algorithm
3 |
4 | let db = open("", "", "", "")
5 | exec(db, sql"CREATE TABLE tst (a int primary key, b text, c varchar(2))")
6 |
7 | exec(db, sql"INSERT INTO tst VALUES (1, 'Fritz', 'ui')")
8 | exec(db, sql"INSERT INTO tst VALUES (2, 'Fritz', 'ui')")
9 | exec(db, sql"INSERT INTO tst VALUES (3, 'Fritz', 'uh')")
10 | exec(db, sql"INSERT INTO tst VALUES (4, 'Fritz', 'ui')")
11 |
12 | var rows = getAllRows(db, sql"SELECT DISTINCT b, c FROM tst ORDER BY c")
13 | doAssert rows.len == 2
14 | doAssert rows[0][0] == "Fritz"
15 | doAssert rows[0][1] == "uh"
16 | doAssert rows[1][0] == "Fritz"
17 | doAssert rows[1][1] == "ui"
18 |
19 | rows = getAllRows(db, sql"SELECT DISTINCT b, c FROM tst")
20 | rows.sort(proc(r1, r2: Row): int =
21 | result = cmp(r1[1], r2[1]))
22 | doAssert rows.len == 2
23 | doAssert rows[0][0] == "Fritz"
24 | doAssert rows[0][1] == "uh"
25 | doAssert rows[1][0] == "Fritz"
26 | doAssert rows[1][1] == "ui"
27 |
28 | exec(db, sql"INSERT INTO tst VALUES (5, 'Fritz', 'uh')")
29 | exec(db, sql"INSERT INTO tst VALUES (6, 'Fritz', 'ui')")
30 |
31 | rows = getAllRows(db, sql"SELECT DISTINCT b, c FROM tst ORDER BY b")
32 | rows.sort(proc(r1, r2: Row): int =
33 | result = cmp(r1[1], r2[1]))
34 | doAssert rows.len == 2
35 | doAssert rows[0][0] == "Fritz"
36 | doAssert rows[0][1] == "uh"
37 | doAssert rows[1][0] == "Fritz"
38 | doAssert rows[1][1] == "ui"
39 |
40 | rows = getAllRows(db, sql"SELECT DISTINCT b, c FROM tst ORDER BY b, c DESC")
41 | doAssert rows.len == 2
42 | doAssert rows[0][0] == "Fritz"
43 | doAssert rows[0][1] == "ui"
44 | doAssert rows[1][0] == "Fritz"
45 | doAssert rows[1][1] == "uh"
46 |
--------------------------------------------------------------------------------
/tests/except.nim:
--------------------------------------------------------------------------------
1 | import db_nimternalsql
2 | import db_common
3 |
4 | let db = open("", "", "", "")
5 | exec(db, sql"CREATE TABLE tst (a int, b text, c int primary key)")
6 | exec(db, sql"CREATE TABLE tst2 (a int, b text, c int, primary key(c, b))")
7 | exec(db, sql"INSERT INTO tst VALUES (1, 'ace', 1)")
8 | exec(db, sql"INSERT INTO tst VALUES (2, 'king', 2)")
9 | exec(db, sql"INSERT INTO tst VALUES (2, 'jack', 3)")
10 | exec(db, sql"INSERT INTO tst2 VALUES (2, 'king', 2)")
11 | exec(db, sql"INSERT INTO tst2 VALUES (3, 'queen', 2)")
12 | exec(db, sql"INSERT INTO tst2 VALUES (4, 'jack', 4)")
13 |
14 | var rows: seq[seq[string]]
15 | var cols: DbColumns
16 |
17 | for r in instantRows(db, cols,
18 | sql"""SELECT * FROM tst
19 | EXCEPT
20 | SELECT * FROM tst2
21 | ORDER BY c"""):
22 | rows.add(@[r[0], r[1], r[2]])
23 |
24 | doAssert cols.len == 3
25 | doAssert cols[0].name == "A"
26 | doAssert cols[0].typ.kind == dbInt
27 | doAssert cols[1].name == "B"
28 | doAssert cols[1].typ.kind == dbVarchar
29 | doAssert cols[2].name == "C"
30 | doAssert cols[2].typ.kind == dbInt
31 |
32 | doAssert rows.len == 2
33 | doAssert rows[0][0] == "1"
34 | doAssert rows[0][1] == "ace"
35 | doAssert rows[0][2] == "1"
36 | doAssert rows[1][0] == "2"
37 | doAssert rows[1][1] == "jack"
38 | doAssert rows[1][2] == "3"
39 |
40 | rows = getAllRows(db, sql"""SELECT * FROM tst2
41 | EXCEPT
42 | SELECT * FROM tst
43 | ORDER BY a""")
44 |
45 | doAssert rows.len == 2
46 | doAssert rows[0][0] == "3"
47 | doAssert rows[0][1] == "queen"
48 | doAssert rows[1][0] == "4"
49 | doAssert rows[1][1] == "jack"
50 |
51 | rows = getAllRows(db, sql"""SELECT a, b FROM tst
52 | EXCEPT
53 | SELECT a, b FROM tst2
54 | ORDER BY a""")
55 |
56 | doAssert rows.len == 2
57 | doAssert rows[0][0] == "1"
58 | doAssert rows[0][1] == "ace"
59 | doAssert rows[1][0] == "2"
60 | doAssert rows[1][1] == "jack"
61 |
62 | rows = getAllRows(db, sql"""SELECT c FROM tst2
63 | EXCEPT
64 | SELECT c * 2 FROM tst
65 | WHERE c = 2
66 | ORDER BY c""")
67 |
68 | doAssert rows.len == 1
69 | doAssert rows[0][0] == "2"
70 |
71 | rows = getAllRows(db, sql"""SELECT c FROM tst2
72 | EXCEPT ALL
73 | SELECT 4 FROM tst
74 | ORDER BY c""")
75 |
76 | doAssert rows.len == 2
77 | doAssert rows[0][0] == "2"
78 | doAssert rows[1][0] == "2"
79 |
--------------------------------------------------------------------------------
/tests/expjoin.nim:
--------------------------------------------------------------------------------
1 | import db_nimternalsql
2 |
3 | let db = open("", "", "", "")
4 | exec(db, sql"CREATE TABLE emp (empno int primary key, firstName text not null, last_name text)")
5 | exec(db, sql"CREATE TABLE emp_team (empno int, team_name text, primary key (empno, team_name))")
6 | exec(db, sql"CREATE TABLE emp2 (no int primary key, firstName text not null, last_name text)")
7 |
8 | exec(db, sql"INSERT INTO emp VALUES(1, 'Bob', 'Base')")
9 | exec(db, sql"INSERT INTO emp VALUES(2, 'Daisy', 'Database')")
10 | exec(db, sql"INSERT INTO emp_team VALUES(1, 'Team A')")
11 | exec(db, sql"INSERT INTO emp_team VALUES(2, 'Team B')")
12 | exec(db, sql"INSERT INTO emp2 VALUES(1, 'Bob', 'Base')")
13 |
14 | var rows = getAllRows(db,
15 | sql"""SELECT * FROM emp
16 | CROSS JOIN emp_team
17 | ORDER BY emp.empno, emp_team.empno""")
18 | doAssert rows.len == 4
19 | doAssert rows[0][0] == "1"
20 | doAssert rows[0][1] == "Bob"
21 | doAssert rows[0][2] == "Base"
22 | doAssert rows[0][3] == "1"
23 | doAssert rows[0][4] == "Team A"
24 | doAssert rows[1][0] == "1"
25 | doAssert rows[1][1] == "Bob"
26 | doAssert rows[1][2] == "Base"
27 | doAssert rows[1][3] == "2"
28 | doAssert rows[1][4] == "Team B"
29 | doAssert rows[2][0] == "2"
30 | doAssert rows[2][1] == "Daisy"
31 | doAssert rows[2][2] == "Database"
32 | doAssert rows[2][3] == "1"
33 | doAssert rows[2][4] == "Team A"
34 | doAssert rows[3][0] == "2"
35 | doAssert rows[3][1] == "Daisy"
36 | doAssert rows[3][2] == "Database"
37 | doAssert rows[3][3] == "2"
38 | doAssert rows[3][4] == "Team B"
39 |
40 | rows = getAllRows(db,
41 | sql"""SELECT * FROM emp
42 | CROSS JOIN emp_team t1 CROSS JOIN emp_team t2
43 | WHERE emp.empno = t1.empno and t1.empno = t2.empno
44 | ORDER BY emp.empno""")
45 | doAssert rows.len == 2
46 | doAssert rows[0][0] == "1"
47 | doAssert rows[0][1] == "Bob"
48 | doAssert rows[0][2] == "Base"
49 | doAssert rows[0][3] == "1"
50 | doAssert rows[0][4] == "Team A"
51 | doAssert rows[1][0] == "2"
52 | doAssert rows[1][1] == "Daisy"
53 | doAssert rows[1][2] == "Database"
54 | doAssert rows[1][3] == "2"
55 | doAssert rows[1][4] == "Team B"
56 |
57 | rows = getAllRows(db, sql"""SELECT * FROM emp_team t
58 | JOIN emp ON t.empno = emp.empno
59 | ORDER BY last_name""")
60 | doAssert rows.len == 2
61 | doAssert rows[0][0] == "1"
62 | doAssert rows[0][1] == "Team A"
63 | doAssert rows[0][2] == "1"
64 | doAssert rows[0][3] == "Bob"
65 | doAssert rows[0][4] == "Base"
66 | doAssert rows[1][0] == "2"
67 | doAssert rows[1][1] == "Team B"
68 | doAssert rows[1][2] == "2"
69 | doAssert rows[1][3] == "Daisy"
70 | doAssert rows[1][4] == "Database"
71 |
72 | rows = getAllRows(db, sql"""SELECT * FROM emp2 INNER JOIN emp_team t
73 | ON no = empno
74 | ORDER BY last_name""")
75 | doAssert rows.len == 1
76 | doAssert rows[0][0] == "1"
77 | doAssert rows[0][1] == "Bob"
78 | doAssert rows[0][2] == "Base"
79 | doAssert rows[0][3] == "1"
80 | doAssert rows[0][4] == "Team A"
81 |
82 | # OUTER JOIN is not supported
83 | try:
84 | rows = getAllRows(db, sql"""SELECT * FROM emp_team t
85 | OUTER JOIN emp ON t.empno = emp.empno
86 | ORDER BY last_name""")
87 | raiseAssert("OUTER JOIN succeeded")
88 | except DbError:
89 | discard
90 |
--------------------------------------------------------------------------------
/tests/group.nim:
--------------------------------------------------------------------------------
1 | import db_nimternalsql
2 | import db_common
3 |
4 | let db = open("", "", "", "")
5 | exec(db, sql"CREATE TABLE tst (a int primary key, c text, rank text)")
6 |
7 | var rows = getAllRows(db, sql"SELECT COUNT(*), MAX(a), SUM(a), AVG(a) FROM tst")
8 | doAssert rows.len == 1
9 | doAssert rows[0][0] == "0"
10 | doAssert rows[0][1] == ""
11 | doAssert rows[0][2] == ""
12 | doAssert rows[0][3] == ""
13 |
14 | exec(db, sql"INSERT INTO tst VALUES (1, 'y', 'Ace')")
15 | exec(db, sql"INSERT INTO tst VALUES (2, 'x', 'King')")
16 | exec(db, sql"INSERT INTO tst VALUES (3, 'z', 'Queen')")
17 | exec(db, sql"INSERT INTO tst VALUES (4, 'x', 'Jack')")
18 | exec(db, sql"INSERT INTO tst VALUES (5, 'y', 'Ace')")
19 | exec(db, sql"INSERT INTO tst VALUES (6, 'y', 'Ace')")
20 | exec(db, sql"INSERT INTO tst VALUES (7, 'z', 'Queen')")
21 |
22 | doAssert getValue(db, sql"SELECT COUNT(*) FROM tst") == "7"
23 |
24 | rows = @[]
25 | var cols: DbColumns
26 | for r in instantRows(db, cols,
27 | sql"""SELECT c, rank, COUNT(*), MAX(a) AS MA, MIN(t.a), SUM(a), AVG(a)
28 | FROM tst t
29 | GROUP BY rank, c
30 | ORDER BY c"""):
31 | rows.add(@[r[0], r[1], r[2], r[3], r[4], r[5], r[6]])
32 |
33 | doAssert cols.len == 7
34 | doAssert cols[0].name == "C"
35 | doAssert cols[0].typ.kind == dbVarchar
36 | doAssert cols[1].name == "RANK"
37 | doAssert cols[1].typ.kind == dbVarchar
38 | doAssert cols[2].name == ""
39 | doAssert cols[2].typ.kind == dbInt
40 | doAssert cols[3].name == "MA"
41 | doAssert cols[3].typ.kind == dbInt
42 | doAssert cols[4].name == ""
43 | doAssert cols[4].typ.kind == dbInt
44 | doAssert cols[5].name == ""
45 | doAssert cols[5].typ.kind == dbInt
46 | doAssert cols[6].name == ""
47 | doAssert cols[6].typ.kind == dbFloat
48 |
49 | doAssert rows.len == 4
50 | doAssert rows[0][0] == "x"
51 | doAssert rows[0][1] == "King"
52 | doAssert rows[0][2] == "1"
53 | doAssert rows[0][3] == "2"
54 | doAssert rows[0][4] == "2"
55 | doAssert rows[0][5] == "2"
56 | doAssert rows[0][6] == "2.0"
57 | doAssert rows[1][0] == "x"
58 | doAssert rows[1][1] == "Jack"
59 | doAssert rows[1][2] == "1"
60 | doAssert rows[1][3] == "4"
61 | doAssert rows[1][4] == "4"
62 | doAssert rows[1][5] == "4"
63 | doAssert rows[1][6] == "4.0"
64 | doAssert rows[2][0] == "y"
65 | doAssert rows[2][1] == "Ace"
66 | doAssert rows[2][2] == "3"
67 | doAssert rows[2][3] == "6"
68 | doAssert rows[2][4] == "6"
69 | doAssert rows[2][5] == "12"
70 | doAssert rows[2][6] == "4.0"
71 | doAssert rows[3][0] == "z"
72 | doAssert rows[3][1] == "Queen"
73 | doAssert rows[3][2] == "2"
74 | doAssert rows[3][3] == "7"
75 | doAssert rows[3][4] == "7"
76 | doAssert rows[3][5] == "10"
77 | doAssert rows[3][6] == "5.0"
78 |
79 | rows = getAllRows(db, sql"""SELECT COUNT(*), MAX(a), c, rank r
80 | FROM tst t
81 | GROUP BY c, r
82 | ORDER BY r""")
83 | doAssert rows.len == 4
84 | doAssert rows[0][0] == "3"
85 | doAssert rows[0][1] == "6"
86 | doAssert rows[0][2] == "y"
87 | doAssert rows[0][3] == "Ace"
88 | doAssert rows[1][0] == "1"
89 | doAssert rows[1][1] == "4"
90 | doAssert rows[1][2] == "x"
91 | doAssert rows[1][3] == "Jack"
92 | doAssert rows[2][0] == "1"
93 | doAssert rows[2][1] == "2"
94 | doAssert rows[2][2] == "x"
95 | doAssert rows[2][3] == "King"
96 | doAssert rows[3][0] == "2"
97 | doAssert rows[3][1] == "7"
98 | doAssert rows[3][2] == "z"
99 | doAssert rows[3][3] == "Queen"
100 |
101 | rows = getAllRows(db, sql"""SELECT rank r, COUNT(*), MAX(a), c
102 | FROM tst t
103 | WHERE a < ?
104 | GROUP BY c, r
105 | ORDER BY c""",
106 | "8")
107 | doAssert rows.len == 4
108 | doAssert rows[0][0] == "King"
109 | doAssert rows[0][1] == "1"
110 | doAssert rows[0][2] == "2"
111 | doAssert rows[0][3] == "x"
112 | doAssert rows[1][0] == "Jack"
113 | doAssert rows[1][1] == "1"
114 | doAssert rows[1][2] == "4"
115 | doAssert rows[1][3] == "x"
116 | doAssert rows[2][0] == "Ace"
117 | doAssert rows[2][1] == "3"
118 | doAssert rows[2][2] == "6"
119 | doAssert rows[2][3] == "y"
120 | doAssert rows[3][0] == "Queen"
121 | doAssert rows[3][1] == "2"
122 | doAssert rows[3][2] == "7"
123 | doAssert rows[3][3] == "z"
124 |
125 | rows = getAllRows(db, sql"""SELECT a, c, rank
126 | FROM tst
127 | GROUP BY a, c, rank
128 | ORDER BY a""")
129 |
130 | doAssert rows.len == 7
131 | doAssert rows[0][0] == "1"
132 | doAssert rows[0][1] == "y"
133 | doAssert rows[0][2] == "Ace"
134 | doAssert rows[1][0] == "2"
135 | doAssert rows[1][1] == "x"
136 | doAssert rows[1][2] == "King"
137 | doAssert rows[2][0] == "3"
138 | doAssert rows[2][1] == "z"
139 | doAssert rows[2][2] == "Queen"
140 | doAssert rows[3][0] == "4"
141 | doAssert rows[3][1] == "x"
142 | doAssert rows[3][2] == "Jack"
143 | doAssert rows[4][0] == "5"
144 | doAssert rows[4][1] == "y"
145 | doAssert rows[4][2] == "Ace"
146 | doAssert rows[5][0] == "6"
147 | doAssert rows[5][1] == "y"
148 | doAssert rows[5][2] == "Ace"
149 | doAssert rows[6][0] == "7"
150 | doAssert rows[6][1] == "z"
151 | doAssert rows[6][2] == "Queen"
152 |
153 | try:
154 | rows = getAllRows(db, sql"""SELECT a, c, rank
155 | FROM tst
156 | GROUP BY c, rank
157 | ORDER BY a""")
158 | raiseAssert("invalid grouping succeeded")
159 | except DbError as e:
160 | doAssert sqlState(e) == "42803"
161 |
162 | rows = getAllRows(db, sql"""SELECT *
163 | FROM tst
164 | GROUP BY a, c, rank
165 | ORDER BY a""")
166 |
167 | doAssert rows.len == 7
168 | doAssert rows[0][0] == "1"
169 | doAssert rows[0][1] == "y"
170 | doAssert rows[0][2] == "Ace"
171 | doAssert rows[1][0] == "2"
172 | doAssert rows[1][1] == "x"
173 | doAssert rows[1][2] == "King"
174 | doAssert rows[2][0] == "3"
175 | doAssert rows[2][1] == "z"
176 | doAssert rows[2][2] == "Queen"
177 | doAssert rows[3][0] == "4"
178 | doAssert rows[3][1] == "x"
179 | doAssert rows[3][2] == "Jack"
180 | doAssert rows[4][0] == "5"
181 | doAssert rows[4][1] == "y"
182 | doAssert rows[4][2] == "Ace"
183 | doAssert rows[5][0] == "6"
184 | doAssert rows[5][1] == "y"
185 | doAssert rows[5][2] == "Ace"
186 | doAssert rows[6][0] == "7"
187 | doAssert rows[6][1] == "z"
188 | doAssert rows[6][2] == "Queen"
189 |
190 | try:
191 | rows = getAllRows(db, sql"""SELECT *
192 | FROM tst
193 | GROUP BY c, rank
194 | ORDER BY a""")
195 | raiseAssert("invalid grouping succeeded")
196 | except DbError as e:
197 | doAssert sqlState(e) == "42803"
198 |
199 | exec(db, sql"CREATE TABLE tst2 (a int primary key, b int, rank text)")
200 |
201 | exec(db, sql"INSERT INTO tst2 VALUES (1, 1, 'Jack')")
202 | exec(db, sql"INSERT INTO tst2 VALUES (2, 1, 'Ace')")
203 | exec(db, sql"INSERT INTO tst2 VALUES (3, 1, 'King')")
204 | exec(db, sql"INSERT INTO tst2 VALUES (4, 2, 'Queen')")
205 | exec(db, sql"INSERT INTO tst2 VALUES (5, 2, 'Jack')")
206 |
207 | rows = getAllRows(db, sql"""SELECT b, MIN(rank), MAX(rank)
208 | FROM tst2
209 | GROUP BY b
210 | ORDER BY b""")
211 | doAssert rows.len == 2
212 | doAssert rows[0][0] == "1"
213 | doAssert rows[0][1] == "Ace"
214 | doAssert rows[0][2] == "King"
215 | doAssert rows[1][0] == "2"
216 | doAssert rows[1][1] == "Jack"
217 | doAssert rows[1][2] == "Queen"
218 |
--------------------------------------------------------------------------------
/tests/impjoin.nim:
--------------------------------------------------------------------------------
1 | import db_nimternalsql
2 | import db_common
3 |
4 | let db = open("", "", "", "")
5 | exec(db, sql"CREATE TABLE test1 (a text not null, b text, c int primary key)")
6 | exec(db, sql"CREATE TABLE test2 (d text, e int primary key)")
7 |
8 | exec(db, sql"INSERT INTO test1 VALUES('Pitch', 'P', 1)")
9 | exec(db, sql"INSERT INTO test1 VALUES('Pitsh', 'Px', 2)")
10 | exec(db, sql"INSERT INTO test2 VALUES('Sulphur', 1)")
11 | exec(db, sql"INSERT INTO test2 VALUES('Sulfur', 2)")
12 |
13 | var rows: seq[seq[string]]
14 |
15 | var cols: DbColumns
16 | for r in instantRows(db, cols,
17 | sql"""SELECT * FROM test1, test2 t2
18 | WHERE test1.c = t2.e
19 | ORDER BY a"""):
20 | rows.add(@[r[0], r[1], r[2], r[3]])
21 |
22 | doAssert cols.len == 5
23 | doAssert cols[0].name == "A"
24 | doAssert cols[0].tableName == "TEST1"
25 | doAssert cols[0].typ.kind == dbVarchar
26 | doAssert cols[1].name == "B"
27 | doAssert cols[1].tableName == "TEST1"
28 | doAssert cols[1].typ.kind == dbVarchar
29 | doAssert cols[2].name == "C"
30 | doAssert cols[2].tableName == "TEST1"
31 | doAssert cols[2].typ.kind == dbInt
32 | doAssert cols[3].name == "D"
33 | doAssert cols[3].tableName == "TEST2"
34 | doAssert cols[3].typ.kind == dbVarchar
35 | doAssert cols[4].name == "E"
36 | doAssert cols[4].tableName == "TEST2"
37 | doAssert cols[4].typ.kind == dbInt
38 |
39 | doAssert rows.len == 2
40 |
41 | rows = getAllRows(db,
42 | sql"""SELECT * FROM test2 t2, test1
43 | WHERE test1.c = t2.e
44 | ORDER BY e""")
45 | doAssert rows.len == 2
46 | doAssert rows[0][0] == "Sulphur"
47 | doAssert rows[0][1] == "1"
48 | doAssert rows[0][2] == "Pitch"
49 | doAssert rows[0][3] == "P"
50 | doAssert rows[0][4] == "1"
51 | doAssert rows[1][0] == "Sulfur"
52 | doAssert rows[1][1] == "2"
53 | doAssert rows[1][2] == "Pitsh"
54 | doAssert rows[1][3] == "Px"
55 | doAssert rows[1][4] == "2"
56 |
57 | rows = getAllRows(db,
58 | sql"""SELECT * FROM test1, test2 t2, test2 t3
59 | WHERE test1.c = t2.e AND t2.e = t3.e
60 | ORDER BY c, t2.e, t3.e""")
61 | doAssert rows.len == 4
62 | doAssert rows[0][0] == "Pitch"
63 | doAssert rows[0][1] == "P"
64 | doAssert rows[0][2] == "1"
65 | doAssert rows[0][3] == "Sulphur"
66 | doAssert rows[0][4] == "1"
67 | doAssert rows[0][5] == "Sulphur"
68 | doAssert rows[0][6] == "1"
69 | doAssert rows[1][0] == "Pitch"
70 | doAssert rows[1][1] == "P"
71 | doAssert rows[1][2] == "1"
72 | doAssert rows[1][3] == "Sulfur"
73 | doAssert rows[1][4] == "2"
74 | doAssert rows[1][5] == "Sulfur"
75 | doAssert rows[1][6] == "2"
76 | doAssert rows[2][0] == "Pitsh"
77 | doAssert rows[2][1] == "Px"
78 | doAssert rows[2][2] == "2"
79 | doAssert rows[2][3] == "Sulphur"
80 | doAssert rows[2][4] == "1"
81 | doAssert rows[2][5] == "Sulphur"
82 | doAssert rows[2][6] == "1"
83 | doAssert rows[3][0] == "Pitsh"
84 | doAssert rows[3][1] == "Px"
85 | doAssert rows[3][2] == "2"
86 | doAssert rows[3][3] == "Sulfur"
87 | doAssert rows[3][4] == "2"
88 | doAssert rows[3][5] == "Sulfur"
89 | doAssert rows[3][6] == "2"
90 |
91 | try:
92 | rows = getAllRows(db, sql"""SELECT * FROM test1, test2 t2, test2 t3
93 | WHERE test1.c = t2.e and t2.e = e""")
94 | raiseAssert("SELECT with ambiguous column refs succeeded")
95 | except DbError:
96 | discard
97 |
--------------------------------------------------------------------------------
/tests/insert_select.nim:
--------------------------------------------------------------------------------
1 | import db_nimternalsql
2 | import db_common
3 |
4 | let db = open("", "", "", "")
5 | exec(db, sql"CREATE TABLE tst (a int primary key, b char, c text)")
6 |
7 | exec(db, sql"INSERT INTO tst VALUES (1, 'a', 'Alpha')")
8 | exec(db, sql"INSERT INTO tst VALUES (2, 'b', 'Beta')")
9 | exec(db, sql"INSERT INTO tst VALUES (3, 'g', 'Gamma')")
10 |
11 | exec(db, sql"CREATE TABLE tst2 (b char primary key, c text)")
12 |
13 | doAssert execAffectedRows(db, sql"INSERT INTO tst2 SELECT b, c FROM tst") == 3
14 |
15 | var rows = getAllRows(db, sql"SELECT * FROM tst2 ORDER BY c")
16 | doAssert rows[0][0] == "a"
17 | doAssert rows[0][1] == "Alpha"
18 | doAssert rows[1][0] == "b"
19 | doAssert rows[1][1] == "Beta"
20 | doAssert rows[2][0] == "g"
21 | doAssert rows[2][1] == "Gamma"
22 |
23 | exec(db, sql"CREATE TABLE tst3 (x char primary key, y text)")
24 |
25 | doAssert execAffectedRows(db, sql"INSERT INTO tst3 (y, x) SELECT c, b FROM tst") == 3
26 |
27 | rows = getAllRows(db, sql"SELECT * FROM tst3 ORDER BY y")
28 | doAssert rows[0][0] == "a"
29 | doAssert rows[0][1] == "Alpha"
30 | doAssert rows[1][0] == "b"
31 | doAssert rows[1][1] == "Beta"
32 | doAssert rows[2][0] == "g"
33 | doAssert rows[2][1] == "Gamma"
34 |
35 | exec(db, sql"CREATE TABLE tst4 (y text default '-', x char primary key)")
36 |
37 | doAssert execAffectedRows(db,
38 | sql"INSERT INTO tst4 (x) SELECT b FROM tst WHERE b > ?",
39 | "g"
40 | ) == 0
41 |
42 | rows = getAllRows(db, sql"SELECT * FROM tst4 ORDER BY x")
43 | doAssert rows.len == 0
44 |
45 | doAssert execAffectedRows(db, sql"INSERT INTO tst4 (x) SELECT b FROM tst") == 3
46 |
47 | rows = getAllRows(db, sql"SELECT * FROM tst4 ORDER BY x")
48 | doAssert rows.len == 3
49 | doAssert rows[0][0] == "-"
50 | doAssert rows[0][1] == "a"
51 | doAssert rows[1][0] == "-"
52 | doAssert rows[1][1] == "b"
53 | doAssert rows[2][0] == "-"
54 | doAssert rows[2][1] == "g"
55 |
56 | close(db)
57 |
--------------------------------------------------------------------------------
/tests/intersect.nim:
--------------------------------------------------------------------------------
1 | import db_nimternalsql
2 | import db_common
3 |
4 | let db = open("", "", "", "")
5 | exec(db, sql"CREATE TABLE tst (a int, b text, c int primary key)")
6 | exec(db, sql"CREATE TABLE tst2 (a int, b text, c int, primary key(c, b))")
7 | exec(db, sql"INSERT INTO tst VALUES (1, 'ace', 1)")
8 | exec(db, sql"INSERT INTO tst VALUES (2, 'king', 2)")
9 | exec(db, sql"INSERT INTO tst VALUES (2, 'jack', 3)")
10 | exec(db, sql"INSERT INTO tst2 VALUES (2, 'king', 2)")
11 | exec(db, sql"INSERT INTO tst2 VALUES (3, 'queen', 2)")
12 | exec(db, sql"INSERT INTO tst2 VALUES (4, 'jack', 4)")
13 |
14 | var rows: seq[seq[string]]
15 | var cols: DbColumns
16 |
17 | for r in instantRows(db, cols,
18 | sql"""SELECT * FROM tst
19 | INTERSECT
20 | SELECT * FROM tst2
21 | ORDER BY c"""):
22 | rows.add(@[r[0], r[1], r[2]])
23 |
24 | doAssert cols.len == 3
25 | doAssert cols[0].name == "A"
26 | doAssert cols[0].typ.kind == dbInt
27 | doAssert cols[1].name == "B"
28 | doAssert cols[1].typ.kind == dbVarchar
29 | doAssert cols[2].name == "C"
30 | doAssert cols[2].typ.kind == dbInt
31 |
32 | doAssert rows.len == 1
33 | doAssert rows[0][0] == "2"
34 | doAssert rows[0][1] == "king"
35 | doAssert rows[0][2] == "2"
36 |
37 | exec(db, sql"CREATE TABLE tst3 (a int, b text primary key)")
38 | exec(db, sql"INSERT INTO tst3 VALUES (2, 'king')")
39 | exec(db, sql"INSERT INTO tst3 VALUES (2, 'jack')")
40 | exec(db, sql"INSERT INTO tst3 VALUES (3, 'ace')")
41 |
42 | rows = getAllRows(db, sql"""SELECT a, b FROM tst
43 | INTERSECT
44 | SELECT * FROM tst3
45 | ORDER BY b DESC""")
46 |
47 | doAssert rows.len == 2
48 | doAssert rows[0][0] == "2"
49 | doAssert rows[0][1] == "king"
50 | doAssert rows[1][0] == "2"
51 | doAssert rows[1][1] == "jack"
52 |
53 | rows = getAllRows(db, sql"""SELECT * FROM tst3
54 | INTERSECT
55 | SELECT a, b FROM tst
56 | ORDER BY b DESC""")
57 |
58 | doAssert rows.len == 2
59 | doAssert rows[0][0] == "2"
60 | doAssert rows[0][1] == "king"
61 | doAssert rows[1][0] == "2"
62 | doAssert rows[1][1] == "jack"
63 |
64 | rows = getAllRows(db, sql"""SELECT c FROM tst2
65 | INTERSECT
66 | SELECT c * 2 FROM tst
67 | WHERE c = 2
68 | ORDER BY c""")
69 |
70 | doAssert rows.len == 1
71 | doAssert rows[0][0] == "4"
72 |
73 | rows = getAllRows(db, sql"""SELECT a FROM tst
74 | INTERSECT ALL
75 | SELECT 2 AS a FROM tst""")
76 |
77 | doAssert rows.len == 2
78 | doAssert rows[0][0] == "2"
79 | doAssert rows[0][0] == "2"
80 |
81 | close(db)
82 |
--------------------------------------------------------------------------------
/tests/key.nim:
--------------------------------------------------------------------------------
1 | import db_nimternalsql
2 |
3 | let db = open("", "", "", "")
4 |
5 | try:
6 | exec(db, sql"CREATE TABLE tst (a int primary key, a text, c text)")
7 | raiseAssert("CREATE TABLE succeeded with two columns having the same name")
8 | except DbError as e:
9 | doAssert e.sqlState() == "42601"
10 |
11 | exec(db, sql"CREATE TABLE tst (a int primary key, b text, c text)")
12 |
13 | exec(db, sql"INSERT INTO tst VALUES (1, 'x', 'y')")
14 |
15 | var rows = getAllRows(db, sql"SELECT * FROM tst WHERE a = 1")
16 | doAssert rows.len == 1
17 | doAssert rows[0][0] == "1"
18 | doAssert rows[0][1] == "x"
19 | doAssert rows[0][2] == "y"
20 |
21 | try:
22 | exec(db, sql"CREATE TABLE tst (a int, b text, c text, primary key(a, b))")
23 | raiseAssert("CREATE TABLE recreating existing table succeeded")
24 | except DbError as e:
25 | doAssert e.sqlState() == "42N01"
26 |
27 | try:
28 | exec(db, sql"INSERT INTO tst VALUES (1, 'x', 'z ')")
29 | raiseAssert("INSERT succeeded with same key")
30 | except DbError as e:
31 | doAssert e.sqlState() == "23505"
32 |
33 | exec(db, sql"CREATE TABLE tst2 (a int, b text, c text, primary key(b, a))")
34 |
35 | exec(db, sql"INSERT INTO tst2 VALUES (1, 'x', 'y')")
36 |
37 | rows = getAllRows(db, sql"SELECT * FROM tst2 WHERE a = 1 AND b = ?", "x")
38 | doAssert rows.len == 1
39 | doAssert rows[0][0] == "1"
40 | doAssert rows[0][1] == "x"
41 | doAssert rows[0][2] == "y"
42 |
43 | rows = getAllRows(db, sql"SELECT * FROM tst2 WHERE a = 1 AND b = 'x' AND c ='Y'")
44 | doAssert rows.len == 0
45 |
46 | rows = getAllRows(db, sql"SELECT * FROM tst2 WHERE a = 1")
47 | doAssert rows.len == 1
48 | doAssert rows[0][0] == "1"
49 | doAssert rows[0][1] == "x"
50 | doAssert rows[0][2] == "y"
51 |
52 | rows = getAllRows(db, sql"SELECT a, b FROM tst2 WHERE a = 1 AND b = 'x'")
53 | doAssert rows.len == 1
54 | doAssert rows[0].len == 2
55 | doAssert rows[0][0] == "1"
56 | doAssert rows[0][1] == "x"
57 |
58 | try:
59 | exec(db, sql"INSERT INTO tst2 VALUES (1, 'x', 'y')")
60 | raiseAssert("INSERT succeeded with same key")
61 | except DbError as e:
62 | doAssert e.sqlState() == "23505"
63 |
--------------------------------------------------------------------------------
/tests/leftjoin.nim:
--------------------------------------------------------------------------------
1 | import db_nimternalsql
2 |
3 | let db = open("", "", "", "")
4 | exec(db, sql"CREATE TABLE emp (empno int primary key, first_name text not null, last_name text)")
5 | exec(db, sql"CREATE TABLE emp_team (empno int, team_name text, primary key (empno, team_name))")
6 | exec(db, sql"CREATE TABLE emp2 (no int primary key, first_name text not null, last_name text, team_name text)")
7 |
8 | exec(db, sql"INSERT INTO emp VALUES(1, 'Bob', 'Base')")
9 | exec(db, sql"INSERT INTO emp VALUES(2, 'Daisy', 'Database')")
10 | exec(db, sql"INSERT INTO emp_team VALUES(1, 'Team A')")
11 | exec(db, sql"INSERT INTO emp_team VALUES(2, 'Team B')")
12 | exec(db, sql"INSERT INTO emp_team VALUES(3, 'Team C')")
13 | exec(db, sql"INSERT INTO emp2 VALUES(1, 'Bob', 'Base', 'Team A')")
14 | exec(db, sql"INSERT INTO emp2 VALUES(4, 'Dusty', 'Database', 'Team C')")
15 |
16 | var rows = getAllRows(db, sql"""SELECT * FROM emp_team t
17 | LEFT JOIN emp ON t.empno = emp.empno
18 | WHERE t.empno <= 2
19 | ORDER BY last_name""")
20 | doAssert rows.len == 2
21 | doAssert rows[0][0] == "1"
22 | doAssert rows[0][1] == "Team A"
23 | doAssert rows[0][2] == "1"
24 | doAssert rows[0][3] == "Bob"
25 | doAssert rows[0][4] == "Base"
26 | doAssert rows[1][0] == "2"
27 | doAssert rows[1][1] == "Team B"
28 | doAssert rows[1][2] == "2"
29 | doAssert rows[1][3] == "Daisy"
30 | doAssert rows[1][4] == "Database"
31 |
32 | rows = getAllRows(db, sql"""SELECT * FROM emp_team LEFT OUTER JOIN emp2
33 | ON no = empno
34 | ORDER BY emp_team.team_name""")
35 | doAssert rows.len == 3
36 | doAssert rows[0][0] == "1"
37 | doAssert rows[0][1] == "Team A"
38 | doAssert rows[0][2] == "1"
39 | doAssert rows[0][3] == "Bob"
40 | doAssert rows[0][4] == "Base"
41 | doAssert rows[1][0] == "2"
42 | doAssert rows[1][1] == "Team B"
43 | doAssert rows[1][2] == ""
44 | doAssert rows[1][3] == ""
45 | doAssert rows[1][4] == ""
46 | doAssert rows[2][0] == "3"
47 | doAssert rows[2][1] == "Team C"
48 | doAssert rows[2][2] == ""
49 | doAssert rows[2][3] == ""
50 | doAssert rows[2][4] == ""
51 |
52 | rows = getAllRows(db, sql"""SELECT * FROM emp_team LEFT JOIN emp2
53 | ON emp_team.team_name = emp2.team_name
54 | ORDER BY emp_team.team_name""")
55 | doAssert rows.len == 3
56 | doAssert rows[0][0] == "1"
57 | doAssert rows[0][1] == "Team A"
58 | doAssert rows[0][2] == "1"
59 | doAssert rows[0][3] == "Bob"
60 | doAssert rows[0][4] == "Base"
61 | doAssert rows[0][5] == "Team A"
62 | doAssert rows[1][0] == "2"
63 | doAssert rows[1][1] == "Team B"
64 | doAssert rows[1][2] == ""
65 | doAssert rows[1][3] == ""
66 | doAssert rows[1][4] == ""
67 | doAssert rows[1][5] == ""
68 | doAssert rows[2][0] == "3"
69 | doAssert rows[2][1] == "Team C"
70 | doAssert rows[2][2] == "4"
71 | doAssert rows[2][3] == "Dusty"
72 | doAssert rows[2][4] == "Database"
73 | doAssert rows[2][5] == "Team C"
74 |
--------------------------------------------------------------------------------
/tests/like.nim:
--------------------------------------------------------------------------------
1 | import db_nimternalsql/like
2 |
3 | doAssert matchesLike("", "")
4 | doAssert matchesLike("", "%")
5 | doAssert matchesLike("Grummel", "%")
6 | doAssert matchesLike("Grummel", "%_")
7 | doAssert matchesLike("Grummel", "%umme%")
8 | doAssert matchesLike("Grummel", "%ru%me%")
9 | doAssert matchesLike("Grummel", "Grum%mel")
10 | doAssert matchesLike("Grummel", "Grum%mel")
11 | doAssert matchesLike("Grummel", "Grum_el")
12 | doAssert matchesLike("Grummel", "Gr%l")
13 | doAssert matchesLike("Grummel", "Gr%m%l")
14 | doAssert matchesLike("Grummel", "Gru__el")
15 | doAssert matchesLike("Blabli", "%l_")
16 | doAssert matchesLike("Blabli", "%l%")
17 | doAssert matchesLike("Sql", "Sq_")
18 | doAssert matchesLike("Abrakadabra", "%ra_ad%")
19 |
20 | doAssert not matchesLike(" ", "")
21 | doAssert not matchesLike("", "_")
22 | doAssert not matchesLike("Grummel", "%umme")
23 | doAssert not matchesLike("Grummel", "umme%")
24 | doAssert not matchesLike("Grummel", "Gru_el")
25 | doAssert not matchesLike("Grummel", "Gr%ml")
26 | doAssert not matchesLike("Blabli", "%la_")
27 | doAssert not matchesLike("Abrakadabra", "%ra_ab%")
28 |
--------------------------------------------------------------------------------
/tests/nim.cfg:
--------------------------------------------------------------------------------
1 | --path:"../src/"
2 |
--------------------------------------------------------------------------------
/tests/null.nim:
--------------------------------------------------------------------------------
1 | import db_nimternalsql
2 |
3 | let db = open("", "", "", "")
4 | exec(db, sql"CREATE TABLE tst (a int primary key, b text, c text, d text NOT NULL)")
5 | exec(db, sql"INSERT INTO tst VALUES (1, NULL, 'yo', 'x')")
6 | exec(db, sql"INSERT INTO tst (a, b, d) VALUES (2, 'yoyo', 'y')")
7 | exec(db, sql"INSERT INTO tst (a, c, d) VALUES (3, NULL, 'z')")
8 | exec(db, sql"INSERT INTO tst VALUES (4, NULL, NULL, 'z')")
9 |
10 | try:
11 | exec(db, sql"INSERT INTO tst (a, c, d) VALUES (3, NULL, NULL)")
12 | raiseAssert("INSERT with non-nullable column set to NULL should fail")
13 | except DbError:
14 | discard
15 |
16 | var res: seq[seq[string]]
17 |
18 | for r in instantRows(db, sql"SELECT * FROM tst ORDER BY a"):
19 | res.add(@[r[0], r[1], r[2], r[3]])
20 | doAssert res.len == 4
21 | doAssert res[0][0] == "1"
22 | doAssert res[0][1] == ""
23 | doAssert res[0][2] == "yo"
24 | doAssert res[0][3] == "x"
25 | doAssert res[1][0] == "2"
26 | doAssert res[1][1] == "yoyo"
27 | doAssert res[1][2] == ""
28 | doAssert res[1][3] == "y"
29 | doAssert res[2][0] == "3"
30 | doAssert res[2][1] == ""
31 | doAssert res[2][2] == ""
32 | doAssert res[2][3] == "z"
33 | doAssert res[3][0] == "4"
34 | doAssert res[3][1] == ""
35 | doAssert res[3][2] == ""
36 | doAssert res[3][3] == "z"
37 |
38 | var count = 0
39 | for r in instantRows(db, sql"SELECT * FROM tst WHERE a = NULL"):
40 | count += 1
41 | doAssert count == 0
42 |
43 | var rows = getAllRows(db, sql"SELECT b FROM tst WHERE a IN (?, ?) ORDER BY b", 1, 2)
44 | doAssert rows.len == 2
45 | doAssert rows[0][0] == ""
46 | doAssert rows[1][0] == "yoyo"
47 |
48 | exec(db, sql"UPDATE tst SET b = NULL WHERE a = 2")
49 |
50 | res = @[]
51 | for r in instantRows(db, sql"SELECT * FROM tst WHERE a = 2 AND b IS NULL"):
52 | res.add(@[r[0], r[1], r[2], r[3]])
53 | doAssert res.len == 1
54 | doAssert res[0][0] == "2"
55 | doAssert res[0][1] == ""
56 | doAssert res[0][2] == ""
57 | doAssert res[0][3] == "y"
58 |
59 | res = @[]
60 | for r in instantRows(db, sql"SELECT * FROM tst WHERE c IS NOT NULL"):
61 | res.add(@[r[0], r[1], r[2], r[3]])
62 | doAssert res.len == 1
63 | doAssert res[0][0] == "1"
64 | doAssert res[0][1] == ""
65 | doAssert res[0][2] == "yo"
66 | doAssert res[0][3] == "x"
67 |
68 | # Error
69 | try:
70 | exec(db, sql"UPDATE tst SET a = NULL WHERE a = 2")
71 | raiseAssert("UPDATE setting primary key to NULL should fail")
72 | except DbError:
73 | discard
74 |
75 | try:
76 | exec(db, sql"UPDATE tst SET d = NULL WHERE a = 2")
77 | raiseAssert("UPDATE setting non-null column to NULL should fail")
78 | except DbError:
79 | discard
80 |
81 | doAssert getValue(db, sql"SELECT TRUE OR b FROM tst WHERE a = 4") == ""
82 |
--------------------------------------------------------------------------------
/tests/numeric.nim:
--------------------------------------------------------------------------------
1 | import db_nimternalsql
2 | import db_common
3 | import strutils
4 |
5 | let db = open("", "", "", "")
6 | exec(db, sql"""CREATE TABLE tst
7 | (a int primary key, b numeric, c numeric(10), d numeric(18, 5),
8 | e real, f integer, g double precision, h bigint)""")
9 |
10 | doAssert execAffectedRows(db, sql"INSERT INTO tst VALUES (1, 2, 3.6, 1200.004, 130.12, 7, 1.7e6, 9223372036854775807)") == 1
11 |
12 | var res: seq[Row]
13 |
14 | for r in rows(db, sql"SELECT * FROM tst"):
15 | res.add(r)
16 |
17 | doAssert res.len == 1
18 | doAssert res[0][0] == "1"
19 | doAssert res[0][1] == "2"
20 | doAssert res[0][2] == "4"
21 | doAssert res[0][3] == "1200.00400"
22 | doAssert res[0][4] == "130.12"
23 | doAssert res[0][5] == "7"
24 | doAssert parseFloat(res[0][6]) == 1.7e6
25 | doAssert res[0][7] == "9223372036854775807"
26 |
27 | res = getAllRows(db, sql"SELECT t.d * 2, t.e * 2, t.d * 2.1, 1.1 * t.e, d + f, h - b FROM tst t")
28 |
29 | doAssert res.len == 1
30 | doAssert parseFloat(res[0][0]) == 2400.008
31 | doAssert res[0][1] == "260.24"
32 | doAssert parseFloat(res[0][2]) == 2520.0084
33 | doAssert res[0][3] == "143.132"
34 | doAssert parseFloat(res[0][4]) == 1207.004
35 | doAssert res[0][5] == "9223372036854775805"
36 |
37 | res = getAllRows(db,
38 | sql"""SELECT ? + ?, 5.5 + 200.25, 20 - ?, ? / ?,
39 | CASE
40 | WHEN tst.b > 1000 THEN 'Very high'
41 | WHEN tst.b > 100 THEN 'High'
42 | WHEN tst.b > 10 THEN 'Medium'
43 | WHEN tst.b > 1 THEN 'Low'
44 | ELSE 'Very low'
45 | END,
46 | CASE tst.f
47 | WHEN 6 THEN 'Six'
48 | WHEN 7 THEN 'Seven'
49 | WHEN 8 THEN 'Eight'
50 | ELSE 'Other'
51 | END,
52 | CASE tst.f
53 | WHEN 6 THEN 'Six'
54 | END
55 | FROM tst""",
56 | "3", "2", "1.1", "5", "2")
57 |
58 | doAssert res.len == 1
59 | doAssert res[0][0] == "5"
60 | doAssert res[0][1] == "205.75"
61 | doAssert res[0][2] == "18.9"
62 | doAssert res[0][3] == "2.5"
63 | doAssert res[0][4] == "Low"
64 | doAssert res[0][5] == "Seven"
65 | doAssert res[0][6] == ""
66 |
67 | try:
68 | exec(db, sql"UPDATE tst SET f = h")
69 | raiseAssert("updating integer column with large bigint succeeded")
70 | except DbError:
71 | discard
72 |
73 | exec(db, sql"UPDATE tst SET f = h / 100000000000000")
74 |
75 | exec(db, sql"CREATE TABLE tst2 (a decimal primary key, b decimal(10), c dec(18, 8))")
76 |
77 | doAssert execAffectedRows(db, sql"INSERT INTO tst2 VALUES (1, 12345678901, 1111111111.11111111)") == 1
78 |
79 | res = @[]
80 | var cols: DbColumns
81 | for r in instantRows(db, cols, sql"SELECT a, b, c, c + 1000000000.00000001, a + 1 a1 FROM tst2"):
82 | res.add(@[r[0], r[1], r[2], r[3]])
83 |
84 | doAssert cols.len == 5
85 | doAssert cols[0].name == "A"
86 | doAssert cols[0].typ.kind == dbDecimal
87 | doAssert cols[1].name == "B"
88 | doAssert cols[1].typ.kind == dbDecimal
89 | doAssert cols[2].name == "C"
90 | doAssert cols[2].typ.kind == dbDecimal
91 | doAssert cols[3].name == ""
92 | doAssert cols[3].typ.kind == dbUnknown
93 | doAssert cols[4].name == "A1"
94 | doAssert cols[4].typ.kind == dbUnknown
95 |
96 | doAssert res[0][0] == "1"
97 | doAssert res[0][1] == "12345678901"
98 | doAssert res[0][2] == "1111111111.11111111"
99 | doAssert res[0][3] == "2111111111.11111112"
100 |
101 | exec(db, sql"UPDATE tst SET d = 12345.123455, f = 12345.5")
102 |
103 | var r = getRow(db, sql"SELECT d, f FROM tst")
104 | doAssert r[0] == "12345.12346"
105 | doAssert r[1] == "12346"
106 |
107 | doAssert getValue(db, sql"SELECT COUNT(*) FROM tst WHERE b <= ?", "2") == "1"
108 |
109 | try:
110 | exec(db, sql"UPDATE tst set d = 12345678901234.1234")
111 | raiseAssert("UPDATE succeded although value was too large")
112 | except DbError:
113 | discard
114 |
115 | close(db)
116 |
--------------------------------------------------------------------------------
/tests/order.nim:
--------------------------------------------------------------------------------
1 | import db_nimternalsql
2 |
3 | let db = open("", "", "", "")
4 | exec(db, sql"CREATE TABLE tst (a int PRIMARY KEY, b text, c text)")
5 | exec(db, sql"INSERT INTO tst VALUES (1, 'y', 'ace')")
6 | exec(db, sql"INSERT INTO tst VALUES (2, 'x', 'king')")
7 | exec(db, sql"INSERT INTO tst VALUES (3, 'y', 'queen')")
8 | exec(db, sql"INSERT INTO tst VALUES (4, 'x', 'jack')")
9 |
10 | var rows = getAllRows(db, sql"SELECT * FROM tst t ORDER BY b, t.a")
11 | doAssert rows.len == 4
12 | doAssert rows[0][0] == "2"
13 | doAssert rows[0][1] == "x"
14 | doAssert rows[0][2] == "king"
15 | doAssert rows[1][0] == "4"
16 | doAssert rows[1][1] == "x"
17 | doAssert rows[1][2] == "jack"
18 | doAssert rows[2][0] == "1"
19 | doAssert rows[2][1] == "y"
20 | doAssert rows[2][2] == "ace"
21 | doAssert rows[3][0] == "3"
22 | doAssert rows[3][1] == "y"
23 | doAssert rows[3][2] == "queen"
24 |
25 | rows = getAllRows(db, sql"SELECT a, b, c, a + 1 AS a1 FROM tst t ORDER BY a1 DESC")
26 | doAssert rows.len == 4
27 | doAssert rows[0][0] == "4"
28 | doAssert rows[0][1] == "x"
29 | doAssert rows[0][2] == "jack"
30 | doAssert rows[1][0] == "3"
31 | doAssert rows[1][1] == "y"
32 | doAssert rows[1][2] == "queen"
33 | doAssert rows[2][0] == "2"
34 | doAssert rows[2][1] == "x"
35 | doAssert rows[2][2] == "king"
36 | doAssert rows[3][0] == "1"
37 | doAssert rows[3][1] == "y"
38 | doAssert rows[3][2] == "ace"
39 |
--------------------------------------------------------------------------------
/tests/prepared.nim:
--------------------------------------------------------------------------------
1 | import db_nimternalsql
2 |
3 | let db = open("", "", "", "")
4 | exec(db, sql"CREATE TABLE tst (a int primary key, b char, c text)")
5 |
6 | exec(db, prepare(db, sql"INSERT INTO tst VALUES ($1, $2, $3)"), "1", "y", "Yoyoo")
7 |
8 | doAssert tryExec(db, prepare(db, sql"INSERT INTO tst VALUES ($1, $2, $3)"),
9 | "2", "c", "Xox") == true
10 |
11 | doAssert execAffectedRows(db, prepare(db, sql"INSERT INTO tst VALUES ($1, $2, $3)"),
12 | "3", "d", "bloo") == 1
13 |
14 | var res: seq[seq[string]]
15 | for r in instantRows(db, prepare(db, sql"SELECT * FROM tst WHERE a <= $1 ORDER BY a"), "2"):
16 | res.add(@[r[0], r[1], r[2]])
17 |
18 | doAssert res.len == 2
19 | doAssert res[0][0] == "1"
20 | doAssert res[0][1] == "y"
21 | doAssert res[0][2] == "Yoyoo"
22 | doAssert res[1][0] == "2"
23 | doAssert res[1][1] == "c"
24 | doAssert res[1][2] == "Xox"
25 |
26 | res = @[]
27 | for r in rows(db, prepare(db, sql"SELECT * FROM tst WHERE a <= $1 ORDER BY a"), "2"):
28 | res.add(@[r[0], r[1], r[2]])
29 |
30 | doAssert res.len == 2
31 | doAssert res[0][0] == "1"
32 | doAssert res[0][1] == "y"
33 | doAssert res[0][2] == "Yoyoo"
34 | doAssert res[1][0] == "2"
35 | doAssert res[1][1] == "c"
36 | doAssert res[1][2] == "Xox"
37 |
38 | res = getAllRows(db, prepare(db, sql"SELECT * FROM tst WHERE a >= $1 ORDER BY b"), "2")
39 |
40 | doAssert res.len == 2
41 | doAssert res[0][0] == "2"
42 | doAssert res[0][1] == "c"
43 | doAssert res[0][2] == "Xox"
44 | doAssert res[1][0] == "3"
45 | doAssert res[1][1] == "d"
46 | doAssert res[1][2] == "bloo"
47 |
48 | let row = getRow(db, prepare(db, sql"SELECT * FROM tst WHERE a = $1"), "1")
49 | doAssert row[0] == "1"
50 | doAssert row[1] == "y"
51 | doAssert row[2] == "Yoyoo"
52 |
53 | let val = getValue(db, prepare(db, sql"SELECT c FROM tst WHERE a = $1"), "1")
54 | doAssert val == "Yoyoo"
55 |
--------------------------------------------------------------------------------
/tests/rollback.nim:
--------------------------------------------------------------------------------
1 | import db_nimternalsql
2 |
3 | let db = open("", "", "", "")
4 | exec(db, sql"CREATE TABLE tst (a int primary key, b int, c text)")
5 | exec(db, sql"CREATE TABLE tst2 (a int primary key, s text)")
6 |
7 | exec(db, sql"INSERT INTO tst VALUES (1, 2, 'yo')")
8 | exec(db, sql"INSERT INTO tst VALUES (2, 3, 'ya')")
9 |
10 | db.setAutocommit(false)
11 | exec(db, sql"INSERT INTO tst VALUES (3, 3, 'yai')")
12 |
13 | exec(db, sql"UPDATE tst SET a = a + 10 WHERE b = 3")
14 | exec(db, sql"UPDATE tst SET c = 'yi' WHERE a = 1")
15 |
16 | exec(db, sql"DELETE FROM tst WHERE a = 12");
17 |
18 | exec(db, sql"DROP TABLE tst2")
19 |
20 | exec(db, sql"CREATE TABLE tst3 (a int primary key, s text)")
21 |
22 | exec(db, sql"INSERT INTO tst3 VALUES (1, 'xoo')")
23 |
24 | exec(db, sql"ROLLBACK")
25 |
26 | var rows = getAllRows(db, sql"SELECT * FROM tst ORDER BY a")
27 | doAssert rows.len == 2
28 | doAssert rows[0][0] == "1"
29 | doAssert rows[0][1] == "2"
30 | doAssert rows[0][2] == "yo"
31 | doAssert rows[1][0] == "2"
32 | doAssert rows[1][1] == "3"
33 | doAssert rows[1][2] == "ya"
34 |
35 | # tst2 must exist again
36 | rows = getAllRows(db, sql"SELECT * FROM tst2")
37 |
38 | # tst3 must be have been dropped by the rollback
39 | try:
40 | rows = getAllRows(db, sql"SELECT * FROM tst3")
41 | raiseAssert("Accessing tst3 was succeeded")
42 | except DbError:
43 | # ok
44 | discard
45 |
46 | db.close()
47 |
--------------------------------------------------------------------------------
/tests/snapshots.nim:
--------------------------------------------------------------------------------
1 | import db_nimternalsql
2 |
3 | var db = open("", "", "", "")
4 | exec(db, sql"""CREATE TABLE tst(
5 | a int primary key,
6 | b numeric(10,5) DEFAULT 1.23,
7 | c integer,
8 | d text,
9 | e varchar(40),
10 | f real,
11 | g bigint,
12 | h time,
13 | k date)""")
14 |
15 | exec(db, sql"INSERT INTO tst VALUES (1, 3.6, 1200, 'Water', 'Fire', 7.8, 9223372036854775805, '17:05:06', '1901-05-02')")
16 |
17 | exec(db, sql"""CREATE TABLE tstdef(
18 | a int primary key,
19 | t time default '11:11:00',
20 | d date default '2007-06-05',
21 | ts timestamp default '2000-01-01 09:00:00.50000',
22 | ts3 timestamp(3) default '2020-02-01 14:00:00.123')""")
23 |
24 | save(db, "snapshot.dump")
25 |
26 | db = open("", "", "", "")
27 | restore(db, "snapshot.dump")
28 |
29 | exec(db, sql"INSERT INTO tst (a, c, d, e, f, g) VALUES (2, 2000, 'Wine', 'Earth', 1.5e5, 1000)")
30 |
31 | let rows = getAllRows(db, sql"SELECT * FROM tst ORDER BY a")
32 |
33 | doAssert rows.len == 2
34 | doAssert rows[0][0] == "1"
35 | doAssert rows[0][1] == "3.60000"
36 | doAssert rows[0][2] == "1200"
37 | doAssert rows[0][3] == "Water"
38 | doAssert rows[0][4] == "Fire"
39 | doAssert rows[0][5] == "7.8"
40 | doAssert rows[0][6] == "9223372036854775805"
41 | doAssert rows[0][7] == "17:05:06"
42 | doAssert rows[0][8] == "1901-05-02"
43 | doAssert rows[1][0] == "2"
44 | doAssert rows[1][1] == "1.23000"
45 | doAssert rows[1][2] == "2000"
46 | doAssert rows[1][3] == "Wine"
47 | doAssert rows[1][4] == "Earth"
48 | doAssert rows[1][5] == "150000.0"
49 | doAssert rows[1][6] == "1000"
50 |
51 | exec(db, sql"""INSERT INTO tstdef (a) values(1)""")
52 |
53 | let row = getRow(db, sql"""SELECT t, d, ts, ts3 FROM tstdef""")
54 | assert row[0] == "11:11:00"
55 | assert row[1] == "2007-06-05"
56 | assert row[2] == "2000-01-01 09:00:00.500000"
57 | assert row[3] == "2020-02-01 14:00:00.123"
58 |
--------------------------------------------------------------------------------
/tests/subqueries.nim:
--------------------------------------------------------------------------------
1 | import db_nimternalsql
2 | import parseutils
3 |
4 | let db = open("", "", "", "")
5 | exec(db, sql"CREATE TABLE s (sno integer primary key, sname text)")
6 | exec(db, sql"CREATE TABLE sp (sno integer, pno integer, primary key(sno, pno))")
7 |
8 | exec(db, sql"INSERT INTO s VALUES(1, 'one')")
9 | exec(db, sql"INSERT INTO s VALUES(2, 'two')")
10 | exec(db, sql"INSERT INTO s VALUES(3, 'three')")
11 | exec(db, sql"INSERT INTO s VALUES(4, 'four')")
12 | exec(db, sql"INSERT INTO sp VALUES(1, 1)")
13 | exec(db, sql"INSERT INTO sp VALUES(2, 2)")
14 | exec(db, sql"INSERT INTO sp VALUES(3, 1)")
15 | exec(db, sql"INSERT INTO sp VALUES(4, 3)")
16 |
17 | var res = getAllRows(db, sql"""SELECT s.sname FROM s
18 | WHERE EXISTS (
19 | SELECT * FROM sp
20 | WHERE sp.pno = s.sno)
21 | ORDER BY s.sname""")
22 | doAssert res.len == 3
23 | doAssert res[0][0] == "one"
24 | doAssert res[1][0] == "three"
25 | doAssert res[2][0] == "two"
26 |
27 | res = getAllRows(db, sql"""SELECT DISTINCT s.sname FROM s
28 | WHERE 1 IN (
29 | SELECT sp.pno FROM sp
30 | WHERE sp.sno = s.sno)
31 | ORDER BY s.sname DESC""")
32 | doAssert res.len == 2
33 | doAssert res[0][0] == "three"
34 | doAssert res[1][0] == "one"
35 |
36 | res = getAllRows(db, sql"""SELECT DISTINCT s.sname FROM s
37 | WHERE s.sno = (
38 | SELECT sp.sno FROM sp
39 | WHERE sp.pno = 3) AND TRUE""")
40 | doAssert res.len == 1
41 | doAssert res[0][0] == "four"
42 |
43 | res = getAllRows(db, sql"""SELECT DISTINCT s.sname FROM s
44 | WHERE s.sno = (
45 | SELECT sp.sno FROM sp
46 | WHERE sp.pno = 3) AND FALSE""")
47 | doAssert res.len == 0
48 |
49 | res = getAllRows(db, sql"""SELECT * FROM s
50 | WHERE sname = (SELECT MIN(sname) FROM s)""")
51 | doAssert res.len == 1
52 | doAssert res[0][0] == "4"
53 | doAssert res[0][1] == "four"
54 |
55 | res = getAllRows(db, sql"""SELECT * FROM s
56 | WHERE sname = (SELECT MAX(sname) FROM s)""")
57 | doAssert res.len == 1
58 | doAssert res[0][0] == "2"
59 | doAssert res[0][1] == "two"
60 |
61 | exec(db, sql"CREATE TABLE employees (name text primary key, department int, salary int)")
62 | exec(db, sql"INSERT INTO employees VALUES('Fred', 1, 2000)")
63 | exec(db, sql"INSERT INTO employees VALUES('John', 2, 1200)")
64 | exec(db, sql"INSERT INTO employees VALUES('Laura', 1, 2200)")
65 |
66 | res = getAllRows(db,
67 | sql"""SELECT
68 | name,
69 | (SELECT AVG(salary)
70 | FROM employees
71 | WHERE department = emp.department),
72 | (SELECT SUM(salary)
73 | FROM employees
74 | WHERE department = emp.department)
75 | FROM employees emp
76 | ORDER by name""")
77 |
78 | doAssert res.len == 3
79 | var num: int
80 | doAssert res[0][0] == "Fred"
81 | discard parseInt(res[0][1], num)
82 | doAssert num == 2100
83 | doAssert res[0][2] == "4200"
84 | doAssert res[1][0] == "John"
85 | discard parseInt(res[1][1], num)
86 | doAssert num == 1200
87 | doAssert res[1][2] == "1200"
88 | doAssert res[2][0] == "Laura"
89 | discard parseInt(res[2][1], num)
90 | doAssert num == 2100
91 | doAssert res[2][2] == "4200"
92 |
--------------------------------------------------------------------------------
/tests/txlog.nim:
--------------------------------------------------------------------------------
1 | import db_nimternalsql
2 | import os
3 |
4 | removeDir("db")
5 |
6 | var db = open("db", "", "", "")
7 | exec(db, sql"""CREATE TABLE tst
8 | (a int primary key, b numeric(10,5) DEFAULT 1.23, c integer, d text, e varchar(40),
9 | f real)""")
10 |
11 | exec(db, sql"INSERT INTO tst VALUES (1, 3.6, 1200, 'Water', 'Fire', 7.8)")
12 |
13 | exec(db, sql"INSERT INTO tst VALUES (2, 7.6, 200, 'Earth', 'Fire', 7.7)")
14 |
15 | exec(db, sql"DELETE FROM tst WHERE a = 2")
16 |
17 | close(db)
18 |
19 | db = open("db", "", "", "")
20 |
21 | exec(db, sql"INSERT INTO tst (a, c, d, e, f) VALUES (2, 2000, 'Wine', 'Earth', 1.5e5)")
22 |
23 | let rows = getAllRows(db, sql"SELECT * FROM tst ORDER BY a")
24 |
25 | doAssert rows.len == 2
26 | doAssert rows[0][0] == "1"
27 | doAssert rows[0][1] == "3.60000"
28 | doAssert rows[0][2] == "1200"
29 | doAssert rows[0][3] == "Water"
30 | doAssert rows[0][4] == "Fire"
31 | doAssert rows[0][5] == "7.8"
32 | doAssert rows[1][0] == "2"
33 | doAssert rows[1][1] == "1.23000"
34 | doAssert rows[1][2] == "2000"
35 | doAssert rows[1][3] == "Wine"
36 | doAssert rows[1][4] == "Earth"
37 | doAssert rows[1][5] == "150000.0"
38 |
--------------------------------------------------------------------------------
/tests/txlog_snapshot.nim:
--------------------------------------------------------------------------------
1 | import db_nimternalsql
2 | import os
3 |
4 | removeDir("db")
5 |
6 | var db = open("db", "", "", "")
7 | exec(db, sql"""CREATE TABLE tst
8 | (a int primary key, b numeric(10,5) DEFAULT 1.23, c integer, d text, e varchar(40),
9 | f real)""")
10 |
11 | exec(db, sql"INSERT INTO tst VALUES (1, 3.6, 1200, 'Water', 'Fire', 7.8)")
12 |
13 | exec(db, sql"INSERT INTO tst VALUES (2, 7.6, 200, 'Earth', 'Fire', 7.7)")
14 |
15 | exec(db, sql"DELETE FROM tst WHERE a = 2")
16 |
17 | exec(db, sql"""CREATE TABLE ttst
18 | (t time primary key, d date, ts timestamp, t3 time(3), ts2 timestamp(2))""")
19 |
20 | exec(db, sql"""INSERT INTO ttst VALUES ('20:05:10', '1950-05-11', '2002-03-05 15:16:17.654321',
21 | time '23:10:11.234',
22 | timestamp '1901-01-02 03:04:05.56')""")
23 |
24 | save(db)
25 |
26 | exec(db, sql"INSERT INTO tst (a, c, d, e, f) VALUES (3, 2000, 'Wine', 'Earth', 1.5e5)")
27 |
28 | close(db)
29 |
30 | db = open("db", "", "", "")
31 |
32 | var rows = getAllRows(db, sql"SELECT * FROM tst ORDER BY a")
33 |
34 | doAssert rows.len == 2
35 | doAssert rows[0][0] == "1"
36 | doAssert rows[0][1] == "3.60000"
37 | doAssert rows[0][2] == "1200"
38 | doAssert rows[0][3] == "Water"
39 | doAssert rows[0][4] == "Fire"
40 | doAssert rows[0][5] == "7.8"
41 | doAssert rows[1][0] == "3"
42 | doAssert rows[1][1] == "1.23000"
43 | doAssert rows[1][2] == "2000"
44 | doAssert rows[1][3] == "Wine"
45 | doAssert rows[1][4] == "Earth"
46 | doAssert rows[1][5] == "150000.0"
47 |
48 | rows = getAllRows(db, sql"SELECT * FROM ttst")
49 |
50 | doAssert rows.len == 1
51 | doAssert rows[0][0] == "20:05:10"
52 | doAssert rows[0][1] == "1950-05-11"
53 | doAssert rows[0][2] == "2002-03-05 15:16:17.654321"
54 | doAssert rows[0][3] == "23:10:11.234"
55 | doAssert rows[0][4] == "1901-01-02 03:04:05.56"
56 |
57 | close(db)
58 |
--------------------------------------------------------------------------------
/tests/union.nim:
--------------------------------------------------------------------------------
1 | import db_nimternalsql
2 | import db_common
3 |
4 | let db = open("", "", "", "")
5 | exec(db, sql"CREATE TABLE tst (a int primary key, b text)")
6 | exec(db, sql"CREATE TABLE tst2 (a int primary key, b text)")
7 | exec(db, sql"INSERT INTO tst VALUES (1, 'ace')")
8 | exec(db, sql"INSERT INTO tst VALUES (2, 'king')")
9 | exec(db, sql"INSERT INTO tst2 VALUES (2, 'king')")
10 | exec(db, sql"INSERT INTO tst2 VALUES (3, 'queen')")
11 | exec(db, sql"INSERT INTO tst2 VALUES (4, 'jack')")
12 |
13 | var rows: seq[seq[string]]
14 | var cols: DbColumns
15 | for r in instantRows(db, cols,
16 | sql"""SELECT * FROM tst
17 | UNION
18 | SELECT * FROM tst2
19 | ORDER BY a"""):
20 | rows.add(@[r[0], r[1]])
21 |
22 | doAssert cols.len == 2
23 | doAssert cols[0].name == "A"
24 | doAssert cols[0].typ.kind == dbInt
25 | doAssert cols[1].name == "B"
26 | doAssert cols[1].typ.kind == dbVarchar
27 |
28 | doAssert rows.len == 4
29 | doAssert rows[0][0] == "1"
30 | doAssert rows[0][1] == "ace"
31 | doAssert rows[1][0] == "2"
32 | doAssert rows[1][1] == "king"
33 | doAssert rows[2][0] == "3"
34 | doAssert rows[2][1] == "queen"
35 | doAssert rows[3][0] == "4"
36 | doAssert rows[3][1] == "jack"
37 |
38 | rows = getAllRows(db,
39 | sql"""SELECT * FROM tst
40 | UNION ALL
41 | SELECT * FROM tst2
42 | ORDER BY a""")
43 | doAssert rows.len == 5
44 | doAssert rows[0][0] == "1"
45 | doAssert rows[0][1] == "ace"
46 | doAssert rows[1][0] == "2"
47 | doAssert rows[1][1] == "king"
48 | doAssert rows[2][0] == "2"
49 | doAssert rows[2][1] == "king"
50 | doAssert rows[3][0] == "3"
51 | doAssert rows[3][1] == "queen"
52 | doAssert rows[4][0] == "4"
53 | doAssert rows[4][1] == "jack"
54 |
55 | exec(db, sql"CREATE TABLE tst3 (a int primary key, n int)")
56 | exec(db, sql"INSERT INTO tst3 VALUES (3, 11)")
57 |
58 | rows = @[]
59 | for r in instantRows(db, cols,
60 | sql"""SELECT a, b FROM tst
61 | UNION
62 | SELECT a, CAST(n AS text) FROM tst3
63 | ORDER BY a"""):
64 | rows.add(@[r[0], r[1]])
65 | doAssert cols.len == 2
66 | doAssert cols[0].name == "A"
67 | doAssert cols[0].typ.kind == dbInt
68 | doAssert cols[1].typ.kind == dbVarchar
69 |
70 | doAssert rows.len == 3
71 | doAssert rows[0][0] == "1"
72 | doAssert rows[0][1] == "ace"
73 | doAssert rows[1][0] == "2"
74 | doAssert rows[1][1] == "king"
75 | doAssert rows[2][0] == "3"
76 | doAssert rows[2][1] == "11"
77 |
--------------------------------------------------------------------------------
/tests/update.nim:
--------------------------------------------------------------------------------
1 | import db_nimternalsql
2 |
3 | let db = open("", "", "", "")
4 | exec(db, sql"CREATE TABLE tst (a int primary key, b int, c text)")
5 | exec(db, sql"INSERT INTO tst VALUES (1, 2, 'yo')")
6 | exec(db, sql"INSERT INTO tst VALUES (2, 3, 'ya')")
7 |
8 | exec(db, sql"UPDATE tst SET c = 'yoyo')")
9 |
10 | var rows = getAllRows(db, sql"SELECT * FROM tst ORDER BY b")
11 | doAssert rows.len == 2
12 | doAssert rows[0][0] == "1"
13 | doAssert rows[0][1] == "2"
14 | doAssert rows[0][2] == "yoyo"
15 | doAssert rows[1][0] == "2"
16 | doAssert rows[1][1] == "3"
17 | doAssert rows[1][2] == "yoyo"
18 |
19 | exec(db, sql"UPDATE tst SET b = b + 10 WHERE a = 1)")
20 |
21 | rows = getAllRows(db, sql"SELECT * FROM tst ORDER BY a")
22 | doAssert rows.len == 2
23 | doAssert rows[0][0] == "1"
24 | doAssert rows[0][1] == "12"
25 | doAssert rows[0][2] == "yoyo"
26 | doAssert rows[1][0] == "2"
27 | doAssert rows[1][1] == "3"
28 | doAssert rows[1][2] == "yoyo"
29 |
30 | exec(db, sql"UPDATE tst SET a = a + 10, c = 'x' WHERE a = 1)")
31 |
32 | rows = getAllRows(db, sql"SELECT * FROM tst ORDER BY a DESC")
33 | doAssert rows.len == 2
34 | doAssert rows[0][0] == "11"
35 | doAssert rows[0][1] == "12"
36 | doAssert rows[0][2] == "x"
37 | doAssert rows[1][0] == "2"
38 | doAssert rows[1][1] == "3"
39 | doAssert rows[1][2] == "yoyo"
40 |
41 | exec(db, sql"UPDATE tst SET a = a + 10, c = c || 'y')")
42 |
43 | rows = getAllRows(db, sql"SELECT * FROM tst ORDER BY a DESC")
44 | doAssert rows.len == 2
45 | doAssert rows[0][0] == "21"
46 | doAssert rows[0][1] == "12"
47 | doAssert rows[0][2] == "xy"
48 | doAssert rows[1][0] == "12"
49 | doAssert rows[1][1] == "3"
50 | doAssert rows[1][2] == "yoyoy"
51 |
--------------------------------------------------------------------------------
/tests/where.nim:
--------------------------------------------------------------------------------
1 | import db_nimternalsql
2 | import db_common
3 | import algorithm
4 | import strutils
5 |
6 | let db = open("", "", "", "")
7 | exec(db, sql"CREATE TABLE babababa (a text not null, b text, c int primary key, d bigint)")
8 | doAssert execAffectedRows(db,
9 | sql"""INSERT INTO babababa (a, b, c)
10 | VALUES('Baba', 'Ba' || lower('Baa') || upper('Baa'), 1)"""
11 | ) == 1
12 | exec(db,
13 | sql"""INSERT INTO babababa (a, b, c) VALUES('Electrica', 'Salsa', (1 + 2) * -3)""")
14 | exec(db,
15 | sql"""INSERT INTO babababa (a, b, c) VALUES('Alpen', NULL, 2)""")
16 | exec(db,
17 | sql"""INSERT INTO babababa (a, b, c, d) VALUES(?, ?, ?, ?)""", "Adam", "Eve", "3", "-9223372036854775808")
18 |
19 | var rows = getAllRows(db, sql"SELECT * FROM babababa b WHERE b.a = 'Baba' or c > 1")
20 | sort(rows) do (row1, row2: Row) -> int:
21 | parseInt(row1[2]) - parseInt(row2[2])
22 | doAssert rows.len == 3
23 | doAssert rows[0][0] == "Baba"
24 | doAssert rows[0][1] == "BabaaBAA"
25 | doAssert rows[0][2] == "1"
26 | doAssert rows[1][0] == "Alpen"
27 | doAssert rows[1][1] == ""
28 | doAssert rows[1][2] == "2"
29 | doAssert rows[2][0] == "Adam"
30 | doAssert rows[2][1] == "Eve"
31 | doAssert rows[2][2] == "3"
32 |
33 | rows = getAllRows(db, sql"SELECT a FROM babababa WHERE b <> 'Eve' AND c >= 1")
34 | doAssert rows.len == 1
35 | doAssert rows[0][0] == "Baba"
36 |
37 | rows = @[]
38 | var cols: DbColumns
39 | for r in instantRows(db, cols, sql"SELECT * FROM babababa WHERE c IN (1,-9) ORDER BY c"):
40 | rows.add(@[r[0], r[1], r[2]])
41 |
42 | doAssert cols.len == 4
43 | doAssert cols[0].name == "A"
44 | doAssert cols[0].typ.kind == dbVarchar
45 | doAssert cols[1].name == "B"
46 | doAssert cols[1].typ.kind == dbVarchar
47 | doAssert cols[2].name == "C"
48 | doAssert cols[2].typ.kind == dbInt
49 | doAssert cols[2].typ.size == 4
50 | doAssert cols[3].name == "D"
51 | doAssert cols[3].typ.kind == dbInt
52 | doAssert cols[3].typ.size == 8
53 |
54 | doAssert rows.len == 2
55 | doAssert rows[0][0] == "Electrica"
56 | doAssert rows[0][1] == "Salsa"
57 | doAssert rows[0][2] == "-9"
58 | doAssert rows[1][0] == "Baba"
59 | doAssert rows[1][1] == "BabaaBAA"
60 | doAssert rows[1][2] == "1"
61 |
62 | rows = getAllRows(db, sql"""SELECT * FROM babababa
63 | WHERE a NOT IN ('Adam', 'Baba')
64 | ORDER BY a""")
65 | doAssert rows.len == 2
66 | doAssert rows[0][0] == "Alpen"
67 | doAssert rows[0][1] == ""
68 | doAssert rows[0][2] == "2"
69 | doAssert rows[1][0] == "Electrica"
70 | doAssert rows[1][1] == "Salsa"
71 | doAssert rows[1][2] == "-9"
72 |
73 | rows = getAllRows(db, sql"SELECT * FROM babababa WHERE a LIKE ?", "%lpe%")
74 | doAssert rows.len == 1
75 | doAssert rows[0][0] == "Alpen"
76 | doAssert rows[0][1] == ""
77 | doAssert rows[0][2] == "2"
78 |
79 | rows = getAllRows(db, sql"SELECT * FROM babababa WHERE d < ?", "-9223372036854775000")
80 | doAssert rows.len == 1
81 | doAssert rows[0][0] == "Adam"
82 | doAssert rows[0][1] == "Eve"
83 | doAssert rows[0][2] == "3"
84 | doAssert rows[0][3] == "-9223372036854775808"
85 |
86 | rows = getAllRows(db, sql"SELECT * FROM babababa WHERE d = ?", "-9223372036854775808")
87 | doAssert rows.len == 1
88 | doAssert rows[0][0] == "Adam"
89 | doAssert rows[0][1] == "Eve"
90 | doAssert rows[0][2] == "3"
91 | doAssert rows[0][3] == "-9223372036854775808"
92 |
--------------------------------------------------------------------------------
/tests/with.nim:
--------------------------------------------------------------------------------
1 | import db_nimternalsql
2 | import db_common
3 |
4 | let db = open("", "", "", "")
5 | exec(db, sql"CREATE TABLE tst (a int primary key, b text)")
6 |
7 | exec(db, sql"INSERT INTO tst VALUES (1, 'Abcdef')")
8 | exec(db, sql"INSERT INTO tst VALUES (2, 'Bcdefg')")
9 |
10 | var rows = getAllRows(db,
11 | sql"""WITH t1 AS (
12 | SELECT a, b FROM tst WHERE a = 2
13 | )
14 | SELECT b FROM t1""")
15 |
16 | doAssert rows.len == 1
17 | doAssert rows[0][0] == "Bcdefg"
18 |
19 | exec(db, sql"CREATE TABLE d (t text primary key)")
20 | exec(db, sql"INSERT INTO d VALUES ('')")
21 |
22 | exec(db, sql"INSERT INTO tst VALUES (3, '123.111')")
23 |
24 | rows = getAllRows(db,
25 | sql"""WITH t1 AS (
26 | SELECT a, b FROM tst WHERE a = 3
27 | )
28 | SELECT
29 | CAST((SELECT b FROM t1) AS NUMERIC(5, 2)),
30 | TRIM(CAST((SELECT b FROM t1) AS TEXT)),
31 | CASE
32 | WHEN (SELECT b FROM t1) = 123.111 THEN 'yes'
33 | ELSE 'no'
34 | END
35 | FROM d""")
36 |
37 | doAssert rows.len == 1
38 | doAssert rows[0][0] == "123.11"
39 | doAssert rows[0][1] == "123.111"
40 | doAssert rows[0][2] == "yes"
41 |
42 | exec(db, sql"CREATE TABLE tst2 (a int primary key, b text)")
43 | exec(db, sql"INSERT INTO tst2 VALUES (1, 'w')")
44 | exec(db, sql"INSERT INTO tst2 VALUES (2, 'x')")
45 | exec(db, sql"INSERT INTO tst2 VALUES (3, 'y')")
46 |
47 | rows = getAllRows(db,
48 | sql"""WITH t2 AS (
49 | SELECT * FROM tst2 WHERE a = 2
50 | )
51 | SELECT b FROM tst WHERE a IN (SELECT a FROM t2)""")
52 |
53 | doAssert rows.len == 1
54 | doAssert rows[0][0] == "Bcdefg"
55 |
56 | rows = getAllRows(db,
57 | sql"""WITH t2 AS (
58 | SELECT * FROM tst2 WHERE a = 2
59 | )
60 | SELECT b FROM tst WHERE EXISTS (SELECT a FROM t2 WHERE t2.a = tst.a)""")
61 |
62 | doAssert rows.len == 1
63 | doAssert rows[0][0] == "Bcdefg"
64 |
65 | rows = getAllRows(db,
66 | sql"""WITH t2 AS (
67 | SELECT a, b FROM tst2 WHERE a = 2
68 | )
69 | SELECT b FROM tst WHERE EXISTS (SELECT a FROM t2 WHERE t2.a = tst.a)""")
70 |
71 | doAssert rows.len == 1
72 | doAssert rows[0][0] == "Bcdefg"
73 |
74 | exec(db, sql"CREATE TABLE orders (order_id int primary key, region text, quantity int, amount int, product text)")
75 |
76 | exec(db, sql"INSERT INTO orders VALUES(1, 'USA', 7, 50, 'Coffee')")
77 | exec(db, sql"INSERT INTO orders VALUES(2, 'France', 17, 80, 'Coffee')")
78 | exec(db, sql"INSERT INTO orders VALUES(3, 'Italy', 1, 4, 'Tea')")
79 | exec(db, sql"INSERT INTO orders VALUES(4, 'Italy', 5, 10, 'Coffee')")
80 | exec(db, sql"INSERT INTO orders VALUES(5, 'France', 10, 20, 'Tea')")
81 | exec(db, sql"INSERT INTO orders VALUES(6, 'France', 2, 10, 'Coffee')")
82 |
83 | rows = getAllRows(db,
84 | sql"""WITH regional_sales AS (
85 | SELECT region, SUM(amount) AS total_sales
86 | FROM orders
87 | GROUP BY region
88 | ), top_regions AS (
89 | SELECT region
90 | FROM regional_sales
91 | WHERE total_sales * 10 > (SELECT SUM(total_sales) FROM regional_sales)
92 | )
93 | SELECT region,
94 | product,
95 | SUM(quantity) AS product_units,
96 | SUM(amount) AS product_sales
97 | FROM orders
98 | WHERE region IN (SELECT region FROM top_regions)
99 | GROUP BY region, product
100 | ORDER BY region, product""")
101 |
102 | doAssert rows.len == 3
103 | doAssert rows[0][0] == "France"
104 | doAssert rows[0][1] == "Coffee"
105 | doAssert rows[0][2] == "19"
106 | doAssert rows[0][3] == "90"
107 | doAssert rows[1][0] == "France"
108 | doAssert rows[1][1] == "Tea"
109 | doAssert rows[1][2] == "10"
110 | doAssert rows[1][3] == "20"
111 | doAssert rows[2][0] == "USA"
112 | doAssert rows[2][1] == "Coffee"
113 | doAssert rows[2][2] == "7"
114 | doAssert rows[2][3] == "50"
115 |
116 | exec(db, sql"CREATE TABLE employees (name text primary key, department_id int)")
117 | exec(db, sql"CREATE TABLE departments (department_id int primary key, name text)")
118 |
119 | exec(db, sql"INSERT INTO departments VALUES (1, 'Sales')")
120 | exec(db, sql"INSERT INTO departments VALUES (2, 'Production')")
121 |
122 | exec(db, sql"INSERT INTO employees VALUES ('Fred', 1)")
123 | exec(db, sql"INSERT INTO employees VALUES ('Daisy', 1)")
124 | exec(db, sql"INSERT INTO employees VALUES ('John', 2)")
125 | exec(db, sql"INSERT INTO employees VALUES ('Eve', 1)")
126 |
127 | rows = getAllRows(db,
128 | sql"""WITH grp AS (
129 | SELECT dept.name AS dept_name, COUNT(*) AS emp_count
130 | FROM employees AS emp
131 | JOIN departments AS dept ON emp.department_id = dept.department_id
132 | GROUP BY dept_name)
133 | SELECT * FROM grp
134 | WHERE grp.emp_count > 1""")
135 |
136 | doAssert rows.len == 1
137 |
138 | doAssert rows[0][0] == "Sales"
139 | doAssert rows[0][1] == "3"
140 |
141 | close(db)
142 |
--------------------------------------------------------------------------------