diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a68cc5e25..81c22d94b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -27,28 +27,20 @@ jobs: target: - x64 node: - - 10 - - 11 - - 12 - - 13 - - 14 - - 15 - - 16 - - 17 - 18 include: - os: windows-latest - node: 16 + node: 18 host: x86 target: x86 - os: macos-m1 - node: 16 + node: 18 host: arm64 target: arm64 - name: ${{ matrix.os }} (node=${{ matrix.node }}, host=${{ matrix.host }}, target=${{ matrix.target }}) + name: ${{ matrix.os }} (host=${{ matrix.host }}, target=${{ matrix.target }}) steps: - - uses: actions/checkout@v3 - - uses: actions/setup-node@v3 + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 + - uses: actions/setup-node@v4 with: node-version: ${{ matrix.node }} architecture: ${{ matrix.host }} @@ -57,8 +49,12 @@ jobs: if: matrix.os == 'macos-m1' run: npm install -g yarn + - name: Add setuptools for Python 3.12 (temp) + if: matrix.os != 'macos-m1' + run: pip install setuptools + - name: Add msbuild to PATH - uses: microsoft/setup-msbuild@v1.1 + uses: microsoft/setup-msbuild@v1.3 if: contains(matrix.os, 'windows') with: msbuild-architecture: ${{ matrix.target }} @@ -66,6 +62,9 @@ jobs: - name: Install dependencies run: yarn install --ignore-scripts + - name: Check Node compatibility + run: node tools/semver-check.js + - name: Add env vars shell: bash run: | @@ -83,40 +82,33 @@ jobs: echo "CFLAGS=${CFLAGS:-} -include ../src/gcc-preinclude.h" >> $GITHUB_ENV echo "CXXFLAGS=${CXXFLAGS:-} -include ../src/gcc-preinclude.h" >> $GITHUB_ENV - - name: Configure build - run: yarn node-pre-gyp configure --target_arch=${{ env.TARGET }} - - name: Build binaries - run: yarn node-pre-gyp build --target_arch=${{ env.TARGET }} + run: yarn prebuild -a ${{ env.TARGET }} - name: Print binary info if: contains(matrix.os, 'ubuntu') run: | - ldd lib/binding/*/node_sqlite3.node + ldd build/**/node_sqlite3.node echo "---" - nm lib/binding/*/node_sqlite3.node | grep "GLIBC_" | c++filt || true + nm build/**/node_sqlite3.node | grep "GLIBC_" | c++filt || true echo "---" - file lib/binding/napi-v*/* + file build/**/node_sqlite3.node - name: Run tests run: yarn test - - name: Package prebuilt binaries - run: yarn node-pre-gyp package --target_arch=${{ env.TARGET }} - - name: Upload binaries to commit artifacts - uses: actions/upload-artifact@v3 - if: matrix.node == 16 + uses: actions/upload-artifact@v4 + if: matrix.node == 18 with: name: prebuilt-binaries - path: build/stage/*/* + path: prebuilds/* retention-days: 7 - name: Upload binaries to GitHub Release - run: yarn node-pre-gyp-github publish - if: matrix.node == 16 && startsWith(github.ref, 'refs/tags/') - env: - NODE_PRE_GYP_GITHUB_TOKEN: ${{ github.token }} + run: yarn upload --upload-all ${{ github.token }} + if: matrix.node == 18 && startsWith(github.ref, 'refs/tags/') + build-qemu: runs-on: ubuntu-latest if: github.event_name == 'workflow_dispatch' || startsWith(github.ref, 'refs/tags/') @@ -124,7 +116,7 @@ jobs: fail-fast: false matrix: node: - - 16 + - 18 target: - linux/arm64 variant: @@ -134,16 +126,16 @@ jobs: # musl x64 builds - target: linux/amd64 variant: alpine3.15 - node: 16 + node: 18 name: ${{ matrix.variant }} (node=${{ matrix.node }}, target=${{ matrix.target }}) steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 - name: Set up QEMU - uses: docker/setup-qemu-action@v2 + uses: docker/setup-qemu-action@v3 - name: Setup Docker Buildx - uses: docker/setup-buildx-action@v2 + uses: docker/setup-buildx-action@v3 - name: Build binaries and test run: | @@ -157,18 +149,16 @@ jobs: --build-arg NODE_VERSION=${{ matrix.node }} \ . CONTAINER_ID=$(docker create -it sqlite-builder) - docker cp $CONTAINER_ID:/usr/src/build/build/ ./build + docker cp $CONTAINER_ID:/usr/src/build/prebuilds/ ./prebuilds - name: Upload binaries to commit artifacts - uses: actions/upload-artifact@v3 - if: matrix.node == 16 + uses: actions/upload-artifact@v4 + if: matrix.node == 18 with: name: prebuilt-binaries - path: build/stage/*/* + path: prebuilds/* retention-days: 7 - name: Upload binaries to GitHub Release - run: yarn install --ignore-scripts && yarn node-pre-gyp-github publish - if: matrix.node == 16 && startsWith(github.ref, 'refs/tags/') - env: - NODE_PRE_GYP_GITHUB_TOKEN: ${{ github.token }} + run: yarn install --ignore-scripts && yarn upload --upload-all ${{ github.token }} + if: matrix.node == 18 && startsWith(github.ref, 'refs/tags/') diff --git a/.gitignore b/.gitignore index 3a26475cb..108a59ae0 100644 --- a/.gitignore +++ b/.gitignore @@ -29,3 +29,4 @@ setup.sh *.tgz package-lock.json yarn.lock +prebuilds diff --git a/README.md b/README.md index b510cca48..9af9061b0 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ Asynchronous, non-blocking [SQLite3](https://sqlite.org/) bindings for [Node.js] - [Extension support](https://github.com/TryGhost/node-sqlite3/wiki/API#databaseloadextensionpath-callback), including bundled support for the [json1 extension](https://www.sqlite.org/json1.html) - Big test suite - Written in modern C++ and tested for memory leaks - - Bundles SQLite v3.40.0, or you can build using a local SQLite + - Bundles SQLite v3.45.0, or you can build using a local SQLite # Installing @@ -35,32 +35,22 @@ yarn add sqlite3 `sqlite3` v5+ was rewritten to use [Node-API](https://nodejs.org/api/n-api.html) so prebuilt binaries do not need to be built for specific Node versions. `sqlite3` currently builds for both Node-API v3 and v6. Check the [Node-API version matrix](https://nodejs.org/api/n-api.html#node-api-version-matrix) to ensure your Node version supports one of these. The prebuilt binaries should be supported on Node v10+. -The module uses [node-pre-gyp](https://github.com/mapbox/node-pre-gyp) to download the prebuilt binary for your platform, if it exists. These binaries are hosted on GitHub Releases for `sqlite3` versions above 5.0.2, and they are hosted on S3 otherwise. The following targets are currently provided: - -Format: `napi-v{napi_build_version}-{platform}-{libc}-{arch}` - -* `napi-v3-darwin-unknown-arm64` -* `napi-v3-darwin-unknown-x64` -* `napi-v3-linux-glibc-arm64` -* `napi-v3-linux-glibc-x64` -* `napi-v3-linux-musl-arm64` -* `napi-v3-linux-musl-x64` -* `napi-v3-win32-unknown-ia32` -* `napi-v3-win32-unknown-x64` -* `napi-v6-darwin-unknown-arm64` -* `napi-v6-darwin-unknown-x64` -* `napi-v6-linux-glibc-arm64` -* `napi-v6-linux-glibc-x64` -* `napi-v6-linux-musl-arm64` -* `napi-v6-linux-musl-x64` -* `napi-v6-win32-unknown-ia32` -* `napi-v6-win32-unknown-x64` - -Unfortunately, [node-pre-gyp](https://github.com/mapbox/node-pre-gyp) cannot differentiate between `armv6` and `armv7`, and instead uses `arm` as the `{arch}`. Until that is fixed, you will still need to install `sqlite3` from [source](#source-install). +The module uses [`prebuild-install`](https://github.com/prebuild/prebuild-install) to download the prebuilt binary for your platform, if it exists. These binaries are hosted on GitHub Releases for `sqlite3` versions above 5.0.2, and they are hosted on S3 otherwise. The following targets are currently provided: + +* `darwin-arm64` +* `darwin-x64` +* `linux-arm64` +* `linux-x64` +* `linuxmusl-arm64` +* `linuxmusl-x64` +* `win32-ia32` +* `win32-x64` + +Unfortunately, [prebuild](https://github.com/prebuild/prebuild/issues/174) cannot differentiate between `armv6` and `armv7`, and instead uses `arm` as the `{arch}`. Until that is fixed, you will still need to install `sqlite3` from [source](#source-install). Support for other platforms and architectures may be added in the future if CI supports building on them. -If your environment isn't supported, it'll use `node-gyp` to build SQLite but you will need to install a C++ compiler and linker. +If your environment isn't supported, it'll use `node-gyp` to build SQLite, but you will need to install a C++ compiler and linker. ### Other ways to install @@ -148,8 +138,6 @@ NODE_WEBKIT_VERSION="0.8.6" # see latest version at https://github.com/rogerwang npm install sqlite3 --build-from-source --runtime=node-webkit --target_arch=ia32 --target=$(NODE_WEBKIT_VERSION) ``` -This command internally calls out to [`node-pre-gyp`](https://github.com/mapbox/node-pre-gyp) which itself calls out to [`nw-gyp`](https://github.com/rogerwang/nw-gyp) when the `--runtime=node-webkit` option is passed. - You can also run this command from within a `sqlite3` checkout: ```bash @@ -226,6 +214,7 @@ npm test # Contributors +* [Daniel Lockyer](https://github.com/daniellockyer) * [Konstantin Käfer](https://github.com/kkaefer) * [Dane Springmeyer](https://github.com/springmeyer) * [Will White](https://github.com/willwhite) diff --git a/binding.gyp b/binding.gyp index f1336f6f7..a8fccd0c4 100644 --- a/binding.gyp +++ b/binding.gyp @@ -2,7 +2,8 @@ "includes": [ "deps/common-sqlite.gypi" ], "variables": { "sqlite%":"internal", - "sqlite_libname%":"sqlite3" + "sqlite_libname%":"sqlite3", + "module_name": "node_sqlite3", }, "targets": [ { @@ -25,8 +26,10 @@ "libraries": [ "-l<(sqlite_libname)" ], - "conditions": [ [ "OS=='linux'", {"libraries+":["-Wl,-rpath=<@(sqlite)/lib"]} ] ], - "conditions": [ [ "OS!='win'", {"libraries+":["-L<@(sqlite)/lib"]} ] ], + "conditions": [ + [ "OS=='linux'", {"libraries+":["-Wl,-rpath=<@(sqlite)/lib"]} ], + [ "OS!='win'", {"libraries+":["-L<@(sqlite)/lib"]} ] + ], 'msvs_settings': { 'VCLinkerTool': { 'AdditionalLibraryDirectories': [ @@ -50,17 +53,6 @@ "src/statement.cc" ], "defines": [ "NAPI_VERSION=<(napi_build_version)", "NAPI_DISABLE_CPP_EXCEPTIONS=1" ] - }, - { - "target_name": "action_after_build", - "type": "none", - "dependencies": [ "<(module_name)" ], - "copies": [ - { - "files": [ "<(PRODUCT_DIR)/<(module_name).node" ], - "destination": "<(module_path)" - } - ] } ] } diff --git a/deps/common-sqlite.gypi b/deps/common-sqlite.gypi index 0a0ff567d..f921d8120 100644 --- a/deps/common-sqlite.gypi +++ b/deps/common-sqlite.gypi @@ -1,6 +1,6 @@ { 'variables': { - 'sqlite_version%':'3400000', + 'sqlite_version%':'3450000', "toolset%":'', }, 'target_defaults': { diff --git a/deps/sqlite-autoconf-3400000.tar.gz b/deps/sqlite-autoconf-3400000.tar.gz deleted file mode 100644 index 2cd54ef5a..000000000 Binary files a/deps/sqlite-autoconf-3400000.tar.gz and /dev/null differ diff --git a/deps/sqlite-autoconf-3450000.tar.gz b/deps/sqlite-autoconf-3450000.tar.gz new file mode 100644 index 000000000..f4508c9bc Binary files /dev/null and b/deps/sqlite-autoconf-3450000.tar.gz differ diff --git a/lib/sqlite3-binding.js b/lib/sqlite3-binding.js index 65f01546e..98d1b91b7 100644 --- a/lib/sqlite3-binding.js +++ b/lib/sqlite3-binding.js @@ -1,5 +1 @@ -const binary = require('@mapbox/node-pre-gyp'); -const path = require('path'); -const binding_path = binary.find(path.resolve(path.join(__dirname,'../package.json'))); -const binding = require(binding_path); -module.exports = exports = binding; +module.exports = require('bindings')('node_sqlite3.node'); diff --git a/lib/sqlite3.d.ts b/lib/sqlite3.d.ts index b27b0cf51..15e66230e 100644 --- a/lib/sqlite3.d.ts +++ b/lib/sqlite3.d.ts @@ -80,16 +80,16 @@ export class Statement extends events.EventEmitter { run(params: any, callback?: (this: RunResult, err: Error | null) => void): this; run(...params: any[]): this; - get(callback?: (err: Error | null, row?: any) => void): this; - get(params: any, callback?: (this: RunResult, err: Error | null, row?: any) => void): this; + get(callback?: (err: Error | null, row?: T) => void): this; + get(params: any, callback?: (this: RunResult, err: Error | null, row?: T) => void): this; get(...params: any[]): this; - all(callback?: (err: Error | null, rows: any[]) => void): this; - all(params: any, callback?: (this: RunResult, err: Error | null, rows: any[]) => void): this; + all(callback?: (err: Error | null, rows: T[]) => void): this; + all(params: any, callback?: (this: RunResult, err: Error | null, rows: T[]) => void): this; all(...params: any[]): this; - each(callback?: (err: Error | null, row: any) => void, complete?: (err: Error | null, count: number) => void): this; - each(params: any, callback?: (this: RunResult, err: Error | null, row: any) => void, complete?: (err: Error | null, count: number) => void): this; + each(callback?: (err: Error | null, row: T) => void, complete?: (err: Error | null, count: number) => void): this; + each(params: any, callback?: (this: RunResult, err: Error | null, row: T) => void, complete?: (err: Error | null, count: number) => void): this; each(...params: any[]): this; } @@ -103,16 +103,16 @@ export class Database extends events.EventEmitter { run(sql: string, params: any, callback?: (this: RunResult, err: Error | null) => void): this; run(sql: string, ...params: any[]): this; - get(sql: string, callback?: (this: Statement, err: Error | null, row: any) => void): this; - get(sql: string, params: any, callback?: (this: Statement, err: Error | null, row: any) => void): this; + get(sql: string, callback?: (this: Statement, err: Error | null, row: T) => void): this; + get(sql: string, params: any, callback?: (this: Statement, err: Error | null, row: T) => void): this; get(sql: string, ...params: any[]): this; - all(sql: string, callback?: (this: Statement, err: Error | null, rows: any[]) => void): this; - all(sql: string, params: any, callback?: (this: Statement, err: Error | null, rows: any[]) => void): this; + all(sql: string, callback?: (this: Statement, err: Error | null, rows: T[]) => void): this; + all(sql: string, params: any, callback?: (this: Statement, err: Error | null, rows: T[]) => void): this; all(sql: string, ...params: any[]): this; - each(sql: string, callback?: (this: Statement, err: Error | null, row: any) => void, complete?: (err: Error | null, count: number) => void): this; - each(sql: string, params: any, callback?: (this: Statement, err: Error | null, row: any) => void, complete?: (err: Error | null, count: number) => void): this; + each(sql: string, callback?: (this: Statement, err: Error | null, row: T) => void, complete?: (err: Error | null, count: number) => void): this; + each(sql: string, params: any, callback?: (this: Statement, err: Error | null, row: T) => void, complete?: (err: Error | null, count: number) => void): this; each(sql: string, ...params: any[]): this; exec(sql: string, callback?: (this: Statement, err: Error | null) => void): this; diff --git a/package.json b/package.json index a505725c0..ab413ff4a 100644 --- a/package.json +++ b/package.json @@ -1,24 +1,20 @@ { "name": "sqlite3", "description": "Asynchronous, non-blocking SQLite3 bindings", - "version": "5.1.4", + "version": "5.1.7", "homepage": "https://github.com/TryGhost/node-sqlite3", "author": { "name": "Mapbox", "url": "https://mapbox.com/" }, "binary": { - "module_name": "node_sqlite3", - "module_path": "./lib/binding/napi-v{napi_build_version}-{platform}-{libc}-{arch}", - "host": "https://github.com/TryGhost/node-sqlite3/releases/download/", - "remote_path": "v{version}", - "package_name": "napi-v{napi_build_version}-{platform}-{libc}-{arch}.tar.gz", "napi_versions": [ 3, 6 ] }, "contributors": [ + "Daniel Lockyer ", "Konstantin Käfer ", "Dane Springmeyer ", "Will White ", @@ -48,14 +44,15 @@ "url": "https://github.com/TryGhost/node-sqlite3.git" }, "dependencies": { - "@mapbox/node-pre-gyp": "^1.0.0", - "node-addon-api": "^4.2.0", + "bindings": "^1.5.0", + "node-addon-api": "^7.0.0", + "prebuild-install": "^7.1.1", "tar": "^6.1.11" }, "devDependencies": { - "eslint": "6.8.0", - "mocha": "7.2.0", - "node-pre-gyp-github": "1.4.4" + "eslint": "8.56.0", + "mocha": "10.2.0", + "prebuild": "12.1.0" }, "peerDependencies": { "node-gyp": "8.x" @@ -69,12 +66,11 @@ "node-gyp": "8.x" }, "scripts": { - "build": "node-pre-gyp build", - "build:debug": "node-pre-gyp build --debug", - "install": "node-pre-gyp install --fallback-to-build", - "pretest": "node test/support/createdb.js", - "test": "mocha -R spec --timeout 480000", - "pack": "node-pre-gyp package" + "install": "prebuild-install -r napi || node-gyp rebuild", + "prebuild": "prebuild --runtime napi --all --verbose", + "rebuild": "node-gyp rebuild", + "upload": "prebuild --verbose --prerelease", + "test": "node test/support/createdb.js && mocha -R spec --timeout 480000" }, "license": "BSD-3-Clause", "keywords": [ diff --git a/src/async.h b/src/async.h index b1a8f9dd6..f36e4cbc2 100644 --- a/src/async.h +++ b/src/async.h @@ -29,20 +29,19 @@ template class Async { } static void listener(uv_async_t* handle) { - Async* async = static_cast(handle->data); + auto* async = static_cast(handle->data); std::vector rows; NODE_SQLITE3_MUTEX_LOCK(&async->mutex) rows.swap(async->data); NODE_SQLITE3_MUTEX_UNLOCK(&async->mutex) - for (unsigned int i = 0, size = rows.size(); i < size; i++) { - async->callback(async->parent, rows[i]); - } + for(auto row : rows) + async->callback(async->parent, row); } static void close(uv_handle_t* handle) { assert(handle != NULL); assert(handle->data != NULL); - Async* async = static_cast(handle->data); + auto* async = static_cast(handle->data); delete async; } @@ -56,7 +55,7 @@ template class Async { void add(Item* item) { NODE_SQLITE3_MUTEX_LOCK(&mutex); - data.push_back(item); + data.emplace_back(item); NODE_SQLITE3_MUTEX_UNLOCK(&mutex) } diff --git a/src/backup.cc b/src/backup.cc index 9f3893b96..0f971f5e9 100644 --- a/src/backup.cc +++ b/src/backup.cc @@ -1,6 +1,5 @@ -#include +#include #include - #include "macros.h" #include "database.h" #include "backup.h" @@ -11,9 +10,9 @@ Napi::Object Backup::Init(Napi::Env env, Napi::Object exports) { Napi::HandleScope scope(env); // declare napi_default_method here as it is only available in Node v14.12.0+ - napi_property_attributes napi_default_method = static_cast(napi_writable | napi_configurable); + auto napi_default_method = static_cast(napi_writable | napi_configurable); - Napi::Function t = DefineClass(env, "Backup", { + auto t = DefineClass(env, "Backup", { InstanceMethod("step", &Backup::Step, napi_default_method), InstanceMethod("finish", &Backup::Finish, napi_default_method), InstanceAccessor("idle", &Backup::IdleGetter, nullptr), @@ -34,7 +33,7 @@ void Backup::Process() { } while (inited && !locked && !queue.empty()) { - std::unique_ptr call(queue.front()); + auto call = std::move(queue.front()); queue.pop(); call->callback(call->baton); @@ -43,11 +42,11 @@ void Backup::Process() { void Backup::Schedule(Work_Callback callback, Baton* baton) { if (finished) { - queue.push(new Call(callback, baton)); + queue.emplace(new Call(callback, baton)); CleanQueue(); } else if (!inited || locked || !queue.empty()) { - queue.push(new Call(callback, baton)); + queue.emplace(new Call(callback, baton)); } else { callback(baton); @@ -55,7 +54,7 @@ void Backup::Schedule(Work_Callback callback, Baton* baton) { } template void Backup::Error(T* baton) { - Napi::Env env = baton->backup->Env(); + auto env = baton->backup->Env(); Napi::HandleScope scope(env); Backup* backup = baton->backup; @@ -76,7 +75,7 @@ template void Backup::Error(T* baton) { } void Backup::CleanQueue() { - Napi::Env env = this->Env(); + auto env = this->Env(); Napi::HandleScope scope(env); if (inited && !queue.empty()) { @@ -88,7 +87,7 @@ void Backup::CleanQueue() { // Clear out the queue so that this object can get GC'ed. while (!queue.empty()) { - std::unique_ptr call(queue.front()); + auto call = std::move(queue.front()); queue.pop(); std::unique_ptr baton(call->baton); @@ -111,7 +110,7 @@ void Backup::CleanQueue() { else while (!queue.empty()) { // Just delete all items in the queue; we already fired an event when // initializing the backup failed. - std::unique_ptr call(queue.front()); + auto call = std::move(queue.front()); queue.pop(); // We don't call the actual callback, so we have to make sure that @@ -121,13 +120,13 @@ void Backup::CleanQueue() { } Backup::Backup(const Napi::CallbackInfo& info) : Napi::ObjectWrap(info) { - Napi::Env env = info.Env(); + auto env = info.Env(); if (!info.IsConstructCall()) { Napi::TypeError::New(env, "Use the new operator to create new Backup objects").ThrowAsJavaScriptException(); return; } - int length = info.Length(); + auto length = info.Length(); if (length <= 0 || !Database::HasInstance(info[0])) { Napi::TypeError::New(env, "Database object expected").ThrowAsJavaScriptException(); @@ -154,37 +153,33 @@ Backup::Backup(const Napi::CallbackInfo& info) : Napi::ObjectWrap(info) return; } - Database* db = Napi::ObjectWrap::Unwrap(info[0].As()); - Napi::String filename = info[1].As(); - Napi::String sourceName = info[2].As(); - Napi::String destName = info[3].As(); - Napi::Boolean filenameIsDest = info[4].As(); + this->db = Napi::ObjectWrap::Unwrap(info[0].As()); + this->db->Ref(); + + auto filename = info[1].As(); + auto sourceName = info[2].As(); + auto destName = info[3].As(); + auto filenameIsDest = info[4].As(); info.This().As().DefineProperty(Napi::PropertyDescriptor::Value("filename", filename)); info.This().As().DefineProperty(Napi::PropertyDescriptor::Value("sourceName", sourceName)); info.This().As().DefineProperty(Napi::PropertyDescriptor::Value("destName", destName)); info.This().As().DefineProperty(Napi::PropertyDescriptor::Value("filenameIsDest", filenameIsDest)); - init(db); - - InitializeBaton* baton = new InitializeBaton(db, info[5].As(), this); + auto* baton = new InitializeBaton(this->db, info[5].As(), this); baton->filename = filename.Utf8Value(); baton->sourceName = sourceName.Utf8Value(); baton->destName = destName.Utf8Value(); baton->filenameIsDest = filenameIsDest.Value(); - db->Schedule(Work_BeginInitialize, baton); + + this->db->Schedule(Work_BeginInitialize, baton); } void Backup::Work_BeginInitialize(Database::Baton* baton) { assert(baton->db->open); baton->db->pending++; - Napi::Env env = baton->db->Env(); - int status = napi_create_async_work( - env, NULL, Napi::String::New(env, "sqlite3.Backup.Initialize"), - Work_Initialize, Work_AfterInitialize, baton, &baton->request - ); - assert(status == 0); - napi_queue_async_work(env, baton->request); + auto env = baton->db->Env(); + CREATE_WORK("sqlite3.Backup.Initialize", Work_Initialize, Work_AfterInitialize); } void Backup::Work_Initialize(napi_env e, void* data) { @@ -192,7 +187,7 @@ void Backup::Work_Initialize(napi_env e, void* data) { // In case stepping fails, we use a mutex to make sure we get the associated // error message. - sqlite3_mutex* mtx = sqlite3_db_mutex(baton->db->_handle); + auto* mtx = sqlite3_db_mutex(baton->db->_handle); sqlite3_mutex_enter(mtx); backup->status = sqlite3_open(baton->filename.c_str(), &backup->_otherDb); @@ -218,9 +213,9 @@ void Backup::Work_Initialize(napi_env e, void* data) { void Backup::Work_AfterInitialize(napi_env e, napi_status status, void* data) { std::unique_ptr baton(static_cast(data)); - Backup* backup = baton->backup; + auto* backup = baton->backup; - Napi::Env env = backup->Env(); + auto env = backup->Env(); Napi::HandleScope scope(env); if (backup->status != SQLITE_OK) { @@ -239,13 +234,13 @@ void Backup::Work_AfterInitialize(napi_env e, napi_status status, void* data) { } Napi::Value Backup::Step(const Napi::CallbackInfo& info) { - Backup* backup = this; - Napi::Env env = backup->Env(); + auto* backup = this; + auto env = backup->Env(); REQUIRE_ARGUMENT_INTEGER(0, pages); OPTIONAL_ARGUMENT_FUNCTION(1, callback); - StepBaton* baton = new StepBaton(backup, callback, pages); + auto* baton = new StepBaton(backup, callback, pages); backup->GetRetryErrors(baton->retryErrorsSet); backup->Schedule(Work_BeginStep, baton); return info.This(); @@ -281,9 +276,9 @@ void Backup::Work_Step(napi_env e, void* data) { void Backup::Work_AfterStep(napi_env e, napi_status status, void* data) { std::unique_ptr baton(static_cast(data)); - Backup* backup = baton->backup; + auto* backup = baton->backup; - Napi::Env env = backup->Env(); + auto env = backup->Env(); Napi::HandleScope scope(env); if (backup->status == SQLITE_DONE) { @@ -308,12 +303,12 @@ void Backup::Work_AfterStep(napi_env e, napi_status status, void* data) { } Napi::Value Backup::Finish(const Napi::CallbackInfo& info) { - Backup* backup = this; - Napi::Env env = backup->Env(); + auto* backup = this; + auto env = backup->Env(); OPTIONAL_ARGUMENT_FUNCTION(0, callback); - Baton* baton = new Baton(backup, callback); + auto* baton = new Baton(backup, callback); backup->Schedule(Work_BeginFinish, baton); return info.This(); } @@ -329,9 +324,9 @@ void Backup::Work_Finish(napi_env e, void* data) { void Backup::Work_AfterFinish(napi_env e, napi_status status, void* data) { std::unique_ptr baton(static_cast(data)); - Backup* backup = baton->backup; + auto* backup = baton->backup; - Napi::Env env = backup->Env(); + auto env = backup->Env(); Napi::HandleScope scope(env); backup->FinishAll(); @@ -369,39 +364,39 @@ void Backup::FinishSqlite() { } Napi::Value Backup::IdleGetter(const Napi::CallbackInfo& info) { - Backup* backup = this; + auto* backup = this; bool idle = backup->inited && !backup->locked && backup->queue.empty(); return Napi::Boolean::New(this->Env(), idle); } Napi::Value Backup::CompletedGetter(const Napi::CallbackInfo& info) { - Backup* backup = this; + auto* backup = this; return Napi::Boolean::New(this->Env(), backup->completed); } Napi::Value Backup::FailedGetter(const Napi::CallbackInfo& info) { - Backup* backup = this; + auto* backup = this; return Napi::Boolean::New(this->Env(), backup->failed); } Napi::Value Backup::RemainingGetter(const Napi::CallbackInfo& info) { - Backup* backup = this; + auto* backup = this; return Napi::Number::New(this->Env(), backup->remaining); } Napi::Value Backup::PageCountGetter(const Napi::CallbackInfo& info) { - Backup* backup = this; + auto* backup = this; return Napi::Number::New(this->Env(), backup->pageCount); } Napi::Value Backup::RetryErrorGetter(const Napi::CallbackInfo& info) { - Backup* backup = this; + auto* backup = this; return backup->retryErrors.Value(); } void Backup::RetryErrorSetter(const Napi::CallbackInfo& info, const Napi::Value& value) { - Backup* backup = this; - Napi::Env env = backup->Env(); + auto* backup = this; + auto env = backup->Env(); if (!value.IsArray()) { Napi::Error::New(env, "retryErrors must be an array").ThrowAsJavaScriptException(); return; @@ -413,9 +408,9 @@ void Backup::RetryErrorSetter(const Napi::CallbackInfo& info, const Napi::Value& void Backup::GetRetryErrors(std::set& retryErrorsSet) { retryErrorsSet.clear(); Napi::Array array = retryErrors.Value(); - int length = array.Length(); - for (int i = 0; i < length; i++) { - Napi::Value code = (array).Get(i); + auto length = array.Length(); + for (size_t i = 0; i < length; i++) { + Napi::Value code = (array).Get(static_cast(i)); if (code.IsNumber()) { retryErrorsSet.insert(code.As().Int32Value()); } diff --git a/src/backup.h b/src/backup.h index c15b77bfe..b894aca1a 100644 --- a/src/backup.h +++ b/src/backup.h @@ -121,7 +121,7 @@ class Backup : public Napi::ObjectWrap { Baton(db_, cb_), backup(backup_), filenameIsDest(true) { backup->Ref(); } - virtual ~InitializeBaton() { + virtual ~InitializeBaton() override { backup->Unref(); if (!db->IsOpen() && db->IsLocked()) { // The database handle was closed before the backup could be opened. @@ -135,6 +135,7 @@ class Backup : public Napi::ObjectWrap { std::set retryErrorsSet; StepBaton(Backup* backup_, Napi::Function cb_, int pages_) : Baton(backup_, cb_), pages(pages_) {} + virtual ~StepBaton() override = default; }; typedef void (*Work_Callback)(Baton* baton); @@ -145,21 +146,6 @@ class Backup : public Napi::ObjectWrap { Baton* baton; }; - void init(Database* db_) { - db = db_; - _handle = NULL; - _otherDb = NULL; - _destDb = NULL; - inited = false; - locked = true; - completed = false; - failed = false; - remaining = -1; - pageCount = -1; - finished = false; - db->Ref(); - } - Backup(const Napi::CallbackInfo& info); ~Backup() { @@ -169,8 +155,9 @@ class Backup : public Napi::ObjectWrap { retryErrors.Reset(); } - WORK_DEFINITION(Step); - WORK_DEFINITION(Finish); + WORK_DEFINITION(Step) + WORK_DEFINITION(Finish) + Napi::Value IdleGetter(const Napi::CallbackInfo& info); Napi::Value CompletedGetter(const Napi::CallbackInfo& info); Napi::Value FailedGetter(const Napi::CallbackInfo& info); @@ -198,20 +185,21 @@ class Backup : public Napi::ObjectWrap { Database* db; - sqlite3_backup* _handle; - sqlite3* _otherDb; - sqlite3* _destDb; + sqlite3_backup* _handle = NULL; + sqlite3* _otherDb = NULL; + sqlite3* _destDb = NULL; + + bool inited = false; + bool locked = true; + bool completed = false; + bool failed = false; + int remaining = -1; + int pageCount = -1; + bool finished = false; + int status; std::string message; - - bool inited; - bool locked; - bool completed; - bool failed; - int remaining; - int pageCount; - bool finished; - std::queue queue; + std::queue> queue; Napi::Reference retryErrors; }; diff --git a/src/database.cc b/src/database.cc index 15709ce3d..d495ce98f 100644 --- a/src/database.cc +++ b/src/database.cc @@ -1,4 +1,4 @@ -#include +#include #include #include "macros.h" @@ -14,9 +14,9 @@ Napi::FunctionReference Database::constructor; Napi::Object Database::Init(Napi::Env env, Napi::Object exports) { Napi::HandleScope scope(env); // declare napi_default_method here as it is only available in Node v14.12.0+ - napi_property_attributes napi_default_method = static_cast(napi_writable | napi_configurable); + auto napi_default_method = static_cast(napi_writable | napi_configurable); - Napi::Function t = DefineClass(env, "Database", { + auto t = DefineClass(env, "Database", { InstanceMethod("close", &Database::Close, napi_default_method), InstanceMethod("exec", &Database::Exec, napi_default_method), InstanceMethod("wait", &Database::Wait, napi_default_method), @@ -25,7 +25,7 @@ Napi::Object Database::Init(Napi::Env env, Napi::Object exports) { InstanceMethod("parallelize", &Database::Parallelize, napi_default_method), InstanceMethod("configure", &Database::Configure, napi_default_method), InstanceMethod("interrupt", &Database::Interrupt, napi_default_method), - InstanceAccessor("open", &Database::OpenGetter, nullptr) + InstanceAccessor("open", &Database::Open, nullptr) }); #if NAPI_VERSION < 6 @@ -42,7 +42,7 @@ Napi::Object Database::Init(Napi::Env env, Napi::Object exports) { } void Database::Process() { - Napi::Env env = this->Env(); + auto env = this->Env(); Napi::HandleScope scope(env); if (!open && locked && !queue.empty()) { @@ -52,9 +52,9 @@ void Database::Process() { // Call all callbacks with the error object. while (!queue.empty()) { - std::unique_ptr call(queue.front()); + auto call = std::unique_ptr(queue.front()); queue.pop(); - std::unique_ptr baton(call->baton); + auto baton = std::unique_ptr(call->baton); Napi::Function cb = baton->callback.Value(); if (IS_FUNCTION(cb)) { TRY_CATCH_CALL(this->Value(), cb, 1, argv); @@ -88,7 +88,7 @@ void Database::Process() { } void Database::Schedule(Work_Callback callback, Baton* baton, bool exclusive) { - Napi::Env env = this->Env(); + auto env = this->Env(); Napi::HandleScope scope(env); if (!open && locked) { @@ -109,7 +109,7 @@ void Database::Schedule(Work_Callback callback, Baton* baton, bool exclusive) { } if (!open || ((locked || exclusive || serialize) && pending > 0)) { - queue.push(new Call(callback, baton, exclusive || serialize)); + queue.emplace(new Call(callback, baton, exclusive || serialize)); } else { locked = exclusive; @@ -118,14 +118,13 @@ void Database::Schedule(Work_Callback callback, Baton* baton, bool exclusive) { } Database::Database(const Napi::CallbackInfo& info) : Napi::ObjectWrap(info) { - init(); - Napi::Env env = info.Env(); + auto env = info.Env(); if (info.Length() <= 0 || !info[0].IsString()) { Napi::TypeError::New(env, "String expected").ThrowAsJavaScriptException(); return; } - std::string filename = info[0].As(); + auto filename = info[0].As().Utf8Value(); unsigned int pos = 1; @@ -146,23 +145,18 @@ Database::Database(const Napi::CallbackInfo& info) : Napi::ObjectWrap( info.This().As().DefineProperty(Napi::PropertyDescriptor::Value("mode", Napi::Number::New(env, mode), napi_default)); // Start opening the database. - OpenBaton* baton = new OpenBaton(this, callback, filename.c_str(), mode); + auto* baton = new OpenBaton(this, callback, filename.c_str(), mode); Work_BeginOpen(baton); } void Database::Work_BeginOpen(Baton* baton) { - Napi::Env env = baton->db->Env(); - int status = napi_create_async_work( - env, NULL, Napi::String::New(env, "sqlite3.Database.Open"), - Work_Open, Work_AfterOpen, baton, &baton->request - ); - assert(status == 0); - napi_queue_async_work(env, baton->request); + auto env = baton->db->Env(); + CREATE_WORK("sqlite3.Database.Open", Work_Open, Work_AfterOpen); } void Database::Work_Open(napi_env e, void* data) { - OpenBaton* baton = static_cast(data); - Database* db = baton->db; + auto* baton = static_cast(data); + auto* db = baton->db; baton->status = sqlite3_open_v2( baton->filename.c_str(), @@ -185,9 +179,9 @@ void Database::Work_Open(napi_env e, void* data) { void Database::Work_AfterOpen(napi_env e, napi_status status, void* data) { std::unique_ptr baton(static_cast(data)); - Database* db = baton->db; + auto* db = baton->db; - Napi::Env env = db->Env(); + auto env = db->Env(); Napi::HandleScope scope(env); Napi::Value argv[1]; @@ -217,18 +211,18 @@ void Database::Work_AfterOpen(napi_env e, napi_status status, void* data) { } } -Napi::Value Database::OpenGetter(const Napi::CallbackInfo& info) { - Napi::Env env = this->Env(); - Database* db = this; +Napi::Value Database::Open(const Napi::CallbackInfo& info) { + auto env = this->Env(); + auto* db = this; return Napi::Boolean::New(env, db->open); } Napi::Value Database::Close(const Napi::CallbackInfo& info) { - Napi::Env env = info.Env(); - Database* db = this; + auto env = info.Env(); + auto* db = this; OPTIONAL_ARGUMENT_FUNCTION(0, callback); - Baton* baton = new Baton(db, callback); + auto* baton = new Baton(db, callback); db->Schedule(Work_BeginClose, baton, true); return info.This(); @@ -244,19 +238,13 @@ void Database::Work_BeginClose(Baton* baton) { baton->db->RemoveCallbacks(); baton->db->closing = true; - Napi::Env env = baton->db->Env(); - - int status = napi_create_async_work( - env, NULL, Napi::String::New(env, "sqlite3.Database.Close"), - Work_Close, Work_AfterClose, baton, &baton->request - ); - assert(status == 0); - napi_queue_async_work(env, baton->request); + auto env = baton->db->Env(); + CREATE_WORK("sqlite3.Database.Close", Work_Close, Work_AfterClose); } void Database::Work_Close(napi_env e, void* data) { - Baton* baton = static_cast(data); - Database* db = baton->db; + auto* baton = static_cast(data); + auto* db = baton->db; baton->status = sqlite3_close(db->_handle); @@ -271,9 +259,9 @@ void Database::Work_Close(napi_env e, void* data) { void Database::Work_AfterClose(napi_env e, napi_status status, void* data) { std::unique_ptr baton(static_cast(data)); - Database* db = baton->db; + auto* db = baton->db; - Napi::Env env = db->Env(); + auto env = db->Env(); Napi::HandleScope scope(env); db->pending--; @@ -303,15 +291,15 @@ void Database::Work_AfterClose(napi_env e, napi_status status, void* data) { } if (!db->open) { - Napi::Value info[] = { Napi::String::New(env, "close"), argv[0] }; + Napi::Value info[] = { Napi::String::New(env, "close") }; EMIT_EVENT(db->Value(), 1, info); db->Process(); } } Napi::Value Database::Serialize(const Napi::CallbackInfo& info) { - Napi::Env env = this->Env(); - Database* db = this; + auto env = this->Env(); + auto* db = this; OPTIONAL_ARGUMENT_FUNCTION(0, callback); bool before = db->serialize; @@ -328,11 +316,11 @@ Napi::Value Database::Serialize(const Napi::CallbackInfo& info) { } Napi::Value Database::Parallelize(const Napi::CallbackInfo& info) { - Napi::Env env = this->Env(); - Database* db = this; + auto env = this->Env(); + auto* db = this; OPTIONAL_ARGUMENT_FUNCTION(0, callback); - bool before = db->serialize; + auto before = db->serialize; db->serialize = false; if (!callback.IsEmpty() && callback.IsFunction()) { @@ -346,19 +334,18 @@ Napi::Value Database::Parallelize(const Napi::CallbackInfo& info) { } Napi::Value Database::Configure(const Napi::CallbackInfo& info) { - Napi::Env env = this->Env(); - Database* db = this; + auto env = this->Env(); + auto* db = this; REQUIRE_ARGUMENTS(2); - if (info[0].StrictEquals( Napi::String::New(env, "trace"))) { - Napi::Function handle; - Baton* baton = new Baton(db, handle); + Napi::Function handle; + if (info[0].StrictEquals( Napi::String::New(env, "trace"))) { + auto* baton = new Baton(db, handle); db->Schedule(RegisterTraceCallback, baton); } else if (info[0].StrictEquals( Napi::String::New(env, "profile"))) { - Napi::Function handle; - Baton* baton = new Baton(db, handle); + auto* baton = new Baton(db, handle); db->Schedule(RegisterProfileCallback, baton); } else if (info[0].StrictEquals( Napi::String::New(env, "busyTimeout"))) { @@ -366,8 +353,7 @@ Napi::Value Database::Configure(const Napi::CallbackInfo& info) { Napi::TypeError::New(env, "Value must be an integer").ThrowAsJavaScriptException(); return env.Null(); } - Napi::Function handle; - Baton* baton = new Baton(db, handle); + auto* baton = new Baton(db, handle); baton->status = info[1].As().Int32Value(); db->Schedule(SetBusyTimeout, baton); } @@ -381,15 +367,13 @@ Napi::Value Database::Configure(const Napi::CallbackInfo& info) { Napi::TypeError::New(env, "limit value must be an integer").ThrowAsJavaScriptException(); return env.Null(); } - Napi::Function handle; int id = info[1].As().Int32Value(); int value = info[2].As().Int32Value(); Baton* baton = new LimitBaton(db, handle, id, value); db->Schedule(SetLimit, baton); } else if (info[0].StrictEquals(Napi::String::New(env, "change"))) { - Napi::Function handle; - Baton* baton = new Baton(db, handle); + auto* baton = new Baton(db, handle); db->Schedule(RegisterUpdateCallback, baton); } else { @@ -409,8 +393,8 @@ Napi::Value Database::Configure(const Napi::CallbackInfo& info) { } Napi::Value Database::Interrupt(const Napi::CallbackInfo& info) { - Napi::Env env = this->Env(); - Database* db = this; + auto env = this->Env(); + auto* db = this; if (!db->open) { Napi::Error::New(env, "Database is not open").ThrowAsJavaScriptException(); @@ -427,7 +411,7 @@ Napi::Value Database::Interrupt(const Napi::CallbackInfo& info) { } void Database::SetBusyTimeout(Baton* b) { - std::unique_ptr baton(b); + auto baton = std::unique_ptr(b); assert(baton->db->open); assert(baton->db->_handle); @@ -446,10 +430,10 @@ void Database::SetLimit(Baton* b) { } void Database::RegisterTraceCallback(Baton* b) { - std::unique_ptr baton(b); + auto baton = std::unique_ptr(b); assert(baton->db->open); assert(baton->db->_handle); - Database* db = baton->db; + auto* db = baton->db; if (db->debug_trace == NULL) { // Add it. @@ -473,7 +457,7 @@ void Database::TraceCallback(void* db, const char* sql) { void Database::TraceCallback(Database* db, std::string* s) { std::unique_ptr sql(s); // Note: This function is called in the main V8 thread. - Napi::Env env = db->Env(); + auto env = db->Env(); Napi::HandleScope scope(env); Napi::Value argv[] = { @@ -484,10 +468,10 @@ void Database::TraceCallback(Database* db, std::string* s) { } void Database::RegisterProfileCallback(Baton* b) { - std::unique_ptr baton(b); + auto baton = std::unique_ptr(b); assert(baton->db->open); assert(baton->db->_handle); - Database* db = baton->db; + auto* db = baton->db; if (db->debug_profile == NULL) { // Add it. @@ -505,15 +489,15 @@ void Database::RegisterProfileCallback(Baton* b) { void Database::ProfileCallback(void* db, const char* sql, sqlite3_uint64 nsecs) { // Note: This function is called in the thread pool. // Note: Some queries, such as "EXPLAIN" queries, are not sent through this. - ProfileInfo* info = new ProfileInfo(); + auto* info = new ProfileInfo(); info->sql = std::string(sql); info->nsecs = nsecs; static_cast(db)->debug_profile->send(info); } void Database::ProfileCallback(Database *db, ProfileInfo* i) { - std::unique_ptr info(i); - Napi::Env env = db->Env(); + auto info = std::unique_ptr(i); + auto env = db->Env(); Napi::HandleScope scope(env); Napi::Value argv[] = { @@ -525,10 +509,10 @@ void Database::ProfileCallback(Database *db, ProfileInfo* i) { } void Database::RegisterUpdateCallback(Baton* b) { - std::unique_ptr baton(b); + auto baton = std::unique_ptr(b); assert(baton->db->open); assert(baton->db->_handle); - Database* db = baton->db; + auto* db = baton->db; if (db->update_event == NULL) { // Add it. @@ -547,7 +531,7 @@ void Database::UpdateCallback(void* db, int type, const char* database, const char* table, sqlite3_int64 rowid) { // Note: This function is called in the thread pool. // Note: Some queries, such as "EXPLAIN" queries, are not sent through this. - UpdateInfo* info = new UpdateInfo(); + auto* info = new UpdateInfo(); info->type = type; info->database = std::string(database); info->table = std::string(table); @@ -556,8 +540,8 @@ void Database::UpdateCallback(void* db, int type, const char* database, } void Database::UpdateCallback(Database *db, UpdateInfo* i) { - std::unique_ptr info(i); - Napi::Env env = db->Env(); + auto info = std::unique_ptr(i); + auto env = db->Env(); Napi::HandleScope scope(env); Napi::Value argv[] = { @@ -571,8 +555,8 @@ void Database::UpdateCallback(Database *db, UpdateInfo* i) { } Napi::Value Database::Exec(const Napi::CallbackInfo& info) { - Napi::Env env = this->Env(); - Database* db = this; + auto env = this->Env(); + auto* db = this; REQUIRE_ARGUMENT_STRING(0, sql); OPTIONAL_ARGUMENT_FUNCTION(1, callback); @@ -589,17 +573,13 @@ void Database::Work_BeginExec(Baton* baton) { assert(baton->db->_handle); assert(baton->db->pending == 0); baton->db->pending++; - Napi::Env env = baton->db->Env(); - int status = napi_create_async_work( - env, NULL, Napi::String::New(env, "sqlite3.Database.Exec"), - Work_Exec, Work_AfterExec, baton, &baton->request - ); - assert(status == 0); - napi_queue_async_work(env, baton->request); + + auto env = baton->db->Env(); + CREATE_WORK("sqlite3.Database.Exec", Work_Exec, Work_AfterExec); } void Database::Work_Exec(napi_env e, void* data) { - ExecBaton* baton = static_cast(data); + auto* baton = static_cast(data); char* message = NULL; baton->status = sqlite3_exec( @@ -619,10 +599,10 @@ void Database::Work_Exec(napi_env e, void* data) { void Database::Work_AfterExec(napi_env e, napi_status status, void* data) { std::unique_ptr baton(static_cast(data)); - Database* db = baton->db; + auto* db = baton->db; db->pending--; - Napi::Env env = db->Env(); + auto env = db->Env(); Napi::HandleScope scope(env); Napi::Function cb = baton->callback.Value(); @@ -648,21 +628,21 @@ void Database::Work_AfterExec(napi_env e, napi_status status, void* data) { } Napi::Value Database::Wait(const Napi::CallbackInfo& info) { - Napi::Env env = info.Env(); - Database* db = this; + auto env = info.Env(); + auto* db = this; OPTIONAL_ARGUMENT_FUNCTION(0, callback); - Baton* baton = new Baton(db, callback); + auto* baton = new Baton(db, callback); db->Schedule(Work_Wait, baton, true); return info.This(); } void Database::Work_Wait(Baton* b) { - std::unique_ptr baton(b); + auto baton = std::unique_ptr(b); - Napi::Env env = baton->db->Env(); + auto env = baton->db->Env(); Napi::HandleScope scope(env); assert(baton->db->locked); @@ -680,8 +660,8 @@ void Database::Work_Wait(Baton* b) { } Napi::Value Database::LoadExtension(const Napi::CallbackInfo& info) { - Napi::Env env = this->Env(); - Database* db = this; + auto env = this->Env(); + auto* db = this; REQUIRE_ARGUMENT_STRING(0, filename); OPTIONAL_ARGUMENT_FUNCTION(1, callback); @@ -698,17 +678,13 @@ void Database::Work_BeginLoadExtension(Baton* baton) { assert(baton->db->_handle); assert(baton->db->pending == 0); baton->db->pending++; - Napi::Env env = baton->db->Env(); - int status = napi_create_async_work( - env, NULL, Napi::String::New(env, "sqlite3.Database.LoadExtension"), - Work_LoadExtension, Work_AfterLoadExtension, baton, &baton->request - ); - assert(status == 0); - napi_queue_async_work(env, baton->request); + + auto env = baton->db->Env(); + CREATE_WORK("sqlite3.Database.LoadExtension", Work_LoadExtension, Work_AfterLoadExtension); } void Database::Work_LoadExtension(napi_env e, void* data) { - LoadExtensionBaton* baton = static_cast(data); + auto* baton = static_cast(data); sqlite3_enable_load_extension(baton->db->_handle, 1); @@ -731,10 +707,10 @@ void Database::Work_LoadExtension(napi_env e, void* data) { void Database::Work_AfterLoadExtension(napi_env e, napi_status status, void* data) { std::unique_ptr baton(static_cast(data)); - Database* db = baton->db; + auto* db = baton->db; db->pending--; - Napi::Env env = db->Env(); + auto env = db->Env(); Napi::HandleScope scope(env); Napi::Function cb = baton->callback.Value(); diff --git a/src/database.h b/src/database.h index 420b5dd1c..8ffd300d2 100644 --- a/src/database.h +++ b/src/database.h @@ -27,14 +27,14 @@ class Database : public Napi::ObjectWrap { static Napi::Object Init(Napi::Env env, Napi::Object exports); static inline bool HasInstance(Napi::Value val) { - Napi::Env env = val.Env(); + auto env = val.Env(); Napi::HandleScope scope(env); if (!val.IsObject()) return false; - Napi::Object obj = val.As(); + auto obj = val.As(); #if NAPI_VERSION < 6 return obj.InstanceOf(constructor.Value()); #else - Napi::FunctionReference* constructor = + auto constructor = env.GetInstanceData(); return obj.InstanceOf(constructor->Value()); #endif @@ -66,18 +66,21 @@ class Database : public Napi::ObjectWrap { int mode; OpenBaton(Database* db_, Napi::Function cb_, const char* filename_, int mode_) : Baton(db_, cb_), filename(filename_), mode(mode_) {} + virtual ~OpenBaton() override = default; }; struct ExecBaton : Baton { std::string sql; ExecBaton(Database* db_, Napi::Function cb_, const char* sql_) : Baton(db_, cb_), sql(sql_) {} + virtual ~ExecBaton() override = default; }; struct LoadExtensionBaton : Baton { std::string filename; LoadExtensionBaton(Database* db_, Napi::Function cb_, const char* filename_) : Baton(db_, cb_), filename(filename_) {} + virtual ~LoadExtensionBaton() override = default; }; struct LimitBaton : Baton { @@ -85,6 +88,7 @@ class Database : public Napi::ObjectWrap { int value; LimitBaton(Database* db_, Napi::Function cb_, int id_, int value_) : Baton(db_, cb_), id(id_), value(value_) {} + virtual ~LimitBaton() override = default; }; typedef void (*Work_Callback)(Baton* baton); @@ -119,18 +123,6 @@ class Database : public Napi::ObjectWrap { friend class Statement; friend class Backup; - void init() { - _handle = NULL; - open = false; - closing = false; - locked = false; - pending = 0; - serialize = false; - debug_trace = NULL; - debug_profile = NULL; - update_event = NULL; - } - Database(const Napi::CallbackInfo& info); ~Database() { @@ -141,38 +133,20 @@ class Database : public Napi::ObjectWrap { } protected: - static void Work_BeginOpen(Baton* baton); - static void Work_Open(napi_env env, void* data); - static void Work_AfterOpen(napi_env env, napi_status status, void* data); - - Napi::Value OpenGetter(const Napi::CallbackInfo& info); + WORK_DEFINITION(Open); + WORK_DEFINITION(Exec); + WORK_DEFINITION(Close); + WORK_DEFINITION(LoadExtension); void Schedule(Work_Callback callback, Baton* baton, bool exclusive = false); void Process(); - Napi::Value Exec(const Napi::CallbackInfo& info); - static void Work_BeginExec(Baton* baton); - static void Work_Exec(napi_env env, void* data); - static void Work_AfterExec(napi_env env, napi_status status, void* data); - Napi::Value Wait(const Napi::CallbackInfo& info); static void Work_Wait(Baton* baton); - Napi::Value Close(const Napi::CallbackInfo& info); - static void Work_BeginClose(Baton* baton); - static void Work_Close(napi_env env, void* data); - static void Work_AfterClose(napi_env env, napi_status status, void* data); - - Napi::Value LoadExtension(const Napi::CallbackInfo& info); - static void Work_BeginLoadExtension(Baton* baton); - static void Work_LoadExtension(napi_env env, void* data); - static void Work_AfterLoadExtension(napi_env env, napi_status status, void* data); - Napi::Value Serialize(const Napi::CallbackInfo& info); Napi::Value Parallelize(const Napi::CallbackInfo& info); - Napi::Value Configure(const Napi::CallbackInfo& info); - Napi::Value Interrupt(const Napi::CallbackInfo& info); static void SetBusyTimeout(Baton* baton); @@ -193,20 +167,20 @@ class Database : public Napi::ObjectWrap { void RemoveCallbacks(); protected: - sqlite3* _handle; + sqlite3* _handle = NULL; - bool open; - bool closing; - bool locked; - unsigned int pending; + bool open = false; + bool closing = false; + bool locked = false; + unsigned int pending = 0; - bool serialize; + bool serialize = false; std::queue queue; - AsyncTrace* debug_trace; - AsyncProfile* debug_profile; - AsyncUpdate* update_event; + AsyncTrace* debug_trace = NULL; + AsyncProfile* debug_profile = NULL; + AsyncUpdate* update_event = NULL; }; } diff --git a/src/gcc-preinclude.h b/src/gcc-preinclude.h index f7e5ed59f..7a52a4dc1 100644 --- a/src/gcc-preinclude.h +++ b/src/gcc-preinclude.h @@ -12,6 +12,7 @@ __asm__(".symver memcpy,memcpy@GLIBC_2.2.5"); __asm__(".symver exp,exp@GLIBC_2.2.5"); __asm__(".symver log,log@GLIBC_2.2.5"); +__asm__(".symver log2,log2@GLIBC_2.2.5"); __asm__(".symver pow,pow@GLIBC_2.2.5"); __asm__(".symver fcntl64,fcntl@GLIBC_2.2.5"); #endif @@ -20,6 +21,7 @@ __asm__(".symver fcntl64,fcntl@GLIBC_2.2.5"); __asm__(".symver memcpy,memcpy@GLIBC_2.17"); __asm__(".symver exp,exp@GLIBC_2.17"); __asm__(".symver log,log@GLIBC_2.17"); +__asm__(".symver log2,log2@GLIBC_2.17"); __asm__(".symver pow,pow@GLIBC_2.17"); __asm__(".symver fcntl64,fcntl@GLIBC_2.17"); #endif diff --git a/src/macros.h b/src/macros.h index 344642d9d..3bcde83c6 100644 --- a/src/macros.h +++ b/src/macros.h @@ -15,7 +15,7 @@ inline Napi::String StringConcat(Napi::Value str1, Napi::Value str2) { // A Napi substitute IsInt32() inline bool OtherIsInt(Napi::Number source) { double orig_val = source.DoubleValue(); - double int_val = (double)source.Int32Value(); + double int_val = static_cast(source.Int32Value()); if (orig_val == int_val) { return true; } else { @@ -137,6 +137,19 @@ inline bool OtherIsInt(Napi::Number source) { static void Work_##name(napi_env env, void* data); \ static void Work_After##name(napi_env env, napi_status status, void* data); +#ifdef DEBUG + #define ASSERT_STATUS() assert(status == 0); +#else + #define ASSERT_STATUS() (void)status; +#endif + +#define CREATE_WORK(name, workerFn, afterFn) \ + int status = napi_create_async_work(env, NULL, Napi::String::New(env, name),\ + workerFn, afterFn, baton, &baton->request); \ + \ + ASSERT_STATUS(); \ + napi_queue_async_work(env, baton->request); + #define STATEMENT_BEGIN(type) \ assert(baton); \ assert(baton->stmt); \ @@ -145,13 +158,8 @@ inline bool OtherIsInt(Napi::Number source) { assert(baton->stmt->prepared); \ baton->stmt->locked = true; \ baton->stmt->db->pending++; \ - Napi::Env env = baton->stmt->Env(); \ - int status = napi_create_async_work( \ - env, NULL, Napi::String::New(env, "sqlite3.Statement."#type), \ - Work_##type, Work_After##type, baton, &baton->request \ - ); \ - assert(status == 0); \ - napi_queue_async_work(env, baton->request); + auto env = baton->stmt->Env(); \ + CREATE_WORK("sqlite3.Statement."#type, Work_##type, Work_After##type); #define STATEMENT_INIT(type) \ type* baton = static_cast(data); \ @@ -181,13 +189,8 @@ inline bool OtherIsInt(Napi::Number source) { assert(baton->backup->inited); \ baton->backup->locked = true; \ baton->backup->db->pending++; \ - Napi::Env env = baton->backup->Env(); \ - int status = napi_create_async_work( \ - env, NULL, Napi::String::New(env, "sqlite3.Backup."#type), \ - Work_##type, Work_After##type, baton, &baton->request \ - ); \ - assert(status == 0); \ - napi_queue_async_work(env, baton->request); + auto env = baton->backup->Env(); \ + CREATE_WORK("sqlite3.Backup."#type, Work_##type, Work_After##type); #define BACKUP_INIT(type) \ type* baton = static_cast(data); \ @@ -201,15 +204,4 @@ inline bool OtherIsInt(Napi::Number source) { backup->Process(); \ backup->db->Process(); -#define DELETE_FIELD(field) \ - if (field != NULL) { \ - switch ((field)->type) { \ - case SQLITE_INTEGER: delete (Values::Integer*)(field); break; \ - case SQLITE_FLOAT: delete (Values::Float*)(field); break; \ - case SQLITE_TEXT: delete (Values::Text*)(field); break; \ - case SQLITE_BLOB: delete (Values::Blob*)(field); break; \ - case SQLITE_NULL: delete (Values::Null*)(field); break; \ - } \ - } - -#endif +#endif \ No newline at end of file diff --git a/src/statement.cc b/src/statement.cc index f1b835ba2..fc49b90f1 100644 --- a/src/statement.cc +++ b/src/statement.cc @@ -1,4 +1,4 @@ -#include +#include #include #include @@ -12,9 +12,9 @@ Napi::Object Statement::Init(Napi::Env env, Napi::Object exports) { Napi::HandleScope scope(env); // declare napi_default_method here as it is only available in Node v14.12.0+ - napi_property_attributes napi_default_method = static_cast(napi_writable | napi_configurable); + auto napi_default_method = static_cast(napi_writable | napi_configurable); - Napi::Function t = DefineClass(env, "Statement", { + auto t = DefineClass(env, "Statement", { InstanceMethod("bind", &Statement::Bind, napi_default_method), InstanceMethod("get", &Statement::Get, napi_default_method), InstanceMethod("run", &Statement::Run, napi_default_method), @@ -45,7 +45,7 @@ void Statement::Process() { } while (prepared && !locked && !queue.empty()) { - std::unique_ptr call(queue.front()); + auto call = std::unique_ptr(queue.front()); queue.pop(); call->callback(call->baton); @@ -54,11 +54,11 @@ void Statement::Process() { void Statement::Schedule(Work_Callback callback, Baton* baton) { if (finalized) { - queue.push(new Call(callback, baton)); + queue.emplace(new Call(callback, baton)); CleanQueue(); } else if (!prepared || locked) { - queue.push(new Call(callback, baton)); + queue.emplace(new Call(callback, baton)); } else { callback(baton); @@ -68,7 +68,7 @@ void Statement::Schedule(Work_Callback callback, Baton* baton) { template void Statement::Error(T* baton) { Statement* stmt = baton->stmt; - Napi::Env env = stmt->Env(); + auto env = stmt->Env(); Napi::HandleScope scope(env); // Fail hard on logic errors. @@ -89,7 +89,7 @@ template void Statement::Error(T* baton) { // { Database db, String sql, Array params, Function callback } Statement::Statement(const Napi::CallbackInfo& info) : Napi::ObjectWrap(info) { - Napi::Env env = info.Env(); + auto env = info.Env(); int length = info.Length(); if (length <= 0 || !Database::HasInstance(info[0])) { @@ -105,29 +105,27 @@ Statement::Statement(const Napi::CallbackInfo& info) : Napi::ObjectWrap::Unwrap(info[0].As()); - Napi::String sql = info[1].As(); + this->db = Napi::ObjectWrap::Unwrap(info[0].As()); + this->db->Ref(); + + auto sql = info[1].As(); info.This().As().DefineProperty(Napi::PropertyDescriptor::Value("sql", sql, napi_default)); - init(db); + Statement* stmt = this; - PrepareBaton* baton = new PrepareBaton(db, info[2].As(), stmt); + auto* baton = new PrepareBaton(this->db, info[2].As(), stmt); baton->sql = std::string(sql.As().Utf8Value().c_str()); - db->Schedule(Work_BeginPrepare, baton); + this->db->Schedule(Work_BeginPrepare, baton); } void Statement::Work_BeginPrepare(Database::Baton* baton) { assert(baton->db->open); baton->db->pending++; - Napi::Env env = baton->db->Env(); - int status = napi_create_async_work( - env, NULL, Napi::String::New(env, "sqlite3.Statement.Prepare"), - Work_Prepare, Work_AfterPrepare, baton, &baton->request - ); - assert(status == 0); - napi_queue_async_work(env, baton->request); + + auto env = baton->db->Env(); + CREATE_WORK("sqlite3.Statement.Prepare", Work_Prepare, Work_AfterPrepare); } void Statement::Work_Prepare(napi_env e, void* data) { @@ -156,9 +154,9 @@ void Statement::Work_Prepare(napi_env e, void* data) { void Statement::Work_AfterPrepare(napi_env e, napi_status status, void* data) { std::unique_ptr baton(static_cast(data)); - Statement* stmt = baton->stmt; + auto* stmt = baton->stmt; - Napi::Env env = stmt->Env(); + auto env = stmt->Env(); Napi::HandleScope scope(env); if (stmt->status != SQLITE_OK) { @@ -177,45 +175,45 @@ void Statement::Work_AfterPrepare(napi_env e, napi_status status, void* data) { STATEMENT_END(); } -template Values::Field* +template std::unique_ptr Statement::BindParameter(const Napi::Value source, T pos) { if (source.IsString()) { std::string val = source.As().Utf8Value(); - return new Values::Text(pos, val.length(), val.c_str()); + return std::make_unique(pos, val.length(), val.c_str()); } else if (OtherInstanceOf(source.As(), "RegExp")) { std::string val = source.ToString().Utf8Value(); - return new Values::Text(pos, val.length(), val.c_str()); + return std::make_unique(pos, val.length(), val.c_str()); } else if (source.IsNumber()) { if (OtherIsInt(source.As())) { - return new Values::Integer(pos, source.As().Int32Value()); + return std::make_unique(pos, source.As().Int32Value()); } else { - return new Values::Float(pos, source.As().DoubleValue()); + return std::make_unique(pos, source.As().DoubleValue()); } } else if (source.IsBoolean()) { - return new Values::Integer(pos, source.As().Value() ? 1 : 0); + return std::make_unique(pos, source.As().Value() ? 1 : 0); } else if (source.IsNull()) { - return new Values::Null(pos); + return std::make_unique(pos); } else if (source.IsBuffer()) { Napi::Buffer buffer = source.As>(); - return new Values::Blob(pos, buffer.Length(), buffer.Data()); + return std::make_unique(pos, buffer.Length(), buffer.Data()); } else if (OtherInstanceOf(source.As(), "Date")) { - return new Values::Float(pos, source.ToNumber().DoubleValue()); + return std::make_unique(pos, source.ToNumber().DoubleValue()); } else if (source.IsObject()) { - Napi::String napiVal = source.ToString(); + auto napiVal = Napi::String::New(source.Env(), "[object Object]"); // Check whether toString returned a value that is not undefined. if(napiVal.Type() == 0) { return NULL; } std::string val = napiVal.Utf8Value(); - return new Values::Text(pos, val.length(), val.c_str()); + return std::make_unique(pos, val.length(), val.c_str()); } else { return NULL; @@ -223,7 +221,7 @@ template Values::Field* } template T* Statement::Bind(const Napi::CallbackInfo& info, int start, int last) { - Napi::Env env = info.Env(); + auto env = info.Env(); Napi::HandleScope scope(env); if (last < 0) last = info.Length(); @@ -233,38 +231,39 @@ template T* Statement::Bind(const Napi::CallbackInfo& info, int start, last--; } - T* baton = new T(this, callback); + auto *baton = new T(this, callback); if (start < last) { if (info[start].IsArray()) { - Napi::Array array = info[start].As(); + auto array = info[start].As(); int length = array.Length(); // Note: bind parameters start with 1. for (int i = 0, pos = 1; i < length; i++, pos++) { - baton->parameters.push_back(BindParameter((array).Get(i), pos)); + baton->parameters.emplace_back(BindParameter((array).Get(i), i + 1)); } } - else if (!info[start].IsObject() || OtherInstanceOf(info[start].As(), "RegExp") || OtherInstanceOf(info[start].As(), "Date") || info[start].IsBuffer()) { + else if (!info[start].IsObject() || OtherInstanceOf(info[start].As(), "RegExp") + || OtherInstanceOf(info[start].As(), "Date") || info[start].IsBuffer()) { // Parameters directly in array. // Note: bind parameters start with 1. for (int i = start, pos = 1; i < last; i++, pos++) { - baton->parameters.push_back(BindParameter(info[i], pos)); + baton->parameters.emplace_back(BindParameter(info[i], pos)); } } else if (info[start].IsObject()) { - Napi::Object object = info[start].As(); - Napi::Array array = object.GetPropertyNames(); + auto object = info[start].As(); + auto array = object.GetPropertyNames(); int length = array.Length(); for (int i = 0; i < length; i++) { Napi::Value name = (array).Get(i); Napi::Number num = name.ToNumber(); if (num.Int32Value() == num.DoubleValue()) { - baton->parameters.push_back( + baton->parameters.emplace_back( BindParameter((object).Get(name), num.Int32Value())); } else { - baton->parameters.push_back(BindParameter((object).Get(name), + baton->parameters.emplace_back(BindParameter((object).Get(name), name.As().Utf8Value().c_str())); } } @@ -278,67 +277,63 @@ template T* Statement::Bind(const Napi::CallbackInfo& info, int start, } bool Statement::Bind(const Parameters & parameters) { - if (parameters.size() == 0) { + if (parameters.empty()) { return true; } sqlite3_reset(_handle); sqlite3_clear_bindings(_handle); - Parameters::const_iterator it = parameters.begin(); - Parameters::const_iterator end = parameters.end(); + for (auto& field : parameters) { + if (field == NULL) + continue; - for (; it < end; ++it) { - Values::Field* field = *it; - - if (field != NULL) { - unsigned int pos; - if (field->index > 0) { - pos = field->index; - } - else { - pos = sqlite3_bind_parameter_index(_handle, field->name.c_str()); - } + unsigned int pos; + if (field->index > 0) { + pos = field->index; + } + else { + pos = sqlite3_bind_parameter_index(_handle, field->name.c_str()); + } - switch (field->type) { - case SQLITE_INTEGER: { - status = sqlite3_bind_int(_handle, pos, - ((Values::Integer*)field)->value); - } break; - case SQLITE_FLOAT: { - status = sqlite3_bind_double(_handle, pos, - ((Values::Float*)field)->value); - } break; - case SQLITE_TEXT: { - status = sqlite3_bind_text(_handle, pos, - ((Values::Text*)field)->value.c_str(), - ((Values::Text*)field)->value.size(), SQLITE_TRANSIENT); - } break; - case SQLITE_BLOB: { - status = sqlite3_bind_blob(_handle, pos, - ((Values::Blob*)field)->value, - ((Values::Blob*)field)->length, SQLITE_TRANSIENT); - } break; - case SQLITE_NULL: { - status = sqlite3_bind_null(_handle, pos); - } break; - } + switch (field->type) { + case SQLITE_INTEGER: { + status = sqlite3_bind_int(_handle, pos, + (static_cast(field.get()))->value); + } break; + case SQLITE_FLOAT: { + status = sqlite3_bind_double(_handle, pos, + (static_cast(field.get()))->value); + } break; + case SQLITE_TEXT: { + status = sqlite3_bind_text(_handle, pos, + (static_cast(field.get()))->value.c_str(), + (static_cast(field.get()))->value.size(), SQLITE_TRANSIENT); + } break; + case SQLITE_BLOB: { + status = sqlite3_bind_blob(_handle, pos, + (static_cast(field.get()))->value, + (static_cast(field.get()))->length, SQLITE_TRANSIENT); + } break; + case SQLITE_NULL: { + status = sqlite3_bind_null(_handle, pos); + } break; + } if (status != SQLITE_OK) { message = std::string(sqlite3_errmsg(db->_handle)); return false; } } - } return true; } Napi::Value Statement::Bind(const Napi::CallbackInfo& info) { - Napi::Env env = info.Env(); + auto env = info.Env(); Statement* stmt = this; - Baton* baton = stmt->Bind(info); + auto baton = stmt->Bind(info); if (baton == NULL) { Napi::TypeError::New(env, "Data type is not supported").ThrowAsJavaScriptException(); return env.Null(); @@ -364,9 +359,9 @@ void Statement::Work_Bind(napi_env e, void* data) { void Statement::Work_AfterBind(napi_env e, napi_status status, void* data) { std::unique_ptr baton(static_cast(data)); - Statement* stmt = baton->stmt; + auto* stmt = baton->stmt; - Napi::Env env = stmt->Env(); + auto env = stmt->Env(); Napi::HandleScope scope(env); if (stmt->status != SQLITE_OK) { @@ -387,7 +382,7 @@ void Statement::Work_AfterBind(napi_env e, napi_status status, void* data) { Napi::Value Statement::Get(const Napi::CallbackInfo& info) { - Napi::Env env = info.Env(); + auto env = info.Env(); Statement* stmt = this; Baton* baton = stmt->Bind(info); @@ -431,9 +426,9 @@ void Statement::Work_Get(napi_env e, void* data) { void Statement::Work_AfterGet(napi_env e, napi_status status, void* data) { std::unique_ptr baton(static_cast(data)); - Statement* stmt = baton->stmt; + auto* stmt = baton->stmt; - Napi::Env env = stmt->Env(); + auto env = stmt->Env(); Napi::HandleScope scope(env); if (stmt->status != SQLITE_ROW && stmt->status != SQLITE_DONE) { @@ -459,7 +454,7 @@ void Statement::Work_AfterGet(napi_env e, napi_status status, void* data) { } Napi::Value Statement::Run(const Napi::CallbackInfo& info) { - Napi::Env env = info.Env(); + auto env = info.Env(); Statement* stmt = this; Baton* baton = stmt->Bind(info); @@ -505,9 +500,9 @@ void Statement::Work_Run(napi_env e, void* data) { void Statement::Work_AfterRun(napi_env e, napi_status status, void* data) { std::unique_ptr baton(static_cast(data)); - Statement* stmt = baton->stmt; + auto* stmt = baton->stmt; - Napi::Env env = stmt->Env(); + auto env = stmt->Env(); Napi::HandleScope scope(env); if (stmt->status != SQLITE_ROW && stmt->status != SQLITE_DONE) { @@ -529,7 +524,7 @@ void Statement::Work_AfterRun(napi_env e, napi_status status, void* data) { } Napi::Value Statement::All(const Napi::CallbackInfo& info) { - Napi::Env env = info.Env(); + auto env = info.Env(); Statement* stmt = this; Baton* baton = stmt->Bind(info); @@ -560,9 +555,9 @@ void Statement::Work_All(napi_env e, void* data) { if (stmt->Bind(baton->parameters)) { while ((stmt->status = sqlite3_step(stmt->_handle)) == SQLITE_ROW) { - Row* row = new Row(); - GetRow(row, stmt->_handle); - baton->rows.push_back(row); + auto row = std::make_unique(); + GetRow(row.get(), stmt->_handle); + baton->rows.emplace_back(std::move(row)); } if (stmt->status != SQLITE_DONE) { @@ -575,9 +570,9 @@ void Statement::Work_All(napi_env e, void* data) { void Statement::Work_AfterAll(napi_env e, napi_status status, void* data) { std::unique_ptr baton(static_cast(data)); - Statement* stmt = baton->stmt; + auto* stmt = baton->stmt; - Napi::Env env = stmt->Env(); + auto env = stmt->Env(); Napi::HandleScope scope(env); if (stmt->status != SQLITE_DONE) { @@ -590,11 +585,10 @@ void Statement::Work_AfterAll(napi_env e, napi_status status, void* data) { if (baton->rows.size()) { // Create the result array from the data we acquired. Napi::Array result(Napi::Array::New(env, baton->rows.size())); - Rows::const_iterator it = baton->rows.begin(); - Rows::const_iterator end = baton->rows.end(); + auto it = static_cast(baton->rows.begin()); + decltype(it) end = baton->rows.end(); for (int i = 0; it < end; ++it, i++) { - std::unique_ptr row(*it); - (result).Set(i, RowToJS(env,row.get())); + (result).Set(i, RowToJS(env, it->get())); } Napi::Value argv[] = { env.Null(), result }; @@ -615,7 +609,7 @@ void Statement::Work_AfterAll(napi_env e, napi_status status, void* data) { } Napi::Value Statement::Each(const Napi::CallbackInfo& info) { - Napi::Env env = info.Env(); + auto env = info.Env(); Statement* stmt = this; int last = info.Length(); @@ -625,7 +619,7 @@ Napi::Value Statement::Each(const Napi::CallbackInfo& info) { completed = info[--last].As(); } - EachBaton* baton = stmt->Bind(info, 0, last); + auto baton = stmt->Bind(info, 0, last); if (baton == NULL) { Napi::Error::New(env, "Data type is not supported").ThrowAsJavaScriptException(); return env.Null(); @@ -640,7 +634,7 @@ Napi::Value Statement::Each(const Napi::CallbackInfo& info) { void Statement::Work_BeginEach(Baton* baton) { // Only create the Async object when we're actually going into // the event loop. This prevents dangling events. - EachBaton* each_baton = static_cast(baton); + auto* each_baton = static_cast(baton); each_baton->async = new Async(each_baton->stmt, reinterpret_cast(AsyncEach)); each_baton->async->item_cb.Reset(each_baton->callback.Value(), 1); each_baton->async->completed_cb.Reset(each_baton->completed.Value(), 1); @@ -651,12 +645,10 @@ void Statement::Work_BeginEach(Baton* baton) { void Statement::Work_Each(napi_env e, void* data) { STATEMENT_INIT(EachBaton); - Async* async = baton->async; + auto* async = baton->async; STATEMENT_MUTEX(mtx); - int retrieved = 0; - // Make sure that we also reset when there are no parameters. if (!baton->parameters.size()) { sqlite3_reset(stmt->_handle); @@ -668,11 +660,10 @@ void Statement::Work_Each(napi_env e, void* data) { stmt->status = sqlite3_step(stmt->_handle); if (stmt->status == SQLITE_ROW) { sqlite3_mutex_leave(mtx); - Row* row = new Row(); - GetRow(row, stmt->_handle); + auto row = std::make_unique(); + GetRow(row.get(), stmt->_handle); NODE_SQLITE3_MUTEX_LOCK(&async->mutex) - async->data.push_back(row); - retrieved++; + async->data.emplace_back(std::move(row)); NODE_SQLITE3_MUTEX_UNLOCK(&async->mutex) uv_async_send(&async->watcher); @@ -694,14 +685,14 @@ void Statement::Work_Each(napi_env e, void* data) { void Statement::CloseCallback(uv_handle_t* handle) { assert(handle != NULL); assert(handle->data != NULL); - Async* async = static_cast(handle->data); + auto* async = static_cast(handle->data); delete async; } void Statement::AsyncEach(uv_async_t* handle) { - Async* async = static_cast(handle->data); + auto* async = static_cast(handle->data); - Napi::Env env = async->stmt->Env(); + auto env = async->stmt->Env(); Napi::HandleScope scope(env); while (true) { @@ -720,10 +711,7 @@ void Statement::AsyncEach(uv_async_t* handle) { Napi::Value argv[2]; argv[0] = env.Null(); - Rows::const_iterator it = rows.begin(); - Rows::const_iterator end = rows.end(); - for (int i = 0; it < end; ++it, i++) { - std::unique_ptr row(*it); + for(auto& row : rows) { argv[1] = RowToJS(env,row.get()); async->retrieved++; TRY_CATCH_CALL(async->stmt->Value(), cb, 2, argv); @@ -747,9 +735,9 @@ void Statement::AsyncEach(uv_async_t* handle) { void Statement::Work_AfterEach(napi_env e, napi_status status, void* data) { std::unique_ptr baton(static_cast(data)); - Statement* stmt = baton->stmt; + auto* stmt = baton->stmt; - Napi::Env env = stmt->Env(); + auto env = stmt->Env(); Napi::HandleScope scope(env); if (stmt->status != SQLITE_DONE) { @@ -760,12 +748,12 @@ void Statement::Work_AfterEach(napi_env e, napi_status status, void* data) { } Napi::Value Statement::Reset(const Napi::CallbackInfo& info) { - Napi::Env env = info.Env(); + auto env = info.Env(); Statement* stmt = this; OPTIONAL_ARGUMENT_FUNCTION(0, callback); - Baton* baton = new Baton(stmt, callback); + auto* baton = new Baton(stmt, callback); stmt->Schedule(Work_BeginReset, baton); return info.This(); @@ -784,9 +772,9 @@ void Statement::Work_Reset(napi_env e, void* data) { void Statement::Work_AfterReset(napi_env e, napi_status status, void* data) { std::unique_ptr baton(static_cast(data)); - Statement* stmt = baton->stmt; + auto* stmt = baton->stmt; - Napi::Env env = stmt->Env(); + auto env = stmt->Env(); Napi::HandleScope scope(env); // Fire callbacks. @@ -802,36 +790,33 @@ void Statement::Work_AfterReset(napi_env e, napi_status status, void* data) { Napi::Value Statement::RowToJS(Napi::Env env, Row* row) { Napi::EscapableHandleScope scope(env); - Napi::Object result = Napi::Object::New(env); + auto result = Napi::Object::New(env); - Row::const_iterator it = row->begin(); - Row::const_iterator end = row->end(); - for (int i = 0; it < end; ++it, i++) { - Values::Field* field = *it; + for (auto& field : *row) { Napi::Value value; switch (field->type) { case SQLITE_INTEGER: { - value = Napi::Number::New(env, ((Values::Integer*)field)->value); + value = Napi::Number::New(env, (static_cast(field.get()))->value); } break; case SQLITE_FLOAT: { - value = Napi::Number::New(env, ((Values::Float*)field)->value); + value = Napi::Number::New(env, (static_cast(field.get()))->value); } break; case SQLITE_TEXT: { - value = Napi::String::New(env, ((Values::Text*)field)->value.c_str(), ((Values::Text*)field)->value.size()); + value = Napi::String::New(env, (static_cast(field.get()))->value.c_str(), + (static_cast(field.get()))->value.size()); } break; case SQLITE_BLOB: { - value = Napi::Buffer::Copy(env, ((Values::Blob*)field)->value, ((Values::Blob*)field)->length); + value = Napi::Buffer::Copy(env, (static_cast(field.get()))->value, + (static_cast(field.get()))->length); } break; case SQLITE_NULL: { value = env.Null(); } break; } - (result).Set(Napi::String::New(env, field->name.c_str()), value); - - DELETE_FIELD(field); + result.Set(field->name, value); } return scope.Escape(result); @@ -849,23 +834,23 @@ void Statement::GetRow(Row* row, sqlite3_stmt* stmt) { switch (type) { case SQLITE_INTEGER: { - row->push_back(new Values::Integer(name, sqlite3_column_int64(stmt, i))); + row->emplace_back(std::make_unique(name, sqlite3_column_int64(stmt, i))); } break; case SQLITE_FLOAT: { - row->push_back(new Values::Float(name, sqlite3_column_double(stmt, i))); + row->emplace_back(std::make_unique(name, sqlite3_column_double(stmt, i))); } break; case SQLITE_TEXT: { const char* text = (const char*)sqlite3_column_text(stmt, i); int length = sqlite3_column_bytes(stmt, i); - row->push_back(new Values::Text(name, length, text)); + row->emplace_back(std::make_unique(name, length, text)); } break; case SQLITE_BLOB: { const void* blob = sqlite3_column_blob(stmt, i); int length = sqlite3_column_bytes(stmt, i); - row->push_back(new Values::Blob(name, length, blob)); + row->emplace_back(std::make_unique(name, length, blob)); } break; case SQLITE_NULL: { - row->push_back(new Values::Null(name)); + row->emplace_back(std::make_unique(name)); } break; default: assert(false); @@ -874,19 +859,19 @@ void Statement::GetRow(Row* row, sqlite3_stmt* stmt) { } Napi::Value Statement::Finalize_(const Napi::CallbackInfo& info) { - Napi::Env env = info.Env(); + auto env = info.Env(); Statement* stmt = this; OPTIONAL_ARGUMENT_FUNCTION(0, callback); - Baton* baton = new Baton(stmt, callback); + auto *baton = new Baton(stmt, callback); stmt->Schedule(Finalize_, baton); return stmt->db->Value(); } void Statement::Finalize_(Baton* b) { - std::unique_ptr baton(b); - Napi::Env env = baton->stmt->Env(); + auto baton = std::unique_ptr(b); + auto env = baton->stmt->Env(); Napi::HandleScope scope(env); baton->stmt->Finalize_(); @@ -910,7 +895,7 @@ void Statement::Finalize_() { } void Statement::CleanQueue() { - Napi::Env env = this->Env(); + auto env = this->Env(); Napi::HandleScope scope(env); if (prepared && !queue.empty()) { @@ -922,10 +907,10 @@ void Statement::CleanQueue() { // Clear out the queue so that this object can get GC'ed. while (!queue.empty()) { - std::unique_ptr call(queue.front()); + auto call = std::unique_ptr(queue.front()); queue.pop(); - std::unique_ptr baton(call->baton); + auto baton = std::unique_ptr(call->baton); Napi::Function cb = baton->callback.Value(); if (prepared && !cb.IsEmpty() && @@ -945,7 +930,7 @@ void Statement::CleanQueue() { else while (!queue.empty()) { // Just delete all items in the queue; we already fired an event when // preparing the statement failed. - std::unique_ptr call(queue.front()); + auto call = std::unique_ptr(queue.front()); queue.pop(); // We don't call the actual callback, so we have to make sure that // the baton gets destroyed. diff --git a/src/statement.h b/src/statement.h index dec0015d1..c522c0fdf 100644 --- a/src/statement.h +++ b/src/statement.h @@ -6,7 +6,6 @@ #include #include #include - #include #include #include @@ -28,34 +27,40 @@ namespace Values { unsigned short type; unsigned short index; std::string name; + + virtual ~Field() = default; }; struct Integer : Field { template inline Integer(T _name, int64_t val) : Field(_name, SQLITE_INTEGER), value(val) {} int64_t value; + virtual ~Integer() override = default; }; struct Float : Field { template inline Float(T _name, double val) : Field(_name, SQLITE_FLOAT), value(val) {} double value; + virtual ~Float() override = default; }; struct Text : Field { template inline Text(T _name, size_t len, const char* val) : Field(_name, SQLITE_TEXT), value(val, len) {} std::string value; + virtual ~Text() override = default; }; struct Blob : Field { template inline Blob(T _name, size_t len, const void* val) : Field(_name, SQLITE_BLOB), length(len) { - value = (char*)malloc(len); + value = new char[len]; + assert(value != nullptr); memcpy(value, val, len); } - inline ~Blob() { - free(value); + inline virtual ~Blob() override { + delete[] value; } int length; char* value; @@ -64,8 +69,8 @@ namespace Values { typedef Field Null; } -typedef std::vector Row; -typedef std::vector Rows; +typedef std::vector > Row; +typedef std::vector > Rows; typedef Row Parameters; @@ -86,10 +91,7 @@ class Statement : public Napi::ObjectWrap { callback.Reset(cb_, 1); } virtual ~Baton() { - for (size_t i = 0; i < parameters.size(); i++) { - Values::Field* field = parameters[i]; - DELETE_FIELD(field); - } + parameters.clear(); if (request) napi_delete_async_work(stmt->Env(), request); stmt->Unref(); callback.Reset(); @@ -100,6 +102,7 @@ class Statement : public Napi::ObjectWrap { RowBaton(Statement* stmt_, Napi::Function cb_) : Baton(stmt_, cb_) {} Row row; + virtual ~RowBaton() override = default; }; struct RunBaton : Baton { @@ -107,12 +110,14 @@ class Statement : public Napi::ObjectWrap { Baton(stmt_, cb_), inserted_id(0), changes(0) {} sqlite3_int64 inserted_id; int changes; + virtual ~RunBaton() override = default; }; struct RowsBaton : Baton { RowsBaton(Statement* stmt_, Napi::Function cb_) : Baton(stmt_, cb_) {} Rows rows; + virtual ~RowsBaton() override = default; }; struct Async; @@ -123,7 +128,7 @@ class Statement : public Napi::ObjectWrap { EachBaton(Statement* stmt_, Napi::Function cb_) : Baton(stmt_, cb_) {} - virtual ~EachBaton() { + virtual ~EachBaton() override { completed.Reset(); } }; @@ -135,7 +140,7 @@ class Statement : public Napi::ObjectWrap { Baton(db_, cb_), stmt(stmt_) { stmt->Ref(); } - virtual ~PrepareBaton() { + virtual ~PrepareBaton() override { stmt->Unref(); if (!db->IsOpen() && db->IsLocked()) { // The database handle was closed before the statement could be @@ -184,28 +189,18 @@ class Statement : public Napi::ObjectWrap { } }; - void init(Database* db_) { - db = db_; - _handle = NULL; - status = SQLITE_OK; - prepared = false; - locked = true; - finalized = false; - db->Ref(); - } - Statement(const Napi::CallbackInfo& info); ~Statement() { if (!finalized) Finalize_(); } - WORK_DEFINITION(Bind); - WORK_DEFINITION(Get); - WORK_DEFINITION(Run); - WORK_DEFINITION(All); - WORK_DEFINITION(Each); - WORK_DEFINITION(Reset); + WORK_DEFINITION(Bind) + WORK_DEFINITION(Get) + WORK_DEFINITION(Run) + WORK_DEFINITION(All) + WORK_DEFINITION(Each) + WORK_DEFINITION(Reset) Napi::Value Finalize_(const Napi::CallbackInfo& info); @@ -220,7 +215,7 @@ class Statement : public Napi::ObjectWrap { static void Finalize_(Baton* baton); void Finalize_(); - template inline Values::Field* BindParameter(const Napi::Value source, T pos); + template inline std::unique_ptr BindParameter(const Napi::Value source, T pos); template T* Bind(const Napi::CallbackInfo& info, int start = 0, int end = -1); bool Bind(const Parameters ¶meters); @@ -234,14 +229,14 @@ class Statement : public Napi::ObjectWrap { protected: Database* db; - sqlite3_stmt* _handle; - int status; - std::string message; + sqlite3_stmt* _handle = NULL; + int status = SQLITE_OK; + bool prepared = false; + bool locked = true; + bool finalized = false; - bool prepared; - bool locked; - bool finalized; std::queue queue; + std::string message; }; } diff --git a/test/other_objects.test.js b/test/other_objects.test.js index 718598768..cc516c490 100644 --- a/test/other_objects.test.js +++ b/test/other_objects.test.js @@ -95,4 +95,20 @@ describe('data types', function() { }); }); + it('should ignore faulty toString in array', function(done) { + const faulty = [[{toString: null}], 1]; + db.all('SELECT * FROM txt_table WHERE txt = ? LIMIT ?', faulty, function (err) { + assert.equal(err, null); + done(); + }); + }); + + it('should ignore faulty toString set to function', function(done) { + const faulty = [[{toString: function () {console.log('oh no');}}], 1]; + db.all('SELECT * FROM txt_table WHERE txt = ? LIMIT ?', faulty, function (err) { + assert.equal(err, undefined); + done(); + }); + }); + }); diff --git a/test/support/createdb.js b/test/support/createdb.js index 3c7308ed8..ee22d05e8 100755 --- a/test/support/createdb.js +++ b/test/support/createdb.js @@ -2,6 +2,7 @@ function createdb(callback) { var existsSync = require('fs').existsSync || require('path').existsSync; + var statSync = require('fs').statSync || require('path').statSync; var path = require('path'); var sqlite3 = require('../../lib/sqlite3'); @@ -18,8 +19,8 @@ function createdb(callback) { return str; } - - if (existsSync(db_path)) { +// Make sure the file exists and is also valid. + if (existsSync(db_path) && statSync(db_path).size !== 0) { console.log('okay: database already created (' + db_path + ')'); if (callback) callback(); } else { diff --git a/test/support/helper.js b/test/support/helper.js index 99671b8ff..cb2075d2f 100644 --- a/test/support/helper.js +++ b/test/support/helper.js @@ -29,9 +29,5 @@ assert.fileDoesNotExist = function(name) { }; assert.fileExists = function(name) { - try { - fs.statSync(name); - } catch(err) { - throw err; - } + fs.statSync(name); }; \ No newline at end of file diff --git a/tools/BinaryBuilder.Dockerfile b/tools/BinaryBuilder.Dockerfile index ec0b9e59e..2e089b31d 100644 --- a/tools/BinaryBuilder.Dockerfile +++ b/tools/BinaryBuilder.Dockerfile @@ -1,30 +1,23 @@ -ARG NODE_VERSION=16 +ARG NODE_VERSION=18 ARG VARIANT=bullseye FROM node:$NODE_VERSION-$VARIANT ARG VARIANT -RUN if [[ "$VARIANT" =~ alpine* ]] ; then apk add build-base python3 --update-cache ; fi +RUN if case $VARIANT in "alpine"*) true;; *) false;; esac; then apk add build-base python3 --update-cache ; fi WORKDIR /usr/src/build COPY . . RUN npm install --ignore-scripts -# Workaround for https://github.com/mapbox/node-pre-gyp/issues/644 -RUN cd node_modules/\@mapbox/node-pre-gyp \ - && npm install fs-extra@10.0.1 \ - && sed -i -e s/\'fs/\'fs-extra/ -e s/fs\.renameSync/fs.moveSync/ ./lib/util/napi.js - ENV CFLAGS="${CFLAGS:-} -include ../src/gcc-preinclude.h" ENV CXXFLAGS="${CXXFLAGS:-} -include ../src/gcc-preinclude.h" -RUN npx node-pre-gyp configure -RUN npx node-pre-gyp build +RUN npm run prebuild -RUN if [[ ! "$VARIANT" =~ alpine* ]] ; then ldd lib/binding/*/node_sqlite3.node; nm lib/binding/*/node_sqlite3.node | grep "GLIBC_" | c++filt || true ; fi +RUN if case $VARIANT in "alpine"*) false;; *) true;; esac; then ldd build/**/node_sqlite3.node; nm build/**/node_sqlite3.node | grep \"GLIBC_\" | c++filt || true ; fi RUN npm run test -RUN npx node-pre-gyp package CMD ["sh"] diff --git a/tools/benchmark/select-data.sql b/tools/benchmark/select-data.sql index 64015274c..2f89a4ddd 100644 --- a/tools/benchmark/select-data.sql +++ b/tools/benchmark/select-data.sql @@ -111,4 +111,904 @@ INSERT INTO foo SELECT 96000 + Num, 'Row ' || (96000 + Num) FROM Nums WHERE Num INSERT INTO foo SELECT 97000 + Num, 'Row ' || (97000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; INSERT INTO foo SELECT 98000 + Num, 'Row ' || (98000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; INSERT INTO foo SELECT 99000 + Num, 'Row ' || (99000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 0 + Num, 'Row ' || ( 0 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 1000 + Num, 'Row ' || ( 1000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 2000 + Num, 'Row ' || ( 2000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 3000 + Num, 'Row ' || ( 3000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 4000 + Num, 'Row ' || ( 4000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 5000 + Num, 'Row ' || ( 5000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 6000 + Num, 'Row ' || ( 6000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 7000 + Num, 'Row ' || ( 7000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 8000 + Num, 'Row ' || ( 8000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 9000 + Num, 'Row ' || ( 9000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 10000 + Num, 'Row ' || (10000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 11000 + Num, 'Row ' || (11000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 12000 + Num, 'Row ' || (12000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 13000 + Num, 'Row ' || (13000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 14000 + Num, 'Row ' || (14000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 15000 + Num, 'Row ' || (15000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 16000 + Num, 'Row ' || (16000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 17000 + Num, 'Row ' || (17000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 18000 + Num, 'Row ' || (18000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 19000 + Num, 'Row ' || (19000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 20000 + Num, 'Row ' || (20000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 21000 + Num, 'Row ' || (21000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 22000 + Num, 'Row ' || (22000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 23000 + Num, 'Row ' || (23000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 24000 + Num, 'Row ' || (24000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 25000 + Num, 'Row ' || (25000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 26000 + Num, 'Row ' || (26000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 27000 + Num, 'Row ' || (27000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 28000 + Num, 'Row ' || (28000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 29000 + Num, 'Row ' || (29000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 30000 + Num, 'Row ' || (30000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 31000 + Num, 'Row ' || (31000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 32000 + Num, 'Row ' || (32000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 33000 + Num, 'Row ' || (33000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 34000 + Num, 'Row ' || (34000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 35000 + Num, 'Row ' || (35000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 36000 + Num, 'Row ' || (36000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 37000 + Num, 'Row ' || (37000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 38000 + Num, 'Row ' || (38000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 39000 + Num, 'Row ' || (39000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 40000 + Num, 'Row ' || (40000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 41000 + Num, 'Row ' || (41000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 42000 + Num, 'Row ' || (42000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 43000 + Num, 'Row ' || (43000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 44000 + Num, 'Row ' || (44000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 45000 + Num, 'Row ' || (45000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 46000 + Num, 'Row ' || (46000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 47000 + Num, 'Row ' || (47000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 48000 + Num, 'Row ' || (48000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 49000 + Num, 'Row ' || (49000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 50000 + Num, 'Row ' || (50000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 51000 + Num, 'Row ' || (51000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 52000 + Num, 'Row ' || (52000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 53000 + Num, 'Row ' || (53000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 54000 + Num, 'Row ' || (54000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 55000 + Num, 'Row ' || (55000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 56000 + Num, 'Row ' || (56000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 57000 + Num, 'Row ' || (57000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 58000 + Num, 'Row ' || (58000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 59000 + Num, 'Row ' || (59000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 60000 + Num, 'Row ' || (60000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 61000 + Num, 'Row ' || (61000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 62000 + Num, 'Row ' || (62000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 63000 + Num, 'Row ' || (63000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 64000 + Num, 'Row ' || (64000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 65000 + Num, 'Row ' || (65000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 66000 + Num, 'Row ' || (66000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 67000 + Num, 'Row ' || (67000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 68000 + Num, 'Row ' || (68000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 69000 + Num, 'Row ' || (69000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 70000 + Num, 'Row ' || (70000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 71000 + Num, 'Row ' || (71000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 72000 + Num, 'Row ' || (72000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 73000 + Num, 'Row ' || (73000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 74000 + Num, 'Row ' || (74000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 75000 + Num, 'Row ' || (75000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 76000 + Num, 'Row ' || (76000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 77000 + Num, 'Row ' || (77000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 78000 + Num, 'Row ' || (78000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 79000 + Num, 'Row ' || (79000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 80000 + Num, 'Row ' || (80000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 81000 + Num, 'Row ' || (81000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 82000 + Num, 'Row ' || (82000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 83000 + Num, 'Row ' || (83000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 84000 + Num, 'Row ' || (84000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 85000 + Num, 'Row ' || (85000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 86000 + Num, 'Row ' || (86000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 87000 + Num, 'Row ' || (87000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 88000 + Num, 'Row ' || (88000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 89000 + Num, 'Row ' || (89000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 90000 + Num, 'Row ' || (90000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 91000 + Num, 'Row ' || (91000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 92000 + Num, 'Row ' || (92000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 93000 + Num, 'Row ' || (93000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 94000 + Num, 'Row ' || (94000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 95000 + Num, 'Row ' || (95000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 96000 + Num, 'Row ' || (96000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 97000 + Num, 'Row ' || (97000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 98000 + Num, 'Row ' || (98000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 99000 + Num, 'Row ' || (99000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 0 + Num, 'Row ' || ( 0 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 1000 + Num, 'Row ' || ( 1000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 2000 + Num, 'Row ' || ( 2000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 3000 + Num, 'Row ' || ( 3000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 4000 + Num, 'Row ' || ( 4000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 5000 + Num, 'Row ' || ( 5000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 6000 + Num, 'Row ' || ( 6000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 7000 + Num, 'Row ' || ( 7000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 8000 + Num, 'Row ' || ( 8000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 9000 + Num, 'Row ' || ( 9000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 10000 + Num, 'Row ' || (10000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 11000 + Num, 'Row ' || (11000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 12000 + Num, 'Row ' || (12000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 13000 + Num, 'Row ' || (13000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 14000 + Num, 'Row ' || (14000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 15000 + Num, 'Row ' || (15000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 16000 + Num, 'Row ' || (16000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 17000 + Num, 'Row ' || (17000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 18000 + Num, 'Row ' || (18000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 19000 + Num, 'Row ' || (19000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 20000 + Num, 'Row ' || (20000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 21000 + Num, 'Row ' || (21000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 22000 + Num, 'Row ' || (22000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 23000 + Num, 'Row ' || (23000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 24000 + Num, 'Row ' || (24000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 25000 + Num, 'Row ' || (25000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 26000 + Num, 'Row ' || (26000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 27000 + Num, 'Row ' || (27000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 28000 + Num, 'Row ' || (28000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 29000 + Num, 'Row ' || (29000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 30000 + Num, 'Row ' || (30000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 31000 + Num, 'Row ' || (31000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 32000 + Num, 'Row ' || (32000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 33000 + Num, 'Row ' || (33000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 34000 + Num, 'Row ' || (34000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 35000 + Num, 'Row ' || (35000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 36000 + Num, 'Row ' || (36000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 37000 + Num, 'Row ' || (37000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 38000 + Num, 'Row ' || (38000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 39000 + Num, 'Row ' || (39000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 40000 + Num, 'Row ' || (40000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 41000 + Num, 'Row ' || (41000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 42000 + Num, 'Row ' || (42000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 43000 + Num, 'Row ' || (43000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 44000 + Num, 'Row ' || (44000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 45000 + Num, 'Row ' || (45000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 46000 + Num, 'Row ' || (46000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 47000 + Num, 'Row ' || (47000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 48000 + Num, 'Row ' || (48000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 49000 + Num, 'Row ' || (49000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 50000 + Num, 'Row ' || (50000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 51000 + Num, 'Row ' || (51000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 52000 + Num, 'Row ' || (52000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 53000 + Num, 'Row ' || (53000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 54000 + Num, 'Row ' || (54000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 55000 + Num, 'Row ' || (55000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 56000 + Num, 'Row ' || (56000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 57000 + Num, 'Row ' || (57000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 58000 + Num, 'Row ' || (58000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 59000 + Num, 'Row ' || (59000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 60000 + Num, 'Row ' || (60000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 61000 + Num, 'Row ' || (61000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 62000 + Num, 'Row ' || (62000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 63000 + Num, 'Row ' || (63000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 64000 + Num, 'Row ' || (64000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 65000 + Num, 'Row ' || (65000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 66000 + Num, 'Row ' || (66000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 67000 + Num, 'Row ' || (67000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 68000 + Num, 'Row ' || (68000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 69000 + Num, 'Row ' || (69000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 70000 + Num, 'Row ' || (70000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 71000 + Num, 'Row ' || (71000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 72000 + Num, 'Row ' || (72000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 73000 + Num, 'Row ' || (73000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 74000 + Num, 'Row ' || (74000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 75000 + Num, 'Row ' || (75000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 76000 + Num, 'Row ' || (76000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 77000 + Num, 'Row ' || (77000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 78000 + Num, 'Row ' || (78000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 79000 + Num, 'Row ' || (79000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 80000 + Num, 'Row ' || (80000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 81000 + Num, 'Row ' || (81000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 82000 + Num, 'Row ' || (82000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 83000 + Num, 'Row ' || (83000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 84000 + Num, 'Row ' || (84000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 85000 + Num, 'Row ' || (85000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 86000 + Num, 'Row ' || (86000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 87000 + Num, 'Row ' || (87000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 88000 + Num, 'Row ' || (88000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 89000 + Num, 'Row ' || (89000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 90000 + Num, 'Row ' || (90000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 91000 + Num, 'Row ' || (91000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 92000 + Num, 'Row ' || (92000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 93000 + Num, 'Row ' || (93000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 94000 + Num, 'Row ' || (94000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 95000 + Num, 'Row ' || (95000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 96000 + Num, 'Row ' || (96000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 97000 + Num, 'Row ' || (97000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 98000 + Num, 'Row ' || (98000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 99000 + Num, 'Row ' || (99000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 0 + Num, 'Row ' || ( 0 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 1000 + Num, 'Row ' || ( 1000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 2000 + Num, 'Row ' || ( 2000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 3000 + Num, 'Row ' || ( 3000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 4000 + Num, 'Row ' || ( 4000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 5000 + Num, 'Row ' || ( 5000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 6000 + Num, 'Row ' || ( 6000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 7000 + Num, 'Row ' || ( 7000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 8000 + Num, 'Row ' || ( 8000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 9000 + Num, 'Row ' || ( 9000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 10000 + Num, 'Row ' || (10000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 11000 + Num, 'Row ' || (11000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 12000 + Num, 'Row ' || (12000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 13000 + Num, 'Row ' || (13000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 14000 + Num, 'Row ' || (14000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 15000 + Num, 'Row ' || (15000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 16000 + Num, 'Row ' || (16000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 17000 + Num, 'Row ' || (17000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 18000 + Num, 'Row ' || (18000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 19000 + Num, 'Row ' || (19000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 20000 + Num, 'Row ' || (20000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 21000 + Num, 'Row ' || (21000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 22000 + Num, 'Row ' || (22000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 23000 + Num, 'Row ' || (23000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 24000 + Num, 'Row ' || (24000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 25000 + Num, 'Row ' || (25000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 26000 + Num, 'Row ' || (26000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 27000 + Num, 'Row ' || (27000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 28000 + Num, 'Row ' || (28000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 29000 + Num, 'Row ' || (29000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 30000 + Num, 'Row ' || (30000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 31000 + Num, 'Row ' || (31000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 32000 + Num, 'Row ' || (32000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 33000 + Num, 'Row ' || (33000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 34000 + Num, 'Row ' || (34000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 35000 + Num, 'Row ' || (35000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 36000 + Num, 'Row ' || (36000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 37000 + Num, 'Row ' || (37000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 38000 + Num, 'Row ' || (38000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 39000 + Num, 'Row ' || (39000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 40000 + Num, 'Row ' || (40000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 41000 + Num, 'Row ' || (41000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 42000 + Num, 'Row ' || (42000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 43000 + Num, 'Row ' || (43000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 44000 + Num, 'Row ' || (44000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 45000 + Num, 'Row ' || (45000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 46000 + Num, 'Row ' || (46000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 47000 + Num, 'Row ' || (47000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 48000 + Num, 'Row ' || (48000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 49000 + Num, 'Row ' || (49000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 50000 + Num, 'Row ' || (50000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 51000 + Num, 'Row ' || (51000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 52000 + Num, 'Row ' || (52000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 53000 + Num, 'Row ' || (53000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 54000 + Num, 'Row ' || (54000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 55000 + Num, 'Row ' || (55000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 56000 + Num, 'Row ' || (56000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 57000 + Num, 'Row ' || (57000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 58000 + Num, 'Row ' || (58000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 59000 + Num, 'Row ' || (59000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 60000 + Num, 'Row ' || (60000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 61000 + Num, 'Row ' || (61000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 62000 + Num, 'Row ' || (62000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 63000 + Num, 'Row ' || (63000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 64000 + Num, 'Row ' || (64000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 65000 + Num, 'Row ' || (65000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 66000 + Num, 'Row ' || (66000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 67000 + Num, 'Row ' || (67000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 68000 + Num, 'Row ' || (68000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 69000 + Num, 'Row ' || (69000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 70000 + Num, 'Row ' || (70000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 71000 + Num, 'Row ' || (71000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 72000 + Num, 'Row ' || (72000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 73000 + Num, 'Row ' || (73000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 74000 + Num, 'Row ' || (74000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 75000 + Num, 'Row ' || (75000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 76000 + Num, 'Row ' || (76000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 77000 + Num, 'Row ' || (77000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 78000 + Num, 'Row ' || (78000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 79000 + Num, 'Row ' || (79000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 80000 + Num, 'Row ' || (80000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 81000 + Num, 'Row ' || (81000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 82000 + Num, 'Row ' || (82000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 83000 + Num, 'Row ' || (83000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 84000 + Num, 'Row ' || (84000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 85000 + Num, 'Row ' || (85000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 86000 + Num, 'Row ' || (86000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 87000 + Num, 'Row ' || (87000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 88000 + Num, 'Row ' || (88000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 89000 + Num, 'Row ' || (89000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 90000 + Num, 'Row ' || (90000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 91000 + Num, 'Row ' || (91000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 92000 + Num, 'Row ' || (92000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 93000 + Num, 'Row ' || (93000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 94000 + Num, 'Row ' || (94000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 95000 + Num, 'Row ' || (95000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 96000 + Num, 'Row ' || (96000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 97000 + Num, 'Row ' || (97000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 98000 + Num, 'Row ' || (98000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 99000 + Num, 'Row ' || (99000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 0 + Num, 'Row ' || ( 0 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 1000 + Num, 'Row ' || ( 1000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 2000 + Num, 'Row ' || ( 2000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 3000 + Num, 'Row ' || ( 3000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 4000 + Num, 'Row ' || ( 4000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 5000 + Num, 'Row ' || ( 5000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 6000 + Num, 'Row ' || ( 6000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 7000 + Num, 'Row ' || ( 7000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 8000 + Num, 'Row ' || ( 8000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 9000 + Num, 'Row ' || ( 9000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 10000 + Num, 'Row ' || (10000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 11000 + Num, 'Row ' || (11000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 12000 + Num, 'Row ' || (12000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 13000 + Num, 'Row ' || (13000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 14000 + Num, 'Row ' || (14000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 15000 + Num, 'Row ' || (15000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 16000 + Num, 'Row ' || (16000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 17000 + Num, 'Row ' || (17000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 18000 + Num, 'Row ' || (18000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 19000 + Num, 'Row ' || (19000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 20000 + Num, 'Row ' || (20000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 21000 + Num, 'Row ' || (21000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 22000 + Num, 'Row ' || (22000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 23000 + Num, 'Row ' || (23000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 24000 + Num, 'Row ' || (24000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 25000 + Num, 'Row ' || (25000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 26000 + Num, 'Row ' || (26000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 27000 + Num, 'Row ' || (27000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 28000 + Num, 'Row ' || (28000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 29000 + Num, 'Row ' || (29000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 30000 + Num, 'Row ' || (30000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 31000 + Num, 'Row ' || (31000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 32000 + Num, 'Row ' || (32000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 33000 + Num, 'Row ' || (33000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 34000 + Num, 'Row ' || (34000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 35000 + Num, 'Row ' || (35000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 36000 + Num, 'Row ' || (36000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 37000 + Num, 'Row ' || (37000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 38000 + Num, 'Row ' || (38000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 39000 + Num, 'Row ' || (39000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 40000 + Num, 'Row ' || (40000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 41000 + Num, 'Row ' || (41000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 42000 + Num, 'Row ' || (42000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 43000 + Num, 'Row ' || (43000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 44000 + Num, 'Row ' || (44000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 45000 + Num, 'Row ' || (45000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 46000 + Num, 'Row ' || (46000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 47000 + Num, 'Row ' || (47000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 48000 + Num, 'Row ' || (48000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 49000 + Num, 'Row ' || (49000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 50000 + Num, 'Row ' || (50000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 51000 + Num, 'Row ' || (51000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 52000 + Num, 'Row ' || (52000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 53000 + Num, 'Row ' || (53000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 54000 + Num, 'Row ' || (54000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 55000 + Num, 'Row ' || (55000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 56000 + Num, 'Row ' || (56000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 57000 + Num, 'Row ' || (57000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 58000 + Num, 'Row ' || (58000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 59000 + Num, 'Row ' || (59000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 60000 + Num, 'Row ' || (60000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 61000 + Num, 'Row ' || (61000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 62000 + Num, 'Row ' || (62000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 63000 + Num, 'Row ' || (63000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 64000 + Num, 'Row ' || (64000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 65000 + Num, 'Row ' || (65000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 66000 + Num, 'Row ' || (66000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 67000 + Num, 'Row ' || (67000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 68000 + Num, 'Row ' || (68000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 69000 + Num, 'Row ' || (69000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 70000 + Num, 'Row ' || (70000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 71000 + Num, 'Row ' || (71000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 72000 + Num, 'Row ' || (72000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 73000 + Num, 'Row ' || (73000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 74000 + Num, 'Row ' || (74000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 75000 + Num, 'Row ' || (75000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 76000 + Num, 'Row ' || (76000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 77000 + Num, 'Row ' || (77000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 78000 + Num, 'Row ' || (78000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 79000 + Num, 'Row ' || (79000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 80000 + Num, 'Row ' || (80000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 81000 + Num, 'Row ' || (81000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 82000 + Num, 'Row ' || (82000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 83000 + Num, 'Row ' || (83000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 84000 + Num, 'Row ' || (84000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 85000 + Num, 'Row ' || (85000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 86000 + Num, 'Row ' || (86000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 87000 + Num, 'Row ' || (87000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 88000 + Num, 'Row ' || (88000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 89000 + Num, 'Row ' || (89000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 90000 + Num, 'Row ' || (90000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 91000 + Num, 'Row ' || (91000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 92000 + Num, 'Row ' || (92000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 93000 + Num, 'Row ' || (93000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 94000 + Num, 'Row ' || (94000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 95000 + Num, 'Row ' || (95000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 96000 + Num, 'Row ' || (96000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 97000 + Num, 'Row ' || (97000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 98000 + Num, 'Row ' || (98000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 99000 + Num, 'Row ' || (99000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 0 + Num, 'Row ' || ( 0 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 1000 + Num, 'Row ' || ( 1000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 2000 + Num, 'Row ' || ( 2000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 3000 + Num, 'Row ' || ( 3000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 4000 + Num, 'Row ' || ( 4000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 5000 + Num, 'Row ' || ( 5000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 6000 + Num, 'Row ' || ( 6000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 7000 + Num, 'Row ' || ( 7000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 8000 + Num, 'Row ' || ( 8000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 9000 + Num, 'Row ' || ( 9000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 10000 + Num, 'Row ' || (10000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 11000 + Num, 'Row ' || (11000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 12000 + Num, 'Row ' || (12000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 13000 + Num, 'Row ' || (13000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 14000 + Num, 'Row ' || (14000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 15000 + Num, 'Row ' || (15000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 16000 + Num, 'Row ' || (16000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 17000 + Num, 'Row ' || (17000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 18000 + Num, 'Row ' || (18000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 19000 + Num, 'Row ' || (19000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 20000 + Num, 'Row ' || (20000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 21000 + Num, 'Row ' || (21000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 22000 + Num, 'Row ' || (22000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 23000 + Num, 'Row ' || (23000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 24000 + Num, 'Row ' || (24000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 25000 + Num, 'Row ' || (25000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 26000 + Num, 'Row ' || (26000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 27000 + Num, 'Row ' || (27000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 28000 + Num, 'Row ' || (28000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 29000 + Num, 'Row ' || (29000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 30000 + Num, 'Row ' || (30000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 31000 + Num, 'Row ' || (31000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 32000 + Num, 'Row ' || (32000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 33000 + Num, 'Row ' || (33000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 34000 + Num, 'Row ' || (34000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 35000 + Num, 'Row ' || (35000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 36000 + Num, 'Row ' || (36000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 37000 + Num, 'Row ' || (37000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 38000 + Num, 'Row ' || (38000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 39000 + Num, 'Row ' || (39000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 40000 + Num, 'Row ' || (40000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 41000 + Num, 'Row ' || (41000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 42000 + Num, 'Row ' || (42000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 43000 + Num, 'Row ' || (43000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 44000 + Num, 'Row ' || (44000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 45000 + Num, 'Row ' || (45000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 46000 + Num, 'Row ' || (46000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 47000 + Num, 'Row ' || (47000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 48000 + Num, 'Row ' || (48000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 49000 + Num, 'Row ' || (49000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 50000 + Num, 'Row ' || (50000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 51000 + Num, 'Row ' || (51000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 52000 + Num, 'Row ' || (52000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 53000 + Num, 'Row ' || (53000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 54000 + Num, 'Row ' || (54000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 55000 + Num, 'Row ' || (55000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 56000 + Num, 'Row ' || (56000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 57000 + Num, 'Row ' || (57000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 58000 + Num, 'Row ' || (58000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 59000 + Num, 'Row ' || (59000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 60000 + Num, 'Row ' || (60000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 61000 + Num, 'Row ' || (61000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 62000 + Num, 'Row ' || (62000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 63000 + Num, 'Row ' || (63000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 64000 + Num, 'Row ' || (64000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 65000 + Num, 'Row ' || (65000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 66000 + Num, 'Row ' || (66000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 67000 + Num, 'Row ' || (67000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 68000 + Num, 'Row ' || (68000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 69000 + Num, 'Row ' || (69000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 70000 + Num, 'Row ' || (70000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 71000 + Num, 'Row ' || (71000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 72000 + Num, 'Row ' || (72000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 73000 + Num, 'Row ' || (73000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 74000 + Num, 'Row ' || (74000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 75000 + Num, 'Row ' || (75000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 76000 + Num, 'Row ' || (76000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 77000 + Num, 'Row ' || (77000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 78000 + Num, 'Row ' || (78000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 79000 + Num, 'Row ' || (79000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 80000 + Num, 'Row ' || (80000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 81000 + Num, 'Row ' || (81000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 82000 + Num, 'Row ' || (82000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 83000 + Num, 'Row ' || (83000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 84000 + Num, 'Row ' || (84000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 85000 + Num, 'Row ' || (85000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 86000 + Num, 'Row ' || (86000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 87000 + Num, 'Row ' || (87000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 88000 + Num, 'Row ' || (88000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 89000 + Num, 'Row ' || (89000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 90000 + Num, 'Row ' || (90000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 91000 + Num, 'Row ' || (91000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 92000 + Num, 'Row ' || (92000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 93000 + Num, 'Row ' || (93000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 94000 + Num, 'Row ' || (94000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 95000 + Num, 'Row ' || (95000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 96000 + Num, 'Row ' || (96000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 97000 + Num, 'Row ' || (97000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 98000 + Num, 'Row ' || (98000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 99000 + Num, 'Row ' || (99000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 0 + Num, 'Row ' || ( 0 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 1000 + Num, 'Row ' || ( 1000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 2000 + Num, 'Row ' || ( 2000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 3000 + Num, 'Row ' || ( 3000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 4000 + Num, 'Row ' || ( 4000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 5000 + Num, 'Row ' || ( 5000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 6000 + Num, 'Row ' || ( 6000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 7000 + Num, 'Row ' || ( 7000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 8000 + Num, 'Row ' || ( 8000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 9000 + Num, 'Row ' || ( 9000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 10000 + Num, 'Row ' || (10000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 11000 + Num, 'Row ' || (11000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 12000 + Num, 'Row ' || (12000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 13000 + Num, 'Row ' || (13000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 14000 + Num, 'Row ' || (14000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 15000 + Num, 'Row ' || (15000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 16000 + Num, 'Row ' || (16000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 17000 + Num, 'Row ' || (17000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 18000 + Num, 'Row ' || (18000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 19000 + Num, 'Row ' || (19000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 20000 + Num, 'Row ' || (20000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 21000 + Num, 'Row ' || (21000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 22000 + Num, 'Row ' || (22000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 23000 + Num, 'Row ' || (23000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 24000 + Num, 'Row ' || (24000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 25000 + Num, 'Row ' || (25000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 26000 + Num, 'Row ' || (26000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 27000 + Num, 'Row ' || (27000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 28000 + Num, 'Row ' || (28000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 29000 + Num, 'Row ' || (29000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 30000 + Num, 'Row ' || (30000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 31000 + Num, 'Row ' || (31000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 32000 + Num, 'Row ' || (32000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 33000 + Num, 'Row ' || (33000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 34000 + Num, 'Row ' || (34000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 35000 + Num, 'Row ' || (35000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 36000 + Num, 'Row ' || (36000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 37000 + Num, 'Row ' || (37000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 38000 + Num, 'Row ' || (38000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 39000 + Num, 'Row ' || (39000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 40000 + Num, 'Row ' || (40000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 41000 + Num, 'Row ' || (41000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 42000 + Num, 'Row ' || (42000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 43000 + Num, 'Row ' || (43000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 44000 + Num, 'Row ' || (44000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 45000 + Num, 'Row ' || (45000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 46000 + Num, 'Row ' || (46000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 47000 + Num, 'Row ' || (47000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 48000 + Num, 'Row ' || (48000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 49000 + Num, 'Row ' || (49000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 50000 + Num, 'Row ' || (50000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 51000 + Num, 'Row ' || (51000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 52000 + Num, 'Row ' || (52000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 53000 + Num, 'Row ' || (53000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 54000 + Num, 'Row ' || (54000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 55000 + Num, 'Row ' || (55000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 56000 + Num, 'Row ' || (56000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 57000 + Num, 'Row ' || (57000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 58000 + Num, 'Row ' || (58000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 59000 + Num, 'Row ' || (59000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 60000 + Num, 'Row ' || (60000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 61000 + Num, 'Row ' || (61000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 62000 + Num, 'Row ' || (62000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 63000 + Num, 'Row ' || (63000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 64000 + Num, 'Row ' || (64000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 65000 + Num, 'Row ' || (65000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 66000 + Num, 'Row ' || (66000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 67000 + Num, 'Row ' || (67000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 68000 + Num, 'Row ' || (68000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 69000 + Num, 'Row ' || (69000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 70000 + Num, 'Row ' || (70000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 71000 + Num, 'Row ' || (71000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 72000 + Num, 'Row ' || (72000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 73000 + Num, 'Row ' || (73000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 74000 + Num, 'Row ' || (74000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 75000 + Num, 'Row ' || (75000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 76000 + Num, 'Row ' || (76000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 77000 + Num, 'Row ' || (77000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 78000 + Num, 'Row ' || (78000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 79000 + Num, 'Row ' || (79000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 80000 + Num, 'Row ' || (80000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 81000 + Num, 'Row ' || (81000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 82000 + Num, 'Row ' || (82000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 83000 + Num, 'Row ' || (83000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 84000 + Num, 'Row ' || (84000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 85000 + Num, 'Row ' || (85000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 86000 + Num, 'Row ' || (86000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 87000 + Num, 'Row ' || (87000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 88000 + Num, 'Row ' || (88000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 89000 + Num, 'Row ' || (89000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 90000 + Num, 'Row ' || (90000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 91000 + Num, 'Row ' || (91000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 92000 + Num, 'Row ' || (92000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 93000 + Num, 'Row ' || (93000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 94000 + Num, 'Row ' || (94000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 95000 + Num, 'Row ' || (95000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 96000 + Num, 'Row ' || (96000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 97000 + Num, 'Row ' || (97000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 98000 + Num, 'Row ' || (98000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 99000 + Num, 'Row ' || (99000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 0 + Num, 'Row ' || ( 0 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 1000 + Num, 'Row ' || ( 1000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 2000 + Num, 'Row ' || ( 2000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 3000 + Num, 'Row ' || ( 3000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 4000 + Num, 'Row ' || ( 4000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 5000 + Num, 'Row ' || ( 5000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 6000 + Num, 'Row ' || ( 6000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 7000 + Num, 'Row ' || ( 7000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 8000 + Num, 'Row ' || ( 8000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 9000 + Num, 'Row ' || ( 9000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 10000 + Num, 'Row ' || (10000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 11000 + Num, 'Row ' || (11000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 12000 + Num, 'Row ' || (12000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 13000 + Num, 'Row ' || (13000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 14000 + Num, 'Row ' || (14000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 15000 + Num, 'Row ' || (15000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 16000 + Num, 'Row ' || (16000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 17000 + Num, 'Row ' || (17000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 18000 + Num, 'Row ' || (18000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 19000 + Num, 'Row ' || (19000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 20000 + Num, 'Row ' || (20000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 21000 + Num, 'Row ' || (21000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 22000 + Num, 'Row ' || (22000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 23000 + Num, 'Row ' || (23000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 24000 + Num, 'Row ' || (24000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 25000 + Num, 'Row ' || (25000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 26000 + Num, 'Row ' || (26000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 27000 + Num, 'Row ' || (27000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 28000 + Num, 'Row ' || (28000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 29000 + Num, 'Row ' || (29000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 30000 + Num, 'Row ' || (30000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 31000 + Num, 'Row ' || (31000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 32000 + Num, 'Row ' || (32000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 33000 + Num, 'Row ' || (33000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 34000 + Num, 'Row ' || (34000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 35000 + Num, 'Row ' || (35000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 36000 + Num, 'Row ' || (36000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 37000 + Num, 'Row ' || (37000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 38000 + Num, 'Row ' || (38000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 39000 + Num, 'Row ' || (39000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 40000 + Num, 'Row ' || (40000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 41000 + Num, 'Row ' || (41000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 42000 + Num, 'Row ' || (42000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 43000 + Num, 'Row ' || (43000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 44000 + Num, 'Row ' || (44000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 45000 + Num, 'Row ' || (45000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 46000 + Num, 'Row ' || (46000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 47000 + Num, 'Row ' || (47000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 48000 + Num, 'Row ' || (48000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 49000 + Num, 'Row ' || (49000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 50000 + Num, 'Row ' || (50000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 51000 + Num, 'Row ' || (51000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 52000 + Num, 'Row ' || (52000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 53000 + Num, 'Row ' || (53000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 54000 + Num, 'Row ' || (54000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 55000 + Num, 'Row ' || (55000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 56000 + Num, 'Row ' || (56000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 57000 + Num, 'Row ' || (57000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 58000 + Num, 'Row ' || (58000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 59000 + Num, 'Row ' || (59000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 60000 + Num, 'Row ' || (60000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 61000 + Num, 'Row ' || (61000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 62000 + Num, 'Row ' || (62000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 63000 + Num, 'Row ' || (63000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 64000 + Num, 'Row ' || (64000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 65000 + Num, 'Row ' || (65000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 66000 + Num, 'Row ' || (66000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 67000 + Num, 'Row ' || (67000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 68000 + Num, 'Row ' || (68000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 69000 + Num, 'Row ' || (69000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 70000 + Num, 'Row ' || (70000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 71000 + Num, 'Row ' || (71000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 72000 + Num, 'Row ' || (72000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 73000 + Num, 'Row ' || (73000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 74000 + Num, 'Row ' || (74000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 75000 + Num, 'Row ' || (75000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 76000 + Num, 'Row ' || (76000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 77000 + Num, 'Row ' || (77000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 78000 + Num, 'Row ' || (78000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 79000 + Num, 'Row ' || (79000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 80000 + Num, 'Row ' || (80000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 81000 + Num, 'Row ' || (81000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 82000 + Num, 'Row ' || (82000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 83000 + Num, 'Row ' || (83000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 84000 + Num, 'Row ' || (84000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 85000 + Num, 'Row ' || (85000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 86000 + Num, 'Row ' || (86000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 87000 + Num, 'Row ' || (87000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 88000 + Num, 'Row ' || (88000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 89000 + Num, 'Row ' || (89000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 90000 + Num, 'Row ' || (90000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 91000 + Num, 'Row ' || (91000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 92000 + Num, 'Row ' || (92000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 93000 + Num, 'Row ' || (93000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 94000 + Num, 'Row ' || (94000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 95000 + Num, 'Row ' || (95000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 96000 + Num, 'Row ' || (96000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 97000 + Num, 'Row ' || (97000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 98000 + Num, 'Row ' || (98000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 99000 + Num, 'Row ' || (99000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 0 + Num, 'Row ' || ( 0 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 1000 + Num, 'Row ' || ( 1000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 2000 + Num, 'Row ' || ( 2000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 3000 + Num, 'Row ' || ( 3000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 4000 + Num, 'Row ' || ( 4000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 5000 + Num, 'Row ' || ( 5000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 6000 + Num, 'Row ' || ( 6000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 7000 + Num, 'Row ' || ( 7000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 8000 + Num, 'Row ' || ( 8000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 9000 + Num, 'Row ' || ( 9000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 10000 + Num, 'Row ' || (10000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 11000 + Num, 'Row ' || (11000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 12000 + Num, 'Row ' || (12000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 13000 + Num, 'Row ' || (13000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 14000 + Num, 'Row ' || (14000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 15000 + Num, 'Row ' || (15000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 16000 + Num, 'Row ' || (16000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 17000 + Num, 'Row ' || (17000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 18000 + Num, 'Row ' || (18000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 19000 + Num, 'Row ' || (19000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 20000 + Num, 'Row ' || (20000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 21000 + Num, 'Row ' || (21000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 22000 + Num, 'Row ' || (22000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 23000 + Num, 'Row ' || (23000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 24000 + Num, 'Row ' || (24000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 25000 + Num, 'Row ' || (25000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 26000 + Num, 'Row ' || (26000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 27000 + Num, 'Row ' || (27000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 28000 + Num, 'Row ' || (28000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 29000 + Num, 'Row ' || (29000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 30000 + Num, 'Row ' || (30000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 31000 + Num, 'Row ' || (31000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 32000 + Num, 'Row ' || (32000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 33000 + Num, 'Row ' || (33000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 34000 + Num, 'Row ' || (34000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 35000 + Num, 'Row ' || (35000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 36000 + Num, 'Row ' || (36000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 37000 + Num, 'Row ' || (37000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 38000 + Num, 'Row ' || (38000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 39000 + Num, 'Row ' || (39000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 40000 + Num, 'Row ' || (40000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 41000 + Num, 'Row ' || (41000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 42000 + Num, 'Row ' || (42000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 43000 + Num, 'Row ' || (43000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 44000 + Num, 'Row ' || (44000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 45000 + Num, 'Row ' || (45000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 46000 + Num, 'Row ' || (46000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 47000 + Num, 'Row ' || (47000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 48000 + Num, 'Row ' || (48000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 49000 + Num, 'Row ' || (49000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 50000 + Num, 'Row ' || (50000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 51000 + Num, 'Row ' || (51000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 52000 + Num, 'Row ' || (52000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 53000 + Num, 'Row ' || (53000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 54000 + Num, 'Row ' || (54000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 55000 + Num, 'Row ' || (55000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 56000 + Num, 'Row ' || (56000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 57000 + Num, 'Row ' || (57000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 58000 + Num, 'Row ' || (58000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 59000 + Num, 'Row ' || (59000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 60000 + Num, 'Row ' || (60000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 61000 + Num, 'Row ' || (61000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 62000 + Num, 'Row ' || (62000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 63000 + Num, 'Row ' || (63000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 64000 + Num, 'Row ' || (64000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 65000 + Num, 'Row ' || (65000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 66000 + Num, 'Row ' || (66000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 67000 + Num, 'Row ' || (67000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 68000 + Num, 'Row ' || (68000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 69000 + Num, 'Row ' || (69000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 70000 + Num, 'Row ' || (70000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 71000 + Num, 'Row ' || (71000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 72000 + Num, 'Row ' || (72000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 73000 + Num, 'Row ' || (73000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 74000 + Num, 'Row ' || (74000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 75000 + Num, 'Row ' || (75000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 76000 + Num, 'Row ' || (76000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 77000 + Num, 'Row ' || (77000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 78000 + Num, 'Row ' || (78000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 79000 + Num, 'Row ' || (79000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 80000 + Num, 'Row ' || (80000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 81000 + Num, 'Row ' || (81000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 82000 + Num, 'Row ' || (82000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 83000 + Num, 'Row ' || (83000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 84000 + Num, 'Row ' || (84000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 85000 + Num, 'Row ' || (85000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 86000 + Num, 'Row ' || (86000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 87000 + Num, 'Row ' || (87000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 88000 + Num, 'Row ' || (88000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 89000 + Num, 'Row ' || (89000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 90000 + Num, 'Row ' || (90000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 91000 + Num, 'Row ' || (91000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 92000 + Num, 'Row ' || (92000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 93000 + Num, 'Row ' || (93000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 94000 + Num, 'Row ' || (94000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 95000 + Num, 'Row ' || (95000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 96000 + Num, 'Row ' || (96000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 97000 + Num, 'Row ' || (97000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 98000 + Num, 'Row ' || (98000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 99000 + Num, 'Row ' || (99000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 0 + Num, 'Row ' || ( 0 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 1000 + Num, 'Row ' || ( 1000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 2000 + Num, 'Row ' || ( 2000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 3000 + Num, 'Row ' || ( 3000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 4000 + Num, 'Row ' || ( 4000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 5000 + Num, 'Row ' || ( 5000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 6000 + Num, 'Row ' || ( 6000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 7000 + Num, 'Row ' || ( 7000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 8000 + Num, 'Row ' || ( 8000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 9000 + Num, 'Row ' || ( 9000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 10000 + Num, 'Row ' || (10000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 11000 + Num, 'Row ' || (11000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 12000 + Num, 'Row ' || (12000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 13000 + Num, 'Row ' || (13000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 14000 + Num, 'Row ' || (14000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 15000 + Num, 'Row ' || (15000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 16000 + Num, 'Row ' || (16000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 17000 + Num, 'Row ' || (17000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 18000 + Num, 'Row ' || (18000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 19000 + Num, 'Row ' || (19000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 20000 + Num, 'Row ' || (20000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 21000 + Num, 'Row ' || (21000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 22000 + Num, 'Row ' || (22000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 23000 + Num, 'Row ' || (23000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 24000 + Num, 'Row ' || (24000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 25000 + Num, 'Row ' || (25000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 26000 + Num, 'Row ' || (26000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 27000 + Num, 'Row ' || (27000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 28000 + Num, 'Row ' || (28000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 29000 + Num, 'Row ' || (29000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 30000 + Num, 'Row ' || (30000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 31000 + Num, 'Row ' || (31000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 32000 + Num, 'Row ' || (32000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 33000 + Num, 'Row ' || (33000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 34000 + Num, 'Row ' || (34000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 35000 + Num, 'Row ' || (35000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 36000 + Num, 'Row ' || (36000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 37000 + Num, 'Row ' || (37000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 38000 + Num, 'Row ' || (38000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 39000 + Num, 'Row ' || (39000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 40000 + Num, 'Row ' || (40000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 41000 + Num, 'Row ' || (41000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 42000 + Num, 'Row ' || (42000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 43000 + Num, 'Row ' || (43000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 44000 + Num, 'Row ' || (44000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 45000 + Num, 'Row ' || (45000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 46000 + Num, 'Row ' || (46000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 47000 + Num, 'Row ' || (47000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 48000 + Num, 'Row ' || (48000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 49000 + Num, 'Row ' || (49000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 50000 + Num, 'Row ' || (50000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 51000 + Num, 'Row ' || (51000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 52000 + Num, 'Row ' || (52000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 53000 + Num, 'Row ' || (53000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 54000 + Num, 'Row ' || (54000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 55000 + Num, 'Row ' || (55000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 56000 + Num, 'Row ' || (56000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 57000 + Num, 'Row ' || (57000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 58000 + Num, 'Row ' || (58000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 59000 + Num, 'Row ' || (59000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 60000 + Num, 'Row ' || (60000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 61000 + Num, 'Row ' || (61000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 62000 + Num, 'Row ' || (62000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 63000 + Num, 'Row ' || (63000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 64000 + Num, 'Row ' || (64000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 65000 + Num, 'Row ' || (65000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 66000 + Num, 'Row ' || (66000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 67000 + Num, 'Row ' || (67000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 68000 + Num, 'Row ' || (68000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 69000 + Num, 'Row ' || (69000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 70000 + Num, 'Row ' || (70000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 71000 + Num, 'Row ' || (71000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 72000 + Num, 'Row ' || (72000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 73000 + Num, 'Row ' || (73000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 74000 + Num, 'Row ' || (74000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 75000 + Num, 'Row ' || (75000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 76000 + Num, 'Row ' || (76000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 77000 + Num, 'Row ' || (77000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 78000 + Num, 'Row ' || (78000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 79000 + Num, 'Row ' || (79000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 80000 + Num, 'Row ' || (80000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 81000 + Num, 'Row ' || (81000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 82000 + Num, 'Row ' || (82000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 83000 + Num, 'Row ' || (83000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 84000 + Num, 'Row ' || (84000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 85000 + Num, 'Row ' || (85000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 86000 + Num, 'Row ' || (86000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 87000 + Num, 'Row ' || (87000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 88000 + Num, 'Row ' || (88000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 89000 + Num, 'Row ' || (89000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 90000 + Num, 'Row ' || (90000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 91000 + Num, 'Row ' || (91000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 92000 + Num, 'Row ' || (92000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 93000 + Num, 'Row ' || (93000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 94000 + Num, 'Row ' || (94000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 95000 + Num, 'Row ' || (95000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 96000 + Num, 'Row ' || (96000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 97000 + Num, 'Row ' || (97000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 98000 + Num, 'Row ' || (98000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; +INSERT INTO foo SELECT 99000 + Num, 'Row ' || (99000 + Num) FROM Nums WHERE Num BETWEEN 1 AND 1000; COMMIT; diff --git a/tools/semver-check.js b/tools/semver-check.js new file mode 100644 index 000000000..3b4a9a9c9 --- /dev/null +++ b/tools/semver-check.js @@ -0,0 +1,33 @@ +const fs = require('fs'); +const path = require('path'); +const semver = require('semver'); + +const supportedVersions = '10.12.0'; + +function checkEngines(modulePath) { + const packageJsonPath = path.join(modulePath, 'package.json'); + + if (!fs.existsSync(packageJsonPath)) return; + + const packageJson = JSON.parse(fs.readFileSync(packageJsonPath)); + const engines = packageJson.engines; + + if (engines && engines.node) { + const minVersion = semver.minVersion(engines.node); + + if (semver.gt(minVersion, supportedVersions)) { + console.log(`${packageJson.name}@${packageJson.version} requires ${engines.node}`); + process.exit(1); + } + } +} + +const packageJson = JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'package.json'))); + +const allDependencies = Object.keys(packageJson.dependencies || {}).concat(Object.keys(packageJson.optionalDependencies || {})); + +for (const dependency of allDependencies) { + const modulePath = path.join(__dirname, '..', 'node_modules', dependency); + checkEngines(modulePath); +} +