├── .github └── ISSUE_TEMPLATE │ └── bug_report.md ├── .gitignore ├── .npmignore ├── CHANGELOG.md ├── LICENSE ├── Podfile ├── README.md ├── instructions ├── addFilesToProject.png ├── addFilesToProjectSelect.png ├── addlibs.png ├── after-rnpm.png ├── before-rnpm.png ├── libs.png ├── libssummary.png ├── projectStructureAfter.png └── require.png ├── lib └── sqlite.core.js ├── package.json ├── platforms ├── android-native │ ├── build.gradle │ ├── gradle.properties │ ├── libs │ │ ├── arm64-v8a │ │ │ └── libsqlc-native-driver.so │ │ ├── armeabi-v7a │ │ │ └── libsqlc-native-driver.so │ │ ├── sqlite-connector.jar │ │ ├── x86 │ │ │ └── libsqlc-native-driver.so │ │ └── x86_64 │ │ │ └── libsqlc-native-driver.so │ ├── settings.gradle │ └── src │ │ └── main │ │ ├── AndroidManifest.xml │ │ └── java │ │ └── io │ │ └── liteglue │ │ ├── CallbackContext.java │ │ ├── SQLiteAndroidDatabase.java │ │ ├── SQLitePlugin.java │ │ ├── SQLitePluginConverter.java │ │ └── SQLitePluginPackage.java ├── android │ ├── build.gradle │ ├── settings.gradle │ └── src │ │ └── main │ │ ├── AndroidManifest.xml │ │ └── java │ │ └── org │ │ └── pgsqlite │ │ ├── CallbackContext.java │ │ ├── SQLitePlugin.java │ │ ├── SQLitePluginConverter.java │ │ └── SQLitePluginPackage.java ├── ios │ ├── SQLite.h │ ├── SQLite.m │ ├── SQLite.xcodeproj │ │ ├── project.pbxproj │ │ └── project.xcworkspace │ │ │ └── contents.xcworkspacedata │ ├── SQLiteResult.h │ └── SQLiteResult.m └── windows │ ├── .gitignore │ ├── SQLitePlugin.sln │ └── SQLitePlugin │ ├── PropertySheet.props │ ├── ReactPackageProvider.cpp │ ├── ReactPackageProvider.h │ ├── ReactPackageProvider.idl │ ├── SQLitePlugin.cpp │ ├── SQLitePlugin.def │ ├── SQLitePlugin.h │ ├── SQLitePlugin.vcxproj │ ├── SQLitePlugin.vcxproj.filters │ ├── packages.config │ ├── pch.cpp │ └── pch.h ├── react-native-sqlite-storage.podspec ├── react-native.config.js ├── sqlite.js └── test ├── index.android.json1.js ├── index.ios.callback.js ├── index.ios.promise.js └── index.windows.callback.js /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | 5 | --- 6 | 7 | 8 | 9 | ## Expected Behavior 10 | 11 | 12 | 13 | ## Current Behavior 14 | 15 | 16 | 17 | ## Possible Solution 18 | 19 | 20 | 21 | ## Steps to Reproduce (for bugs) 22 | 23 | 25 | 26 | ## Context 27 | 28 | 29 | 30 | ## Your Environment 31 | 32 | * React Native SQLite Storage Version used: 33 | * React Native version used: 34 | * Operating System and version (simulator or device): 35 | * IDE used: 36 | * Link to your project: 37 | 38 | ## Debug logs 39 | 40 | 41 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | 5 | # Runtime data 6 | pids 7 | *.pid 8 | *.seed 9 | 10 | # Directory for instrumented libs generated by jscoverage/JSCover 11 | lib-cov 12 | 13 | # Coverage directory used by tools like istanbul 14 | coverage 15 | 16 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 17 | .grunt 18 | 19 | # node-waf configuration 20 | .lock-wscript 21 | 22 | # Compiled binary addons (http://nodejs.org/api/addons.html) 23 | build/Release 24 | 25 | # Dependency directory 26 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git 27 | node_modules 28 | 29 | # OSX 30 | # 31 | .DS_Store 32 | 33 | # Xcode 34 | # 35 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 36 | 37 | ## Build generated 38 | build/ 39 | DerivedData 40 | 41 | ## Various settings 42 | *.pbxuser 43 | !default.pbxuser 44 | *.mode1v3 45 | !default.mode1v3 46 | *.mode2v3 47 | !default.mode2v3 48 | *.perspectivev3 49 | !default.perspectivev3 50 | xcuserdata 51 | 52 | ## Other 53 | *.xccheckout 54 | *.moved-aside 55 | *.xcuserstate 56 | *.xcscmblueprint 57 | *.xcscheme 58 | .vscode 59 | 60 | android/.gradle/ 61 | # node.js 62 | # 63 | node_modules/ 64 | npm-debug.log 65 | *.iml 66 | .idea 67 | local.properties 68 | 69 | # Created by https://www.gitignore.io/api/rade,gradle 70 | 71 | #!! ERROR: rade is undefined. Use list command to see defined gitignore types !!# 72 | 73 | ### Gradle ### 74 | .gradle 75 | gradle 76 | gradlew 77 | gradlew.bat 78 | 79 | # Ignore Gradle GUI config 80 | gradle-app.setting 81 | 82 | # Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) 83 | !gradle-wrapper.jar 84 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | 5 | # Runtime data 6 | pids 7 | *.pid 8 | *.seed 9 | 10 | # Directory for instrumented libs generated by jscoverage/JSCover 11 | lib-cov 12 | 13 | # Coverage directory used by tools like istanbul 14 | coverage 15 | 16 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 17 | .grunt 18 | 19 | # node-waf configuration 20 | .lock-wscript 21 | 22 | # Compiled binary addons (http://nodejs.org/api/addons.html) 23 | build/Release 24 | 25 | # Dependency directory 26 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git 27 | node_modules 28 | 29 | # OSX 30 | # 31 | .DS_Store 32 | 33 | # Xcode 34 | # 35 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 36 | 37 | ## Build generated 38 | build/ 39 | DerivedData 40 | 41 | ## Various settings 42 | *.pbxuser 43 | !default.pbxuser 44 | *.mode1v3 45 | !default.mode1v3 46 | *.mode2v3 47 | !default.mode2v3 48 | *.perspectivev3 49 | !default.perspectivev3 50 | xcuserdata 51 | 52 | ## Other 53 | *.xccheckout 54 | *.moved-aside 55 | *.xcuserstate 56 | *.xcscmblueprint 57 | *.xcscheme 58 | 59 | android/.gradle/ 60 | # node.js 61 | # 62 | node_modules/ 63 | npm-debug.log 64 | *.iml 65 | .idea 66 | local.properties 67 | 68 | # Created by https://www.gitignore.io/api/rade,gradle 69 | 70 | #!! ERROR: rade is undefined. Use list command to see defined gitignore types !!# 71 | 72 | ### Gradle ### 73 | .gradle 74 | gradle 75 | gradlew 76 | gradlew.bat 77 | 78 | # Ignore Gradle GUI config 79 | gradle-app.setting 80 | 81 | # Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) 82 | !gradle-wrapper.jar 83 | 84 | instructions/ -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Version History 2 | 3 | v6.0.1 4 | 1. Add missing error function to plugin. 5 | 6 | v6.0.0 7 | 1. Added RNW>=0.62 WinRT CPP implementation thanks to tsytsarkin (https://github.com/andpor/react-native-sqlite-storage/pull/461) 8 | 2. Fix xcode 12 compatibility (https://github.com/andpor/react-native-sqlite-storage/pull/447) 9 | 3. Add warn method to the plugin (https://github.com/andpor/react-native-sqlite-storage/issues/402) 10 | 11 | v5.0.0 12 | 1. Change RN to Google Maven (https://github.com/andpor/react-native-sqlite-storage/pull/405) 13 | 2. Native Android with JSON1 support (https://github.com/andpor/react-native-sqlite-storage/pull/392) 14 | 3. Resolve errors linking library via CocoaPods in iOS (https://github.com/andpor/react-native-sqlite-storage/pull/396) 15 | 4. Documentation enhancements for Android native (https://github.com/andpor/react-native-sqlite-storage/pull/393) 16 | 5. Documentation enhancements (https://github.com/andpor/react-native-sqlite-storage/pull/385) 17 | 18 | v4.1.0 19 | 1. New native SQLite libraries for Android. Dropping support for armeabi. 20 | 21 | v4.0.0 22 | 1. RN 0.60 compatibility (https://github.com/andpor/react-native-sqlite-storage/pull/361) 23 | 24 | v3.3.10 25 | 1. Fix package org.pgsqlite not found error for RN 0.58.4 (https://github.com/andpor/react-native-sqlite-storage/pull/324) 26 | 27 | v3.3.9 28 | 1. Gradle upgrade to 3.1.4 and addition of google repo (https://github.com/andpor/react-native-sqlite-storage/issues/294) 29 | 30 | v3.3.8 31 | 1. UWP implementation for SqliteStorage (https://github.com/andpor/react-native-sqlite-storage/pull/302) 32 | 2. Fix the window is not defined (https://github.com/andpor/react-native-sqlite-storage/pull/295) 33 | 34 | v3.3.7 35 | 1. Remove rnpm-postlink (#292) 36 | 2. Use correct parameters for SQLite.openDatabase (#291) 37 | 3. Pulling SDK versions from root project (#287) - Android only 38 | 39 | v3.3.6 40 | 1. Fix INTEGER column value overflow. 41 | 42 | v3.3.5 43 | 1. All JSON conversions in Android modules have been eliminated in favor of direct React Native interfaces. This should provide siginificant performance improvement. 44 | 2. Main Queue Warning issue fixed in iOS. 45 | 3. Exception handling in logic processing asset imports have been fixed and error codes are properly propagated to JS callabcks. 46 | 4. Examples have been revamped and library was tested with XCode 9 and Android Studio 3.1.1 (Gradle 2.2) 47 | 48 | v3.3.4 49 | 1. New version of native binaries compile with latest sqlite version 3.20.1 supporting pcre extension to enable REGEXP function for Android. (https://github.com/andpor/react-native-sqlite-storage/pull/205) 50 | 2. Fixes Xcode warning for potentially insecure string. (https://github.com/andpor/react-native-sqlite-storage/pull/199) 51 | 3. Remove createJSModules @ovveride marker - RN 0.47 compatibility. (https://github.com/andpor/react-native-sqlite-storage/pull/188) 52 | 4. Podfile add macOS support (https://github.com/andpor/react-native-sqlite-storage/pull/179) 53 | 5. instructions directory added on npmignore. (https://github.com/andpor/react-native-sqlite-storage/pull/174) 54 | 55 | v3.3.3 56 | 1. Fix for the db location string [Issue #172] (https://github.com/andpor/react-native-sqlite-storage/issues/172) 57 | 2. #define in iOS casebase for SQLCIPHER. If you include this #define in your main project settings, this library will pick up appropriate key handling code automatically. 58 | 59 | v3.3.2 60 | 1. Yoga import fix 61 | 62 | v3.3.1 63 | 1. Comment of SQLCipher code in iOS implementation as a quick fix. [Issue #155] (https://github.com/andpor/react-native-sqlite-storage/issues/155) 64 | 65 | v3.3.0 (Extended thanks to dryganets for his significant contributions to this release) 66 | 1. Access to MutableDictonary openDBs properly synchronized [PR #130] (https://github.com/andpor/react-native-sqlite-storage/pull/130) 67 | 2. Database attach flow fixed. Threading model fix in order to have all queries executed in the same order [PR #131] (https://github.com/andpor/react-native-sqlite-storage/pull/131) 68 | 3. All statements and queries are closed in finally statements in order to fix SQLiteCipher corner case crashes [PR #132] (https://github.com/andpor/react-native-sqlite-storage/pull/132) 69 | 4. Minor style fix in index.ios.callback.js and index.ios.promise.js [PR #136] (https://github.com/andpor/react-native-sqlite-storage/pull/136) 70 | 5. Fix determination logic for opened db [PR #139] (https://github.com/andpor/react-native-sqlite-storage/pull/139) 71 | 6. Clean up in lib/sqlite.core.js [PR #138] (https://github.com/andpor/react-native-sqlite-storage/pull/138) 72 | 7. Production grade logging for the Android plugin [PR #137] (https://github.com/andpor/react-native-sqlite-storage/pull/137) 73 | 8. Remove pre-honeycomb workaround code in Android that was causing issues in SQL Cipher [PR #147] (https://github.com/andpor/react-native-sqlite-storage/pull/147) 74 | 9. Fix broken Markdown headings [PR #153] (https://github.com/andpor/react-native-sqlite-storage/pull/153) 75 | 10. Drop usage of the dead rnpm repository [PR #148] (https://github.com/andpor/react-native-sqlite-storage/pull/148) 76 | 77 | v3.2.2 78 | 1. Corrects the CocoaPods based development set-up instructions and includes sample Podfile. [Issue #125] (https://github.com/andpor/react-native-sqlite-storage/issues/125) 79 | 80 | v3.2.1 81 | 1. Sample apps in test directory adjusted for React Native 0.41 and plugability in AwesomeProject. [Issue #120] (https://github.com/andpor/react-native-sqlite-storage/issues/120) 82 | 83 | v3.2.0 84 | 1. This is a backward incompatible release with baseline React Native 0.40 support. 85 | 2. [React Native 0.40 compatibility fixes] (https://github.com/andpor/react-native-sqlite-storage/pull/110) - thanks K-Leon for this contribution 86 | 87 | v3.1.3 88 | 1. Add support for ATTACH (thanks to itinance for this contribution) 89 | 2. Example applications are now hosted in separate repo [react-native-sqlite-examples] (https://github.com/andpor/react-native-sqlite-storage-examples) 90 | 91 | 92 | v3.1.2 93 | 1. Add support for CocoaPods (thanks to JAStanton for this contribution) 94 | 2. Set base iOS build to 8.0 95 | 96 | v3.1.1 97 | 1. Fix for Cordova issue #517: reject ALTER, REINDEX and REPLACE operations in readTransactions 98 | 2. Stop remaining transaction callback in case of an error with no error handler returning false 99 | 100 | v3.1.0 101 | 1. Backward incompatible change. Boolean params will now be converted and stored as int type, 0 and 1, in compliance with SQLite specifications. Issue [#63] (https://github.com/andpor/react-native-sqlite-storage/issues/63) 102 | 2. Database decoupled from the Activity lifecycle on Android. With this change, the database will not be closed without explicit instructions to close it. SQLitePluginPackage constructor change. Pull Request [#62] (https://github.com/andpor/react-native-sqlite-storage/pull/62) 103 | 3. Correct handling for executeSql with object as sql value (solves a possible crash on iOS) 104 | 4. Backfill cordova-sqlite-storage fix - readTransaction allows modification in case of extra semicolon before SQL. Issue [#460] (https://github.com/litehelpers/Cordova-sqlite-storage/issues/460) 105 | 106 | v3.0.0 107 | 1. Default location changes for iOS for App Store iCloud compliance - backward incompatible release. Default now is no-sync location instead of docs. 108 | 2. Ability to point to read-only db file in app bundle directly without requiring it to be copied elsewhere. 109 | 2. Check if db is open before throwing an exception (triggered in android lock workaround) 110 | 3. Fix for issue #57. Can't find variable: Blob 111 | 112 | v2.1.6 113 | 1. rnpm linking for iOS - contributed by @clozr 114 | 2. Backfill Cordova read transaction bug fix. 115 | 116 | v2.1.5 117 | 1. Allow retrieval of pre-populated db files from user defined locations in application bundle as well as the sandbox. 118 | 2. Implement Activity lifecycle mgmt in Android native 119 | 3. Fix issue [#37] (https://github.com/andpor/react-native-sqlite-storage/issues/37) - Int Column type value overflow 120 | 4. Fix issue [#38] (https://github.com/andpor/react-native-sqlite-storage/issues/38) - Transactions not aborted with Promise runtime 121 | 5. Backfill fixes from Cordova SQLite Storage 122 | - add sqlBatch to facilitate batch exec of simple SQL statements (Android + iOS) 123 | - add echoTest for plugin integrity test 124 | 125 | v2.1.4 - tested with React 0.21.0 126 | 1. Expose a bulk data retrieval interface from JS 127 | 2. Fix JS 'strict' mode execution errors 128 | 129 | v2.1.3 130 | 1. Fix the runtime error in reflection. 131 | 132 | v2.1.2 133 | 1. Android Native SQLite connectivity 134 | 2. Change how React parameters are processed to map a Number to Java Double 135 | 3. Implement hooks for activity lifecycle and automatic db closing on destroy 136 | 4. Fix How To Get Started instructions for Android 137 | 138 | v2.1.1 - Fixes issues with XCode path and React Native version compatibility 139 | 140 | v2.1 - Android support 141 | 142 | v2.0 - Full support for Promise API. Backward compatible with Callbacks. 143 | 144 | v1.0 - Initial release for iOS with full support of all operations based on plan JavaScript callbacks. 145 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 andpor 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /Podfile: -------------------------------------------------------------------------------- 1 | platform :ios, '8.0' 2 | target 'AwesomeProject' do 3 | pod 'yoga', :path => '../node_modules/react-native/ReactCommon/yoga' 4 | pod 'React', :path => '../node_modules/react-native' 5 | pod 'react-native-sqlite-storage', :path => '../node_modules/react-native-sqlite-storage' 6 | end 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # react-native-sqlite-storage 2 | SQLite3 Native Plugin for React Native for both Android (Classic and Native), iOS and Windows 3 | 4 | Foundation of this library is based on Chris Brody's Cordova SQLite plugin. 5 | 6 | Features: 7 | 1. iOS and Android supported via identical JavaScript API. 8 | 2. Android in pure Java and Native modes 9 | 3. SQL transactions 10 | 4. JavaScript interface via plain callbacks or Promises. 11 | 5. Pre-populated SQLite database import from application bundle and sandbox 12 | 6. Windows supports callback API, identical to iOS and Android 13 | 14 | There are sample apps provided in test directory that can be used in with the AwesomeProject generated by React Native. All you have to do is to copy one of those files into your AwesomeProject replacing index.ios.js. 15 | 16 | Please let me know your projects that use these SQLite React Native modules. I will list them in the reference section. If there are any features that you think would benefit this library please post them. 17 | 18 | The library has been tested with React 16.2 (and earlier) and XCode 7,8,9 - it works fine out of the box without any need for tweaks or code changes. For XCode 7,8 vs. XCode 6 the only difference is that sqlite ios library name suffix is tbd instead of dylib. 19 | 20 | Version 3.2 is the first version compatible with RN 0.40. 21 | 22 | # Installation 23 | ``` 24 | npm install --save react-native-sqlite-storage 25 | ``` 26 | Then follow the instructions for your platform to link react-native-sqlite-storage into your project 27 | 28 | ## Promises 29 | To enable promises, run 30 | ```javascript 31 | SQLite.enablePromise(true); 32 | ``` 33 | 34 | ## iOS 35 | #### Standard Method 36 | ** React Native 0.60 and above ** 37 | Run `cd ios && pod install && cd ..`. Linking is not required in React Native 0.60 and above 38 | 39 | ** React Native 0.59 and below ** 40 | 41 | #### Step 1. Install Dependencies 42 | 43 | ##### With CocoaPods: 44 | 45 | Add this to your Podfile which should be located inside the ios project subdirectory 46 | ```ruby 47 | pod 'React', :path => '../node_modules/react-native' 48 | pod 'react-native-sqlite-storage', :path => '../node_modules/react-native-sqlite-storage' 49 | ``` 50 | Or use the sample Podfile included in the package by copying it over to ios subdirectory and replacing AwesomeProject inside of it with the name of your RN project. 51 | 52 | Refresh the Pods installation 53 | ```ruby 54 | pod install 55 | ``` 56 | OR 57 | ```ruby 58 | pod update 59 | ``` 60 | 61 | Done, skip to Step 2. 62 | 63 | ##### Without CocoaPods: 64 | 65 | This command should be executed in the root directory of your RN project 66 | ```shell 67 | react-native link 68 | ``` 69 | 70 | rnpm and xcode are dependencies of this project and should get installed with the module but in case there are issue running rnpm link and rnpm/xcode are not already installed you can try to install it globally as follows: 71 | ```shell 72 | npm -g install rnpm xcode 73 | ``` 74 | After linking project should like this: 75 | 76 | ![alt tag](instructions/after-rnpm.png) 77 | 78 | #### Step 1a. If rnpm link does not work for you you can try manually linking according to the instructions below: 79 | 80 | 81 | ##### Drag the SQLite Xcode project as a dependency project into your React Native XCode project 82 | 83 | ![alt tag](https://raw.github.com/andpor/react-native-sqlite-storage/master/instructions/libs.png) 84 | 85 | ##### XCode SQLite libraries dependency set up 86 | 87 | Add libSQLite.a (from Workspace location) to the required Libraries and Frameworks. Also add sqlite3.0.tbd (XCode 7) or libsqlite3.0.dylib (XCode 6 and earlier) in the same fashion using Required Libraries view (Do not just add them manually as the build paths will not be properly set) 88 | 89 | ![alt tag](https://raw.github.com/andpor/react-native-sqlite-storage/master/instructions/addlibs.png) 90 | 91 | #### Step 2. Application JavaScript require 92 | 93 | Add var SQLite = require('react-native-sqlite-storage') to your index.ios.js 94 | 95 | ![alt tag](instructions/require.png) 96 | 97 | #### Step 3. Write application JavaScript code using the SQLite plugin 98 | 99 | Add JS application code to use SQLite API in your index.ios.js etc. Here is some sample code. For full working example see test/index.ios.callback.js. Please note that Promise based API is now supported as well with full examples in the working React Native app under test/index.ios.promise.js 100 | 101 | ```javascript 102 | errorCB(err) { 103 | console.log("SQL Error: " + err); 104 | }, 105 | 106 | successCB() { 107 | console.log("SQL executed fine"); 108 | }, 109 | 110 | openCB() { 111 | console.log("Database OPENED"); 112 | }, 113 | 114 | var db = SQLite.openDatabase("test.db", "1.0", "Test Database", 200000, openCB, errorCB); 115 | db.transaction((tx) => { 116 | tx.executeSql('SELECT * FROM Employees a, Departments b WHERE a.department = b.department_id', [], (tx, results) => { 117 | console.log("Query completed"); 118 | 119 | // Get rows with Web SQL Database spec compliance. 120 | 121 | var len = results.rows.length; 122 | for (let i = 0; i < len; i++) { 123 | let row = results.rows.item(i); 124 | console.log(`Employee name: ${row.name}, Dept Name: ${row.deptName}`); 125 | } 126 | 127 | // Alternatively, you can use the non-standard raw method. 128 | 129 | /* 130 | let rows = results.rows.raw(); // shallow copy of rows Array 131 | 132 | rows.map(row => console.log(`Employee name: ${row.name}, Dept Name: ${row.deptName}`)); 133 | */ 134 | }); 135 | }); 136 | ``` 137 | 138 | # How to use (Android): 139 | 140 | ** React Native 0.60 and above ** 141 | If you would like to use the devices SQLite there are no extra steps. 142 | However, if you would like to use the SQLite bundled with this library (includes support for FTS5), add the following to your `react-native.config.js` 143 | 144 | ```js 145 | module.exports = { 146 | ..., 147 | dependencies: { 148 | ..., 149 | "react-native-sqlite-storage": { 150 | platforms: { 151 | android: { 152 | sourceDir: 153 | "../node_modules/react-native-sqlite-storage/platforms/android-native", 154 | packageImportPath: "import io.liteglue.SQLitePluginPackage;", 155 | packageInstance: "new SQLitePluginPackage()" 156 | } 157 | } 158 | } 159 | ... 160 | } 161 | ... 162 | }; 163 | ``` 164 | 165 | ** React Native 0.59 and below ** 166 | 167 | #### Step 1 - Update Gradle Settings (located under Gradle Settings in Project Panel) 168 | 169 | ```gradle 170 | // file: android/settings.gradle 171 | ... 172 | 173 | include ':react-native-sqlite-storage' 174 | project(':react-native-sqlite-storage').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-sqlite-storage/platforms/android') // react-native-sqlite-storage >= 4.0.0 175 | // IMPORTANT: if you are working with a version less than 4.0.0 the project directory is '../node_modules/react-native-sqlite-storage/src/android' 176 | ``` 177 | 178 | #### Step 2 - Update app module Gradle Build script (located under Gradle Settings in Project Panel) 179 | 180 | ```gradle 181 | // file: android/app/build.gradle 182 | ... 183 | 184 | dependencies { 185 | ... 186 | implementation project(':react-native-sqlite-storage') 187 | } 188 | ``` 189 | 190 | #### Step 3 - Register React Package (this should work on React version but if it does not , try the ReactActivity based approach. Note: for version 3.0.0 and below you would have to pass in the instance of your Activity to the SQLitePluginPackage constructor 191 | 192 | ```java 193 | ... 194 | import org.pgsqlite.SQLitePluginPackage; 195 | 196 | public class MainActivity extends Activity implements DefaultHardwareBackBtnHandler { 197 | 198 | private ReactInstanceManager mReactInstanceManager; 199 | private ReactRootView mReactRootView; 200 | 201 | @Override 202 | protected void onCreate(Bundle savedInstanceState) { 203 | super.onCreate(savedInstanceState); 204 | mReactRootView = new ReactRootView(this); 205 | mReactInstanceManager = ReactInstanceManager.builder() 206 | .setApplication(getApplication()) 207 | .setBundleAssetName("index.android.bundle") // this is dependant on how you name you JS files, example assumes index.android.js 208 | .setJSMainModuleName("index.android") // this is dependant on how you name you JS files, example assumes index.android.js 209 | .addPackage(new MainReactPackage()) 210 | .addPackage(new SQLitePluginPackage()) // register SQLite Plugin here 211 | .setUseDeveloperSupport(BuildConfig.DEBUG) 212 | .setInitialLifecycleState(LifecycleState.RESUMED) 213 | .build(); 214 | mReactRootView.startReactApplication(mReactInstanceManager, "AwesomeProject", null); //change "AwesomeProject" to name of your app 215 | setContentView(mReactRootView); 216 | } 217 | ... 218 | 219 | ``` 220 | 221 | Alternative approach on newer versions of React Native (0.18+). Note: for version 3.0.0 and below you would have to pass in the instance of your Activity to the SQLitePluginPackage constructor 222 | 223 | ```java 224 | import org.pgsqlite.SQLitePluginPackage; 225 | 226 | public class MainApplication extends Application implements ReactApplication { 227 | ...... 228 | 229 | /** 230 | * A list of packages used by the app. If the app uses additional views 231 | * or modules besides the default ones, add more packages here. 232 | */ 233 | @Override 234 | protected List getPackages() { 235 | return Arrays.asList( 236 | new SQLitePluginPackage(), // register SQLite Plugin here 237 | new MainReactPackage()); 238 | } 239 | } 240 | ``` 241 | 242 | #### Step 4 - Require and use in Javascript - see full examples (callbacks and Promise) in test directory. 243 | 244 | ```js 245 | // file: index.android.js 246 | 247 | var React = require('react-native'); 248 | var SQLite = require('react-native-sqlite-storage') 249 | ... 250 | ``` 251 | 252 | ## Windows 253 | ** RNW 0.63 with Autolinking and above ** 254 | 255 | No manual steps required 256 | 257 | ** React Native 0.62 ** 258 | ### Step 1: Update the solution file 259 | 260 | Add the `SQLitePlugin` project to your solution. 261 | 262 | 1. Open the solution in Visual Studio 2019 263 | 2. Right-click Solution icon in Solution Explorer > Add > Existing Project 264 | 3. Select `node_modules\react-native-sqlite-storage\platforms\windows\SQLitePlugin\SQLitePlugin.vcxproj` 265 | 266 | ### Step 2: Update the .vcxproj file 267 | 268 | Add a reference to `SQLitePlugin` to your main application project. From Visual Studio 2019: 269 | 270 | 1. Right-click main application project > Add > Reference... 271 | 2. Check `SQLitePlugin` from Solution Projects 272 | 273 | 274 | ### Step 3: Update the `pch.h` file 275 | 276 | Add `#include "winrt/SQLitePlugin.h"`. 277 | 278 | ### Step 4: Register the package in `App.cpp` 279 | 280 | Add `PackageProviders().Append(winrt::SQLitePlugin::ReactPackageProvider());` before `InitializeComponent();`. 281 | 282 | Refer to this guide for more details: https://microsoft.github.io/react-native-windows/docs/next/native-modules-using 283 | 284 | 285 | ## Setting up your project to import a pre-populated SQLite database from application for iOS 286 | 287 | #### Step 1 - Create 'www' folder. 288 | 289 | Create a folder called 'www' (yes must be called precisely that else things won't work) in the project folder via Finder 290 | 291 | #### Step 2 - Create the database file 292 | 293 | Copy/paste your pre-populated database file into the 'www' folder. Give it the same name you are going to use in openDatabase call in your application 294 | 295 | #### Step 3 - Add file to project 296 | 297 | in XCode, right click on the main folder and select Add Files to 'your project name' 298 | 299 | ![alt tag](https://raw.github.com/andpor/react-native-sqlite-storage/master/instructions/addFilesToProject.png) 300 | 301 | #### Step 4 - Choose files to add 302 | 303 | In the Add Files dialog, navigate to the 'www' directory you created in Step 1, select it, make sure you check the option to Create Folder Reference 304 | 305 | ![alt tag](https://raw.github.com/andpor/react-native-sqlite-storage/master/instructions/addFilesToProjectSelect.png) 306 | 307 | #### Step 5 - Verify project structure 308 | 309 | Ensure your project structure after previous steps are executed looks like this 310 | 311 | ![alt tag](https://raw.github.com/andpor/react-native-sqlite-storage/master/instructions/projectStructureAfter.png) 312 | 313 | ### Step 6 - Adjust openDatabase call 314 | 315 | Modify you openDatabase call in your application adding createFromLocation param. If you named your database file in step 2 'testDB' the openDatabase call should look like something like this: 316 | ```js 317 | 318 | ... 319 | 1.SQLite.openDatabase({name : "testDB", createFromLocation : 1}, okCallback,errorCallback); 320 | // default - if your folder is called www and data file is named the same as the dbName - testDB in this example 321 | 2.SQLite.openDatabase({name : "testDB", createFromLocation : "~data/mydbfile.sqlite"}, okCallback,errorCallback); 322 | // if your folder is called data rather than www or your filename does not match the name of the db 323 | 3.SQLite.openDatabase({name : "testDB", createFromLocation : "/data/mydbfile.sqlite"}, okCallback,errorCallback); 324 | // if your folder is not in app bundle but in app sandbox i.e. downloaded from some remote location. 325 | ... 326 | 327 | ``` 328 | For Android, the www directory is always relative to the assets directory for the app: src/main/assets 329 | 330 | Enjoy! 331 | 332 | ## Opening a database 333 | 334 | Opening a database is slightly different between iOS and Android. Where as on Android the location of the database file is fixed, there are three choices of where the database file can be located on iOS. The 'location' parameter you provide to openDatabase call indicated where you would like the file to be created. This parameter is neglected on Android. 335 | 336 | WARNING: the default location on iOS has changed in version 3.0.0 - it is now a no-sync location as mandated by Apple so the release is backward incompatible. 337 | 338 | 339 | To open a database in default no-sync location (affects iOS *only*):: 340 | 341 | ```js 342 | SQLite.openDatabase({name: 'my.db', location: 'default'}, successcb, errorcb); 343 | ``` 344 | 345 | To specify a different location (affects iOS *only*): 346 | 347 | ```js 348 | SQLite.openDatabase({name: 'my.db', location: 'Library'}, successcb, errorcb); 349 | ``` 350 | 351 | where the `location` option may be set to one of the following choices: 352 | - `default`: `Library/LocalDatabase` subdirectory - *NOT* visible to iTunes and *NOT* backed up by iCloud 353 | - `Library`: `Library` subdirectory - backed up by iCloud, *NOT* visible to iTunes 354 | - `Documents`: `Documents` subdirectory - visible to iTunes and backed up by iCloud 355 | - `Shared`: app group's shared container - *see next section* 356 | 357 | The original webSql style openDatabase still works and the location will implicitly default to 'default' option: 358 | 359 | ```js 360 | SQLite.openDatabase("myDatabase.db", "1.0", "Demo", -1); 361 | ``` 362 | 363 | ## Opening a database in an App Group's Shared Container (iOS) 364 | 365 | If you have an iOS app extension which needs to share access to the same DB instance as your main app, you must use the shared container of a registered app group. 366 | 367 | Assuming you have already set up an app group and turned on the "App Groups" entitlement of both the main app and app extension, setting them to the same app group name, the following extra steps must be taken: 368 | 369 | #### Step 1 - supply your app group name in all needed `Info.plist`s 370 | 371 | In both `ios/MY_APP_NAME/Info.plist` and `ios/MY_APP_EXT_NAME/Info.plist` (along with any other app extensions you may have), you simply need to add the `AppGroupName` key to the main dictionary with your app group name as the string value: 372 | 373 | ```xml 374 | 375 | 376 | 377 | AppGroupName 378 | MY_APP_GROUP_NAME 379 | 380 | 381 | 382 | ``` 383 | 384 | #### Step 2 - set shared database location 385 | 386 | When calling `SQLite.openDatabase` in your React Native code, you need to set the `location` param to `'Shared'`: 387 | 388 | ```js 389 | SQLite.openDatabase({name: 'my.db', location: 'Shared'}, successcb, errorcb); 390 | ``` 391 | 392 | ## Importing a pre-populated database. 393 | 394 | You can import an existing - prepopulated database file into your application. Depending on your instructions in openDatabase call, the sqlite-storage will look at different places to locate you pre-populated database file. 395 | 396 | 397 | Use this flavor of openDatabase call, if your folder is called www and data file is named the same as the dbName - testDB in this example 398 | 399 | ```js 400 | SQLite.openDatabase({name : "testDB", createFromLocation : 1}, okCallback,errorCallback); 401 | ``` 402 | 403 | Use this flavor of openDatabase call if your folder is called data rather than www or your filename does not match the name of the db. In this case db is named testDB but the file is mydbfile.sqlite which is located in a data subdirectory of www 404 | 405 | ```js 406 | SQLite.openDatabase({name : "testDB", createFromLocation : "~data/mydbfile.sqlite"}, okCallback,errorCallback); 407 | ``` 408 | 409 | Use this flavor of openDatabase call if your folder is not in application bundle but in app sandbox i.e. downloaded from some remote location. In this case the source file is located in data subdirectory of Documents location (iOS) or FilesDir (Android). 410 | 411 | ```js 412 | SQLite.openDatabase({name : "testDB", createFromLocation : "/data/mydbfile.sqlite"}, okCallback,errorCallback); 413 | ``` 414 | 415 | ## Additional options for pre-populated database file 416 | 417 | You can provide additional instructions to sqlite-storage to tell it how to handle your pre-populated database file. By default, the source file is copied over to the internal location which works in most cases but sometimes this is not really an option particularly when the source db file is large. In such situations you can tell sqlite-storage you do not want to copy the file but rather use it in read-only fashion via direct access. You accomplish this by providing an additional optional readOnly parameter to openDatabase call 418 | 419 | ```js 420 | SQLite.openDatabase({name : "testDB", readOnly: true, createFromLocation : "/data/mydbfile.sqlite"}, okCallback,errorCallback); 421 | ``` 422 | 423 | Note that in this case, the source db file will be open in read-only mode and no updates will be allowed. You cannot delete a database that was open with readOnly option. For Android, the read only option works with pre-populated db files located in FilesDir directory because all other assets are never physically located on the file system but rather read directly from the app bundle. 424 | 425 | ## Attaching another database 426 | 427 | Sqlite3 offers the capability to attach another database to an existing database-instance, i.e. for making cross database JOINs available. 428 | This feature allows to SELECT and JOIN tables over multiple databases with only one statement and only one database connection. 429 | To archieve this, you need to open both databases and to call the attach()-method of the destination (or master) -database to the other ones. 430 | 431 | ```js 432 | let dbMaster, dbSecond; 433 | 434 | dbSecond = SQLite.openDatabase({name: 'second'}, 435 | (db) => { 436 | dbMaster = SQLite.openDatabase({name: 'master'}, 437 | (db) => { 438 | dbMaster.attach( "second", "second", () => console.log("Database attached successfully"), () => console.log("ERROR")) 439 | }, 440 | (err) => console.log("Error on opening database 'master'", err) 441 | ); 442 | }, 443 | (err) => console.log("Error on opening database 'second'", err) 444 | ); 445 | ``` 446 | 447 | The first argument of attach() is the name of the database, which is used in SQLite.openDatabase(). The second argument is the alias, that is used to query on tables of the attached database. 448 | 449 | The following statement would select data from the master database and include the "second"-database within a simple SELECT/JOIN-statement: 450 | 451 | ```sql 452 | SELECT * FROM user INNER JOIN second.subscriptions s ON s.user_id = user.id 453 | ``` 454 | 455 | To detach a database, just use the detach()-method: 456 | 457 | ```js 458 | dbMaster.detach( 'second', successCallback, errorCallback ); 459 | ``` 460 | 461 | For sure, their is also Promise-support available for attach() and detach(), as shown in the example-application under the 462 | directory "examples". 463 | 464 | # Original Cordova SQLite Bindings from Chris Brody and Davide Bertola 465 | https://github.com/litehelpers/Cordova-sqlite-storage 466 | 467 | The issues and limitations for the actual SQLite can be found on this site. 468 | 469 | ## Issues 470 | 471 | 1. Android binds all numeric SQL input values to double. This is due to the underlying React Native limitation where only a Numeric type is available on the interface point making it ambiguous to distinguish integers from doubles. Once I figure out the proper way to do this I will update the codebase [(Issue #4141)] (https://github.com/facebook/react-native/issues/4141). 472 | -------------------------------------------------------------------------------- /instructions/addFilesToProject.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andpor/react-native-sqlite-storage/b6aeac439b9d038bbb9d2e16812d512c38246775/instructions/addFilesToProject.png -------------------------------------------------------------------------------- /instructions/addFilesToProjectSelect.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andpor/react-native-sqlite-storage/b6aeac439b9d038bbb9d2e16812d512c38246775/instructions/addFilesToProjectSelect.png -------------------------------------------------------------------------------- /instructions/addlibs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andpor/react-native-sqlite-storage/b6aeac439b9d038bbb9d2e16812d512c38246775/instructions/addlibs.png -------------------------------------------------------------------------------- /instructions/after-rnpm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andpor/react-native-sqlite-storage/b6aeac439b9d038bbb9d2e16812d512c38246775/instructions/after-rnpm.png -------------------------------------------------------------------------------- /instructions/before-rnpm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andpor/react-native-sqlite-storage/b6aeac439b9d038bbb9d2e16812d512c38246775/instructions/before-rnpm.png -------------------------------------------------------------------------------- /instructions/libs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andpor/react-native-sqlite-storage/b6aeac439b9d038bbb9d2e16812d512c38246775/instructions/libs.png -------------------------------------------------------------------------------- /instructions/libssummary.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andpor/react-native-sqlite-storage/b6aeac439b9d038bbb9d2e16812d512c38246775/instructions/libssummary.png -------------------------------------------------------------------------------- /instructions/projectStructureAfter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andpor/react-native-sqlite-storage/b6aeac439b9d038bbb9d2e16812d512c38246775/instructions/projectStructureAfter.png -------------------------------------------------------------------------------- /instructions/require.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andpor/react-native-sqlite-storage/b6aeac439b9d038bbb9d2e16812d512c38246775/instructions/require.png -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-native-sqlite-storage", 3 | "version": "6.0.1", 4 | "description": "SQLite3 bindings for React Native (Android & iOS)", 5 | "main": "sqlite.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified yet\" && exit 1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "https://github.com/andpor/react-native-sqlite-storage.git" 12 | }, 13 | "keywords": [ 14 | "react-native-sqlite-storage", 15 | "react-native-sqlite", 16 | "react-component", 17 | "reactnative", 18 | "react-native", 19 | "sqlite", 20 | "sqlite3", 21 | "ios", 22 | "android", 23 | "promise", 24 | "cordova-sqlite-storage" 25 | ], 26 | "author": "Andrzej Porebski", 27 | "license": "MIT", 28 | "bugs": { 29 | "url": "https://github.com/andpor/react-native-sqlite-storage/issues" 30 | }, 31 | "homepage": "https://github.com/andpor/react-native-sqlite-storage", 32 | "peerDependencies": { 33 | "react-native": ">=0.14.0" 34 | }, 35 | "devDependencies": { 36 | "react": "16.13.1", 37 | "react-native": "^0.63.2", 38 | "react-native-windows": "^0.63.6" 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /platforms/android-native/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | google() 4 | jcenter() 5 | } 6 | 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:3.1.4' 9 | } 10 | } 11 | 12 | apply plugin: 'com.android.library' 13 | 14 | def safeExtGet(prop, fallback) { 15 | rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback 16 | } 17 | 18 | android { 19 | compileSdkVersion safeExtGet('compileSdkVersion', 23) 20 | buildToolsVersion safeExtGet('buildToolsVersion', '27.0.3') 21 | 22 | defaultConfig { 23 | minSdkVersion safeExtGet('minSdkVersion', 16) 24 | targetSdkVersion safeExtGet('targetSdkVersion', 22) 25 | versionCode 1 26 | versionName "1.0" 27 | } 28 | lintOptions { 29 | abortOnError false 30 | } 31 | sourceSets.main { 32 | jni.srcDirs = [] // This prevents the auto generation of Android.mk 33 | jniLibs.srcDir 'libs' 34 | } 35 | } 36 | 37 | repositories { 38 | mavenCentral() 39 | google() 40 | maven { 41 | url "https://maven.google.com" 42 | } 43 | } 44 | 45 | dependencies { 46 | implementation 'com.facebook.react:react-native:+' 47 | implementation files('libs/sqlite-connector.jar') 48 | } 49 | -------------------------------------------------------------------------------- /platforms/android-native/gradle.properties: -------------------------------------------------------------------------------- 1 | ## Project-wide Gradle settings. 2 | # 3 | # For more details on how to configure your build environment visit 4 | # http://www.gradle.org/docs/current/userguide/build_environment.html 5 | # 6 | # Specifies the JVM arguments used for the daemon process. 7 | # The setting is particularly useful for tweaking memory settings. 8 | # Default value: -Xmx10248m -XX:MaxPermSize=256m 9 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 10 | # 11 | # When configured, Gradle will run in incubating parallel mode. 12 | # This option should only be used with decoupled projects. More details, visit 13 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 14 | # org.gradle.parallel=true 15 | #Mon Nov 16 12:00:58 EST 2015 16 | android.useDeprecatedNdk=true 17 | -------------------------------------------------------------------------------- /platforms/android-native/libs/arm64-v8a/libsqlc-native-driver.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andpor/react-native-sqlite-storage/b6aeac439b9d038bbb9d2e16812d512c38246775/platforms/android-native/libs/arm64-v8a/libsqlc-native-driver.so -------------------------------------------------------------------------------- /platforms/android-native/libs/armeabi-v7a/libsqlc-native-driver.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andpor/react-native-sqlite-storage/b6aeac439b9d038bbb9d2e16812d512c38246775/platforms/android-native/libs/armeabi-v7a/libsqlc-native-driver.so -------------------------------------------------------------------------------- /platforms/android-native/libs/sqlite-connector.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andpor/react-native-sqlite-storage/b6aeac439b9d038bbb9d2e16812d512c38246775/platforms/android-native/libs/sqlite-connector.jar -------------------------------------------------------------------------------- /platforms/android-native/libs/x86/libsqlc-native-driver.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andpor/react-native-sqlite-storage/b6aeac439b9d038bbb9d2e16812d512c38246775/platforms/android-native/libs/x86/libsqlc-native-driver.so -------------------------------------------------------------------------------- /platforms/android-native/libs/x86_64/libsqlc-native-driver.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andpor/react-native-sqlite-storage/b6aeac439b9d038bbb9d2e16812d512c38246775/platforms/android-native/libs/x86_64/libsqlc-native-driver.so -------------------------------------------------------------------------------- /platforms/android-native/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'SQLitePlugin' 2 | include ':app' -------------------------------------------------------------------------------- /platforms/android-native/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /platforms/android-native/src/main/java/io/liteglue/CallbackContext.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Written by Andrzej Porebski Nov 14/2015 3 | * 4 | * Copyright (c) 2015, Andrzej Porebski 5 | */ 6 | package io.liteglue; 7 | 8 | import com.facebook.react.bridge.Callback; 9 | import com.facebook.react.bridge.WritableArray; 10 | import com.facebook.react.bridge.WritableMap; 11 | 12 | import org.json.JSONArray; 13 | import org.json.JSONException; 14 | import org.json.JSONObject; 15 | 16 | public class CallbackContext { 17 | 18 | private static final String LOG_TAG = "SQLitePlugin"; 19 | 20 | private Callback successCallback; 21 | private Callback errorCallback; 22 | 23 | public CallbackContext(Callback success, Callback error) { 24 | this.successCallback = success; 25 | this.errorCallback = error; 26 | } 27 | 28 | /** 29 | * Helper for success callbacks that just returns the Status.OK by default 30 | * 31 | * @param message The message to add to the success result. 32 | */ 33 | public void success(WritableMap message) { 34 | successCallback.invoke(message); 35 | } 36 | 37 | /** 38 | * Helper for success callbacks that just returns the Status.OK by default 39 | * 40 | * @param message The message to add to the success result. 41 | */ 42 | public void success(String message) { 43 | successCallback.invoke(message); 44 | } 45 | 46 | /** 47 | * Helper for success callbacks that just returns the Status.OK by default 48 | * 49 | * @param message The message to add to the success result. 50 | */ 51 | public void success(WritableArray message) { 52 | successCallback.invoke(message); 53 | } 54 | 55 | /** 56 | * Helper for success callbacks that just returns the Status.OK by default 57 | */ 58 | public void success() { 59 | successCallback.invoke("Success"); 60 | } 61 | 62 | /** 63 | * Helper for error callbacks that just returns the Status.ERROR by default 64 | * 65 | * @param message The message to add to the error result. 66 | */ 67 | public void error(WritableMap message) { 68 | errorCallback.invoke(message); 69 | } 70 | 71 | /** 72 | * Helper for error callbacks that just returns the Status.ERROR by default 73 | * 74 | * @param message The message to add to the error result. 75 | */ 76 | public void error(String message) { 77 | errorCallback.invoke(message); 78 | } 79 | } -------------------------------------------------------------------------------- /platforms/android-native/src/main/java/io/liteglue/SQLiteAndroidDatabase.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Andrzej Porebski 3 | * Copyright (c) 2012-2015, Chris Brody 4 | * Copyright (c) 2005-2010, Nitobi Software Inc. 5 | * Copyright (c) 2010, IBM Corporation 6 | */ 7 | 8 | package io.liteglue; 9 | 10 | import android.annotation.SuppressLint; 11 | 12 | import android.database.Cursor; 13 | import android.database.sqlite.SQLiteDatabase; 14 | import android.database.sqlite.SQLiteException; 15 | import android.database.sqlite.SQLiteStatement; 16 | 17 | import android.util.Base64; 18 | 19 | import com.facebook.common.logging.FLog; 20 | import com.facebook.react.bridge.Arguments; 21 | import com.facebook.react.bridge.ReadableArray; 22 | import com.facebook.react.bridge.ReadableType; 23 | import com.facebook.react.bridge.WritableArray; 24 | import com.facebook.react.bridge.WritableMap; 25 | 26 | import java.io.File; 27 | import java.lang.IllegalArgumentException; 28 | import java.lang.Number; 29 | import java.util.Locale; 30 | import java.util.regex.Matcher; 31 | import java.util.regex.Pattern; 32 | 33 | /** 34 | * Android Database helper class 35 | */ 36 | class SQLiteAndroidDatabase { 37 | private static final Pattern FIRST_WORD = Pattern.compile("^\\s*(\\S+)", 38 | Pattern.CASE_INSENSITIVE); 39 | 40 | 41 | File dbFile; 42 | int openFlags; 43 | SQLiteDatabase mydb; 44 | 45 | /** 46 | * NOTE: Using default constructor, no explicit constructor. 47 | */ 48 | 49 | /** 50 | * Open a database. 51 | * 52 | * @param dbfile The database File specification 53 | */ 54 | void open(File dbfile) throws Exception { 55 | this.open(dbfile,SQLiteOpenFlags.READWRITE | SQLiteOpenFlags.CREATE); 56 | } 57 | 58 | /** 59 | * Open a database. 60 | * 61 | * @param dbfile The database File specification 62 | */ 63 | void open(File dbfile, int openFlags) throws Exception { 64 | this.dbFile = dbfile; // for possible bug workaround 65 | this.openFlags = openFlags; 66 | this.mydb = SQLiteDatabase.openDatabase(dbfile.getAbsolutePath(), null, openFlags); 67 | } 68 | 69 | /** 70 | * Close a database (in the current thread). 71 | */ 72 | void closeDatabaseNow() { 73 | if (mydb != null) { 74 | mydb.close(); 75 | mydb = null; 76 | } 77 | } 78 | 79 | void bugWorkaround() throws Exception { 80 | this.closeDatabaseNow(); 81 | this.open(this.dbFile,this.openFlags); 82 | } 83 | 84 | /** 85 | * Executes a batch request and sends the results via cbc. 86 | * 87 | * @param queryArr Array of query strings 88 | * @param queryParams Array of JSON query parameters 89 | * @param queryIDs Array of query ids 90 | * @param cbc Callback context from Cordova API 91 | */ 92 | @SuppressLint("NewApi") 93 | void executeSqlBatch(String[] queryArr, ReadableArray[] queryParams, 94 | String[] queryIDs, CallbackContext cbc) { 95 | 96 | if (mydb == null) { 97 | // not allowed - can only happen if someone has closed (and possibly deleted) a database and then re-used the database 98 | cbc.error("database has been closed"); 99 | return; 100 | } 101 | 102 | String query = ""; 103 | String query_id = ""; 104 | int len = queryArr.length; 105 | WritableArray batchResults = Arguments.createArray(); 106 | 107 | for (int i = 0; i < len; i++) { 108 | int rowsAffectedCompat = 0; 109 | boolean needRowsAffectedCompat = false; 110 | query_id = queryIDs[i]; 111 | 112 | WritableMap queryResult = null; 113 | String errorMessage = "unknown"; 114 | 115 | try { 116 | boolean needRawQuery = true; 117 | 118 | query = queryArr[i]; 119 | 120 | QueryType queryType = getQueryType(query); 121 | 122 | if (queryType == QueryType.update || queryType == QueryType.delete) { 123 | 124 | SQLiteStatement myStatement = mydb.compileStatement(query); 125 | 126 | if (queryParams != null) { 127 | bindArgsToStatement(myStatement, queryParams[i]); 128 | } 129 | 130 | int rowsAffected = -1; // (assuming invalid) 131 | 132 | try { 133 | rowsAffected = myStatement.executeUpdateDelete(); 134 | // Indicate valid results: 135 | needRawQuery = false; 136 | } catch (SQLiteException ex) { 137 | // Indicate problem & stop this query: 138 | errorMessage = ex.getMessage(); 139 | FLog.e(SQLitePlugin.TAG, "SQLiteStatement.executeUpdateDelete() failed", ex); 140 | needRawQuery = false; 141 | } 142 | 143 | if (rowsAffected != -1) { 144 | queryResult = Arguments.createMap(); 145 | queryResult.putInt("rowsAffected", rowsAffected); 146 | } 147 | } 148 | 149 | // INSERT: 150 | else if (queryType == QueryType.insert && queryParams != null) { 151 | needRawQuery = false; 152 | SQLiteStatement myStatement = mydb.compileStatement(query); 153 | bindArgsToStatement(myStatement, queryParams[i]); 154 | long insertId = -1; // (invalid) 155 | 156 | try { 157 | insertId = myStatement.executeInsert(); 158 | 159 | // statement has finished with no constraint violation: 160 | queryResult = Arguments.createMap(); 161 | if (insertId != -1) { 162 | queryResult.putDouble("insertId", insertId); 163 | queryResult.putInt("rowsAffected", 1); 164 | } else { 165 | queryResult.putInt("rowsAffected", 0); 166 | } 167 | } catch (SQLiteException ex) { 168 | // report error result with the error message 169 | // could be constraint violation or some other error 170 | errorMessage = ex.getMessage(); 171 | FLog.e(SQLitePlugin.TAG, "SQLiteDatabase.executeInsert() failed", ex); 172 | } 173 | } 174 | 175 | else if (queryType == QueryType.begin) { 176 | needRawQuery = false; 177 | try { 178 | mydb.beginTransaction(); 179 | 180 | queryResult = Arguments.createMap(); 181 | queryResult.putInt("rowsAffected", 0); 182 | } catch (SQLiteException ex) { 183 | errorMessage = ex.getMessage(); 184 | FLog.e(SQLitePlugin.TAG, "SQLiteDatabase.beginTransaction() failed", ex); 185 | } 186 | } 187 | 188 | else if (queryType == QueryType.commit) { 189 | needRawQuery = false; 190 | try { 191 | mydb.setTransactionSuccessful(); 192 | mydb.endTransaction(); 193 | 194 | queryResult = Arguments.createMap(); 195 | queryResult.putInt("rowsAffected", 0); 196 | } catch (SQLiteException ex) { 197 | errorMessage = ex.getMessage(); 198 | FLog.e(SQLitePlugin.TAG, "SQLiteDatabase.setTransactionSuccessful/endTransaction() failed", ex); 199 | } 200 | } 201 | 202 | else if (queryType == QueryType.rollback) { 203 | needRawQuery = false; 204 | try { 205 | mydb.endTransaction(); 206 | 207 | queryResult = Arguments.createMap(); 208 | queryResult.putInt("rowsAffected", 0); 209 | } catch (SQLiteException ex) { 210 | errorMessage = ex.getMessage(); 211 | FLog.e(SQLitePlugin.TAG, "SQLiteDatabase.endTransaction() failed", ex); 212 | } 213 | } 214 | 215 | // raw query for other statements: 216 | if (needRawQuery) { 217 | queryResult = this.executeSqlStatementQuery(mydb, query, queryParams != null ? queryParams[i] : null, cbc); 218 | 219 | if (needRowsAffectedCompat) { 220 | queryResult.putInt("rowsAffected", rowsAffectedCompat); 221 | } 222 | } 223 | } catch (Exception ex) { 224 | errorMessage = ex.getMessage(); 225 | FLog.e(SQLitePlugin.TAG, "SQLiteAndroidDatabase.executeSql[Batch]() failed", ex); 226 | } 227 | 228 | if (queryResult != null) { 229 | WritableMap r = Arguments.createMap(); 230 | r.putString("qid", query_id); 231 | 232 | r.putString("type", "success"); 233 | r.putMap("result", queryResult); 234 | 235 | batchResults.pushMap(r); 236 | } else { 237 | WritableMap r = Arguments.createMap(); 238 | r.putString("qid", query_id); 239 | r.putString("type", "error"); 240 | 241 | WritableMap er = Arguments.createMap(); 242 | er.putString("message", errorMessage); 243 | r.putMap("result", er); 244 | 245 | batchResults.pushMap(r); 246 | } 247 | } 248 | 249 | cbc.success(batchResults); 250 | } 251 | 252 | private void bindArgsToStatement(SQLiteStatement myStatement, ReadableArray sqlArgs) { 253 | if (sqlArgs == null) 254 | return; 255 | 256 | for (int i = 0; i < sqlArgs.size(); i++) { 257 | ReadableType type = sqlArgs.getType(i); 258 | if (type == ReadableType.Number) { 259 | double tmp = sqlArgs.getDouble(i); 260 | if (tmp == (long) tmp) { 261 | myStatement.bindLong(i + 1, (long) tmp); 262 | } else { 263 | myStatement.bindDouble(i + 1, tmp); 264 | } 265 | } else if (sqlArgs.isNull(i)) { 266 | myStatement.bindNull(i + 1); 267 | } else { 268 | myStatement.bindString(i + 1, sqlArgs.getString(i)); 269 | } 270 | } 271 | } 272 | 273 | /** 274 | * Get rows results from query cursor. 275 | * 276 | * @return results in string form 277 | */ 278 | private WritableMap executeSqlStatementQuery(SQLiteDatabase mydb, 279 | String query, ReadableArray queryParams, 280 | CallbackContext cbc) throws Exception { 281 | WritableMap rowsResult = Arguments.createMap(); 282 | 283 | Cursor cur; 284 | try { 285 | String[] params = new String[0]; 286 | if (queryParams != null) { 287 | int size = queryParams.size(); 288 | params = new String[size]; 289 | for (int j = 0; j < size; j++) { 290 | if (queryParams.isNull(j)) 291 | params[j] = ""; 292 | else 293 | params[j] = queryParams.getString(j); 294 | } 295 | } 296 | cur = mydb.rawQuery(query, params); 297 | } catch (Exception ex) { 298 | FLog.e(SQLitePlugin.TAG, "SQLiteAndroidDatabase.executeSql[Batch]() failed", ex); 299 | throw ex; 300 | } 301 | 302 | // If query result has rows 303 | if (cur != null && cur.moveToFirst()) { 304 | WritableArray rowsArrayResult = Arguments.createArray(); 305 | String key = ""; 306 | int colCount = cur.getColumnCount(); 307 | 308 | // Build up JSON result object for each row 309 | do { 310 | WritableMap row = Arguments.createMap(); 311 | for (int i = 0; i < colCount; ++i) { 312 | key = cur.getColumnName(i); 313 | bindRow(row, key, cur, i); 314 | } 315 | 316 | rowsArrayResult.pushMap(row); 317 | } while (cur.moveToNext()); 318 | 319 | rowsResult.putArray("rows", rowsArrayResult); 320 | } 321 | 322 | if (cur != null) { 323 | cur.close(); 324 | } 325 | 326 | return rowsResult; 327 | } 328 | 329 | @SuppressLint("NewApi") 330 | private void bindRow(WritableMap row, String key, Cursor cur, int i) { 331 | int curType = cur.getType(i); 332 | 333 | switch (curType) { 334 | case Cursor.FIELD_TYPE_NULL: 335 | row.putNull(key); 336 | break; 337 | case Cursor.FIELD_TYPE_INTEGER: 338 | row.putDouble(key, cur.getLong(i)); 339 | break; 340 | case Cursor.FIELD_TYPE_FLOAT: 341 | row.putDouble(key, cur.getDouble(i)); 342 | break; 343 | case Cursor.FIELD_TYPE_BLOB: 344 | row.putString(key, new String(Base64.encode(cur.getBlob(i), Base64.DEFAULT))); 345 | break; 346 | case Cursor.FIELD_TYPE_STRING: 347 | default: 348 | row.putString(key, cur.getString(i)); 349 | break; 350 | } 351 | } 352 | 353 | static QueryType getQueryType(String query) { 354 | Matcher matcher = FIRST_WORD.matcher(query); 355 | if (matcher.find()) { 356 | try { 357 | return QueryType.valueOf(matcher.group(1).toLowerCase(Locale.US)); 358 | } catch (IllegalArgumentException ignore) { 359 | // unknown verb 360 | } 361 | } 362 | return QueryType.other; 363 | } 364 | 365 | static enum QueryType { 366 | update, 367 | insert, 368 | delete, 369 | select, 370 | begin, 371 | commit, 372 | rollback, 373 | other 374 | } 375 | } /* vim: set expandtab : */ 376 | -------------------------------------------------------------------------------- /platforms/android-native/src/main/java/io/liteglue/SQLitePluginConverter.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Written by Andrzej Porebski Nov 14/2015 3 | * 4 | * Copyright (c) 2015, Andrzej Porebski 5 | */ 6 | 7 | package io.liteglue; 8 | 9 | import com.facebook.react.bridge.NoSuchKeyException; 10 | import com.facebook.react.bridge.ReadableArray; 11 | import com.facebook.react.bridge.ReadableMap; 12 | import com.facebook.react.bridge.ReadableType; 13 | 14 | public abstract class SQLitePluginConverter { 15 | 16 | /** 17 | * Returns the value at {@code key} if it exists, coercing it if 18 | * necessary. 19 | */ 20 | static String getString(ReadableMap map, String key, String defaultValue) { 21 | if (map == null){ 22 | return defaultValue; 23 | } 24 | try { 25 | ReadableType type = map.getType(key); 26 | switch (type) { 27 | case Number: 28 | double value = map.getDouble(key); 29 | if (value == (long) value) { 30 | return String.valueOf((long) value); 31 | } else { 32 | return String.valueOf(value); 33 | } 34 | case Boolean: 35 | return String.valueOf(map.getBoolean(key)); 36 | case String: 37 | return map.getString(key); 38 | case Null: 39 | return null; 40 | default: 41 | return defaultValue; 42 | } 43 | } catch(NoSuchKeyException ex){ 44 | return defaultValue; 45 | } 46 | } 47 | 48 | /** 49 | * Returns the value at {@code key} if it exists, coercing it if 50 | * necessary. 51 | */ 52 | static boolean getBoolean(ReadableMap map, String key, boolean defaultValue) { 53 | if (map == null){ 54 | return defaultValue; 55 | } 56 | try { 57 | ReadableType type = map.getType(key); 58 | switch (type) { 59 | case Boolean: 60 | return map.getBoolean(key); 61 | case String: { 62 | String value = map.getString(key); 63 | if ("true".equalsIgnoreCase(value)) { 64 | return true; 65 | } else if ("false".equalsIgnoreCase(value)) { 66 | return false; 67 | } 68 | return false; 69 | } 70 | case Number: { 71 | double value = map.getDouble(key); 72 | if (value == (long) 0) { 73 | return Boolean.FALSE; 74 | } else { 75 | return Boolean.TRUE; 76 | } 77 | } 78 | case Null: 79 | return false; 80 | default: 81 | return defaultValue; 82 | } 83 | } catch(NoSuchKeyException ex){ 84 | return defaultValue; 85 | } 86 | } 87 | 88 | /** 89 | * Returns the value at {@code index} if it exists, coercing it if 90 | * necessary. 91 | */ 92 | static String getString(ReadableArray array, int index, String defaultValue) { 93 | if (array == null){ 94 | return defaultValue; 95 | } 96 | try { 97 | ReadableType type = array.getType(index); 98 | switch (type) { 99 | case Number: 100 | double value = array.getDouble(index); 101 | if (value == (long) value) { 102 | return String.valueOf((long) value); 103 | } else { 104 | return String.valueOf(value); 105 | } 106 | case Boolean: 107 | return String.valueOf(array.getBoolean(index)); 108 | case String: 109 | return array.getString(index); 110 | case Null: 111 | return null; 112 | default: 113 | return defaultValue; 114 | } 115 | } catch(NoSuchKeyException ex){ 116 | return defaultValue; 117 | } 118 | } 119 | 120 | /** 121 | * Returns the value at {@code index} if it exists, coercing it if 122 | * necessary. 123 | */ 124 | static boolean getBoolean(ReadableArray array, int index, boolean defaultValue) { 125 | if (array == null){ 126 | return defaultValue; 127 | } 128 | try { 129 | ReadableType type = array.getType(index); 130 | switch (type) { 131 | case Boolean: 132 | return array.getBoolean(index); 133 | case String: { 134 | String value = array.getString(index); 135 | if ("true".equalsIgnoreCase(value)) { 136 | return true; 137 | } else if ("false".equalsIgnoreCase(value)) { 138 | return false; 139 | } 140 | return false; 141 | } 142 | case Number: { 143 | double value = array.getDouble(index); 144 | if (value == 0) { 145 | return Boolean.FALSE; 146 | } else { 147 | return Boolean.TRUE; 148 | } 149 | } 150 | case Null: 151 | return false; 152 | default: 153 | return defaultValue; 154 | } 155 | } catch(NoSuchKeyException ex){ 156 | return defaultValue; 157 | } 158 | } 159 | 160 | 161 | static Object get(ReadableMap map,String key,Object defaultValue){ 162 | if (map == null){ 163 | return defaultValue; 164 | } 165 | 166 | try { 167 | Object value = null; 168 | ReadableType type = map.getType(key); 169 | switch(type){ 170 | case Boolean: 171 | value = map.getBoolean(key); 172 | break; 173 | case Number: 174 | value = map.getDouble(key); 175 | break; 176 | case String: 177 | value = map.getString(key); 178 | break; 179 | case Map: 180 | value = map.getMap(key); 181 | break; 182 | case Array: 183 | value = map.getArray(key); 184 | break; 185 | case Null: 186 | value = null; 187 | break; 188 | } 189 | return value; 190 | } catch (NoSuchKeyException ex){ 191 | return defaultValue; 192 | } 193 | } 194 | 195 | static Object get(ReadableArray array,int index,Object defaultValue){ 196 | if (array == null){ 197 | return defaultValue; 198 | } 199 | 200 | try { 201 | Object value = null; 202 | ReadableType type = array.getType(index); 203 | switch(type){ 204 | case Boolean: 205 | value = array.getBoolean(index); 206 | break; 207 | case Number: 208 | value = array.getDouble(index); 209 | break; 210 | case String: 211 | value = array.getString(index); 212 | break; 213 | case Map: 214 | value = array.getMap(index); 215 | break; 216 | case Array: 217 | value = array.getArray(index); 218 | break; 219 | case Null: 220 | break; 221 | } 222 | return value; 223 | } catch (NoSuchKeyException ex){ 224 | return defaultValue; 225 | } 226 | } 227 | } 228 | -------------------------------------------------------------------------------- /platforms/android-native/src/main/java/io/liteglue/SQLitePluginPackage.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Written by Andrzej Porebski Nov 14/2015 3 | * 4 | * Copyright (c) 2015, Andrzej Porebski 5 | */ 6 | package io.liteglue; 7 | 8 | import android.app.Activity; 9 | 10 | import com.facebook.react.ReactPackage; 11 | import com.facebook.react.bridge.JavaScriptModule; 12 | import com.facebook.react.bridge.NativeModule; 13 | import com.facebook.react.bridge.ReactApplicationContext; 14 | import com.facebook.react.uimanager.ViewManager; 15 | 16 | import java.util.ArrayList; 17 | import java.util.Collections; 18 | import java.util.List; 19 | 20 | public class SQLitePluginPackage implements ReactPackage { 21 | 22 | /** 23 | * @deprecated Please use version without activity parameter 24 | * activity parameter is ignored 25 | */ 26 | public SQLitePluginPackage(Activity activity) { 27 | this(); 28 | } 29 | 30 | public SQLitePluginPackage(){ 31 | } 32 | 33 | @Override 34 | public List createNativeModules( 35 | ReactApplicationContext reactContext) { 36 | List modules = new ArrayList<>(); 37 | modules.add(new SQLitePlugin(reactContext)); 38 | return modules; 39 | } 40 | 41 | // Deprecated RN 0.47 42 | public List> createJSModules() { 43 | return Collections.emptyList(); 44 | } 45 | 46 | @Override 47 | public List createViewManagers(ReactApplicationContext reactContext) { 48 | return Collections.emptyList(); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /platforms/android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | google() 4 | jcenter() 5 | } 6 | 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:3.1.4' 9 | } 10 | } 11 | 12 | apply plugin: 'com.android.library' 13 | 14 | def safeExtGet(prop, fallback) { 15 | rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback 16 | } 17 | 18 | android { 19 | compileSdkVersion safeExtGet('compileSdkVersion', 23) 20 | buildToolsVersion safeExtGet('buildToolsVersion', '27.0.3') 21 | 22 | defaultConfig { 23 | minSdkVersion safeExtGet('minSdkVersion', 16) 24 | targetSdkVersion safeExtGet('targetSdkVersion', 22) 25 | versionCode 1 26 | versionName "1.0" 27 | } 28 | lintOptions { 29 | abortOnError false 30 | } 31 | } 32 | 33 | repositories { 34 | mavenCentral() 35 | google() 36 | maven { 37 | url "https://maven.google.com" 38 | } 39 | } 40 | 41 | dependencies { 42 | implementation 'com.facebook.react:react-native:+' 43 | } 44 | -------------------------------------------------------------------------------- /platforms/android/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'SQLitePlugin' 2 | include ':app' -------------------------------------------------------------------------------- /platforms/android/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /platforms/android/src/main/java/org/pgsqlite/CallbackContext.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Written by Andrzej Porebski Nov 14/2015 3 | * 4 | * Copyright (c) 2015, Andrzej Porebski 5 | */ 6 | package org.pgsqlite; 7 | 8 | import com.facebook.react.bridge.Callback; 9 | import com.facebook.react.bridge.WritableArray; 10 | import com.facebook.react.bridge.WritableMap; 11 | 12 | public class CallbackContext { 13 | 14 | private static final String LOG_TAG = CallbackContext.class.getSimpleName(); 15 | 16 | private Callback successCallback; 17 | private Callback errorCallback; 18 | 19 | public CallbackContext(Callback success, Callback error) { 20 | this.successCallback = success; 21 | this.errorCallback = error; 22 | } 23 | 24 | /** 25 | * Helper for success callbacks that just returns the Status.OK by default 26 | * 27 | * @param message The message to add to the success result. 28 | */ 29 | public void success(WritableMap message) { 30 | successCallback.invoke(message); 31 | 32 | } 33 | 34 | /** 35 | * Helper for success callbacks that just returns the Status.OK by default 36 | * 37 | * @param message The message to add to the success result. 38 | */ 39 | public void success(String message) { 40 | successCallback.invoke(message); 41 | } 42 | 43 | /** 44 | * Helper for success callbacks that just returns the Status.OK by default 45 | * 46 | * @param message The message to add to the success result. 47 | */ 48 | public void success(WritableArray message) { 49 | successCallback.invoke(message); 50 | } 51 | 52 | /** 53 | * Helper for success callbacks that just returns the Status.OK by default 54 | */ 55 | public void success() { 56 | successCallback.invoke("Success"); 57 | } 58 | 59 | /** 60 | * Helper for error callbacks that just returns the Status.ERROR by default 61 | * 62 | * @param message The message to add to the error result. 63 | */ 64 | public void error(WritableMap message) { 65 | errorCallback.invoke(message); 66 | } 67 | 68 | /** 69 | * Helper for error callbacks that just returns the Status.ERROR by default 70 | * 71 | * @param message The message to add to the error result. 72 | */ 73 | public void error(String message) { 74 | errorCallback.invoke(message); 75 | } 76 | } -------------------------------------------------------------------------------- /platforms/android/src/main/java/org/pgsqlite/SQLitePluginConverter.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Written by Andrzej Porebski Nov 14/2015 3 | * 4 | * Copyright (c) 2015, Andrzej Porebski 5 | */ 6 | 7 | package org.pgsqlite; 8 | 9 | import com.facebook.react.bridge.NoSuchKeyException; 10 | import com.facebook.react.bridge.ReadableArray; 11 | import com.facebook.react.bridge.ReadableMap; 12 | import com.facebook.react.bridge.ReadableType; 13 | 14 | public abstract class SQLitePluginConverter { 15 | 16 | /** 17 | * Returns the value at {@code key} if it exists, coercing it if 18 | * necessary. 19 | */ 20 | static String getString(ReadableMap map, String key, String defaultValue) { 21 | if (map == null){ 22 | return defaultValue; 23 | } 24 | try { 25 | ReadableType type = map.getType(key); 26 | switch (type) { 27 | case Number: 28 | double value = map.getDouble(key); 29 | if (value == (long) value) { 30 | return String.valueOf((long) value); 31 | } else { 32 | return String.valueOf(value); 33 | } 34 | case Boolean: 35 | return String.valueOf(map.getBoolean(key)); 36 | case String: 37 | return map.getString(key); 38 | case Null: 39 | return null; 40 | default: 41 | return defaultValue; 42 | } 43 | } catch(NoSuchKeyException ex){ 44 | return defaultValue; 45 | } 46 | } 47 | 48 | /** 49 | * Returns the value at {@code key} if it exists, coercing it if 50 | * necessary. 51 | */ 52 | static boolean getBoolean(ReadableMap map, String key, boolean defaultValue) { 53 | if (map == null){ 54 | return defaultValue; 55 | } 56 | try { 57 | ReadableType type = map.getType(key); 58 | switch (type) { 59 | case Boolean: 60 | return map.getBoolean(key); 61 | case String: { 62 | String value = map.getString(key); 63 | if ("true".equalsIgnoreCase(value)) { 64 | return true; 65 | } else if ("false".equalsIgnoreCase(value)) { 66 | return false; 67 | } 68 | return false; 69 | } 70 | case Number: { 71 | double value = map.getDouble(key); 72 | if (value == (long) 0) { 73 | return Boolean.FALSE; 74 | } else { 75 | return Boolean.TRUE; 76 | } 77 | } 78 | case Null: 79 | return false; 80 | default: 81 | return defaultValue; 82 | } 83 | } catch(NoSuchKeyException ex){ 84 | return defaultValue; 85 | } 86 | } 87 | 88 | /** 89 | * Returns the value at {@code index} if it exists, coercing it if 90 | * necessary. 91 | */ 92 | static String getString(ReadableArray array, int index, String defaultValue) { 93 | if (array == null){ 94 | return defaultValue; 95 | } 96 | try { 97 | ReadableType type = array.getType(index); 98 | switch (type) { 99 | case Number: 100 | double value = array.getDouble(index); 101 | if (value == (long) value) { 102 | return String.valueOf((long) value); 103 | } else { 104 | return String.valueOf(value); 105 | } 106 | case Boolean: 107 | return String.valueOf(array.getBoolean(index)); 108 | case String: 109 | return array.getString(index); 110 | case Null: 111 | return null; 112 | default: 113 | return defaultValue; 114 | } 115 | } catch(NoSuchKeyException ex){ 116 | return defaultValue; 117 | } 118 | } 119 | 120 | /** 121 | * Returns the value at {@code index} if it exists, coercing it if 122 | * necessary. 123 | */ 124 | static boolean getBoolean(ReadableArray array, int index, boolean defaultValue) { 125 | if (array == null){ 126 | return defaultValue; 127 | } 128 | try { 129 | ReadableType type = array.getType(index); 130 | switch (type) { 131 | case Boolean: 132 | return array.getBoolean(index); 133 | case String: { 134 | String value = array.getString(index); 135 | if ("true".equalsIgnoreCase(value)) { 136 | return true; 137 | } else if ("false".equalsIgnoreCase(value)) { 138 | return false; 139 | } 140 | return false; 141 | } 142 | case Number: { 143 | double value = array.getDouble(index); 144 | if (value == 0) { 145 | return Boolean.FALSE; 146 | } else { 147 | return Boolean.TRUE; 148 | } 149 | } 150 | case Null: 151 | return false; 152 | default: 153 | return defaultValue; 154 | } 155 | } catch(NoSuchKeyException ex){ 156 | return defaultValue; 157 | } 158 | } 159 | 160 | 161 | static Object get(ReadableMap map,String key,Object defaultValue){ 162 | if (map == null){ 163 | return defaultValue; 164 | } 165 | 166 | try { 167 | Object value = null; 168 | ReadableType type = map.getType(key); 169 | switch(type){ 170 | case Boolean: 171 | value = map.getBoolean(key); 172 | break; 173 | case Number: 174 | value = map.getDouble(key); 175 | break; 176 | case String: 177 | value = map.getString(key); 178 | break; 179 | case Map: 180 | value = map.getMap(key); 181 | break; 182 | case Array: 183 | value = map.getArray(key); 184 | break; 185 | case Null: 186 | value = null; 187 | break; 188 | } 189 | return value; 190 | } catch (NoSuchKeyException ex){ 191 | return defaultValue; 192 | } 193 | } 194 | 195 | static Object get(ReadableArray array,int index,Object defaultValue){ 196 | if (array == null){ 197 | return defaultValue; 198 | } 199 | 200 | try { 201 | Object value = null; 202 | ReadableType type = array.getType(index); 203 | switch(type){ 204 | case Boolean: 205 | value = array.getBoolean(index); 206 | break; 207 | case Number: 208 | value = array.getDouble(index); 209 | break; 210 | case String: 211 | value = array.getString(index); 212 | break; 213 | case Map: 214 | value = array.getMap(index); 215 | break; 216 | case Array: 217 | value = array.getArray(index); 218 | break; 219 | case Null: 220 | break; 221 | } 222 | return value; 223 | } catch (NoSuchKeyException ex){ 224 | return defaultValue; 225 | } 226 | } 227 | } 228 | -------------------------------------------------------------------------------- /platforms/android/src/main/java/org/pgsqlite/SQLitePluginPackage.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Written by Andrzej Porebski Nov 14/2015 3 | * 4 | * Copyright (c) 2015, Andrzej Porebski 5 | */ 6 | package org.pgsqlite; 7 | 8 | import android.app.Activity; 9 | 10 | import com.facebook.react.ReactPackage; 11 | import com.facebook.react.bridge.JavaScriptModule; 12 | import com.facebook.react.bridge.NativeModule; 13 | import com.facebook.react.bridge.ReactApplicationContext; 14 | import com.facebook.react.uimanager.ViewManager; 15 | 16 | import java.util.ArrayList; 17 | import java.util.Collections; 18 | 19 | import java.util.List; 20 | 21 | public class SQLitePluginPackage implements ReactPackage { 22 | 23 | /** 24 | * @deprecated, use method without activity 25 | * activity parameter is ignored 26 | */ 27 | public SQLitePluginPackage(Activity activity){ 28 | this(); 29 | } 30 | 31 | public SQLitePluginPackage() { 32 | } 33 | 34 | @Override 35 | public List createNativeModules( 36 | ReactApplicationContext reactContext) { 37 | List modules = new ArrayList<>(); 38 | 39 | modules.add(new SQLitePlugin(reactContext)); 40 | 41 | return modules; 42 | } 43 | 44 | // Deprecated RN 0.47 45 | public List> createJSModules() { 46 | return Collections.emptyList(); 47 | } 48 | 49 | @Override 50 | public List createViewManagers(ReactApplicationContext reactContext) { 51 | return Collections.emptyList(); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /platforms/ios/SQLite.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SQLite.h 3 | * 4 | * Created by Andrzej Porebski on 10/29/15. 5 | * Copyright (c) 2015 Andrzej Porebski. 6 | * 7 | * This software is largely based on the SQLLite Storage Cordova Plugin created by Chris Brody & Davide Bertola. 8 | * The implementation was adopted and converted to use React Native bindings. 9 | * 10 | * See https://github.com/litehelpers/Cordova-sqlite-storage 11 | * 12 | * This library is available under the terms of the MIT License (2008). 13 | * See http://opensource.org/licenses/alphabetical for full text. 14 | */ 15 | 16 | #import 17 | 18 | // Used to remove dependency on sqlite3.h in this header: 19 | struct sqlite3; 20 | 21 | enum WebSQLError { 22 | UNKNOWN_ERR = 0, 23 | DATABASE_ERR = 1, 24 | VERSION_ERR = 2, 25 | TOO_LARGE_ERR = 3, 26 | QUOTA_ERR = 4, 27 | SYNTAX_ERR = 5, 28 | CONSTRAINT_ERR = 6, 29 | TIMEOUT_ERR = 7 30 | }; 31 | typedef int WebSQLError; 32 | 33 | @interface SQLite : NSObject { 34 | NSMutableDictionary *openDBs; 35 | } 36 | 37 | @property (nonatomic, copy) NSMutableDictionary *openDBs; 38 | @property (nonatomic, copy) NSMutableDictionary *appDBPaths; 39 | 40 | // Open / Close 41 | -(void) open: (NSDictionary *) options success:(RCTResponseSenderBlock)success error:(RCTResponseSenderBlock)error; 42 | -(void) close: (NSDictionary *) options success:(RCTResponseSenderBlock)success error:(RCTResponseSenderBlock)error; 43 | -(void) attach: (NSDictionary *) options success:(RCTResponseSenderBlock)success error:(RCTResponseSenderBlock)error; 44 | -(void) delete: (NSDictionary *) options success:(RCTResponseSenderBlock)success error:(RCTResponseSenderBlock)error; 45 | 46 | // Batch processing interface 47 | -(void) backgroundExecuteSqlBatch: (NSDictionary *) options success:(RCTResponseSenderBlock)success error:(RCTResponseSenderBlock)error; 48 | -(void) executeSqlBatch: (NSDictionary *) options success:(RCTResponseSenderBlock)success error:(RCTResponseSenderBlock)error; 49 | 50 | // Single requests interface 51 | -(void) backgroundExecuteSql:(NSDictionary *) options success:(RCTResponseSenderBlock)success error:(RCTResponseSenderBlock)error; 52 | -(void) executeSql:(NSDictionary *) options success:(RCTResponseSenderBlock)success error:(RCTResponseSenderBlock)error; 53 | 54 | // Echo Test 55 | -(void) echoStringValue:(NSDictionary *) options success:(RCTResponseSenderBlock)success error:(RCTResponseSenderBlock)error; 56 | @end 57 | -------------------------------------------------------------------------------- /platforms/ios/SQLite.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | C7DCD6E41BE0295900F3300E /* SQLite.h in Headers */ = {isa = PBXBuildFile; fileRef = C7DCD6E21BE0295900F3300E /* SQLite.h */; }; 11 | C7DCD6E51BE0295A00F3300E /* SQLite.m in Sources */ = {isa = PBXBuildFile; fileRef = C7DCD6E31BE0295900F3300E /* SQLite.m */; }; 12 | C7DCD7141BE2D5DE00F3300E /* SQLiteResult.m in Sources */ = {isa = PBXBuildFile; fileRef = C7DCD7131BE2D5DE00F3300E /* SQLiteResult.m */; }; 13 | /* End PBXBuildFile section */ 14 | 15 | /* Begin PBXCopyFilesBuildPhase section */ 16 | E23D7B451ACEFE2A00C59171 /* CopyFiles */ = { 17 | isa = PBXCopyFilesBuildPhase; 18 | buildActionMask = 2147483647; 19 | dstPath = "include/$(PRODUCT_NAME)"; 20 | dstSubfolderSpec = 16; 21 | files = ( 22 | ); 23 | runOnlyForDeploymentPostprocessing = 0; 24 | }; 25 | /* End PBXCopyFilesBuildPhase section */ 26 | 27 | /* Begin PBXFileReference section */ 28 | C7DCD6E21BE0295900F3300E /* SQLite.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SQLite.h; sourceTree = ""; }; 29 | C7DCD6E31BE0295900F3300E /* SQLite.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SQLite.m; sourceTree = ""; }; 30 | C7DCD7131BE2D5DE00F3300E /* SQLiteResult.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SQLiteResult.m; sourceTree = ""; }; 31 | C7DCD7151BE2D61E00F3300E /* SQLiteResult.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SQLiteResult.h; sourceTree = ""; }; 32 | E23D7B471ACEFE2A00C59171 /* libSQLite.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libSQLite.a; sourceTree = BUILT_PRODUCTS_DIR; }; 33 | /* End PBXFileReference section */ 34 | 35 | /* Begin PBXFrameworksBuildPhase section */ 36 | E23D7B441ACEFE2A00C59171 /* Frameworks */ = { 37 | isa = PBXFrameworksBuildPhase; 38 | buildActionMask = 2147483647; 39 | files = ( 40 | ); 41 | runOnlyForDeploymentPostprocessing = 0; 42 | }; 43 | /* End PBXFrameworksBuildPhase section */ 44 | 45 | /* Begin PBXGroup section */ 46 | C7DCD6E11BE0293D00F3300E /* SQLite */ = { 47 | isa = PBXGroup; 48 | children = ( 49 | C7DCD6E21BE0295900F3300E /* SQLite.h */, 50 | C7DCD6E31BE0295900F3300E /* SQLite.m */, 51 | C7DCD7151BE2D61E00F3300E /* SQLiteResult.h */, 52 | C7DCD7131BE2D5DE00F3300E /* SQLiteResult.m */, 53 | ); 54 | name = SQLite; 55 | sourceTree = ""; 56 | }; 57 | E23D7B3E1ACEFE2A00C59171 = { 58 | isa = PBXGroup; 59 | children = ( 60 | C7DCD6E11BE0293D00F3300E /* SQLite */, 61 | E23D7B481ACEFE2A00C59171 /* Products */, 62 | ); 63 | indentWidth = 2; 64 | sourceTree = ""; 65 | tabWidth = 2; 66 | }; 67 | E23D7B481ACEFE2A00C59171 /* Products */ = { 68 | isa = PBXGroup; 69 | children = ( 70 | E23D7B471ACEFE2A00C59171 /* libSQLite.a */, 71 | ); 72 | name = Products; 73 | sourceTree = ""; 74 | }; 75 | /* End PBXGroup section */ 76 | 77 | /* Begin PBXHeadersBuildPhase section */ 78 | E25C749F1ACEFF2C004F0793 /* Headers */ = { 79 | isa = PBXHeadersBuildPhase; 80 | buildActionMask = 2147483647; 81 | files = ( 82 | C7DCD6E41BE0295900F3300E /* SQLite.h in Headers */, 83 | ); 84 | runOnlyForDeploymentPostprocessing = 0; 85 | }; 86 | /* End PBXHeadersBuildPhase section */ 87 | 88 | /* Begin PBXNativeTarget section */ 89 | E23D7B461ACEFE2A00C59171 /* SQLite */ = { 90 | isa = PBXNativeTarget; 91 | buildConfigurationList = E23D7B5B1ACEFE2A00C59171 /* Build configuration list for PBXNativeTarget "SQLite" */; 92 | buildPhases = ( 93 | E23D7B431ACEFE2A00C59171 /* Sources */, 94 | E23D7B441ACEFE2A00C59171 /* Frameworks */, 95 | E23D7B451ACEFE2A00C59171 /* CopyFiles */, 96 | E25C749F1ACEFF2C004F0793 /* Headers */, 97 | ); 98 | buildRules = ( 99 | ); 100 | dependencies = ( 101 | ); 102 | name = SQLite; 103 | productName = AIBSQLite; 104 | productReference = E23D7B471ACEFE2A00C59171 /* libSQLite.a */; 105 | productType = "com.apple.product-type.library.static"; 106 | }; 107 | /* End PBXNativeTarget section */ 108 | 109 | /* Begin PBXProject section */ 110 | E23D7B3F1ACEFE2A00C59171 /* Project object */ = { 111 | isa = PBXProject; 112 | attributes = { 113 | LastUpgradeCheck = 0920; 114 | ORGANIZATIONNAME = "Andrzej Porebski"; 115 | TargetAttributes = { 116 | E23D7B461ACEFE2A00C59171 = { 117 | CreatedOnToolsVersion = 6.1.1; 118 | }; 119 | }; 120 | }; 121 | buildConfigurationList = E23D7B421ACEFE2A00C59171 /* Build configuration list for PBXProject "SQLite" */; 122 | compatibilityVersion = "Xcode 3.2"; 123 | developmentRegion = English; 124 | hasScannedForEncodings = 0; 125 | knownRegions = ( 126 | en, 127 | ); 128 | mainGroup = E23D7B3E1ACEFE2A00C59171; 129 | productRefGroup = E23D7B481ACEFE2A00C59171 /* Products */; 130 | projectDirPath = ""; 131 | projectRoot = ""; 132 | targets = ( 133 | E23D7B461ACEFE2A00C59171 /* SQLite */, 134 | ); 135 | }; 136 | /* End PBXProject section */ 137 | 138 | /* Begin PBXSourcesBuildPhase section */ 139 | E23D7B431ACEFE2A00C59171 /* Sources */ = { 140 | isa = PBXSourcesBuildPhase; 141 | buildActionMask = 2147483647; 142 | files = ( 143 | C7DCD7141BE2D5DE00F3300E /* SQLiteResult.m in Sources */, 144 | C7DCD6E51BE0295A00F3300E /* SQLite.m in Sources */, 145 | ); 146 | runOnlyForDeploymentPostprocessing = 0; 147 | }; 148 | /* End PBXSourcesBuildPhase section */ 149 | 150 | /* Begin XCBuildConfiguration section */ 151 | E23D7B591ACEFE2A00C59171 /* Debug */ = { 152 | isa = XCBuildConfiguration; 153 | buildSettings = { 154 | ALWAYS_SEARCH_USER_PATHS = NO; 155 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 156 | CLANG_CXX_LIBRARY = "libc++"; 157 | CLANG_ENABLE_MODULES = YES; 158 | CLANG_ENABLE_OBJC_ARC = YES; 159 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 160 | CLANG_WARN_BOOL_CONVERSION = YES; 161 | CLANG_WARN_COMMA = YES; 162 | CLANG_WARN_CONSTANT_CONVERSION = YES; 163 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 164 | CLANG_WARN_EMPTY_BODY = YES; 165 | CLANG_WARN_ENUM_CONVERSION = YES; 166 | CLANG_WARN_INFINITE_RECURSION = YES; 167 | CLANG_WARN_INT_CONVERSION = YES; 168 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 169 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 170 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 171 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 172 | CLANG_WARN_STRICT_PROTOTYPES = YES; 173 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 174 | CLANG_WARN_UNREACHABLE_CODE = YES; 175 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 176 | COPY_PHASE_STRIP = NO; 177 | ENABLE_STRICT_OBJC_MSGSEND = YES; 178 | ENABLE_TESTABILITY = YES; 179 | GCC_C_LANGUAGE_STANDARD = gnu99; 180 | GCC_DYNAMIC_NO_PIC = NO; 181 | GCC_NO_COMMON_BLOCKS = YES; 182 | GCC_OPTIMIZATION_LEVEL = 0; 183 | GCC_PREPROCESSOR_DEFINITIONS = ( 184 | "DEBUG=1", 185 | "$(inherited)", 186 | ); 187 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 188 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 189 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 190 | GCC_WARN_UNDECLARED_SELECTOR = YES; 191 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 192 | GCC_WARN_UNUSED_FUNCTION = YES; 193 | GCC_WARN_UNUSED_VARIABLE = YES; 194 | IPHONEOS_DEPLOYMENT_TARGET = 8.1; 195 | MTL_ENABLE_DEBUG_INFO = YES; 196 | ONLY_ACTIVE_ARCH = YES; 197 | SDKROOT = iphoneos; 198 | }; 199 | name = Debug; 200 | }; 201 | E23D7B5A1ACEFE2A00C59171 /* Release */ = { 202 | isa = XCBuildConfiguration; 203 | buildSettings = { 204 | ALWAYS_SEARCH_USER_PATHS = NO; 205 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 206 | CLANG_CXX_LIBRARY = "libc++"; 207 | CLANG_ENABLE_MODULES = YES; 208 | CLANG_ENABLE_OBJC_ARC = YES; 209 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 210 | CLANG_WARN_BOOL_CONVERSION = YES; 211 | CLANG_WARN_COMMA = YES; 212 | CLANG_WARN_CONSTANT_CONVERSION = YES; 213 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 214 | CLANG_WARN_EMPTY_BODY = YES; 215 | CLANG_WARN_ENUM_CONVERSION = YES; 216 | CLANG_WARN_INFINITE_RECURSION = YES; 217 | CLANG_WARN_INT_CONVERSION = YES; 218 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 219 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 220 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 221 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 222 | CLANG_WARN_STRICT_PROTOTYPES = YES; 223 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 224 | CLANG_WARN_UNREACHABLE_CODE = YES; 225 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 226 | COPY_PHASE_STRIP = YES; 227 | ENABLE_NS_ASSERTIONS = NO; 228 | ENABLE_STRICT_OBJC_MSGSEND = YES; 229 | GCC_C_LANGUAGE_STANDARD = gnu99; 230 | GCC_NO_COMMON_BLOCKS = YES; 231 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 232 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 233 | GCC_WARN_UNDECLARED_SELECTOR = YES; 234 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 235 | GCC_WARN_UNUSED_FUNCTION = YES; 236 | GCC_WARN_UNUSED_VARIABLE = YES; 237 | IPHONEOS_DEPLOYMENT_TARGET = 8.1; 238 | MTL_ENABLE_DEBUG_INFO = NO; 239 | SDKROOT = iphoneos; 240 | VALIDATE_PRODUCT = YES; 241 | }; 242 | name = Release; 243 | }; 244 | E23D7B5C1ACEFE2A00C59171 /* Debug */ = { 245 | isa = XCBuildConfiguration; 246 | buildSettings = { 247 | FRAMEWORK_SEARCH_PATHS = "$(inherited)"; 248 | HEADER_SEARCH_PATHS = ( 249 | "$(inherited)", 250 | /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, 251 | "$(SRCROOT)/../../../react-native/React/**", 252 | ); 253 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 254 | OTHER_LDFLAGS = "-ObjC"; 255 | PRODUCT_NAME = SQLite; 256 | SKIP_INSTALL = YES; 257 | USER_HEADER_SEARCH_PATHS = "$(SRCROOT)/../../../react-native/React/**"; 258 | }; 259 | name = Debug; 260 | }; 261 | E23D7B5D1ACEFE2A00C59171 /* Release */ = { 262 | isa = XCBuildConfiguration; 263 | buildSettings = { 264 | FRAMEWORK_SEARCH_PATHS = "$(inherited)"; 265 | HEADER_SEARCH_PATHS = ( 266 | "$(inherited)", 267 | /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, 268 | "$(SRCROOT)/../../../react-native/React/**", 269 | ); 270 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 271 | OTHER_LDFLAGS = "-ObjC"; 272 | PRODUCT_NAME = SQLite; 273 | SKIP_INSTALL = YES; 274 | USER_HEADER_SEARCH_PATHS = "$(SRCROOT)/../../../react-native/React/**"; 275 | }; 276 | name = Release; 277 | }; 278 | /* End XCBuildConfiguration section */ 279 | 280 | /* Begin XCConfigurationList section */ 281 | E23D7B421ACEFE2A00C59171 /* Build configuration list for PBXProject "SQLite" */ = { 282 | isa = XCConfigurationList; 283 | buildConfigurations = ( 284 | E23D7B591ACEFE2A00C59171 /* Debug */, 285 | E23D7B5A1ACEFE2A00C59171 /* Release */, 286 | ); 287 | defaultConfigurationIsVisible = 0; 288 | defaultConfigurationName = Release; 289 | }; 290 | E23D7B5B1ACEFE2A00C59171 /* Build configuration list for PBXNativeTarget "SQLite" */ = { 291 | isa = XCConfigurationList; 292 | buildConfigurations = ( 293 | E23D7B5C1ACEFE2A00C59171 /* Debug */, 294 | E23D7B5D1ACEFE2A00C59171 /* Release */, 295 | ); 296 | defaultConfigurationIsVisible = 0; 297 | defaultConfigurationName = Release; 298 | }; 299 | /* End XCConfigurationList section */ 300 | }; 301 | rootObject = E23D7B3F1ACEFE2A00C59171 /* Project object */; 302 | } 303 | -------------------------------------------------------------------------------- /platforms/ios/SQLite.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /platforms/ios/SQLiteResult.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SQLiteResult.h 3 | * 4 | * Created by Andrzej Porebski on 10/29/15. 5 | * Copyright (c) 2015 Andrzej Porebski. 6 | * 7 | * This software is largely based on the SQLLite Storage Cordova Plugin created by Chris Brody & Davide Bertola. 8 | * The implementation was adopted and converted to use React Native bindings. 9 | * 10 | * See https://github.com/litehelpers/Cordova-sqlite-storage 11 | * 12 | * This library is available under the terms of the MIT License (2008). 13 | * See http://opensource.org/licenses/alphabetical for full text. 14 | */ 15 | 16 | typedef enum { 17 | SQLiteStatus_NO_RESULT = 0, 18 | SQLiteStatus_OK, 19 | SQLiteStatus_ERROR 20 | } SQLiteStatus; 21 | 22 | 23 | @interface SQLiteResult : NSObject {} 24 | 25 | @property (nonatomic, strong, readonly) NSNumber* status; 26 | @property (nonatomic, strong, readonly) id message; 27 | 28 | + (SQLiteResult*)resultWithStatus:(SQLiteStatus)statusOrdinal messageAsString:(NSString*)theMessage; 29 | + (SQLiteResult*)resultWithStatus:(SQLiteStatus)statusOrdinal messageAsArray:(NSArray*)theMessage; 30 | + (SQLiteResult*)resultWithStatus:(SQLiteStatus)statusOrdinal messageAsDictionary:(NSDictionary*)theMessage; 31 | 32 | @end -------------------------------------------------------------------------------- /platforms/ios/SQLiteResult.m: -------------------------------------------------------------------------------- 1 | /* 2 | * SQLiteResult.m 3 | * 4 | * Created by Andrzej Porebski on 10/29/15. 5 | * Copyright (c) 2015 Andrzej Porebski. 6 | * 7 | * This software is largely based on the SQLLite Storage Cordova Plugin created by Chris Brody & Davide Bertola. 8 | * The implementation was adopted and converted to use React Native bindings. 9 | * 10 | * See https://github.com/litehelpers/Cordova-sqlite-storage 11 | * 12 | * This library is available under the terms of the MIT License (2008). 13 | * See http://opensource.org/licenses/alphabetical for full text. 14 | */ 15 | 16 | #import 17 | #import "SQLiteResult.h" 18 | 19 | @interface SQLiteResult () 20 | 21 | - (SQLiteResult *)initWithStatus:(SQLiteStatus)statusOrdinal message:(id)theMessage; 22 | 23 | @end 24 | 25 | @implementation SQLiteResult 26 | @synthesize status, message; 27 | 28 | - (SQLiteResult*)init 29 | { 30 | return [self initWithStatus:SQLiteStatus_NO_RESULT message:nil]; 31 | } 32 | 33 | - (SQLiteResult*)initWithStatus:(SQLiteStatus)statusOrdinal message:(id)theMessage 34 | { 35 | self = [super init]; 36 | if (self) { 37 | status = [NSNumber numberWithInt:statusOrdinal]; 38 | message = theMessage; 39 | } 40 | return self; 41 | } 42 | 43 | + (SQLiteResult*)resultWithStatus:(SQLiteStatus)statusOrdinal messageAsString:(NSString*)theMessage 44 | { 45 | return [[self alloc] initWithStatus:statusOrdinal message:theMessage]; 46 | } 47 | 48 | + (SQLiteResult*)resultWithStatus:(SQLiteStatus)statusOrdinal messageAsArray:(NSArray*)theMessage 49 | { 50 | return [[self alloc] initWithStatus:statusOrdinal message:theMessage]; 51 | } 52 | 53 | + (SQLiteResult*)resultWithStatus:(SQLiteStatus)statusOrdinal messageAsDictionary:(NSDictionary*)theMessage 54 | { 55 | return [[self alloc] initWithStatus:statusOrdinal message:theMessage]; 56 | } 57 | 58 | 59 | 60 | @end -------------------------------------------------------------------------------- /platforms/windows/.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.rsuser 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | 13 | # User-specific files (MonoDevelop/Xamarin Studio) 14 | *.userprefs 15 | 16 | # Mono auto generated files 17 | mono_crash.* 18 | 19 | # Build results 20 | [Dd]ebug/ 21 | [Dd]ebugPublic/ 22 | [Rr]elease/ 23 | [Rr]eleases/ 24 | x64/ 25 | x86/ 26 | [Ww][Ii][Nn]32/ 27 | [Aa][Rr][Mm]/ 28 | [Aa][Rr][Mm]64/ 29 | bld/ 30 | [Bb]in/ 31 | [Oo]bj/ 32 | [Ll]og/ 33 | [Ll]ogs/ 34 | 35 | # Visual Studio 2015/2017 cache/options directory 36 | .vs/ 37 | # Uncomment if you have tasks that create the project's static files in wwwroot 38 | #wwwroot/ 39 | 40 | # Visual Studio 2017 auto generated files 41 | Generated\ Files/ 42 | 43 | # MSTest test Results 44 | [Tt]est[Rr]esult*/ 45 | [Bb]uild[Ll]og.* 46 | 47 | # NUnit 48 | *.VisualState.xml 49 | TestResult.xml 50 | nunit-*.xml 51 | 52 | # Build Results of an ATL Project 53 | [Dd]ebugPS/ 54 | [Rr]eleasePS/ 55 | dlldata.c 56 | 57 | # Benchmark Results 58 | BenchmarkDotNet.Artifacts/ 59 | 60 | # .NET Core 61 | project.lock.json 62 | project.fragment.lock.json 63 | artifacts/ 64 | 65 | # ASP.NET Scaffolding 66 | ScaffoldingReadMe.txt 67 | 68 | # StyleCop 69 | StyleCopReport.xml 70 | 71 | # Files built by Visual Studio 72 | *_i.c 73 | *_p.c 74 | *_h.h 75 | *.ilk 76 | *.meta 77 | *.obj 78 | *.iobj 79 | *.pch 80 | *.pdb 81 | *.ipdb 82 | *.pgc 83 | *.pgd 84 | *.rsp 85 | *.sbr 86 | *.tlb 87 | *.tli 88 | *.tlh 89 | *.tmp 90 | *.tmp_proj 91 | *_wpftmp.csproj 92 | *.log 93 | *.vspscc 94 | *.vssscc 95 | .builds 96 | *.pidb 97 | *.svclog 98 | *.scc 99 | 100 | # Chutzpah Test files 101 | _Chutzpah* 102 | 103 | # Visual C++ cache files 104 | ipch/ 105 | *.aps 106 | *.ncb 107 | *.opendb 108 | *.opensdf 109 | *.sdf 110 | *.cachefile 111 | *.VC.db 112 | *.VC.VC.opendb 113 | 114 | # Visual Studio profiler 115 | *.psess 116 | *.vsp 117 | *.vspx 118 | *.sap 119 | 120 | # Visual Studio Trace Files 121 | *.e2e 122 | 123 | # TFS 2012 Local Workspace 124 | $tf/ 125 | 126 | # Guidance Automation Toolkit 127 | *.gpState 128 | 129 | # ReSharper is a .NET coding add-in 130 | _ReSharper*/ 131 | *.[Rr]e[Ss]harper 132 | *.DotSettings.user 133 | 134 | # TeamCity is a build add-in 135 | _TeamCity* 136 | 137 | # DotCover is a Code Coverage Tool 138 | *.dotCover 139 | 140 | # AxoCover is a Code Coverage Tool 141 | .axoCover/* 142 | !.axoCover/settings.json 143 | 144 | # Coverlet is a free, cross platform Code Coverage Tool 145 | coverage*.json 146 | coverage*.xml 147 | coverage*.info 148 | 149 | # Visual Studio code coverage results 150 | *.coverage 151 | *.coveragexml 152 | 153 | # NCrunch 154 | _NCrunch_* 155 | .*crunch*.local.xml 156 | nCrunchTemp_* 157 | 158 | # MightyMoose 159 | *.mm.* 160 | AutoTest.Net/ 161 | 162 | # Web workbench (sass) 163 | .sass-cache/ 164 | 165 | # Installshield output folder 166 | [Ee]xpress/ 167 | 168 | # DocProject is a documentation generator add-in 169 | DocProject/buildhelp/ 170 | DocProject/Help/*.HxT 171 | DocProject/Help/*.HxC 172 | DocProject/Help/*.hhc 173 | DocProject/Help/*.hhk 174 | DocProject/Help/*.hhp 175 | DocProject/Help/Html2 176 | DocProject/Help/html 177 | 178 | # Click-Once directory 179 | publish/ 180 | 181 | # Publish Web Output 182 | *.[Pp]ublish.xml 183 | *.azurePubxml 184 | # Note: Comment the next line if you want to checkin your web deploy settings, 185 | # but database connection strings (with potential passwords) will be unencrypted 186 | *.pubxml 187 | *.publishproj 188 | 189 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 190 | # checkin your Azure Web App publish settings, but sensitive information contained 191 | # in these scripts will be unencrypted 192 | PublishScripts/ 193 | 194 | # NuGet Packages 195 | *.nupkg 196 | # NuGet Symbol Packages 197 | *.snupkg 198 | # The packages folder can be ignored because of Package Restore 199 | **/[Pp]ackages/* 200 | # except build/, which is used as an MSBuild target. 201 | !**/[Pp]ackages/build/ 202 | # Uncomment if necessary however generally it will be regenerated when needed 203 | #!**/[Pp]ackages/repositories.config 204 | # NuGet v3's project.json files produces more ignorable files 205 | *.nuget.props 206 | *.nuget.targets 207 | 208 | # Microsoft Azure Build Output 209 | csx/ 210 | *.build.csdef 211 | 212 | # Microsoft Azure Emulator 213 | ecf/ 214 | rcf/ 215 | 216 | # Windows Store app package directories and files 217 | AppPackages/ 218 | BundleArtifacts/ 219 | Package.StoreAssociation.xml 220 | _pkginfo.txt 221 | *.appx 222 | *.appxbundle 223 | *.appxupload 224 | 225 | # Visual Studio cache files 226 | # files ending in .cache can be ignored 227 | *.[Cc]ache 228 | # but keep track of directories ending in .cache 229 | !?*.[Cc]ache/ 230 | 231 | # Others 232 | ClientBin/ 233 | ~$* 234 | *~ 235 | *.dbmdl 236 | *.dbproj.schemaview 237 | *.jfm 238 | *.pfx 239 | *.publishsettings 240 | orleans.codegen.cs 241 | 242 | # Including strong name files can present a security risk 243 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 244 | #*.snk 245 | 246 | # Since there are multiple workflows, uncomment next line to ignore bower_components 247 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 248 | #bower_components/ 249 | 250 | # RIA/Silverlight projects 251 | Generated_Code/ 252 | 253 | # Backup & report files from converting an old project file 254 | # to a newer Visual Studio version. Backup files are not needed, 255 | # because we have git ;-) 256 | _UpgradeReport_Files/ 257 | Backup*/ 258 | UpgradeLog*.XML 259 | UpgradeLog*.htm 260 | ServiceFabricBackup/ 261 | *.rptproj.bak 262 | 263 | # SQL Server files 264 | *.mdf 265 | *.ldf 266 | *.ndf 267 | 268 | # Business Intelligence projects 269 | *.rdl.data 270 | *.bim.layout 271 | *.bim_*.settings 272 | *.rptproj.rsuser 273 | *- [Bb]ackup.rdl 274 | *- [Bb]ackup ([0-9]).rdl 275 | *- [Bb]ackup ([0-9][0-9]).rdl 276 | 277 | # Microsoft Fakes 278 | FakesAssemblies/ 279 | 280 | # GhostDoc plugin setting file 281 | *.GhostDoc.xml 282 | 283 | # Node.js Tools for Visual Studio 284 | .ntvs_analysis.dat 285 | node_modules/ 286 | 287 | # Visual Studio 6 build log 288 | *.plg 289 | 290 | # Visual Studio 6 workspace options file 291 | *.opt 292 | 293 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 294 | *.vbw 295 | 296 | # Visual Studio LightSwitch build output 297 | **/*.HTMLClient/GeneratedArtifacts 298 | **/*.DesktopClient/GeneratedArtifacts 299 | **/*.DesktopClient/ModelManifest.xml 300 | **/*.Server/GeneratedArtifacts 301 | **/*.Server/ModelManifest.xml 302 | _Pvt_Extensions 303 | 304 | # Paket dependency manager 305 | .paket/paket.exe 306 | paket-files/ 307 | 308 | # FAKE - F# Make 309 | .fake/ 310 | 311 | # CodeRush personal settings 312 | .cr/personal 313 | 314 | # Python Tools for Visual Studio (PTVS) 315 | __pycache__/ 316 | *.pyc 317 | 318 | # Cake - Uncomment if you are using it 319 | # tools/** 320 | # !tools/packages.config 321 | 322 | # Tabs Studio 323 | *.tss 324 | 325 | # Telerik's JustMock configuration file 326 | *.jmconfig 327 | 328 | # BizTalk build output 329 | *.btp.cs 330 | *.btm.cs 331 | *.odx.cs 332 | *.xsd.cs 333 | 334 | # OpenCover UI analysis results 335 | OpenCover/ 336 | 337 | # Azure Stream Analytics local run output 338 | ASALocalRun/ 339 | 340 | # MSBuild Binary and Structured Log 341 | *.binlog 342 | 343 | # NVidia Nsight GPU debugger configuration file 344 | *.nvuser 345 | 346 | # MFractors (Xamarin productivity tool) working folder 347 | .mfractor/ 348 | 349 | # Local History for Visual Studio 350 | .localhistory/ 351 | 352 | # BeatPulse healthcheck temp database 353 | healthchecksdb 354 | 355 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 356 | MigrationBackup/ 357 | 358 | # Ionide (cross platform F# VS Code tools) working folder 359 | .ionide/ 360 | 361 | # Fody - auto-generated XML schema 362 | FodyWeavers.xsd -------------------------------------------------------------------------------- /platforms/windows/SQLitePlugin.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30611.23 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SQLitePlugin", "SQLitePlugin\SQLitePlugin.vcxproj", "{A09B9A47-E2B9-4294-9746-AC55213FC642}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Common", "..\..\node_modules\react-native-windows\Common\Common.vcxproj", "{FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}" 9 | EndProject 10 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ReactNative", "ReactNative", "{263BA2E9-6537-4141-A210-B082AE5DC2C4}" 11 | EndProject 12 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Folly", "..\..\node_modules\react-native-windows\Folly\Folly.vcxproj", "{A990658C-CE31-4BCC-976F-0FC6B1AF693D}" 13 | EndProject 14 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "JSI.Universal", "..\..\node_modules\react-native-windows\JSI\Universal\JSI.Universal.vcxproj", "{A62D504A-16B8-41D2-9F19-E2E86019E5E4}" 15 | EndProject 16 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.ReactNative", "..\..\node_modules\react-native-windows\Microsoft.ReactNative\Microsoft.ReactNative.vcxproj", "{F7D32BD0-2749-483E-9A0D-1635EF7E3136}" 17 | EndProject 18 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.ReactNative.Managed", "..\..\node_modules\react-native-windows\Microsoft.ReactNative.Managed\Microsoft.ReactNative.Managed.csproj", "{F2824844-CE15-4242-9420-308923CD76C3}" 19 | EndProject 20 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ReactCommon", "..\..\node_modules\react-native-windows\ReactCommon\ReactCommon.vcxproj", "{A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}" 21 | EndProject 22 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Chakra", "..\..\node_modules\react-native-windows\Chakra\Chakra.vcxitems", "{C38970C0-5FBF-4D69-90D8-CBAC225AE895}" 23 | EndProject 24 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Include", "..\..\node_modules\react-native-windows\include\Include.vcxitems", "{EF074BA1-2D54-4D49-A28E-5E040B47CD2E}" 25 | EndProject 26 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "JSI.Shared", "..\..\node_modules\react-native-windows\JSI\Shared\JSI.Shared.vcxitems", "{0CC28589-39E4-4288-B162-97B959F8B843}" 27 | EndProject 28 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.ReactNative.Cxx", "..\..\node_modules\react-native-windows\Microsoft.ReactNative.Cxx\Microsoft.ReactNative.Cxx.vcxitems", "{DA8B35B3-DA00-4B02-BDE6-6A397B3FD46B}" 29 | EndProject 30 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.ReactNative.Shared", "..\..\node_modules\react-native-windows\Shared\Shared.vcxitems", "{2049DBE9-8D13-42C9-AE4B-413AE38FFFD0}" 31 | EndProject 32 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Mso", "..\..\node_modules\react-native-windows\Mso\Mso.vcxitems", "{84E05BFA-CBAF-4F0D-BFB6-4CE85742A57E}" 33 | EndProject 34 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.ReactNative.Managed.CodeGen", "..\..\node_modules\react-native-windows\Microsoft.ReactNative.Managed.CodeGen\Microsoft.ReactNative.Managed.CodeGen.csproj", "{A07DDB04-9965-4EE5-963D-B31368B6E514}" 35 | EndProject 36 | Global 37 | GlobalSection(SharedMSBuildProjectFiles) = preSolution 38 | ..\..\node_modules\react-native-windows\JSI\Shared\JSI.Shared.vcxitems*{0cc28589-39e4-4288-b162-97b959f8b843}*SharedItemsImports = 9 39 | ..\..\node_modules\react-native-windows\Shared\Shared.vcxitems*{2049dbe9-8d13-42c9-ae4b-413ae38fffd0}*SharedItemsImports = 9 40 | ..\..\node_modules\react-native-windows\Mso\Mso.vcxitems*{84e05bfa-cbaf-4f0d-bfb6-4ce85742a57e}*SharedItemsImports = 9 41 | ..\..\node_modules\react-native-windows\JSI\Shared\JSI.Shared.vcxitems*{a62d504a-16b8-41d2-9f19-e2e86019e5e4}*SharedItemsImports = 4 42 | ..\..\node_modules\react-native-windows\Chakra\Chakra.vcxitems*{c38970c0-5fbf-4d69-90d8-cbac225ae895}*SharedItemsImports = 9 43 | ..\..\node_modules\react-native-windows\Microsoft.ReactNative.Cxx\Microsoft.ReactNative.Cxx.vcxitems*{da8b35b3-da00-4b02-bde6-6a397b3fd46b}*SharedItemsImports = 9 44 | ..\..\node_modules\react-native-windows\include\Include.vcxitems*{ef074ba1-2d54-4d49-a28e-5e040b47cd2e}*SharedItemsImports = 9 45 | ..\..\node_modules\react-native-windows\Chakra\Chakra.vcxitems*{f7d32bd0-2749-483e-9a0d-1635ef7e3136}*SharedItemsImports = 4 46 | ..\..\node_modules\react-native-windows\Microsoft.ReactNative.Cxx\Microsoft.ReactNative.Cxx.vcxitems*{f7d32bd0-2749-483e-9a0d-1635ef7e3136}*SharedItemsImports = 4 47 | ..\..\node_modules\react-native-windows\Mso\Mso.vcxitems*{f7d32bd0-2749-483e-9a0d-1635ef7e3136}*SharedItemsImports = 4 48 | ..\..\node_modules\react-native-windows\Shared\Shared.vcxitems*{f7d32bd0-2749-483e-9a0d-1635ef7e3136}*SharedItemsImports = 4 49 | EndGlobalSection 50 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 51 | Debug|ARM = Debug|ARM 52 | Debug|ARM64 = Debug|ARM64 53 | Debug|x64 = Debug|x64 54 | Debug|x86 = Debug|x86 55 | Release|ARM = Release|ARM 56 | Release|ARM64 = Release|ARM64 57 | Release|x64 = Release|x64 58 | Release|x86 = Release|x86 59 | EndGlobalSection 60 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 61 | {A09B9A47-E2B9-4294-9746-AC55213FC642}.Debug|ARM.ActiveCfg = Debug|ARM 62 | {A09B9A47-E2B9-4294-9746-AC55213FC642}.Debug|ARM.Build.0 = Debug|ARM 63 | {A09B9A47-E2B9-4294-9746-AC55213FC642}.Debug|ARM64.ActiveCfg = Debug|ARM64 64 | {A09B9A47-E2B9-4294-9746-AC55213FC642}.Debug|ARM64.Build.0 = Debug|ARM64 65 | {A09B9A47-E2B9-4294-9746-AC55213FC642}.Debug|x64.ActiveCfg = Debug|x64 66 | {A09B9A47-E2B9-4294-9746-AC55213FC642}.Debug|x64.Build.0 = Debug|x64 67 | {A09B9A47-E2B9-4294-9746-AC55213FC642}.Debug|x86.ActiveCfg = Debug|Win32 68 | {A09B9A47-E2B9-4294-9746-AC55213FC642}.Debug|x86.Build.0 = Debug|Win32 69 | {A09B9A47-E2B9-4294-9746-AC55213FC642}.Release|ARM.ActiveCfg = Release|ARM 70 | {A09B9A47-E2B9-4294-9746-AC55213FC642}.Release|ARM.Build.0 = Release|ARM 71 | {A09B9A47-E2B9-4294-9746-AC55213FC642}.Release|ARM64.ActiveCfg = Release|ARM64 72 | {A09B9A47-E2B9-4294-9746-AC55213FC642}.Release|ARM64.Build.0 = Release|ARM64 73 | {A09B9A47-E2B9-4294-9746-AC55213FC642}.Release|x64.ActiveCfg = Release|x64 74 | {A09B9A47-E2B9-4294-9746-AC55213FC642}.Release|x64.Build.0 = Release|x64 75 | {A09B9A47-E2B9-4294-9746-AC55213FC642}.Release|x86.ActiveCfg = Release|Win32 76 | {A09B9A47-E2B9-4294-9746-AC55213FC642}.Release|x86.Build.0 = Release|Win32 77 | {FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Debug|ARM.ActiveCfg = Debug|ARM 78 | {FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Debug|ARM.Build.0 = Debug|ARM 79 | {FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Debug|ARM64.ActiveCfg = Debug|ARM64 80 | {FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Debug|ARM64.Build.0 = Debug|ARM64 81 | {FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Debug|x64.ActiveCfg = Debug|x64 82 | {FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Debug|x64.Build.0 = Debug|x64 83 | {FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Debug|x86.ActiveCfg = Debug|Win32 84 | {FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Debug|x86.Build.0 = Debug|Win32 85 | {FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Release|ARM.ActiveCfg = Release|ARM 86 | {FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Release|ARM.Build.0 = Release|ARM 87 | {FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Release|ARM64.ActiveCfg = Release|ARM64 88 | {FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Release|ARM64.Build.0 = Release|ARM64 89 | {FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Release|x64.ActiveCfg = Release|x64 90 | {FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Release|x64.Build.0 = Release|x64 91 | {FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Release|x86.ActiveCfg = Release|Win32 92 | {FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Release|x86.Build.0 = Release|Win32 93 | {A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Debug|ARM.ActiveCfg = Debug|ARM 94 | {A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Debug|ARM.Build.0 = Debug|ARM 95 | {A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Debug|ARM64.ActiveCfg = Debug|ARM64 96 | {A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Debug|ARM64.Build.0 = Debug|ARM64 97 | {A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Debug|x64.ActiveCfg = Debug|x64 98 | {A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Debug|x64.Build.0 = Debug|x64 99 | {A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Debug|x86.ActiveCfg = Debug|Win32 100 | {A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Debug|x86.Build.0 = Debug|Win32 101 | {A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Release|ARM.ActiveCfg = Release|ARM 102 | {A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Release|ARM.Build.0 = Release|ARM 103 | {A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Release|ARM64.ActiveCfg = Release|ARM64 104 | {A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Release|ARM64.Build.0 = Release|ARM64 105 | {A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Release|x64.ActiveCfg = Release|x64 106 | {A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Release|x64.Build.0 = Release|x64 107 | {A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Release|x86.ActiveCfg = Release|Win32 108 | {A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Release|x86.Build.0 = Release|Win32 109 | {A62D504A-16B8-41D2-9F19-E2E86019E5E4}.Debug|ARM.ActiveCfg = Debug|ARM 110 | {A62D504A-16B8-41D2-9F19-E2E86019E5E4}.Debug|ARM.Build.0 = Debug|ARM 111 | {A62D504A-16B8-41D2-9F19-E2E86019E5E4}.Debug|ARM64.ActiveCfg = Debug|ARM64 112 | {A62D504A-16B8-41D2-9F19-E2E86019E5E4}.Debug|ARM64.Build.0 = Debug|ARM64 113 | {A62D504A-16B8-41D2-9F19-E2E86019E5E4}.Debug|x64.ActiveCfg = Debug|x64 114 | {A62D504A-16B8-41D2-9F19-E2E86019E5E4}.Debug|x64.Build.0 = Debug|x64 115 | {A62D504A-16B8-41D2-9F19-E2E86019E5E4}.Debug|x86.ActiveCfg = Debug|Win32 116 | {A62D504A-16B8-41D2-9F19-E2E86019E5E4}.Debug|x86.Build.0 = Debug|Win32 117 | {A62D504A-16B8-41D2-9F19-E2E86019E5E4}.Release|ARM.ActiveCfg = Release|ARM 118 | {A62D504A-16B8-41D2-9F19-E2E86019E5E4}.Release|ARM.Build.0 = Release|ARM 119 | {A62D504A-16B8-41D2-9F19-E2E86019E5E4}.Release|ARM64.ActiveCfg = Release|ARM64 120 | {A62D504A-16B8-41D2-9F19-E2E86019E5E4}.Release|ARM64.Build.0 = Release|ARM64 121 | {A62D504A-16B8-41D2-9F19-E2E86019E5E4}.Release|x64.ActiveCfg = Release|x64 122 | {A62D504A-16B8-41D2-9F19-E2E86019E5E4}.Release|x64.Build.0 = Release|x64 123 | {A62D504A-16B8-41D2-9F19-E2E86019E5E4}.Release|x86.ActiveCfg = Release|Win32 124 | {A62D504A-16B8-41D2-9F19-E2E86019E5E4}.Release|x86.Build.0 = Release|Win32 125 | {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Debug|ARM.ActiveCfg = Debug|ARM 126 | {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Debug|ARM.Build.0 = Debug|ARM 127 | {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Debug|ARM64.ActiveCfg = Debug|ARM64 128 | {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Debug|ARM64.Build.0 = Debug|ARM64 129 | {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Debug|x64.ActiveCfg = Debug|x64 130 | {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Debug|x64.Build.0 = Debug|x64 131 | {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Debug|x86.ActiveCfg = Debug|Win32 132 | {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Debug|x86.Build.0 = Debug|Win32 133 | {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Release|ARM.ActiveCfg = Release|ARM 134 | {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Release|ARM.Build.0 = Release|ARM 135 | {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Release|ARM64.ActiveCfg = Release|ARM64 136 | {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Release|ARM64.Build.0 = Release|ARM64 137 | {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Release|x64.ActiveCfg = Release|x64 138 | {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Release|x64.Build.0 = Release|x64 139 | {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Release|x86.ActiveCfg = Release|Win32 140 | {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Release|x86.Build.0 = Release|Win32 141 | {F2824844-CE15-4242-9420-308923CD76C3}.Debug|ARM.ActiveCfg = Debug|ARM 142 | {F2824844-CE15-4242-9420-308923CD76C3}.Debug|ARM.Build.0 = Debug|ARM 143 | {F2824844-CE15-4242-9420-308923CD76C3}.Debug|ARM64.ActiveCfg = Debug|ARM64 144 | {F2824844-CE15-4242-9420-308923CD76C3}.Debug|ARM64.Build.0 = Debug|ARM64 145 | {F2824844-CE15-4242-9420-308923CD76C3}.Debug|x64.ActiveCfg = Debug|x64 146 | {F2824844-CE15-4242-9420-308923CD76C3}.Debug|x64.Build.0 = Debug|x64 147 | {F2824844-CE15-4242-9420-308923CD76C3}.Debug|x86.ActiveCfg = Debug|x86 148 | {F2824844-CE15-4242-9420-308923CD76C3}.Debug|x86.Build.0 = Debug|x86 149 | {F2824844-CE15-4242-9420-308923CD76C3}.Release|ARM.ActiveCfg = Release|ARM 150 | {F2824844-CE15-4242-9420-308923CD76C3}.Release|ARM.Build.0 = Release|ARM 151 | {F2824844-CE15-4242-9420-308923CD76C3}.Release|ARM64.ActiveCfg = Release|ARM64 152 | {F2824844-CE15-4242-9420-308923CD76C3}.Release|ARM64.Build.0 = Release|ARM64 153 | {F2824844-CE15-4242-9420-308923CD76C3}.Release|x64.ActiveCfg = Release|x64 154 | {F2824844-CE15-4242-9420-308923CD76C3}.Release|x64.Build.0 = Release|x64 155 | {F2824844-CE15-4242-9420-308923CD76C3}.Release|x86.ActiveCfg = Release|x86 156 | {F2824844-CE15-4242-9420-308923CD76C3}.Release|x86.Build.0 = Release|x86 157 | {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Debug|ARM.ActiveCfg = Debug|ARM 158 | {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Debug|ARM.Build.0 = Debug|ARM 159 | {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Debug|ARM64.ActiveCfg = Debug|ARM64 160 | {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Debug|ARM64.Build.0 = Debug|ARM64 161 | {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Debug|x64.ActiveCfg = Debug|x64 162 | {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Debug|x64.Build.0 = Debug|x64 163 | {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Debug|x86.ActiveCfg = Debug|Win32 164 | {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Debug|x86.Build.0 = Debug|Win32 165 | {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Release|ARM.ActiveCfg = Release|ARM 166 | {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Release|ARM.Build.0 = Release|ARM 167 | {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Release|ARM64.ActiveCfg = Release|ARM64 168 | {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Release|ARM64.Build.0 = Release|ARM64 169 | {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Release|x64.ActiveCfg = Release|x64 170 | {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Release|x64.Build.0 = Release|x64 171 | {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Release|x86.ActiveCfg = Release|Win32 172 | {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Release|x86.Build.0 = Release|Win32 173 | {A07DDB04-9965-4EE5-963D-B31368B6E514}.Debug|ARM.ActiveCfg = Debug|ARM 174 | {A07DDB04-9965-4EE5-963D-B31368B6E514}.Debug|ARM.Build.0 = Debug|ARM 175 | {A07DDB04-9965-4EE5-963D-B31368B6E514}.Debug|ARM64.ActiveCfg = Debug|ARM64 176 | {A07DDB04-9965-4EE5-963D-B31368B6E514}.Debug|ARM64.Build.0 = Debug|ARM64 177 | {A07DDB04-9965-4EE5-963D-B31368B6E514}.Debug|x64.ActiveCfg = Debug|x64 178 | {A07DDB04-9965-4EE5-963D-B31368B6E514}.Debug|x64.Build.0 = Debug|x64 179 | {A07DDB04-9965-4EE5-963D-B31368B6E514}.Debug|x86.ActiveCfg = Debug|x86 180 | {A07DDB04-9965-4EE5-963D-B31368B6E514}.Debug|x86.Build.0 = Debug|x86 181 | {A07DDB04-9965-4EE5-963D-B31368B6E514}.Release|ARM.ActiveCfg = Release|ARM 182 | {A07DDB04-9965-4EE5-963D-B31368B6E514}.Release|ARM.Build.0 = Release|ARM 183 | {A07DDB04-9965-4EE5-963D-B31368B6E514}.Release|ARM64.ActiveCfg = Release|ARM64 184 | {A07DDB04-9965-4EE5-963D-B31368B6E514}.Release|ARM64.Build.0 = Release|ARM64 185 | {A07DDB04-9965-4EE5-963D-B31368B6E514}.Release|x64.ActiveCfg = Release|x64 186 | {A07DDB04-9965-4EE5-963D-B31368B6E514}.Release|x64.Build.0 = Release|x64 187 | {A07DDB04-9965-4EE5-963D-B31368B6E514}.Release|x86.ActiveCfg = Release|x86 188 | {A07DDB04-9965-4EE5-963D-B31368B6E514}.Release|x86.Build.0 = Release|x86 189 | EndGlobalSection 190 | GlobalSection(SolutionProperties) = preSolution 191 | HideSolutionNode = FALSE 192 | EndGlobalSection 193 | GlobalSection(NestedProjects) = preSolution 194 | {FCA38F3C-7C73-4C47-BE4E-32F77FA8538D} = {263BA2E9-6537-4141-A210-B082AE5DC2C4} 195 | {A990658C-CE31-4BCC-976F-0FC6B1AF693D} = {263BA2E9-6537-4141-A210-B082AE5DC2C4} 196 | {A62D504A-16B8-41D2-9F19-E2E86019E5E4} = {263BA2E9-6537-4141-A210-B082AE5DC2C4} 197 | {F7D32BD0-2749-483E-9A0D-1635EF7E3136} = {263BA2E9-6537-4141-A210-B082AE5DC2C4} 198 | {F2824844-CE15-4242-9420-308923CD76C3} = {263BA2E9-6537-4141-A210-B082AE5DC2C4} 199 | {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD} = {263BA2E9-6537-4141-A210-B082AE5DC2C4} 200 | {C38970C0-5FBF-4D69-90D8-CBAC225AE895} = {263BA2E9-6537-4141-A210-B082AE5DC2C4} 201 | {EF074BA1-2D54-4D49-A28E-5E040B47CD2E} = {263BA2E9-6537-4141-A210-B082AE5DC2C4} 202 | {0CC28589-39E4-4288-B162-97B959F8B843} = {263BA2E9-6537-4141-A210-B082AE5DC2C4} 203 | {DA8B35B3-DA00-4B02-BDE6-6A397B3FD46B} = {263BA2E9-6537-4141-A210-B082AE5DC2C4} 204 | {2049DBE9-8D13-42C9-AE4B-413AE38FFFD0} = {263BA2E9-6537-4141-A210-B082AE5DC2C4} 205 | {84E05BFA-CBAF-4F0D-BFB6-4CE85742A57E} = {263BA2E9-6537-4141-A210-B082AE5DC2C4} 206 | {A07DDB04-9965-4EE5-963D-B31368B6E514} = {263BA2E9-6537-4141-A210-B082AE5DC2C4} 207 | EndGlobalSection 208 | GlobalSection(ExtensibilityGlobals) = postSolution 209 | SolutionGuid = {B89B472F-7F21-49C0-B23D-4632A2651021} 210 | EndGlobalSection 211 | EndGlobal 212 | -------------------------------------------------------------------------------- /platforms/windows/SQLitePlugin/PropertySheet.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /platforms/windows/SQLitePlugin/ReactPackageProvider.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "ReactPackageProvider.h" 3 | #include "ReactPackageProvider.g.cpp" 4 | 5 | #include 6 | 7 | // NOTE: You must include the headers of your native modules here in 8 | // order for the AddAttributedModules call below to find them. 9 | #include "SQLitePlugin.h" 10 | 11 | namespace winrt::SQLitePlugin::implementation 12 | { 13 | void ReactPackageProvider::CreatePackage(IReactPackageBuilder const& packageBuilder) noexcept 14 | { 15 | AddAttributedModules(packageBuilder); 16 | } 17 | } -------------------------------------------------------------------------------- /platforms/windows/SQLitePlugin/ReactPackageProvider.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ReactPackageProvider.g.h" 4 | 5 | using namespace winrt::Microsoft::ReactNative; 6 | 7 | namespace winrt::SQLitePlugin::implementation 8 | { 9 | struct ReactPackageProvider : ReactPackageProviderT 10 | { 11 | ReactPackageProvider() = default; 12 | 13 | void CreatePackage(IReactPackageBuilder const& packageBuilder) noexcept; 14 | }; 15 | } 16 | 17 | namespace winrt::SQLitePlugin::factory_implementation 18 | { 19 | struct ReactPackageProvider : ReactPackageProviderT {}; 20 | } -------------------------------------------------------------------------------- /platforms/windows/SQLitePlugin/ReactPackageProvider.idl: -------------------------------------------------------------------------------- 1 | namespace SQLitePlugin 2 | { 3 | [webhosthidden] 4 | [default_interface] 5 | runtimeclass ReactPackageProvider : Microsoft.ReactNative.IReactPackageProvider 6 | { 7 | ReactPackageProvider(); 8 | }; 9 | } 10 | -------------------------------------------------------------------------------- /platforms/windows/SQLitePlugin/SQLitePlugin.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | 3 | #include "SQLitePlugin.h" 4 | 5 | using namespace winrt; 6 | using namespace winrt::Microsoft::ReactNative; 7 | using namespace winrt::Windows::Foundation; 8 | using namespace winrt::Windows::Storage; 9 | using namespace winrt::Windows::Storage::Streams; 10 | using namespace winrt::Windows::Security::Cryptography; 11 | 12 | namespace SQLitePlugin 13 | { 14 | void SQLitePlugin::Attach( 15 | DatabaseAttachOptions options, 16 | std::function onSuccess, 17 | std::function onFailure) noexcept 18 | { 19 | serialReactDispatcher.Post( 20 | [ 21 | options{ std::move(options) }, 22 | onSuccess{ std::move(onSuccess) }, 23 | onFailure{ std::move(onFailure) }, 24 | weak_this = std::weak_ptr(shared_from_this()) 25 | ]() 26 | { 27 | if (auto strongThis = weak_this.lock()) { 28 | 29 | if (options.MainDB == nullptr) 30 | { 31 | onFailure("You must specify a database to attach to"); 32 | return; 33 | } 34 | 35 | if (options.DBAlias == nullptr) 36 | { 37 | onFailure("You must specify a database alias to use"); 38 | return; 39 | } 40 | 41 | if (options.DBFileToAttach == nullptr) 42 | { 43 | onFailure("You must specify database to attach"); 44 | return; 45 | } 46 | 47 | hstring absoluteDbPath; 48 | absoluteDbPath = ResolveDbFilePath(to_hstring(options.MainDB)); 49 | 50 | if (strongThis->openDBs.find(absoluteDbPath) == strongThis->openDBs.end()) 51 | { 52 | onFailure("No such database, you must open it first"); 53 | return; 54 | } 55 | 56 | hstring absoluteDbPathToAttach; 57 | absoluteDbPathToAttach = ResolveDbFilePath(to_hstring(options.DBFileToAttach)); 58 | 59 | std::string statement = ("ATTACH DATABASE '" + to_string(absoluteDbPathToAttach) + "' AS " + options.DBAlias); 60 | 61 | sqlite3* dbHandle = strongThis->openDBs[absoluteDbPath]; 62 | 63 | if (sqlite3_exec(dbHandle, statement.c_str(), NULL, NULL, NULL) == SQLITE_OK) 64 | { 65 | onSuccess("Database successfully attached"); 66 | return; 67 | } 68 | else 69 | { 70 | const char* strPtr = sqlite3_errmsg(dbHandle); 71 | std::string errorMessage(strPtr, strlen(strPtr)); 72 | onFailure("Failed to attach database: " + errorMessage); 73 | return; 74 | } 75 | } 76 | }); 77 | } 78 | 79 | void SQLitePlugin::Close( 80 | DatabaseCloseOptions options, 81 | std::function onSuccess, 82 | std::function onFailure) noexcept 83 | { 84 | serialReactDispatcher.Post( 85 | [ 86 | options{ std::move(options) }, 87 | onSuccess{ std::move(onSuccess) }, 88 | onFailure{ std::move(onFailure) }, 89 | weak_this = std::weak_ptr(shared_from_this()) 90 | ]() 91 | { 92 | 93 | if (auto strongThis = weak_this.lock()) { 94 | 95 | if (options.Path == nullptr || options.Path.empty()) 96 | { 97 | onFailure("You must specify database path"); 98 | return; 99 | } 100 | 101 | hstring absoluteDbPath{ ResolveDbFilePath(to_hstring(options.Path)) }; 102 | 103 | if (CloseDatabaseIfOpen(absoluteDbPath, strongThis->openDBs)) 104 | { 105 | onSuccess("DB Closed"); 106 | } 107 | else 108 | { 109 | onFailure("Specified db was not open"); 110 | } 111 | } 112 | }); 113 | } 114 | 115 | SQLitePlugin::SQLitePlugin() {}; 116 | 117 | SQLitePlugin::~SQLitePlugin() { 118 | for (auto& db : openDBs) 119 | { 120 | sqlite3_close(db.second); 121 | } 122 | }; 123 | 124 | void SQLitePlugin::DeleteDB( 125 | DatabaseDeleteOptions options, 126 | std::function onSuccess, 127 | std::function onFailure) noexcept 128 | { 129 | serialReactDispatcher.Post( 130 | [ 131 | options{ std::move(options) }, 132 | onSuccess{ std::move(onSuccess) }, 133 | onFailure{ std::move(onFailure) }, 134 | weak_this = std::weak_ptr(shared_from_this()) 135 | ]() 136 | { 137 | if (auto strongThis = weak_this.lock()) 138 | { 139 | if (options.Path == nullptr || options.Path.empty()) 140 | { 141 | onFailure("You must specify database name"); 142 | return; 143 | } 144 | 145 | hstring absoluteDbPath{ ResolveDbFilePath(to_hstring(options.Path)) }; 146 | 147 | CloseDatabaseIfOpen(absoluteDbPath, strongThis->openDBs); 148 | 149 | try 150 | { 151 | StorageFile dbFile = StorageFile::GetFileFromPathAsync(absoluteDbPath).get(); 152 | dbFile.DeleteAsync().get(); 153 | } 154 | catch (winrt::hresult_error const& ex) 155 | { 156 | winrt::hstring message = ex.message(); 157 | std::string errorMessage = "Error deleting database: " + to_string(message) + " " + to_string(absoluteDbPath) + "\n"; 158 | onFailure(errorMessage); 159 | return; 160 | } 161 | 162 | onSuccess("Database Deleted"); 163 | } 164 | }); 165 | 166 | 167 | } 168 | 169 | void SQLitePlugin::EchoStringValue( 170 | EchoStringValueOptions options, 171 | std::function onSuccess, 172 | std::function onFailure) noexcept 173 | { 174 | serialReactDispatcher.Post( 175 | [ 176 | options{ std::move(options) }, 177 | onSuccess{ std::move(onSuccess) } 178 | ]() 179 | { 180 | onSuccess(options.Value); 181 | }); 182 | } 183 | 184 | void SQLitePlugin::ExecuteSqlBatch( 185 | ExecuteSqlBatchOptions options, 186 | std::function)> onSuccess, 187 | std::function onFailure) noexcept 188 | { 189 | serialReactDispatcher.Post( 190 | [ 191 | options{ std::move(options) }, 192 | onSuccess{ std::move(onSuccess) }, 193 | onFailure{ std::move(onFailure) }, 194 | weak_this = std::weak_ptr(shared_from_this()) 195 | ]() 196 | { 197 | if (auto strongThis = weak_this.lock()) { 198 | if (options.DBArgs.DBName == nullptr) 199 | { 200 | onFailure("You must specify database path"); 201 | return; 202 | } 203 | 204 | hstring absoluteDbPath; 205 | absoluteDbPath = ResolveDbFilePath(to_hstring(options.DBArgs.DBName)); 206 | 207 | if (strongThis->openDBs.find(absoluteDbPath) == strongThis->openDBs.end()) 208 | { 209 | onFailure("No such database, you must open it first"); 210 | return; 211 | } 212 | 213 | sqlite3* dbHandle = strongThis->openDBs[absoluteDbPath]; 214 | std::vector results; 215 | 216 | for (auto& query : options.Executes) 217 | { 218 | JSValue result; 219 | if (ExecuteQuery(dbHandle, query, result)) 220 | { 221 | // Query succeeded 222 | results.push_back( 223 | { 224 | { "qid", query.QID }, 225 | { "type", "success" }, 226 | { "result", std::move(result)} 227 | } 228 | ); 229 | } 230 | else 231 | { 232 | // Query failed 233 | results.push_back( 234 | { 235 | { "qid", query.QID }, 236 | { "type", "error" }, 237 | { "error", result.AsString()}, 238 | { "result", result.AsString()} 239 | } 240 | ); 241 | } 242 | } 243 | onSuccess(std::move(results)); 244 | } 245 | }); 246 | } 247 | 248 | void SQLitePlugin::Open( 249 | DatabaseOpenOptions options, 250 | std::function onSuccess, 251 | std::function onFailure) noexcept 252 | { 253 | serialReactDispatcher.Post( 254 | [ 255 | options{ std::move(options) }, 256 | onSuccess{ std::move(onSuccess) }, 257 | onFailure{ std::move(onFailure) }, 258 | weak_this = std::weak_ptr(shared_from_this()) 259 | ]() 260 | { 261 | if (auto strongThis = weak_this.lock()) { 262 | const std::string* dbFileName = &options.Name; 263 | 264 | if (dbFileName == nullptr || dbFileName->empty()) 265 | { 266 | onFailure("You must specify the database name"); 267 | return; 268 | } 269 | 270 | hstring absoluteDbPath{ ResolveDbFilePath(to_hstring(*dbFileName)) }; 271 | 272 | if (strongThis->openDBs.find(absoluteDbPath) != strongThis->openDBs.end()) 273 | { 274 | onSuccess("Database opened"); 275 | return; 276 | } 277 | 278 | IAsyncOperation assetFileOp = ResolveAssetFile(options.AssetFileName, *dbFileName); 279 | StorageFile assetFile = nullptr; 280 | if (assetFileOp != nullptr) 281 | { 282 | try 283 | { 284 | assetFile = assetFileOp.get(); 285 | } 286 | catch (hresult_error const& ex) 287 | { 288 | onFailure("Unable to open asset file: " + winrt::to_string(ex.message())); 289 | return; 290 | } 291 | } 292 | 293 | int openFlags{ 0 }; 294 | openFlags |= SQLITE_OPEN_NOMUTEX; 295 | 296 | if (options.ReadOnly && assetFileOp != nullptr) 297 | { 298 | openFlags |= SQLITE_OPEN_READONLY; 299 | absoluteDbPath = assetFile.Path(); 300 | } 301 | else 302 | { 303 | openFlags |= SQLITE_OPEN_READWRITE; 304 | openFlags |= SQLITE_OPEN_CREATE; 305 | 306 | if (assetFileOp != nullptr) 307 | { 308 | try 309 | { 310 | CopyDbAsync(assetFile, to_hstring(*dbFileName)).GetResults(); 311 | } 312 | catch (hresult_error const& ex) 313 | { 314 | // CopyDbAsync throws when the file already exists. 315 | onFailure("Unable to copy asset file: " + winrt::to_string(ex.message())); 316 | return; 317 | } 318 | } 319 | } 320 | 321 | sqlite3* dbHandle = nullptr; 322 | 323 | int result = sqlite3_open_v2(to_string(absoluteDbPath).c_str(), &dbHandle, openFlags, nullptr); 324 | if (result == SQLITE_OK) 325 | { 326 | strongThis->openDBs[absoluteDbPath] = dbHandle; 327 | onSuccess("Database opened"); 328 | } 329 | else 330 | { 331 | onFailure("Unable to open DB"); 332 | } 333 | } 334 | }); 335 | 336 | } 337 | 338 | 339 | void SQLitePlugin::BindStatement(sqlite3_stmt* stmt_ptr, int argIndex, const JSValue& arg) 340 | { 341 | switch (arg.Type()) 342 | { 343 | case JSValueType::Null: 344 | sqlite3_bind_null(stmt_ptr, argIndex); 345 | break; 346 | case JSValueType::Boolean: 347 | sqlite3_bind_int(stmt_ptr, argIndex, arg.AsBoolean()); 348 | break; 349 | case JSValueType::Int64: 350 | sqlite3_bind_int64(stmt_ptr, argIndex, arg.AsInt64()); 351 | break; 352 | case JSValueType::Double: 353 | sqlite3_bind_double(stmt_ptr, argIndex, arg.AsDouble()); 354 | break; 355 | case JSValueType::String: 356 | sqlite3_bind_text(stmt_ptr, argIndex, arg.AsString().c_str(), -1, SQLITE_TRANSIENT); 357 | break; 358 | default: 359 | sqlite3_bind_text(stmt_ptr, argIndex, arg.AsString().c_str(), -1, SQLITE_TRANSIENT); 360 | break; 361 | } 362 | } 363 | 364 | bool SQLitePlugin::CloseDatabaseIfOpen(const hstring& absoluteDbPath, std::map& openDBs) 365 | { 366 | if (openDBs.find(absoluteDbPath) != openDBs.end()) 367 | { 368 | sqlite3* dbHandle = openDBs[absoluteDbPath]; 369 | 370 | if (sqlite3_close(dbHandle) != SQLITE_OK) 371 | { 372 | std::string debugMessage = "SQLitePluginModule: Error closing database: " + to_string(absoluteDbPath) + "\n"; 373 | OutputDebugStringA(debugMessage.c_str()); 374 | } 375 | 376 | openDBs.erase(absoluteDbPath); 377 | return true; 378 | } 379 | return false; 380 | } 381 | 382 | IAsyncOperation SQLitePlugin::CopyDbAsync(const StorageFile& srcDbFile, const hstring& destDbFileName) 383 | { 384 | // This implementation is closely related to ResolveDbFilePath. 385 | return srcDbFile.CopyAsync(ApplicationData::Current().LocalFolder(), destDbFileName, NameCollisionOption::FailIfExists); 386 | } 387 | 388 | bool SQLitePlugin::ExecuteQuery(sqlite3* dbHandle, const DBQuery& query, JSValue& result) 389 | { 390 | if (query.SQL == nullptr || query.SQL == "") 391 | { 392 | result = JSValue{ "You must specify a sql query to execute" }; 393 | return false; 394 | } 395 | 396 | int previousRowsAffected = sqlite3_total_changes(dbHandle); 397 | sqlite3_stmt* stmt; 398 | int prepResult = sqlite3_prepare_v2(dbHandle, query.SQL.c_str(), -1, &stmt, nullptr); 399 | 400 | if (prepResult != SQLITE_OK) 401 | { 402 | result = JSValue{ sqlite3_errmsg(dbHandle) }; 403 | return false; 404 | } 405 | 406 | if (!query.Params.empty()) 407 | { 408 | // sqlite bind uses 1-based indexing for the arguments 409 | int argIndex = 1; 410 | for (auto& arg : query.Params) 411 | { 412 | BindStatement(stmt, argIndex, arg); 413 | argIndex++; 414 | } 415 | } 416 | 417 | std::vector resultRows{}; 418 | 419 | bool keepGoing = true; 420 | int rowsAffected = 0; 421 | sqlite3_int64 insertId = 0; 422 | bool isError = false; 423 | 424 | while (keepGoing) 425 | { 426 | switch (sqlite3_step(stmt)) 427 | { 428 | case SQLITE_ROW: 429 | resultRows.push_back(ExtractRow(stmt)); 430 | break; 431 | 432 | case SQLITE_DONE: 433 | { 434 | int currentRowsAffected = sqlite3_total_changes(dbHandle); 435 | rowsAffected = currentRowsAffected - previousRowsAffected; 436 | sqlite3_int64 currentInsertId = sqlite3_last_insert_rowid(dbHandle); 437 | if (rowsAffected > 0 && currentInsertId != 0) 438 | { 439 | insertId = currentInsertId; 440 | } 441 | keepGoing = false; 442 | break; 443 | } 444 | default: 445 | { 446 | const char* strPtr = sqlite3_errmsg(dbHandle); 447 | std::string errorMessage(strPtr, strlen(strPtr)); 448 | result = JSValue{ errorMessage }; 449 | keepGoing = false; 450 | isError = true; 451 | } 452 | break; 453 | } 454 | } 455 | 456 | sqlite3_finalize(stmt); 457 | 458 | if (isError) 459 | { 460 | return false; 461 | } 462 | 463 | JSValueObject resultSet = 464 | { 465 | { "rows", std::move(resultRows) }, 466 | { "rowsAffected", rowsAffected } 467 | }; 468 | 469 | if (insertId != 0) 470 | { 471 | resultSet["insertId"] = insertId; 472 | } 473 | 474 | result = JSValue(std::move(resultSet)); 475 | return true; 476 | } 477 | 478 | JSValue SQLitePlugin::ExtractColumn(sqlite3_stmt* stmt, int columnIndex) 479 | { 480 | switch (sqlite3_column_type(stmt, columnIndex)) 481 | { 482 | case SQLITE_INTEGER: 483 | return sqlite3_column_int64(stmt, columnIndex); 484 | case SQLITE_FLOAT: 485 | return sqlite3_column_double(stmt, columnIndex); 486 | case SQLITE_TEXT: 487 | { 488 | const char* strPtr = (char*)sqlite3_column_text(stmt, columnIndex); 489 | return std::string(strPtr, strlen(strPtr)); 490 | } 491 | case SQLITE_BLOB: 492 | { 493 | // JSON does not support raw binary data. You can't write a binary blob using this module 494 | // In case we have a pre-populated database with a binary blob in it, 495 | // we are going to base64 encode it and return as a string. 496 | // This is consistent with iOS implementation. 497 | const void* ptr = sqlite3_column_blob(stmt, columnIndex); 498 | int length = sqlite3_column_bytes(stmt, columnIndex); 499 | Buffer buffer = Buffer(length); 500 | memcpy(buffer.data(), ptr, length); 501 | return to_string(CryptographicBuffer::EncodeToBase64String(buffer)); 502 | } 503 | case SQLITE_NULL: 504 | default: 505 | return nullptr; 506 | break; 507 | } 508 | } 509 | 510 | JSValueObject SQLitePlugin::ExtractRow(sqlite3_stmt* stmt) 511 | { 512 | JSValueObject row{}; 513 | int columnCount = sqlite3_column_count(stmt); 514 | for (int i = 0; i < columnCount; i++) 515 | { 516 | const char* strPtr = (char*)sqlite3_column_name(stmt, i); 517 | std::string columnName(strPtr, strlen(strPtr)); 518 | JSValue columnValue = ExtractColumn(stmt, i); 519 | if (!columnValue.IsNull()) 520 | { 521 | row[columnName] = std::move(columnValue); 522 | } 523 | } 524 | return row; 525 | } 526 | 527 | IAsyncOperation SQLitePlugin::ResolveAssetFile(const std::string& assetFilePath, const std::string& dbFileName) 528 | { 529 | if (assetFilePath == nullptr || assetFilePath.length() == 0) 530 | { 531 | return nullptr; 532 | } 533 | else if (assetFilePath == "1") 534 | { 535 | // Build a path to the pre-populated DB asset from app bundle www subdirectory 536 | return StorageFile::GetFileFromApplicationUriAsync(Uri( 537 | L"ms-appx:///www/" + winrt::to_hstring(dbFileName))); 538 | } 539 | else if (assetFilePath[0] == '~') 540 | { 541 | // Build a path to the pre-populated DB asset from app bundle subdirectory 542 | return StorageFile::GetFileFromApplicationUriAsync(Uri( 543 | L"ms-appx:///" + winrt::to_hstring(assetFilePath.substr(1)))); 544 | } 545 | else 546 | { 547 | // Build a path to the pre-populated DB asset from app sandbox directory 548 | return StorageFile::GetFileFromApplicationUriAsync(Uri( 549 | L"ms-appdata:///local/" + winrt::to_hstring(assetFilePath))); 550 | } 551 | } 552 | 553 | hstring SQLitePlugin::ResolveDbFilePath(const hstring dbFileName) 554 | { 555 | return ApplicationData::Current().LocalFolder().Path() + L"\\" + dbFileName; 556 | } 557 | } 558 | -------------------------------------------------------------------------------- /platforms/windows/SQLitePlugin/SQLitePlugin.def: -------------------------------------------------------------------------------- 1 | EXPORTS 2 | DllCanUnloadNow = WINRT_CanUnloadNow PRIVATE 3 | DllGetActivationFactory = WINRT_GetActivationFactory PRIVATE 4 | -------------------------------------------------------------------------------- /platforms/windows/SQLitePlugin/SQLitePlugin.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "pch.h" 4 | 5 | using namespace winrt; 6 | using namespace winrt::Microsoft::ReactNative; 7 | using namespace winrt::Windows::Storage; 8 | 9 | namespace SQLitePlugin 10 | { 11 | /* 12 | * SQLite Plugin for React Native. 13 | * 14 | * As of now, it supports callbacks only. 15 | * All operations on the database have to be serialized to avoid race conditions. 16 | * Each operation posts a task to SerialReactDispatcher 17 | * which executes them sequentially in the background. 18 | */ 19 | 20 | REACT_STRUCT(DatabaseAttachOptions); 21 | struct DatabaseAttachOptions 22 | { 23 | REACT_FIELD(MainDB, L"path"); 24 | // path to current database instance 25 | std::string MainDB; 26 | 27 | REACT_FIELD(DBAlias, L"dbAlias"); 28 | // the Alias that should be use with ATTACH DATABASE 29 | std::string DBAlias; 30 | 31 | REACT_FIELD(DBFileToAttach, L"dbName"); 32 | // dbName that should be attached to MainDB 33 | std::string DBFileToAttach; 34 | }; 35 | 36 | REACT_STRUCT(DatabaseCloseOptions); 37 | struct DatabaseCloseOptions 38 | { 39 | REACT_FIELD(Path, L"path"); 40 | // Path at which the database is located 41 | std::string Path; 42 | }; 43 | 44 | REACT_STRUCT(DatabaseDeleteOptions); 45 | struct DatabaseDeleteOptions 46 | { 47 | REACT_FIELD(Path, L"path"); 48 | // Path at which the database is located 49 | std::string Path; 50 | }; 51 | 52 | REACT_STRUCT(DatabaseOpenOptions); 53 | struct DatabaseOpenOptions 54 | { 55 | REACT_FIELD(Name, L"name"); 56 | // Path at which to store the database 57 | std::string Name; 58 | 59 | REACT_FIELD(AssetFileName, L"assetFilename"); 60 | // Optional. When creating the DB, uses this file as the initial state. 61 | std::string AssetFileName; 62 | 63 | REACT_FIELD(ReadOnly, L"readOnly"); 64 | bool ReadOnly = false; 65 | }; 66 | 67 | REACT_STRUCT(DBArgs); 68 | struct DBArgs 69 | { 70 | REACT_FIELD(DBName, L"dbname"); 71 | std::string DBName; 72 | }; 73 | 74 | REACT_STRUCT(DBQuery); 75 | struct DBQuery 76 | { 77 | REACT_FIELD(QID, L"qid"); 78 | int QID = 0; 79 | 80 | REACT_FIELD(Params, L"params"); 81 | JSValueArray Params; // optional 82 | 83 | REACT_FIELD(SQL, L"sql"); 84 | std::string SQL; 85 | }; 86 | 87 | REACT_STRUCT(EchoStringValueOptions); 88 | struct EchoStringValueOptions 89 | { 90 | REACT_FIELD(Value, L"value"); 91 | std::string Value; 92 | }; 93 | 94 | REACT_STRUCT(ExecuteSqlBatchOptions); 95 | struct ExecuteSqlBatchOptions 96 | { 97 | REACT_FIELD(DBArgs, L"dbargs"); 98 | DBArgs DBArgs; 99 | REACT_FIELD(Executes, L"executes"); 100 | std::vector Executes; 101 | }; 102 | 103 | REACT_MODULE(SQLitePlugin, L"SQLite"); 104 | struct SQLitePlugin : std::enable_shared_from_this 105 | { 106 | public: 107 | REACT_METHOD(Attach, L"attach"); 108 | void Attach( 109 | DatabaseAttachOptions options, 110 | std::function onSuccess, 111 | std::function onFailure) noexcept; 112 | 113 | REACT_METHOD(Close, L"close"); 114 | void Close( 115 | DatabaseCloseOptions options, 116 | std::function onSuccess, 117 | std::function onFailure) noexcept; 118 | 119 | REACT_METHOD(DeleteDB, L"delete"); 120 | void DeleteDB( 121 | DatabaseDeleteOptions options, 122 | std::function onSuccess, 123 | std::function onFailure) noexcept; 124 | 125 | REACT_METHOD(EchoStringValue, L"echoStringValue"); 126 | void EchoStringValue( 127 | EchoStringValueOptions options, 128 | std::function onSuccess, 129 | std::function onFailure) noexcept; 130 | 131 | REACT_METHOD(ExecuteSqlBatch, L"executeSqlBatch"); 132 | REACT_METHOD(ExecuteSqlBatch, L"backgroundExecuteSqlBatch"); 133 | void ExecuteSqlBatch( 134 | ExecuteSqlBatchOptions options, 135 | std::function)> onSuccess, 136 | std::function onFailure) noexcept; 137 | 138 | REACT_METHOD(Open, L"open"); 139 | void Open( 140 | DatabaseOpenOptions options, 141 | std::function onSuccess, 142 | std::function onFailure) noexcept; 143 | 144 | SQLitePlugin::SQLitePlugin(); 145 | SQLitePlugin::~SQLitePlugin(); 146 | 147 | private: 148 | std::map openDBs; 149 | ReactDispatcher serialReactDispatcher{ ReactDispatcher::CreateSerialDispatcher() }; 150 | 151 | static void BindStatement(sqlite3_stmt* stmt_ptr, int argIndex, const JSValue& arg); 152 | static bool CloseDatabaseIfOpen(const hstring& absoluteDbPath, std::map& openDBs); 153 | static IAsyncOperation CopyDbAsync(const StorageFile& srcDbFile, const hstring& destDbFileName); 154 | static bool ExecuteQuery(sqlite3* db, const DBQuery& query, JSValue& result); 155 | static JSValue ExtractColumn(sqlite3_stmt* stmt, int columnIndex); 156 | static JSValueObject ExtractRow(sqlite3_stmt* stmt); 157 | static IAsyncOperation ResolveAssetFile(const std::string& assetFilePath, const std::string& dbFileName); 158 | static hstring ResolveDbFilePath(const hstring dbFileName); 159 | }; 160 | } 161 | -------------------------------------------------------------------------------- /platforms/windows/SQLitePlugin/SQLitePlugin.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | true 6 | true 7 | true 8 | true 9 | {a09b9a47-e2b9-4294-9746-ac55213fc642} 10 | SQLitePlugin 11 | SQLitePlugin 12 | en-US 13 | 14.0 14 | true 15 | Windows Store 16 | 10.0 17 | 10.0.18362.0 18 | 10.0.16299.0 19 | 20 | 21 | 22 | 23 | Debug 24 | ARM 25 | 26 | 27 | Debug 28 | ARM64 29 | 30 | 31 | Debug 32 | Win32 33 | 34 | 35 | Debug 36 | x64 37 | 38 | 39 | Release 40 | ARM 41 | 42 | 43 | Release 44 | ARM64 45 | 46 | 47 | Release 48 | Win32 49 | 50 | 51 | Release 52 | x64 53 | 54 | 55 | 56 | DynamicLibrary 57 | v140 58 | v141 59 | v142 60 | Unicode 61 | false 62 | 63 | 64 | true 65 | true 66 | 67 | 68 | false 69 | true 70 | false 71 | 72 | 73 | 74 | $([MSBuild]::GetDirectoryNameOfFileAbove($(SolutionDir), 'node_modules\react-native-windows\package.json'))\node_modules\react-native-windows\ 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | Use 94 | pch.h 95 | $(IntDir)pch.pch 96 | Level4 97 | %(AdditionalOptions) /bigobj 98 | 99 | /DWINRT_NO_MAKE_DETECTION %(AdditionalOptions) 100 | 101 | 102 | _WINRT_DLL;WIN32_LEAN_AND_MEAN;WINRT_LEAN_AND_MEAN;%(PreprocessorDefinitions) 103 | $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) 104 | 105 | 106 | Console 107 | true 108 | SQLitePlugin.def 109 | 110 | 111 | 112 | 113 | _DEBUG;%(PreprocessorDefinitions) 114 | 115 | 116 | winsqlite3.lib;%(AdditionalDependencies) 117 | 118 | 119 | winsqlite3.lib;%(AdditionalDependencies) 120 | 121 | 122 | winsqlite3.lib;%(AdditionalDependencies) 123 | 124 | 125 | winsqlite3.lib;%(AdditionalDependencies) 126 | 127 | 128 | 129 | 130 | NDEBUG;%(PreprocessorDefinitions) 131 | 132 | 133 | true 134 | true 135 | winsqlite3.lib;%(AdditionalDependencies) 136 | winsqlite3.lib;%(AdditionalDependencies) 137 | winsqlite3.lib;%(AdditionalDependencies) 138 | winsqlite3.lib;%(AdditionalDependencies) 139 | 140 | 141 | 142 | 143 | 144 | ReactPackageProvider.idl 145 | 146 | 147 | 148 | 149 | 150 | Create 151 | 152 | 153 | ReactPackageProvider.idl 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | This project references targets in your node_modules\react-native-windows folder that are missing. The missing file is {0}. 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. 185 | 186 | 187 | 188 | 189 | -------------------------------------------------------------------------------- /platforms/windows/SQLitePlugin/SQLitePlugin.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | accd3aa8-1ba0-4223-9bbe-0c431709210b 6 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tga;tiff;tif;png;wav;mfcribbon-ms 7 | 8 | 9 | {926ab91d-31b4-48c3-b9a4-e681349f27f0} 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /platforms/windows/SQLitePlugin/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /platforms/windows/SQLitePlugin/pch.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | -------------------------------------------------------------------------------- /platforms/windows/SQLitePlugin/pch.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "JSValue.h" 12 | #include "NativeModules.h" -------------------------------------------------------------------------------- /react-native-sqlite-storage.podspec: -------------------------------------------------------------------------------- 1 | require 'json' 2 | 3 | package = JSON.parse(File.read(File.join(__dir__, 'package.json'))) 4 | 5 | Pod::Spec.new do |s| 6 | s.name = "react-native-sqlite-storage" 7 | s.version = package['version'] 8 | s.summary = package['description'] 9 | s.homepage = "https://github.com/andpor/react-native-sqlite-storage" 10 | s.license = package['license'] 11 | s.author = package['author'] 12 | s.source = { :git => "https://github.com/andpor/react-native-sqlite-storage.git", :tag => "#{s.version}" } 13 | 14 | s.ios.deployment_target = '8.0' 15 | s.osx.deployment_target = '10.10' 16 | 17 | s.preserve_paths = 'README.md', 'LICENSE', 'package.json', 'sqlite.js' 18 | s.source_files = "platforms/ios/*.{h,m}" 19 | 20 | s.dependency 'React-Core' 21 | s.library = 'sqlite3' 22 | end 23 | -------------------------------------------------------------------------------- /react-native.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | dependency: { 3 | platforms: { 4 | ios: { 5 | project: './platforms/ios/SQLite.xcodeproj' 6 | }, 7 | android: { 8 | sourceDir: './platforms/android' 9 | }, 10 | windows: { 11 | sourceDir: './platforms/windows', 12 | solutionFile: 'SQLitePlugin.sln', 13 | projects: [ 14 | { 15 | projectFile: 'SQLitePlugin/SQLitePlugin.vcxproj', 16 | directDependency: true, 17 | } 18 | ], 19 | } 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /sqlite.js: -------------------------------------------------------------------------------- 1 | /* 2 | * sqlite.js 3 | * 4 | * Created by Andrzej Porebski on 10/29/15. 5 | * Copyright (c) 2015-16 Andrzej Porebski. 6 | * 7 | * This library is available under the terms of the MIT License (2008). 8 | * See http://opensource.org/licenses/alphabetical for full text. 9 | */ 10 | var plugin = require('./lib/sqlite.core.js'); 11 | var {SQLiteFactory} = plugin; 12 | 13 | var config = [ 14 | 15 | // meaning: [returnValueExpected,prototype,fn,argsNeedPadding,reverseCallbacks,rejectOnError] 16 | 17 | [false,"SQLitePlugin","transaction",false,true,true], 18 | [false,"SQLitePlugin","readTransaction",false,true,true], 19 | [false,"SQLitePlugin","close",false,false,true], 20 | [false,"SQLitePlugin","executeSql",true,false,true], 21 | [false,"SQLitePlugin","sqlBatch",false,false,true], 22 | [false,"SQLitePlugin","attach",true,false,true], 23 | [false,"SQLitePlugin","detach",false,false,true], 24 | [false,"SQLitePluginTransaction","executeSql",true,false,false], 25 | [false,"SQLiteFactory","deleteDatabase",false,false,true], 26 | [true, "SQLiteFactory","openDatabase",false,false,true], 27 | [false,"SQLiteFactory","echoTest",false,false,true] 28 | ]; 29 | 30 | var originalFns = {}; 31 | config.forEach(entry => { 32 | let [returnValueExpected,prototype,fn]= entry; 33 | let originalFn = plugin[prototype].prototype[fn]; 34 | originalFns[prototype + "." + fn] = originalFn; 35 | }); 36 | 37 | function enablePromiseRuntime(enable){ 38 | if (enable){ 39 | createPromiseRuntime(); 40 | } else { 41 | createCallbackRuntime(); 42 | } 43 | } 44 | function createCallbackRuntime() { 45 | config.forEach(entry => { 46 | let [returnValueExpected,prototype,fn,argsNeedPadding,reverseCallbacks,rejectOnError]= entry; 47 | plugin[prototype].prototype[fn] = originalFns[prototype + "." + fn]; 48 | }); 49 | plugin.log("Callback based runtime ready"); 50 | } 51 | function createPromiseRuntime() { 52 | config.forEach(entry => { 53 | let [returnValueExpected,prototype,fn,argsNeedPadding,reverseCallbacks,rejectOnError]= entry; 54 | let originalFn = plugin[prototype].prototype[fn]; 55 | plugin[prototype].prototype[fn] = function(...args){ 56 | if (argsNeedPadding && args.length == 1){ 57 | args.push([]); 58 | } 59 | var promise = new Promise((resolve,reject) => { 60 | let success = function(...args){ 61 | if (!returnValueExpected) { 62 | return resolve(args); 63 | } 64 | }; 65 | let error = function(err){ 66 | plugin.log('error: ',fn,...args,arguments); 67 | if (rejectOnError) { 68 | reject(err); 69 | } 70 | return false; 71 | }; 72 | var retValue = originalFn.call(this,...args,reverseCallbacks ? error : success, reverseCallbacks ? success : error); 73 | if (returnValueExpected){ 74 | return resolve(retValue); 75 | } 76 | }); 77 | 78 | return promise; 79 | } 80 | }); 81 | plugin.log("Promise based runtime ready"); 82 | } 83 | SQLiteFactory.prototype.enablePromise = enablePromiseRuntime; 84 | 85 | module.exports = new SQLiteFactory(); 86 | -------------------------------------------------------------------------------- /test/index.android.json1.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Test App using JSON1 functionality for react-native-sqlite-storage 3 | * 4 | * This library is available under the terms of the MIT License (2008). 5 | * See http://opensource.org/licenses/alphabetical for full text. 6 | */ 7 | 'use strict'; 8 | 9 | import React, { Component } from 'react'; 10 | import { 11 | AppRegistry, 12 | StyleSheet, 13 | Text, 14 | View, 15 | } from 'react-native'; 16 | import ListView from 'deprecated-react-native-listview'; 17 | 18 | import SQLite from 'react-native-sqlite-storage'; 19 | SQLite.DEBUG(true); 20 | SQLite.enablePromise(false); 21 | 22 | const database_name = "Test.db"; 23 | const database_version = "1.0"; 24 | const database_displayname = "SQLite Test Database"; 25 | const database_size = 200000; 26 | let db; 27 | 28 | class SQLiteDemo extends Component { 29 | constructor() { 30 | super(); 31 | this.progress = []; 32 | this.state = { 33 | progress: [], 34 | ds: new ListView.DataSource({ 35 | rowHasChanged: (r1, r2) => r1 !== r2} 36 | ) 37 | }; 38 | } 39 | 40 | updateProgress = (text, resetState) => { 41 | let progress = []; 42 | if (!resetState) { 43 | progress = [...this.progress]; 44 | } 45 | progress.push(text); 46 | this.progress = progress; 47 | this.setState({ 48 | progress 49 | }); 50 | }; 51 | 52 | componentWillUnmount = () => { 53 | this.closeDatabase(); 54 | }; 55 | 56 | errorCB = (err) => { 57 | console.log("error: ",err); 58 | this.updateProgress("Error: "+ (err.message || err)); 59 | return false; 60 | }; 61 | 62 | successCB = () => { 63 | console.log("SQL executed ..."); 64 | }; 65 | 66 | openCB = () => { 67 | this.updateProgress("Database OPEN"); 68 | }; 69 | 70 | closeCB = () => { 71 | this.updateProgress("Database CLOSED"); 72 | }; 73 | 74 | deleteCB = () => { 75 | console.log("Database DELETED"); 76 | this.updateProgress("Database DELETED"); 77 | }; 78 | 79 | populateDatabase = (db) => { 80 | this.updateProgress("Database integrity check"); 81 | db.executeSql('SELECT 1 FROM Version LIMIT 1', [], 82 | () => { 83 | this.updateProgress("Database is ready ... executing query ..."); 84 | db.transaction(this.queryEmployees,this.errorCB,() => { 85 | this.updateProgress("Processing completed"); 86 | }); 87 | }, 88 | (error) => { 89 | console.log("received version error:", error); 90 | this.updateProgress("Database not yet ready ... populating data"); 91 | db.transaction(this.populateDB, this.errorCB, () => { 92 | this.updateProgress("Database populated ... executing query ..."); 93 | db.transaction(this.queryEmployees,this.errorCB, () => { 94 | console.log("Transaction is now finished"); 95 | this.updateProgress("Processing completed"); 96 | this.closeDatabase(); 97 | }); 98 | }); 99 | }); 100 | }; 101 | 102 | populateDB = (tx) => { 103 | this.updateProgress("Executing DROP stmts"); 104 | 105 | tx.executeSql('DROP TABLE IF EXISTS Employees;'); 106 | tx.executeSql('DROP TABLE IF EXISTS Offices;'); 107 | tx.executeSql('DROP TABLE IF EXISTS Departments;'); 108 | 109 | this.updateProgress("Executing CREATE stmts"); 110 | 111 | tx.executeSql('CREATE TABLE IF NOT EXISTS Version( ' 112 | + 'version_id INTEGER PRIMARY KEY NOT NULL); ', [], this.successCB, this.errorCB); 113 | 114 | tx.executeSql('CREATE TABLE IF NOT EXISTS Departments( ' 115 | + 'department_id INTEGER PRIMARY KEY NOT NULL, ' 116 | + 'name VARCHAR(30) ); ', [], this.successCB, this.errorCB); 117 | 118 | tx.executeSql('CREATE TABLE IF NOT EXISTS Offices( ' 119 | + 'office_id INTEGER PRIMARY KEY NOT NULL, ' 120 | + 'name VARCHAR(20), ' 121 | + 'longtitude FLOAT, ' 122 | + 'latitude FLOAT ) ; ', [], this.successCB, this.errorCB); 123 | 124 | tx.executeSql('CREATE TABLE IF NOT EXISTS Employees( ' 125 | + 'employe_id INTEGER PRIMARY KEY NOT NULL, ' 126 | + 'name VARCHAR(55), ' 127 | + 'office INTEGER, ' 128 | + 'department INTEGER, ' 129 | + 'custom_info TEXT DEFAULT "",' 130 | + 'FOREIGN KEY ( office ) REFERENCES Offices ( office_id ) ' 131 | + 'FOREIGN KEY ( department ) REFERENCES Departments ( department_id ));', []); 132 | 133 | this.updateProgress("Executing INSERT stmts"); 134 | 135 | tx.executeSql('INSERT INTO Departments (name) VALUES ("Client Services");', []); 136 | tx.executeSql('INSERT INTO Departments (name) VALUES ("Investor Services");', []); 137 | tx.executeSql('INSERT INTO Departments (name) VALUES ("Shipping");', []); 138 | tx.executeSql('INSERT INTO Departments (name) VALUES ("Direct Sales");', []); 139 | 140 | tx.executeSql('INSERT INTO Offices (name, longtitude, latitude) VALUES ("Denver", 59.8, 34.);', []); 141 | tx.executeSql('INSERT INTO Offices (name, longtitude, latitude) VALUES ("Warsaw", 15.7, 54.);', []); 142 | tx.executeSql('INSERT INTO Offices (name, longtitude, latitude) VALUES ("Berlin", 35.3, 12.);', []); 143 | tx.executeSql('INSERT INTO Offices (name, longtitude, latitude) VALUES ("Paris", 10.7, 14.);', []); 144 | 145 | tx.executeSql(`INSERT INTO Employees (name, office, department, custom_info) VALUES ("Sylvester Stallone", 2, 4, '{"known": true}')`, []); 146 | tx.executeSql(`INSERT INTO Employees (name, office, department, custom_info) VALUES ("Elvis Presley", 2, 4, '{"known": true}')`, []); 147 | tx.executeSql(`INSERT INTO Employees (name, office, department, custom_info) VALUES ("Leslie Nelson", 3, 4, '{"known": true}')`, []); 148 | tx.executeSql(`INSERT INTO Employees (name, office, department, custom_info) VALUES ("Fidel Castro", 3, 3, '{"known": true}')`, []); 149 | tx.executeSql(`INSERT INTO Employees (name, office, department, custom_info) VALUES ("Bill Clinton", 1, 3, '{"known": false}')`, []); 150 | tx.executeSql(`INSERT INTO Employees (name, office, department, custom_info) VALUES ("Margaret Thatcher", 1, 3, '{"known": true}')`, []); 151 | tx.executeSql(`INSERT INTO Employees (name, office, department, custom_info) VALUES ("Donald Trump", 2, 4, '{"known": true, "impeached": true}')`, []); 152 | tx.executeSql(`INSERT INTO Employees (name, office, department, custom_info) VALUES ("Dr DRE", 2, 2, '{"known": true}')`, []); 153 | tx.executeSql(`INSERT INTO Employees (name, office, department, custom_info) VALUES ("Samantha Fox", 2, 1, '{"known": true}')`, []); 154 | 155 | console.log("all config SQL done"); 156 | }; 157 | 158 | queryEmployees = async (tx) => { 159 | console.log("Executing JSON1 queries..."); 160 | 161 | // 1. JSON_OBJECT 162 | await tx.executeSql(`SELECT JSON_OBJECT('name', e.name, 'office_id', e.office, 'department_id', e.department) AS data FROM Employees e`, [], 163 | this.querySuccess, this.errorCB); 164 | 165 | // 2. JSON_ARRAY 166 | // Expected: [1,2,"3",4] 167 | await tx.executeSql(`SELECT JSON_ARRAY(1, 2, '3', 4) AS data `, [], 168 | this.querySuccess, this.errorCB); 169 | 170 | // 3. JSON_ARRAY_LENGTH 171 | // Expected: 4 172 | await tx.executeSql(`SELECT JSON_ARRAY_LENGTH('[1, 2, 3, 4]') AS data`, [], 173 | this.querySuccess, this.errorCB); 174 | 175 | // 4. JSON_EXTRACT 176 | await tx.executeSql(`SELECT JSON_EXTRACT(e.custom_info, '$.known') AS data FROM Employees e`, [], 177 | this.querySuccess, this.errorCB); 178 | 179 | // 5. JSON_INSERT 180 | // Expected: {"a":1,"b":2,"c":3} 181 | await tx.executeSql(`SELECT JSON_INSERT('{"a": 1, "b": 2}', '$.c', 3) AS data`, [], 182 | this.querySuccess, this.errorCB); 183 | 184 | // 6. JSON_REPLACE 185 | // Expected: {"a":1,"b":3} 186 | await tx.executeSql(`SELECT JSON_REPLACE('{"a": 1, "b": 2}', '$.b', 3) AS data`, [], 187 | this.querySuccess, this.errorCB); 188 | 189 | // 7. JSON_SET 190 | // Expected: {"a":1,"b":123} 191 | await tx.executeSql(`SELECT JSON_SET('{"a": 1, "b": 2}', '$.b', 123) AS data`, [], 192 | this.querySuccess, this.errorCB); 193 | 194 | // 8. JSON_REMOVE 195 | // Expected: {"a":1"} 196 | await tx.executeSql(`SELECT JSON_REMOVE('{"a": 1, "b": 2}', '$.b') AS data`, [], 197 | this.querySuccess, this.errorCB); 198 | 199 | // 9. JSON_TYPE 200 | // Expected: integer 201 | await tx.executeSql(`SELECT JSON_TYPE('{"a": 1, "b": 2}', '$.a') AS data`, [], 202 | this.querySuccess, this.errorCB); 203 | 204 | // 10. JSON_VALID 205 | // Expected: 0 206 | await tx.executeSql(`SELECT JSON_VALID('{"a": 1, "b": 2') AS data`, [], 207 | this.querySuccess, this.errorCB); 208 | 209 | // 11. JSON_QUOTE 210 | // Expected: "value" 211 | await tx.executeSql(`SELECT JSON_QUOTE('value') AS data`, [], 212 | this.querySuccess, this.errorCB); 213 | }; 214 | 215 | querySuccess = (tx,results) => { 216 | this.updateProgress("Query completed"); 217 | var len = results.rows.length; 218 | for (let i = 0; i < len; i++) { 219 | let row = results.rows.item(i); 220 | this.updateProgress(`${row.data}`); 221 | } 222 | }; 223 | 224 | loadAndQueryDB = () => { 225 | this.updateProgress("Opening database ...",true); 226 | db = SQLite.openDatabase(database_name, database_version, database_displayname, database_size, this.openCB, this.errorCB); 227 | this.populateDatabase(db); 228 | }; 229 | 230 | deleteDatabase = () => { 231 | this.updateProgress("Deleting database"); 232 | SQLite.deleteDatabase(database_name, this.deleteCB, this.errorCB); 233 | }; 234 | 235 | closeDatabase = () => { 236 | if (db) { 237 | console.log("Closing database ..."); 238 | this.updateProgress("Closing database"); 239 | db.close(this.closeCB,this.errorCB); 240 | } else { 241 | this.updateProgress("Database was not OPENED"); 242 | } 243 | }; 244 | 245 | runDemo = () => { 246 | this.updateProgress("Starting SQLite Callback Demo",true); 247 | this.loadAndQueryDB(); 248 | }; 249 | 250 | renderProgressEntry = (entry) => { 251 | return ( 252 | 253 | {entry} 254 | 255 | ) 256 | }; 257 | 258 | render = () => { 259 | return ( 260 | 261 | 262 | Run Demo 263 | 264 | 265 | Close DB 266 | 267 | 268 | Delete DB 269 | 270 | 271 | 276 | ); 277 | } 278 | } 279 | 280 | var listStyles = StyleSheet.create({ 281 | li: { 282 | borderBottomColor: '#c8c7cc', 283 | borderBottomWidth: 0.5, 284 | paddingTop: 15, 285 | paddingRight: 15, 286 | paddingBottom: 15, 287 | }, 288 | liContainer: { 289 | backgroundColor: '#fff', 290 | flex: 1, 291 | paddingLeft: 15, 292 | }, 293 | liIndent: { 294 | flex: 1, 295 | }, 296 | liText: { 297 | color: '#333', 298 | fontSize: 17, 299 | fontWeight: '400', 300 | marginBottom: -3.5, 301 | marginTop: -3.5, 302 | }, 303 | }); 304 | 305 | var styles = StyleSheet.create({ 306 | container: { 307 | flex: 1, 308 | justifyContent: 'center', 309 | alignItems: 'center', 310 | backgroundColor: '#F5FCFF', 311 | }, 312 | welcome: { 313 | fontSize: 20, 314 | textAlign: 'center', 315 | margin: 10, 316 | }, 317 | instructions: { 318 | textAlign: 'center', 319 | color: '#333333', 320 | marginBottom: 5, 321 | }, 322 | toolbar: { 323 | backgroundColor: '#51c04d', 324 | paddingTop: 30, 325 | paddingBottom: 10, 326 | flexDirection: 'row' 327 | }, 328 | toolbarButton: { 329 | color: 'blue', 330 | textAlign: 'center', 331 | flex: 1 332 | }, 333 | mainContainer: { 334 | flex: 1 335 | } 336 | }); 337 | 338 | AppRegistry.registerComponent('AwesomeProject', () => SQLiteDemo); 339 | -------------------------------------------------------------------------------- /test/index.ios.callback.js: -------------------------------------------------------------------------------- 1 | /** 2 | * sqlite.ios.callback.js 3 | * 4 | * Created by Andrzej Porebski on 10/29/15. 5 | * Copyright (c) 2015 Andrzej Porebski. 6 | * 7 | * Test App using JS Callbacks for react-naive-sqlite-storage 8 | * 9 | * This library is available under the terms of the MIT License (2008). 10 | * See http://opensource.org/licenses/alphabetical for full text. 11 | */ 12 | 'use strict'; 13 | 14 | import React, { Component } from 'react'; 15 | import { 16 | AppRegistry, 17 | StyleSheet, 18 | Text, 19 | View 20 | } from 'react-native'; 21 | import ListView from 'deprecated-react-native-listview'; 22 | 23 | 24 | import SQLite from 'react-native-sqlite-storage'; 25 | SQLite.DEBUG(true); 26 | SQLite.enablePromise(false); 27 | 28 | const database_name = "Test.db"; 29 | const database_version = "1.0"; 30 | const database_displayname = "SQLite Test Database"; 31 | const database_size = 200000; 32 | let db; 33 | 34 | class SQLiteDemo extends Component { 35 | constructor() { 36 | super(); 37 | this.progress = []; 38 | this.state = { 39 | progress: [], 40 | ds: new ListView.DataSource({ 41 | rowHasChanged: (r1, r2) => r1 !== r2} 42 | ) 43 | }; 44 | } 45 | 46 | updateProgress = (text, resetState) => { 47 | let progress = []; 48 | if (!resetState) { 49 | progress = [...this.progress]; 50 | } 51 | progress.push(text); 52 | this.progress = progress; 53 | this.setState({ 54 | progress 55 | }); 56 | } 57 | 58 | componentWillUnmount = () => { 59 | this.closeDatabase(); 60 | } 61 | 62 | errorCB = (err) => { 63 | console.log("error: ",err); 64 | this.updateProgress("Error: "+ (err.message || err)); 65 | return false; 66 | } 67 | 68 | successCB = () => { 69 | console.log("SQL executed ..."); 70 | } 71 | 72 | openCB = () => { 73 | this.updateProgress("Database OPEN"); 74 | } 75 | 76 | closeCB = () => { 77 | this.updateProgress("Database CLOSED"); 78 | } 79 | 80 | deleteCB = () => { 81 | console.log("Database DELETED"); 82 | this.updateProgress("Database DELETED"); 83 | } 84 | 85 | populateDatabase = (db) => { 86 | this.updateProgress("Database integrity check"); 87 | db.executeSql('SELECT 1 FROM Version LIMIT 1', [], 88 | () => { 89 | this.updateProgress("Database is ready ... executing query ..."); 90 | db.transaction(this.queryEmployees,this.errorCB,() => { 91 | this.updateProgress("Processing completed"); 92 | }); 93 | }, 94 | (error) => { 95 | console.log("received version error:", error); 96 | this.updateProgress("Database not yet ready ... populating data"); 97 | db.transaction(this.populateDB, this.errorCB, () => { 98 | this.updateProgress("Database populated ... executing query ..."); 99 | db.transaction(this.queryEmployees,this.errorCB, () => { 100 | console.log("Transaction is now finished"); 101 | this.updateProgress("Processing completed"); 102 | this.closeDatabase(); 103 | }); 104 | }); 105 | }); 106 | } 107 | 108 | populateDB = (tx) => { 109 | this.updateProgress("Executing DROP stmts"); 110 | 111 | tx.executeSql('DROP TABLE IF EXISTS Employees;'); 112 | tx.executeSql('DROP TABLE IF EXISTS Offices;'); 113 | tx.executeSql('DROP TABLE IF EXISTS Departments;'); 114 | 115 | this.updateProgress("Executing CREATE stmts"); 116 | 117 | tx.executeSql('CREATE TABLE IF NOT EXISTS Version( ' 118 | + 'version_id INTEGER PRIMARY KEY NOT NULL); ', [], this.successCB, this.errorCB); 119 | 120 | tx.executeSql('CREATE TABLE IF NOT EXISTS Departments( ' 121 | + 'department_id INTEGER PRIMARY KEY NOT NULL, ' 122 | + 'name VARCHAR(30) ); ', [], this.successCB, this.errorCB); 123 | 124 | tx.executeSql('CREATE TABLE IF NOT EXISTS Offices( ' 125 | + 'office_id INTEGER PRIMARY KEY NOT NULL, ' 126 | + 'name VARCHAR(20), ' 127 | + 'longtitude FLOAT, ' 128 | + 'latitude FLOAT ) ; ', [], this.successCB, this.errorCB); 129 | 130 | tx.executeSql('CREATE TABLE IF NOT EXISTS Employees( ' 131 | + 'employe_id INTEGER PRIMARY KEY NOT NULL, ' 132 | + 'name VARCHAR(55), ' 133 | + 'office INTEGER, ' 134 | + 'department INTEGER, ' 135 | + 'FOREIGN KEY ( office ) REFERENCES Offices ( office_id ) ' 136 | + 'FOREIGN KEY ( department ) REFERENCES Departments ( department_id ));', []); 137 | 138 | this.updateProgress("Executing INSERT stmts"); 139 | 140 | tx.executeSql('INSERT INTO Departments (name) VALUES ("Client Services");', []); 141 | tx.executeSql('INSERT INTO Departments (name) VALUES ("Investor Services");', []); 142 | tx.executeSql('INSERT INTO Departments (name) VALUES ("Shipping");', []); 143 | tx.executeSql('INSERT INTO Departments (name) VALUES ("Direct Sales");', []); 144 | 145 | tx.executeSql('INSERT INTO Offices (name, longtitude, latitude) VALUES ("Denver", 59.8, 34.);', []); 146 | tx.executeSql('INSERT INTO Offices (name, longtitude, latitude) VALUES ("Warsaw", 15.7, 54.);', []); 147 | tx.executeSql('INSERT INTO Offices (name, longtitude, latitude) VALUES ("Berlin", 35.3, 12.);', []); 148 | tx.executeSql('INSERT INTO Offices (name, longtitude, latitude) VALUES ("Paris", 10.7, 14.);', []); 149 | 150 | tx.executeSql('INSERT INTO Employees (name, office, department) VALUES ("Sylvester Stallone", 2, 4);', []); 151 | tx.executeSql('INSERT INTO Employees (name, office, department) VALUES ("Elvis Presley", 2, 4);', []); 152 | tx.executeSql('INSERT INTO Employees (name, office, department) VALUES ("Leslie Nelson", 3, 4);', []); 153 | tx.executeSql('INSERT INTO Employees (name, office, department) VALUES ("Fidel Castro", 3, 3);', []); 154 | tx.executeSql('INSERT INTO Employees (name, office, department) VALUES ("Bill Clinton", 1, 3);', []); 155 | tx.executeSql('INSERT INTO Employees (name, office, department) VALUES ("Margaret Thatcher", 1, 3);', []); 156 | tx.executeSql('INSERT INTO Employees (name, office, department) VALUES ("Donald Trump", 1, 3);', []); 157 | tx.executeSql('INSERT INTO Employees (name, office, department) VALUES ("Dr DRE", 2, 2);', []); 158 | tx.executeSql('INSERT INTO Employees (name, office, department) VALUES ("Samantha Fox", 2, 1);', []); 159 | console.log("all config SQL done"); 160 | } 161 | 162 | queryEmployees = (tx) => { 163 | console.log("Executing employee query..."); 164 | 165 | tx.executeSql('SELECT a.name, b.name as deptName FROM Employees a, Departments b WHERE a.department = b.department_id and a.department=?', [3], 166 | this.queryEmployeesSuccess,this.errorCB); 167 | //tx.executeSql('SELECT a.name, from TEST', [],() => {},this.errorCB); 168 | } 169 | 170 | queryEmployeesSuccess = (tx,results) => { 171 | this.updateProgress("Query completed"); 172 | var len = results.rows.length; 173 | for (let i = 0; i < len; i++) { 174 | let row = results.rows.item(i); 175 | this.updateProgress(`Empl Name: ${row.name}, Dept Name: ${row.deptName}`); 176 | } 177 | } 178 | 179 | loadAndQueryDB = () => { 180 | this.updateProgress("Opening database ...",true); 181 | db = SQLite.openDatabase(database_name, database_version, database_displayname, database_size, this.openCB, this.errorCB); 182 | this.populateDatabase(db); 183 | } 184 | 185 | deleteDatabase = () => { 186 | this.updateProgress("Deleting database"); 187 | SQLite.deleteDatabase(database_name, this.deleteCB, this.errorCB); 188 | } 189 | 190 | closeDatabase = () => { 191 | if (db) { 192 | console.log("Closing database ..."); 193 | this.updateProgress("Closing database"); 194 | db.close(this.closeCB,this.errorCB); 195 | } else { 196 | this.updateProgress("Database was not OPENED"); 197 | } 198 | } 199 | 200 | runDemo = () => { 201 | this.updateProgress("Starting SQLite Callback Demo",true); 202 | this.loadAndQueryDB(); 203 | } 204 | 205 | renderProgressEntry = (entry) => { 206 | return ( 207 | 208 | {entry} 209 | 210 | ) 211 | } 212 | 213 | render = () => { 214 | return ( 215 | 216 | 217 | Run Demo 218 | 219 | 220 | Close DB 221 | 222 | 223 | Delete DB 224 | 225 | 226 | 231 | ); 232 | } 233 | } 234 | 235 | var listStyles = StyleSheet.create({ 236 | li: { 237 | borderBottomColor: '#c8c7cc', 238 | borderBottomWidth: 0.5, 239 | paddingTop: 15, 240 | paddingRight: 15, 241 | paddingBottom: 15, 242 | }, 243 | liContainer: { 244 | backgroundColor: '#fff', 245 | flex: 1, 246 | paddingLeft: 15, 247 | }, 248 | liIndent: { 249 | flex: 1, 250 | }, 251 | liText: { 252 | color: '#333', 253 | fontSize: 17, 254 | fontWeight: '400', 255 | marginBottom: -3.5, 256 | marginTop: -3.5, 257 | }, 258 | }); 259 | 260 | var styles = StyleSheet.create({ 261 | container: { 262 | flex: 1, 263 | justifyContent: 'center', 264 | alignItems: 'center', 265 | backgroundColor: '#F5FCFF', 266 | }, 267 | welcome: { 268 | fontSize: 20, 269 | textAlign: 'center', 270 | margin: 10, 271 | }, 272 | instructions: { 273 | textAlign: 'center', 274 | color: '#333333', 275 | marginBottom: 5, 276 | }, 277 | toolbar: { 278 | backgroundColor: '#51c04d', 279 | paddingTop: 30, 280 | paddingBottom: 10, 281 | flexDirection: 'row' 282 | }, 283 | toolbarButton: { 284 | color: 'blue', 285 | textAlign: 'center', 286 | flex: 1 287 | }, 288 | mainContainer: { 289 | flex: 1 290 | } 291 | }); 292 | 293 | AppRegistry.registerComponent('AwesomeProject', () => SQLiteDemo); 294 | -------------------------------------------------------------------------------- /test/index.ios.promise.js: -------------------------------------------------------------------------------- 1 | /* 2 | * sqlite.ios.promise.js 3 | * 4 | * Created by Andrzej Porebski on 10/29/15. 5 | * Copyright (c) 2015 Andrzej Porebski. 6 | * 7 | * Test App using Promise for react-naive-sqlite-storage 8 | * 9 | * This library is available under the terms of the MIT License (2008). 10 | * See http://opensource.org/licenses/alphabetical for full text. 11 | */ 12 | 'use strict'; 13 | 14 | import React, { Component } from 'react'; 15 | import { 16 | AppRegistry, 17 | StyleSheet, 18 | Text, 19 | View 20 | } from 'react-native'; 21 | import ListView from 'deprecated-react-native-listview'; 22 | 23 | 24 | import SQLite from 'react-native-sqlite-storage'; 25 | SQLite.DEBUG(true); 26 | SQLite.enablePromise(true); 27 | 28 | 29 | const database_name = "Test.db"; 30 | const database_version = "1.0"; 31 | const database_displayname = "SQLite Test Database"; 32 | const database_size = 200000; 33 | let db; 34 | 35 | class SQLiteDemo extends Component { 36 | constructor() { 37 | super(); 38 | this.progress = []; 39 | this.state = { 40 | progress: [], 41 | ds: new ListView.DataSource({ 42 | rowHasChanged: (r1, r2) => r1 !== r2} 43 | ) 44 | }; 45 | } 46 | 47 | updateProgress = (text, resetState) => { 48 | let progress = []; 49 | if (!resetState) { 50 | progress = [...this.progress]; 51 | } 52 | progress.push(text); 53 | this.progress = progress; 54 | this.setState({ 55 | progress 56 | }); 57 | }; 58 | 59 | componentWillUnmount(){ 60 | this.closeDatabase(); 61 | } 62 | 63 | errorCB = (err) => { 64 | console.log("error: ",err); 65 | this.updateProgress("Error " + (err.message || err)); 66 | }; 67 | 68 | populateDatabase = (db) => { 69 | this.updateProgress("Database integrity check"); 70 | db.executeSql('SELECT 1 FROM Version LIMIT 1').then(() =>{ 71 | this.updateProgress("Database is ready ... executing query ..."); 72 | db.transaction(this.queryEmployees).then(() => { 73 | this.updateProgress("Processing completed") 74 | }); 75 | }).catch((error) =>{ 76 | console.log("Received error: ", error); 77 | this.updateProgress("Database not yet ready ... populating data"); 78 | db.transaction(this.populateDB).then(() =>{ 79 | this.updateProgress("Database populated ... executing query ..."); 80 | db.transaction(this.queryEmployees).then((result) => { 81 | console.log("Transaction is now finished"); 82 | this.updateProgress("Processing completed"); 83 | this.closeDatabase()}); 84 | }); 85 | }); 86 | }; 87 | 88 | populateDB = (tx) => { 89 | this.updateProgress("Executing DROP stmts"); 90 | 91 | tx.executeSql('DROP TABLE IF EXISTS Employees;'); 92 | tx.executeSql('DROP TABLE IF EXISTS Offices;'); 93 | tx.executeSql('DROP TABLE IF EXISTS Departments;'); 94 | 95 | 96 | this.updateProgress("Executing CREATE stmts"); 97 | 98 | 99 | tx.executeSql('CREATE TABLE IF NOT EXISTS Version( ' 100 | + 'version_id INTEGER PRIMARY KEY NOT NULL); ').catch((error) => { 101 | this.errorCB(error) 102 | }); 103 | 104 | tx.executeSql('CREATE TABLE IF NOT EXISTS Departments( ' 105 | + 'department_id INTEGER PRIMARY KEY NOT NULL, ' 106 | + 'name VARCHAR(30) ); ').catch((error) => { 107 | this.errorCB(error) 108 | }); 109 | 110 | tx.executeSql('CREATE TABLE IF NOT EXISTS Offices( ' 111 | + 'office_id INTEGER PRIMARY KEY NOT NULL, ' 112 | + 'name VARCHAR(20), ' 113 | + 'longtitude FLOAT, ' 114 | + 'latitude FLOAT ) ; ').catch((error) => { 115 | this.errorCB(error) 116 | }); 117 | 118 | tx.executeSql('CREATE TABLE IF NOT EXISTS Employees( ' 119 | + 'employe_id INTEGER PRIMARY KEY NOT NULL, ' 120 | + 'name VARCHAR(55), ' 121 | + 'office INTEGER, ' 122 | + 'department INTEGER, ' 123 | + 'FOREIGN KEY ( office ) REFERENCES Offices ( office_id ) ' 124 | + 'FOREIGN KEY ( department ) REFERENCES Departments ( department_id ));').catch((error) => { 125 | this.errorCB(error) 126 | }); 127 | 128 | this.updateProgress("Executing INSERT stmts"); 129 | 130 | 131 | tx.executeSql('INSERT INTO Departments (name) VALUES ("Client Services");'); 132 | tx.executeSql('INSERT INTO Departments (name) VALUES ("Investor Services");'); 133 | tx.executeSql('INSERT INTO Departments (name) VALUES ("Shipping");'); 134 | tx.executeSql('INSERT INTO Departments (name) VALUES ("Direct Sales");'); 135 | 136 | tx.executeSql('INSERT INTO Offices (name, longtitude, latitude) VALUES ("Denver", 59.8, 34.1);'); 137 | tx.executeSql('INSERT INTO Offices (name, longtitude, latitude) VALUES ("Warsaw", 15.7, 54.1);'); 138 | tx.executeSql('INSERT INTO Offices (name, longtitude, latitude) VALUES ("Berlin", 35.3, 12.1);'); 139 | tx.executeSql('INSERT INTO Offices (name, longtitude, latitude) VALUES ("Paris", 10.7, 14.1);'); 140 | 141 | tx.executeSql('INSERT INTO Employees (name, office, department) VALUES ("Sylvester Stallone", 2, 4);'); 142 | tx.executeSql('INSERT INTO Employees (name, office, department) VALUES ("Elvis Presley", 2, 4);'); 143 | tx.executeSql('INSERT INTO Employees (name, office, department) VALUES ("Leslie Nelson", 3, 4);'); 144 | tx.executeSql('INSERT INTO Employees (name, office, department) VALUES ("Fidel Castro", 3, 3);'); 145 | tx.executeSql('INSERT INTO Employees (name, office, department) VALUES ("Bill Clinton", 1, 3);'); 146 | tx.executeSql('INSERT INTO Employees (name, office, department) VALUES ("Margaret Thatcher", 1, 3);'); 147 | tx.executeSql('INSERT INTO Employees (name, office, department) VALUES ("Donald Trump", 1, 3);'); 148 | tx.executeSql('INSERT INTO Employees (name, office, department) VALUES ("Dr DRE", 2, 2);'); 149 | tx.executeSql('INSERT INTO Employees (name, office, department) VALUES ("Samantha Fox", 2, 1);'); 150 | console.log("all config SQL done"); 151 | }; 152 | 153 | queryEmployees = (tx) => { 154 | console.log("Executing employee query"); 155 | tx.executeSql('SELECT a.name, b.name as deptName FROM Employees a, Departments b WHERE a.department = b.department_id and a.department=?', [3]).then(([tx,results]) => { 156 | this.updateProgress("Query completed"); 157 | var len = results.rows.length; 158 | for (let i = 0; i < len; i++) { 159 | let row = results.rows.item(i); 160 | this.updateProgress(`Empl Name: ${row.name}, Dept Name: ${row.deptName}`) 161 | } 162 | }).catch((error) => { 163 | console.log(error); 164 | }); 165 | }; 166 | 167 | loadAndQueryDB = () => { 168 | this.updateProgress("Plugin integrity check ..."); 169 | SQLite.echoTest().then(() => { 170 | this.updateProgress("Integrity check passed ..."); 171 | this.updateProgress("Opening database ..."); 172 | SQLite.openDatabase(database_name, database_version, database_displayname, database_size).then((DB) => { 173 | db = DB; 174 | this.updateProgress("Database OPEN"); 175 | this.populateDatabase(DB); 176 | }).catch((error) => { 177 | console.log(error); 178 | }); 179 | }).catch(error => { 180 | this.updateProgress("echoTest failed - plugin not functional"); 181 | }); 182 | }; 183 | 184 | closeDatabase = () => { 185 | if (db) { 186 | console.log("Closing database ..."); 187 | this.updateProgress("Closing DB"); 188 | db.close().then((status) => { 189 | this.updateProgress("Database CLOSED"); 190 | }).catch((error) => { 191 | this.errorCB(error); 192 | }); 193 | } else { 194 | this.updateProgress("Database was not OPENED") 195 | } 196 | }; 197 | 198 | deleteDatabase = () => { 199 | this.updateProgress("Deleting database"); 200 | SQLite.deleteDatabase(database_name).then(() => { 201 | console.log("Database DELETED"); 202 | this.updateProgress("Database DELETED") 203 | }).catch((error) => { 204 | this.errorCB(error); 205 | }); 206 | }; 207 | 208 | runDemo = () => { 209 | console.log('running'); 210 | this.updateProgress("Starting SQLite Promise Demo",true); 211 | this.loadAndQueryDB(); 212 | }; 213 | 214 | renderProgressEntry = (entry) => { 215 | return ( 216 | 217 | {entry} 218 | 219 | ) 220 | }; 221 | 222 | render(){ 223 | let ds = new ListView.DataSource({rowHasChanged: (row1, row2) => row1 !== row2 }); 224 | return ( 225 | 226 | 227 | Run Demo 228 | 229 | 230 | Close DB 231 | 232 | 233 | Delete DB 234 | 235 | 236 | 241 | ); 242 | } 243 | } 244 | 245 | var listStyles = StyleSheet.create({ 246 | li: { 247 | borderBottomColor: '#c8c7cc', 248 | borderBottomWidth: 0.5, 249 | paddingTop: 15, 250 | paddingRight: 15, 251 | paddingBottom: 15, 252 | }, 253 | liContainer: { 254 | backgroundColor: '#fff', 255 | flex: 1, 256 | paddingLeft: 15, 257 | }, 258 | liIndent: { 259 | flex: 1, 260 | }, 261 | liText: { 262 | color: '#333', 263 | fontSize: 17, 264 | fontWeight: '400', 265 | marginBottom: -3.5, 266 | marginTop: -3.5, 267 | }, 268 | }); 269 | 270 | var styles = StyleSheet.create({ 271 | container: { 272 | flex: 1, 273 | justifyContent: 'center', 274 | alignItems: 'center', 275 | backgroundColor: '#F5FCFF', 276 | }, 277 | welcome: { 278 | fontSize: 20, 279 | textAlign: 'center', 280 | margin: 10, 281 | }, 282 | instructions: { 283 | textAlign: 'center', 284 | color: '#333333', 285 | marginBottom: 5, 286 | }, 287 | toolbar: { 288 | backgroundColor: '#51c04d', 289 | paddingTop: 30, 290 | paddingBottom: 10, 291 | flexDirection: 'row' 292 | }, 293 | toolbarButton: { 294 | color: 'blue', 295 | textAlign: 'center', 296 | flex: 1 297 | }, 298 | mainContainer: { 299 | flex: 1 300 | } 301 | }); 302 | 303 | AppRegistry.registerComponent('AwesomeProject', () => SQLiteDemo); 304 | -------------------------------------------------------------------------------- /test/index.windows.callback.js: -------------------------------------------------------------------------------- 1 | /** 2 | * sqlite.windows.callback.js 3 | * 4 | * Created by Andrzej Porebski on 10/29/15. 5 | * Copyright (c) 2015 Andrzej Porebski. 6 | * 7 | * Test App using JS Callbacks for react-naive-sqlite-storage 8 | * 9 | * This library is available under the terms of the MIT License (2008). 10 | * See http://opensource.org/licenses/alphabetical for full text. 11 | */ 12 | 'use strict'; 13 | 14 | import React, { Component } from 'react'; 15 | import { 16 | AppRegistry, 17 | StyleSheet, 18 | Text, 19 | View 20 | } from 'react-native'; 21 | import ListView from 'deprecated-react-native-listview'; 22 | 23 | 24 | import SQLite from 'react-native-sqlite-storage'; 25 | SQLite.DEBUG(true); 26 | SQLite.enablePromise(false); 27 | 28 | const database_name = "Test.db"; 29 | const database_version = "1.0"; 30 | const database_displayname = "SQLite Test Database"; 31 | const database_size = 200000; 32 | let db; 33 | 34 | class SQLiteDemo extends Component { 35 | constructor() { 36 | super(); 37 | this.progress = []; 38 | this.state = { 39 | progress: [], 40 | ds: new ListView.DataSource({ 41 | rowHasChanged: (r1, r2) => r1 !== r2} 42 | ) 43 | }; 44 | } 45 | 46 | updateProgress = (text, resetState) => { 47 | let progress = []; 48 | if (!resetState) { 49 | progress = [...this.progress]; 50 | } 51 | progress.push(text); 52 | this.progress = progress; 53 | this.setState({ 54 | progress 55 | }); 56 | } 57 | 58 | componentWillUnmount = () => { 59 | this.closeDatabase(); 60 | } 61 | 62 | errorCB = (err) => { 63 | console.log("error: ",err); 64 | this.updateProgress("Error: "+ (err.message || err)); 65 | return false; 66 | } 67 | 68 | successCB = () => { 69 | console.log("SQL executed ..."); 70 | } 71 | 72 | openCB = () => { 73 | this.updateProgress("Database OPEN"); 74 | } 75 | 76 | closeCB = () => { 77 | this.updateProgress("Database CLOSED"); 78 | } 79 | 80 | deleteCB = () => { 81 | console.log("Database DELETED"); 82 | this.updateProgress("Database DELETED"); 83 | } 84 | 85 | populateDatabase = (db) => { 86 | this.updateProgress("Database integrity check"); 87 | db.executeSql('SELECT 1 FROM Version LIMIT 1', [], 88 | () => { 89 | this.updateProgress("Database is ready ... executing query ..."); 90 | db.transaction(this.queryEmployees,this.errorCB,() => { 91 | this.updateProgress("Processing completed"); 92 | }); 93 | }, 94 | (error) => { 95 | console.log("received version error:", error); 96 | this.updateProgress("Database not yet ready ... populating data"); 97 | db.transaction(this.populateDB, this.errorCB, () => { 98 | this.updateProgress("Database populated ... executing query ..."); 99 | db.transaction(this.queryEmployees,this.errorCB, () => { 100 | console.log("Transaction is now finished"); 101 | this.updateProgress("Processing completed"); 102 | this.closeDatabase(); 103 | }); 104 | }); 105 | }); 106 | } 107 | 108 | attachDatabase = (db) => { 109 | this.updateProgress("Attaching DB"); 110 | db.attach("TestDBToAttach.db", "TestDBToAttach", 111 | () => { 112 | this.updateProgress("Database is ready ... attaching ..."); 113 | this.updateProgress("Successfully attached to the db"); 114 | console.log("Successfully attached to the db"); 115 | }, 116 | (error) => { 117 | console.log("Error attaching the DB:", error); 118 | this.updateProgress(error); 119 | }); 120 | } 121 | 122 | populateDB = (tx) => { 123 | this.updateProgress("Executing DROP stmts"); 124 | 125 | tx.executeSql('DROP TABLE IF EXISTS Employees;'); 126 | tx.executeSql('DROP TABLE IF EXISTS Offices;'); 127 | tx.executeSql('DROP TABLE IF EXISTS Departments;'); 128 | 129 | this.updateProgress("Executing CREATE stmts"); 130 | 131 | tx.executeSql('CREATE TABLE IF NOT EXISTS Version( ' 132 | + 'version_id INTEGER PRIMARY KEY NOT NULL); ', [], this.successCB, this.errorCB); 133 | 134 | tx.executeSql('CREATE TABLE IF NOT EXISTS Departments( ' 135 | + 'department_id INTEGER PRIMARY KEY NOT NULL, ' 136 | + 'name VARCHAR(30) ); ', [], this.successCB, this.errorCB); 137 | 138 | tx.executeSql('CREATE TABLE IF NOT EXISTS Offices( ' 139 | + 'office_id INTEGER PRIMARY KEY NOT NULL, ' 140 | + 'name VARCHAR(20), ' 141 | + 'longtitude FLOAT, ' 142 | + 'latitude FLOAT ) ; ', [], this.successCB, this.errorCB); 143 | 144 | tx.executeSql('CREATE TABLE IF NOT EXISTS Employees( ' 145 | + 'employe_id INTEGER PRIMARY KEY NOT NULL, ' 146 | + 'name VARCHAR(55), ' 147 | + 'office INTEGER, ' 148 | + 'department INTEGER, ' 149 | + 'FOREIGN KEY ( office ) REFERENCES Offices ( office_id ) ' 150 | + 'FOREIGN KEY ( department ) REFERENCES Departments ( department_id ));', []); 151 | 152 | this.updateProgress("Executing INSERT stmts"); 153 | 154 | tx.executeSql('INSERT INTO Departments (name) VALUES ("Client Services");', []); 155 | tx.executeSql('INSERT INTO Departments (name) VALUES ("Investor Services");', []); 156 | tx.executeSql('INSERT INTO Departments (name) VALUES ("Shipping");', []); 157 | tx.executeSql('INSERT INTO Departments (name) VALUES ("Direct Sales");', []); 158 | 159 | tx.executeSql('INSERT INTO Offices (name, longtitude, latitude) VALUES ("Denver", 59.8, 34.);', []); 160 | tx.executeSql('INSERT INTO Offices (name, longtitude, latitude) VALUES ("Warsaw", 15.7, 54.);', []); 161 | tx.executeSql('INSERT INTO Offices (name, longtitude, latitude) VALUES ("Berlin", 35.3, 12.);', []); 162 | tx.executeSql('INSERT INTO Offices (name, longtitude, latitude) VALUES ("Paris", 10.7, 14.);', []); 163 | 164 | tx.executeSql('INSERT INTO Employees (name, office, department) VALUES ("Sylvester Stallone", 2, 4);', []); 165 | tx.executeSql('INSERT INTO Employees (name, office, department) VALUES ("Elvis Presley", 2, 4);', []); 166 | tx.executeSql('INSERT INTO Employees (name, office, department) VALUES ("Leslie Nelson", 3, 4);', []); 167 | tx.executeSql('INSERT INTO Employees (name, office, department) VALUES ("Fidel Castro", 3, 3);', []); 168 | tx.executeSql('INSERT INTO Employees (name, office, department) VALUES ("Bill Clinton", 1, 3);', []); 169 | tx.executeSql('INSERT INTO Employees (name, office, department) VALUES ("Margaret Thatcher", 1, 3);', []); 170 | tx.executeSql('INSERT INTO Employees (name, office, department) VALUES ("Donald Trump", 1, 3);', []); 171 | tx.executeSql('INSERT INTO Employees (name, office, department) VALUES ("Dr DRE", 2, 2);', []); 172 | tx.executeSql('INSERT INTO Employees (name, office, department) VALUES ("Samantha Fox", 2, 1);', []); 173 | console.log("all config SQL done"); 174 | } 175 | 176 | queryEmployees = (tx) => { 177 | console.log("Executing employee query..."); 178 | 179 | tx.executeSql('SELECT a.name, b.name as deptName FROM Employees a, Departments b WHERE a.department = b.department_id and a.department=?', [3], 180 | this.queryEmployeesSuccess,this.errorCB); 181 | //tx.executeSql('SELECT a.name, from TEST', [],() => {},this.errorCB); 182 | } 183 | 184 | queryEmployeesSuccess = (tx,results) => { 185 | this.updateProgress("Query completed"); 186 | var len = results.rows.length; 187 | for (let i = 0; i < len; i++) { 188 | let row = results.rows.item(i); 189 | this.updateProgress(`Empl Name: ${row.name}, Dept Name: ${row.deptName}`); 190 | } 191 | } 192 | 193 | loadAndQueryDB = () => { 194 | this.updateProgress("Opening database ...",true); 195 | db = SQLite.openDatabase(database_name, database_version, database_displayname, database_size, this.openCB, this.errorCB); 196 | this.populateDatabase(db); 197 | // Test attaching the db. Attaching once, should work. Attaching the second time should fail. 198 | this.attachDatabase(db); 199 | } 200 | 201 | deleteDatabase = () => { 202 | this.updateProgress("Deleting database"); 203 | SQLite.deleteDatabase(database_name, this.deleteCB, this.errorCB); 204 | } 205 | 206 | closeDatabase = () => { 207 | if (db) { 208 | console.log("Closing database ..."); 209 | this.updateProgress("Closing database"); 210 | db.close(this.closeCB,this.errorCB); 211 | } else { 212 | this.updateProgress("Database was not OPENED"); 213 | } 214 | } 215 | 216 | runDemo = () => { 217 | this.updateProgress("Starting SQLite Callback Demo",true); 218 | this.loadAndQueryDB(); 219 | } 220 | 221 | renderProgressEntry = (entry) => { 222 | return ( 223 | 224 | {entry} 225 | 226 | ) 227 | } 228 | 229 | render = () => { 230 | return ( 231 | 232 | 233 | Run Demo 234 | 235 | 236 | Close DB 237 | 238 | 239 | Delete DB 240 | 241 | 242 | 247 | ); 248 | } 249 | } 250 | 251 | var listStyles = StyleSheet.create({ 252 | li: { 253 | borderBottomColor: '#c8c7cc', 254 | borderBottomWidth: 0.5, 255 | paddingTop: 15, 256 | paddingRight: 15, 257 | paddingBottom: 15, 258 | }, 259 | liContainer: { 260 | backgroundColor: '#fff', 261 | flex: 1, 262 | paddingLeft: 15, 263 | }, 264 | liIndent: { 265 | flex: 1, 266 | }, 267 | liText: { 268 | color: '#333', 269 | fontSize: 17, 270 | fontWeight: '400', 271 | marginBottom: -3.5, 272 | marginTop: -3.5, 273 | }, 274 | }); 275 | 276 | var styles = StyleSheet.create({ 277 | container: { 278 | flex: 1, 279 | justifyContent: 'center', 280 | alignItems: 'center', 281 | backgroundColor: '#F5FCFF', 282 | }, 283 | welcome: { 284 | fontSize: 20, 285 | textAlign: 'center', 286 | margin: 10, 287 | }, 288 | instructions: { 289 | textAlign: 'center', 290 | color: '#333333', 291 | marginBottom: 5, 292 | }, 293 | toolbar: { 294 | backgroundColor: '#51c04d', 295 | paddingTop: 30, 296 | paddingBottom: 10, 297 | flexDirection: 'row' 298 | }, 299 | toolbarButton: { 300 | color: 'blue', 301 | textAlign: 'center', 302 | flex: 1 303 | }, 304 | mainContainer: { 305 | flex: 1 306 | } 307 | }); 308 | 309 | AppRegistry.registerComponent('AwesomeProject', () => SQLiteDemo); 310 | --------------------------------------------------------------------------------