├── .gitignore ├── .idea ├── .name ├── breeze-db.iml ├── copyright │ ├── Digital_Strawberry_LLC_MIT.xml │ └── profiles_settings.xml ├── modules.xml └── vcs.xml ├── .travis.yml ├── BreezeDb.iml ├── LICENSE.md ├── README.md ├── build ├── build.properties └── build.xml ├── src ├── breezedb │ ├── BreezeDb.as │ ├── BreezeDbInstance.as │ ├── DB.as │ ├── IBreezeDatabase.as │ ├── breezedb_internal.as │ ├── collections │ │ └── Collection.as │ ├── events │ │ ├── BreezeDatabaseEvent.as │ │ ├── BreezeMigrationEvent.as │ │ ├── BreezeQueryEvent.as │ │ └── BreezeSQLStatementEvent.as │ ├── migrations │ │ ├── BreezeMigration.as │ │ ├── BreezeMigrationsRunner.as │ │ └── breezedb_internal.as │ ├── models │ │ ├── BreezeModel.as │ │ └── BreezeModelQueryBuilder.as │ ├── queries │ │ ├── BreezeInnerQueryBuilder.as │ │ ├── BreezeJoinStatement.as │ │ ├── BreezeQueryBuilder.as │ │ ├── BreezeQueryReference.as │ │ ├── BreezeQueryResult.as │ │ ├── BreezeQueryRunner.as │ │ ├── BreezeRawQuery.as │ │ ├── BreezeSQLMultiStatement.as │ │ ├── BreezeSQLResult.as │ │ ├── BreezeSQLStatement.as │ │ ├── BreezeUnionStatement.as │ │ ├── IRawQuery.as │ │ ├── ISQLStatement.as │ │ ├── SQLStatementQueue.as │ │ └── breezedb_internal.as │ ├── schemas │ │ ├── BreezeSchemaBuilder.as │ │ ├── ColumnDataType.as │ │ ├── IColumnConstraint.as │ │ ├── TableBlueprint.as │ │ ├── TableColumn.as │ │ └── breezedb_internal.as │ └── utils │ │ ├── Callback.as │ │ └── GarbagePrevention.as └── org │ └── kuwamoto │ └── Inflect.as └── test ├── application.xml ├── lib └── breezetest.swc ├── src ├── Main.as └── tests │ ├── TestDatabase.as │ ├── TestQueryBuilder.as │ ├── TestQueryQueue.as │ ├── TestRawQuery.as │ ├── TestSchema.as │ ├── collections │ └── TestCollection.as │ ├── migrations │ ├── Migration_Create_Table_Photos.as │ ├── Migration_Insert_Default_Photos.as │ ├── Migration_Invalid_Class.as │ ├── Migration_Unsuccessful.as │ └── TestMigrations.as │ └── models │ ├── CustomTableModel.as │ ├── Photo.as │ ├── PhotoAlbum.as │ └── TestModel.as └── test.iml /.gitignore: -------------------------------------------------------------------------------- 1 | /.idea/dictionaries 2 | /.idea/compiler.xml 3 | /.idea/flexCompiler.xml 4 | /.idea/misc.xml 5 | /.idea/workspace.xml 6 | /test/bin 7 | /bin -------------------------------------------------------------------------------- /.idea/.name: -------------------------------------------------------------------------------- 1 | BreezeDb -------------------------------------------------------------------------------- /.idea/breeze-db.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.idea/copyright/Digital_Strawberry_LLC_MIT.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | git: 2 | depth: 10 3 | 4 | language: objective-c 5 | 6 | before_script: 7 | #brew 8 | - brew update > /dev/null 9 | - brew install ant > /dev/null 10 | # air 11 | - mkdir -p build/air_sdk 12 | - wget -O AIRSDK_Compiler.tbz2 http://airdownload.adobe.com/air/mac/download/23.0/AIRSDK_Compiler.tbz2 13 | - tar -xjf AIRSDK_Compiler.tbz2 -C build/air_sdk 14 | - mkdir -p build/air_sdk/frameworks/libs/player/11.1/ 15 | - cp -f build/air_sdk/frameworks/libs/player/*/playerglobal.swc build/air_sdk/frameworks/libs/player/11.1/ 16 | 17 | script: 18 | - cd build && ant test 19 | 20 | branches: 21 | only: 22 | - master 23 | -------------------------------------------------------------------------------- /BreezeDb.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Digital Strawberry LLC 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # BreezeDb [![Build Status](https://travis-ci.org/GetBreeze/breeze-db.svg?branch=master)](https://travis-ci.org/GetBreeze/breeze-db) 2 | 3 | BreezeDb is a SQLite database helper and ORM loosely based on the [Laravel database](https://laravel.com/docs/5.3/database) and [Eloquent ORM](https://laravel.com/docs/5.3/eloquent). 4 | 5 | ## Features 6 | 7 | ### Database 8 | 9 | BreezeDb greatly simplifies the process of setting up, managing and interacting with SQLite database in Adobe AIR. It supports multiple database connections and keeps your app responsive by executing all operations asynchronously. 10 | 11 | ### Migrations 12 | 13 | Migrations are used to create and edit database structure between app versions. They are atomic and run within a transaction, thus if one migration fails then all preceding migrations in the same session will be rolled back. After a migration is completed successfully, it will never run again. 14 | 15 | ### Collection 16 | 17 | The `Collection` class provides a wrapper for working with arrays of data. It is built upon the standard `Array` class but adds a handful of new methods. 18 | 19 | ### Query Builder 20 | 21 | Query builder provides a convenient, fluent interface for creating and running database queries, including multi-row inserts, aggregates and joins. The builder uses automatic parameter binding to protect against SQL injection attacks. 22 | 23 | ### ORM 24 | 25 | The ORM support in BreezeDb enables seamless mapping of each database table to an ActionScript class (model). Models are capable of querying data as well as inserting new records using strongly typed objects. -------------------------------------------------------------------------------- /build/build.properties: -------------------------------------------------------------------------------- 1 | flex.sdk = ${basedir}/air_sdk -------------------------------------------------------------------------------- /build/build.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /src/breezedb/BreezeDb.as: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2017 Digital Strawberry LLC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | * 24 | */ 25 | 26 | package breezedb 27 | { 28 | import breezedb.queries.BreezeRawQuery; 29 | 30 | import flash.filesystem.File; 31 | import flash.utils.Dictionary; 32 | 33 | /** 34 | * Class providing API that allows access to databases. 35 | */ 36 | public class BreezeDb 37 | { 38 | /** 39 | * BreezeDb library version. 40 | */ 41 | public static const VERSION:String = "1.1.3"; 42 | 43 | /** 44 | * Name of the default database. 45 | */ 46 | public static const DEFAULT_DB:String = "database"; 47 | 48 | /** 49 | * Constant used in place of a query callback to delay query execution. 50 | */ 51 | public static const DELAY:Boolean = false; 52 | 53 | private static var _isQueryQueueEnabled:Boolean = false; 54 | private static var _databases:Dictionary; 55 | private static var _fileExtension:String = ".sqlite"; 56 | private static var _storageDirectory:File = File.applicationStorageDirectory; 57 | 58 | 59 | /** 60 | * Retrieves the default database object. 61 | */ 62 | public static function get db():IBreezeDatabase 63 | { 64 | return getDb(DEFAULT_DB); 65 | } 66 | 67 | 68 | /** 69 | * Retrieves reference to database of given name. The name database is reserved 70 | * for the default database accessed using BreezeDb.db or the DB 71 | * facade class. 72 | * 73 | * @param databaseName The name of the database to retrieve. It will be created if it does not exist. 74 | * @return Reference to the database. 75 | * 76 | * @see #db 77 | */ 78 | public static function getDb(databaseName:String):IBreezeDatabase 79 | { 80 | if(_databases == null) 81 | { 82 | _databases = new Dictionary(); 83 | } 84 | 85 | // Create new database 86 | if(!(databaseName in _databases)) 87 | { 88 | _databases[databaseName] = new BreezeDbInstance(databaseName); 89 | } 90 | return _databases[databaseName]; 91 | } 92 | 93 | 94 | /** 95 | * The directory where the database files are created. 96 | * 97 | * @default File.applicationStorageDirectory 98 | */ 99 | public static function get storageDirectory():File 100 | { 101 | return _storageDirectory; 102 | } 103 | 104 | 105 | /** 106 | * @private 107 | */ 108 | public static function set storageDirectory(value:File):void 109 | { 110 | if(value == null) 111 | { 112 | throw new ArgumentError("Storage directory cannot be null."); 113 | } 114 | 115 | if(!value.exists || !value.isDirectory) 116 | { 117 | throw new Error("Storage directory must point to an existing directory."); 118 | } 119 | 120 | _storageDirectory = value; 121 | } 122 | 123 | 124 | /** 125 | * File extension for the database files. It must contain a dot followed by at least one character, 126 | * without spaces. 127 | * 128 | * @default .sqlite 129 | */ 130 | public static function get fileExtension():String 131 | { 132 | return _fileExtension; 133 | } 134 | 135 | 136 | /** 137 | * @private 138 | */ 139 | public static function set fileExtension(value:String):void 140 | { 141 | if(value == null) 142 | { 143 | throw new ArgumentError("File extension cannot be null."); 144 | } 145 | 146 | if(value.indexOf(" ") >= 0) 147 | { 148 | throw new ArgumentError("Extension cannot contain spaces"); 149 | } 150 | 151 | var dotIndex:int = value.lastIndexOf("."); 152 | if(!(dotIndex >= 0 && dotIndex != value.length - 1)) 153 | { 154 | throw new ArgumentError("Extension must contain a dot followed by at least one character."); 155 | } 156 | 157 | _fileExtension = value; 158 | } 159 | 160 | 161 | /** 162 | * Flag to control whether BreezeDb should queue SQL queries, 163 | * i.e. run at most one at a time and in the same order as they are created. 164 | * 165 | * Make sure there are no queries running when changing this value. 166 | * 167 | * @default false 168 | */ 169 | public static function get isQueryQueueEnabled():Boolean 170 | { 171 | return _isQueryQueueEnabled; 172 | } 173 | 174 | 175 | /** 176 | * @private 177 | */ 178 | public static function set isQueryQueueEnabled(value:Boolean):void 179 | { 180 | _isQueryQueueEnabled = value; 181 | BreezeRawQuery.breezedb_internal::useQueryQueue = value; 182 | } 183 | } 184 | } 185 | -------------------------------------------------------------------------------- /src/breezedb/IBreezeDatabase.as: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2017 Digital Strawberry LLC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | * 24 | */ 25 | 26 | package breezedb 27 | { 28 | import breezedb.queries.BreezeQueryBuilder; 29 | import breezedb.queries.IRawQuery; 30 | import breezedb.schemas.BreezeSchemaBuilder; 31 | 32 | import flash.data.SQLConnection; 33 | 34 | import flash.events.IEventDispatcher; 35 | import flash.filesystem.File; 36 | 37 | /** 38 | * Interface that defines API to interact with the database. 39 | */ 40 | public interface IBreezeDatabase extends IEventDispatcher, IRawQuery 41 | { 42 | /** 43 | * Sets up the database by creating SQL connection and database file, if it does not exist. 44 | * The connection is created asynchronously. 45 | * 46 | * @param callback Function called once the setup finishes. It must have the following signature: 47 | * 48 | * function callback(error:Error):void { 49 | * if(error == null) 50 | * { 51 | * // setup completed successfully 52 | * } 53 | * }; 54 | * 55 | * @param databaseFile Reference to a file where the database will be created. If not specified, 56 | * it will default to BreezeDb.storageDirectory where the file name is the 57 | * database name followed by BreezeDb.fileExtension. 58 | * 59 | * @see #close() 60 | * @see breezedb.BreezeDb#fileExtension 61 | * @see breezedb.BreezeDb#storageDirectory 62 | */ 63 | function setup(callback:Function, databaseFile:File = null):void; 64 | 65 | 66 | /** 67 | * Returns query builder associated with the given table. 68 | * 69 | * @param tableName The table that will be associated with the returned query builder. 70 | * @return Query builder associated with the given table. 71 | */ 72 | function table(tableName:String):BreezeQueryBuilder; 73 | 74 | 75 | /** 76 | * Begins a transaction within which all SQL statements executed against the connection's database are grouped. 77 | * 78 | * @param callback Function triggered once the operation finishes. It should have a single Error 79 | * object as a parameter. 80 | * 81 | * @see #commit() 82 | * @see #rollBack() 83 | */ 84 | function beginTransaction(callback:Function):void; 85 | 86 | 87 | /** 88 | * Commits an existing transaction, causing any actions performed by the transaction's statements to be 89 | * permanently applied to the database. 90 | * 91 | * @param callback Function triggered once the operation finishes. It should have a single Error 92 | * object as a parameter. 93 | * 94 | * @see #beginTransaction() 95 | * @see #rollBack() 96 | */ 97 | function commit(callback:Function):void; 98 | 99 | 100 | /** 101 | * Rolls back an existing transaction created using the beginTransaction method, 102 | * meaning all changes made by any SQL statements in the transaction are discarded. 103 | * 104 | * @param callback Function triggered once the operation finishes. It should have a single Error 105 | * object as a parameter. 106 | * 107 | * @see #commit() 108 | * @see #beginTransaction() 109 | */ 110 | function rollBack(callback:Function):void; 111 | 112 | 113 | /** 114 | * Closes the existing SQL connection. 115 | * 116 | * @param callback Function called once the operation finishes. It must have the following signature: 117 | * 118 | * function callback(error:Error):void { 119 | * if(error == null) 120 | * { 121 | * // connection closed successfully 122 | * } 123 | * }; 124 | * 125 | * 126 | * @see #setup() 127 | */ 128 | function close(callback:Function):void; 129 | 130 | 131 | /** 132 | * Runs the given migrations. The database must be set up before calling this method. 133 | * 134 | * @param migrations A class or an Array of migration classes. 135 | * Each class must be a subclass of BreezeMigration. 136 | * @param callback Function called once the migrations are completed. It must have the following signature: 137 | * 138 | * function callback(error:Error):void { 139 | * if(error == null) 140 | * { 141 | * // migrations ran successfully 142 | * } 143 | * }; 144 | * 145 | * 146 | * @see #migrations 147 | * @see breezedb.migrations.BreezeMigration 148 | */ 149 | function runMigrations(migrations:*, callback:Function):void; 150 | 151 | 152 | /** 153 | * @private 154 | */ 155 | function set migrations(value:*):void; 156 | 157 | 158 | /** 159 | * A class or an Array of migration classes that will be run during the database setup. 160 | * Each class must be a subclass of BreezeMigration. 161 | * 162 | * @see #runMigrations() 163 | * @see breezedb.migrations.BreezeMigration 164 | */ 165 | function get migrations():*; 166 | 167 | 168 | /** 169 | * Returns schema builder associated with the database. 170 | */ 171 | function get schema():BreezeSchemaBuilder; 172 | 173 | 174 | /** 175 | * Reference to the file where the database is stored. 176 | */ 177 | function get file():File; 178 | 179 | 180 | /** 181 | * Name of the database. 182 | */ 183 | function get name():String; 184 | 185 | 186 | /** 187 | * Returns true if the database is set up and the SQL connection is active. 188 | */ 189 | function get isSetup():Boolean; 190 | 191 | 192 | /** 193 | * @private 194 | */ 195 | function set encryptionKey(value:*):void; 196 | 197 | 198 | /** 199 | * The value used to encrypt the database file. It be either a String 200 | * (at least one character) or 16 bytes long ByteArray. 201 | */ 202 | function get encryptionKey():*; 203 | 204 | 205 | /** 206 | * The SQL connection for this database. 207 | */ 208 | function get connection():SQLConnection; 209 | 210 | 211 | /** 212 | * Returns true if the database connection is currently involved in a transaction. 213 | */ 214 | function get inTransaction():Boolean; 215 | } 216 | 217 | } 218 | -------------------------------------------------------------------------------- /src/breezedb/breezedb_internal.as: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2017 Digital Strawberry LLC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | * 24 | */ 25 | 26 | package breezedb 27 | { 28 | 29 | internal namespace breezedb_internal = "https://getbreeze.io/breezedb"; 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/breezedb/events/BreezeDatabaseEvent.as: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2017 Digital Strawberry LLC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | * 24 | */ 25 | 26 | package breezedb.events 27 | { 28 | import flash.events.Event; 29 | 30 | /** 31 | * Event dispatched after one of the database operations is executed. 32 | */ 33 | public class BreezeDatabaseEvent extends Event 34 | { 35 | 36 | /** 37 | * A transaction has begun successfully. 38 | */ 39 | public static const BEGIN_SUCCESS:String = "BreezeDatabaseEvent::beginSuccess"; 40 | 41 | /** 42 | * Failed to begin a transaction. 43 | */ 44 | public static const BEGIN_ERROR:String = "BreezeDatabaseEvent::beginError"; 45 | 46 | /** 47 | * A transaction was committed successfully. 48 | */ 49 | public static const COMMIT_SUCCESS:String = "BreezeDatabaseEvent::commitSuccess"; 50 | 51 | /** 52 | * Failed to commit a transaction. 53 | */ 54 | public static const COMMIT_ERROR:String = "BreezeDatabaseEvent::commitError"; 55 | 56 | /** 57 | * A transaction was rolled back successfully. 58 | */ 59 | public static const ROLL_BACK_SUCCESS:String = "BreezeDatabaseEvent::rollBackSuccess"; 60 | 61 | /** 62 | * Failed to roll back a transaction. 63 | */ 64 | public static const ROLL_BACK_ERROR:String = "BreezeDatabaseEvent::rollBackError"; 65 | 66 | /** 67 | * A database has been set up successfully. 68 | */ 69 | public static const SETUP_SUCCESS:String = "BreezeDatabaseEvent::setupSuccess"; 70 | 71 | /** 72 | * Failed to set up a database. 73 | */ 74 | public static const SETUP_ERROR:String = "BreezeDatabaseEvent::setupError"; 75 | 76 | /** 77 | * A database was closed successfully. 78 | */ 79 | public static const CLOSE_SUCCESS:String = "BreezeDatabaseEvent::closeSuccess"; 80 | 81 | /** 82 | * Failed to close a database. 83 | */ 84 | public static const CLOSE_ERROR:String = "BreezeDatabaseEvent::closeError"; 85 | 86 | 87 | private var _error:Error; 88 | 89 | 90 | /** 91 | * @private 92 | */ 93 | public function BreezeDatabaseEvent(type:String, error:Error = null) 94 | { 95 | super(type, false, false); 96 | 97 | _error = error; 98 | } 99 | 100 | 101 | /** 102 | * @inheritDoc 103 | */ 104 | override public function clone():Event 105 | { 106 | return new BreezeDatabaseEvent(type, _error); 107 | } 108 | 109 | 110 | /** 111 | * Error that occurred while executing the corresponding operation, or null if there is no error. 112 | */ 113 | public function get error():Error 114 | { 115 | return _error; 116 | } 117 | } 118 | 119 | } 120 | -------------------------------------------------------------------------------- /src/breezedb/events/BreezeMigrationEvent.as: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2017 Digital Strawberry LLC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | * 24 | */ 25 | 26 | package breezedb.events 27 | { 28 | import flash.events.Event; 29 | 30 | /** 31 | * Event dispatched when a database migration is completed, either successfully or with an error. 32 | */ 33 | public class BreezeMigrationEvent extends Event 34 | { 35 | /** 36 | * A migration ran successfully. 37 | */ 38 | public static const RUN_SUCCESS:String = "BreezeMigrationEvent::runSuccess"; 39 | 40 | /** 41 | * Failed to run a migration. 42 | */ 43 | public static const RUN_ERROR:String = "BreezeMigrationEvent::runError"; 44 | 45 | /** 46 | * A migration was skipped because it had already been run. 47 | */ 48 | public static const SKIP:String = "BreezeMigrationEvent::skip"; 49 | 50 | /** 51 | * Finished running migrations. Note this does not mean all migrations had run, 52 | * only that no further migrations will run. 53 | */ 54 | public static const FINISH:String = "BreezeMigrationEvent::finish"; 55 | 56 | 57 | /** 58 | * @private 59 | */ 60 | public function BreezeMigrationEvent(type:String) 61 | { 62 | super(type, false, false); 63 | } 64 | 65 | 66 | /** 67 | * @inheritDoc 68 | */ 69 | override public function clone():Event 70 | { 71 | return new BreezeMigrationEvent(type); 72 | } 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /src/breezedb/events/BreezeQueryEvent.as: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2017 Digital Strawberry LLC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | * 24 | */ 25 | 26 | package breezedb.events 27 | { 28 | import breezedb.queries.BreezeSQLResult; 29 | 30 | import flash.events.Event; 31 | 32 | /** 33 | * Event dispatched when a SQL query execution is finished, either successfully or with an error. 34 | */ 35 | public class BreezeQueryEvent extends Event 36 | { 37 | /** 38 | * A query was executed successfully. 39 | */ 40 | public static const SUCCESS:String = "BreezeQueryEvent::success"; 41 | 42 | /** 43 | * Failed to execute a query. 44 | */ 45 | public static const ERROR:String = "BreezeQueryEvent::error"; 46 | 47 | private var _error:Error; 48 | private var _result:BreezeSQLResult; 49 | private var _query:String; 50 | 51 | 52 | /** 53 | * @private 54 | */ 55 | public function BreezeQueryEvent(type:String, error:Error, result:BreezeSQLResult, query:String) 56 | { 57 | super(type, false, false); 58 | _error = error; 59 | _result = result; 60 | _query = query; 61 | } 62 | 63 | 64 | /** 65 | * @inheritDoc 66 | */ 67 | override public function clone():Event 68 | { 69 | return new BreezeQueryEvent(type, _error, _result, _query); 70 | } 71 | 72 | 73 | /** 74 | * Error that occurred while executing the query, or null if there is no error. 75 | */ 76 | public function get error():Error 77 | { 78 | return _error; 79 | } 80 | 81 | 82 | /** 83 | * SQL result of the query. It is null for queries regarding table / column schema. 84 | */ 85 | public function get result():BreezeSQLResult 86 | { 87 | return _result; 88 | } 89 | 90 | 91 | /** 92 | * The raw SQL query that was executed. 93 | */ 94 | public function get query():String 95 | { 96 | return _query; 97 | } 98 | } 99 | 100 | } 101 | -------------------------------------------------------------------------------- /src/breezedb/events/BreezeSQLStatementEvent.as: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2017 Digital Strawberry LLC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | * 24 | */ 25 | 26 | package breezedb.events 27 | { 28 | import flash.events.Event; 29 | 30 | /** 31 | * Event dispatched when a SQL statement is completed, either successfully or with an error. 32 | * Internal use only. 33 | * @private 34 | */ 35 | public class BreezeSQLStatementEvent extends Event 36 | { 37 | /** 38 | * A SQL statement has completed. 39 | */ 40 | public static const COMPLETE:String = "BreezeSQLStatementEvent::complete"; 41 | 42 | 43 | /** 44 | * @private 45 | */ 46 | public function BreezeSQLStatementEvent(type:String) 47 | { 48 | super(type, false, false); 49 | } 50 | 51 | 52 | /** 53 | * @inheritDoc 54 | */ 55 | override public function clone():Event 56 | { 57 | return new BreezeSQLStatementEvent(type); 58 | } 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /src/breezedb/migrations/BreezeMigration.as: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2017 Digital Strawberry LLC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | * 24 | */ 25 | 26 | package breezedb.migrations 27 | { 28 | import breezedb.IBreezeDatabase; 29 | import breezedb.events.BreezeMigrationEvent; 30 | 31 | import flash.events.EventDispatcher; 32 | import flash.utils.getQualifiedClassName; 33 | 34 | /** 35 | * Base class providing API to run a database migration. 36 | */ 37 | public class BreezeMigration extends EventDispatcher 38 | { 39 | 40 | /** 41 | * @private 42 | */ 43 | public function BreezeMigration() 44 | { 45 | } 46 | 47 | 48 | /** 49 | * Provides the migration functionality. Must be overridden. 50 | * 51 | * @param db Reference to the database used during this migration. 52 | */ 53 | public function run(db:IBreezeDatabase):void 54 | { 55 | throw new Error("The run method must be overridden."); 56 | } 57 | 58 | 59 | /** 60 | * The done method must be called at the end of each migration. 61 | * 62 | * @param successful true if the migration was successful, false otherwise. 63 | */ 64 | protected final function done(successful:Boolean = true):void 65 | { 66 | var eventType:String = successful ? BreezeMigrationEvent.RUN_SUCCESS : BreezeMigrationEvent.RUN_ERROR; 67 | dispatchEvent(new BreezeMigrationEvent(eventType)); 68 | } 69 | 70 | 71 | /** 72 | * @private 73 | * Returns the class name. Stored in a database table to track previously run migrations. 74 | */ 75 | internal function get name():String 76 | { 77 | var className:String = getQualifiedClassName(this); 78 | var index:int = className.lastIndexOf("::"); 79 | if(index >= 0) 80 | { 81 | className = className.slice(index + 2); 82 | } 83 | return className; 84 | } 85 | 86 | } 87 | 88 | } 89 | -------------------------------------------------------------------------------- /src/breezedb/migrations/BreezeMigrationsRunner.as: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2017 Digital Strawberry LLC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | * 24 | */ 25 | 26 | package breezedb.migrations 27 | { 28 | import breezedb.IBreezeDatabase; 29 | import breezedb.collections.Collection; 30 | import breezedb.events.BreezeMigrationEvent; 31 | import breezedb.schemas.TableBlueprint; 32 | 33 | import flash.events.EventDispatcher; 34 | 35 | /** 36 | * @private 37 | */ 38 | public class BreezeMigrationsRunner extends EventDispatcher 39 | { 40 | private static const MIGRATIONS_TABLE:String = "breeze_migrations_internal"; 41 | 42 | private var _currentIndex:int = -1; 43 | 44 | // True if this runner is in control of the current transaction 45 | private var _transactionControl:Boolean; 46 | 47 | private var _db:IBreezeDatabase; 48 | private var _callback:Function; 49 | private var _migrations:Vector.; 50 | private var _previousMigrations:Collection; 51 | 52 | public function BreezeMigrationsRunner(db:IBreezeDatabase) 53 | { 54 | _db = db; 55 | _migrations = new []; 56 | } 57 | 58 | 59 | breezedb_internal function run(migrations:*, callback:Function = null):void 60 | { 61 | _callback = callback; 62 | 63 | if(migrations is Class) 64 | { 65 | migrations = [migrations]; 66 | } 67 | 68 | if(!(migrations is Array) || (migrations.length == 0)) 69 | { 70 | triggerCallback(new ArgumentError("Migrations can be either a Class or Array of Classes.")); 71 | return; 72 | } 73 | 74 | var length:int = migrations.length; 75 | for(var i:int = 0; i < length; ++i) 76 | { 77 | var migrationClass:* = migrations[i]; 78 | if(!(migrationClass is Class)) 79 | { 80 | triggerCallback(new ArgumentError("Migration can be either a Class or Array of Classes.")); 81 | return; 82 | } 83 | if(!addMigrationClass(migrationClass)) 84 | { 85 | triggerCallback(new ArgumentError(migrationClass + " must be a subclass of BreezeMigration.")); 86 | return; 87 | } 88 | } 89 | 90 | loadPreviousMigrations(); 91 | } 92 | 93 | 94 | private function addMigrationClass(migrationClass:Class):Boolean 95 | { 96 | var migration:* = new migrationClass(); 97 | if(!(migration is BreezeMigration)) 98 | { 99 | return false; 100 | } 101 | _migrations[_migrations.length] = migration as BreezeMigration; 102 | return true; 103 | } 104 | 105 | 106 | private function loadPreviousMigrations():void 107 | { 108 | _db.schema.hasTable(MIGRATIONS_TABLE, onMigrationTableSchemaLoaded); 109 | } 110 | 111 | 112 | private function onMigrationTableSchemaLoaded(error:Error, hasTable:Boolean):void 113 | { 114 | // Create the table if it does not exist 115 | if(!hasTable) 116 | { 117 | _db.schema.createTable(MIGRATIONS_TABLE, function(table:TableBlueprint):void 118 | { 119 | table.string("name").unique(); 120 | }, onMigrationsTableCreated); 121 | } 122 | // Otherwise load the table records 123 | else 124 | { 125 | _db.table(MIGRATIONS_TABLE).fetch(onPreviousMigrationsLoaded); 126 | } 127 | } 128 | 129 | 130 | private function onMigrationsTableCreated(error:Error):void 131 | { 132 | if(error == null) 133 | { 134 | // Table has just been created, no migrations exist 135 | onPreviousMigrationsLoaded(null, new Collection()); 136 | } 137 | // Failed to create the table so fail the current migrations 138 | else 139 | { 140 | triggerCallback(error); 141 | } 142 | } 143 | 144 | 145 | private function onPreviousMigrationsLoaded(error:Error, previousMigrations:Collection):void 146 | { 147 | if(error == null) 148 | { 149 | _previousMigrations = previousMigrations; 150 | 151 | // Begin transaction and run the migrations 152 | if(!_db.inTransaction) 153 | { 154 | _transactionControl = true; 155 | _db.beginTransaction(onTransactionBegan); 156 | } 157 | else 158 | { 159 | onTransactionBegan(null); 160 | } 161 | } 162 | // Failed to load previous migrations so fail the current migrations 163 | else 164 | { 165 | triggerCallback(error); 166 | } 167 | } 168 | 169 | 170 | private function onTransactionBegan(error:Error):void 171 | { 172 | if(error == null) 173 | { 174 | runNextMigration(); 175 | } 176 | // Failed to begin transaction so fail the migrations 177 | else 178 | { 179 | triggerCallback(error); 180 | } 181 | } 182 | 183 | 184 | private function runNextMigration():void 185 | { 186 | if(_currentIndex >= _migrations.length - 1) 187 | { 188 | // Finished migrations successfully, commit the transaction 189 | if(_transactionControl) 190 | { 191 | _db.commit(onTransactionCommitted); 192 | } 193 | else 194 | { 195 | onTransactionCommitted(null); 196 | } 197 | return; 198 | } 199 | 200 | var migration:BreezeMigration = _migrations[++_currentIndex]; 201 | migration.addEventListener(BreezeMigrationEvent.RUN_SUCCESS, onMigrationRan); 202 | migration.addEventListener(BreezeMigrationEvent.RUN_ERROR, onMigrationRunError); 203 | migration.addEventListener(BreezeMigrationEvent.SKIP, onMigrationSkipped); 204 | 205 | // Do not run the migration if it ran in the past 206 | if(_previousMigrations.contains(migration.name, "name")) 207 | { 208 | // Dispatch the 'SKIP' event 209 | migration.dispatchEvent(new BreezeMigrationEvent(BreezeMigrationEvent.SKIP)); 210 | return; 211 | } 212 | 213 | // Run the migration now 214 | migration.run(_db); 215 | } 216 | 217 | 218 | private function onMigrationRan(event:BreezeMigrationEvent):void 219 | { 220 | var migration:BreezeMigration = processMigrationEvent(event); 221 | 222 | // The migration was successful, store it in the database so that it does not run again in the future 223 | storeMigration(migration); 224 | } 225 | 226 | 227 | private function onMigrationRunError(event:BreezeMigrationEvent):void 228 | { 229 | var migration:BreezeMigration = processMigrationEvent(event); 230 | 231 | // The migration failed so roll back 232 | if(_transactionControl) 233 | { 234 | _db.rollBack(function(rollBackError:Error):void 235 | { 236 | triggerCallback(new Error("Migration '" + migration.name + "' failed.")); 237 | }); 238 | } 239 | else 240 | { 241 | triggerCallback(new Error("Migration '" + migration.name + "' failed.")); 242 | } 243 | } 244 | 245 | 246 | private function onMigrationSkipped(event:BreezeMigrationEvent):void 247 | { 248 | processMigrationEvent(event); 249 | 250 | // Move on to the next migration 251 | runNextMigration(); 252 | } 253 | 254 | 255 | private function processMigrationEvent(event:BreezeMigrationEvent):BreezeMigration 256 | { 257 | var migration:BreezeMigration = event.currentTarget as BreezeMigration; 258 | migration.removeEventListener(BreezeMigrationEvent.RUN_SUCCESS, onMigrationRan); 259 | migration.removeEventListener(BreezeMigrationEvent.RUN_ERROR, onMigrationRunError); 260 | migration.removeEventListener(BreezeMigrationEvent.SKIP, onMigrationSkipped); 261 | 262 | dispatchEvent(event); 263 | return migration; 264 | } 265 | 266 | 267 | private function storeMigration(migration:BreezeMigration):void 268 | { 269 | _db.table(MIGRATIONS_TABLE).insert({ name: migration.name }, function(insertError:Error):void 270 | { 271 | // Migration stored successfully, run the next migration 272 | if(insertError == null) 273 | { 274 | runNextMigration(); 275 | } 276 | // Otherwise roll back and fail the migrations 277 | else 278 | { 279 | if(_transactionControl) 280 | { 281 | _db.rollBack(function(rollBackError:Error):void 282 | { 283 | triggerCallback(insertError); 284 | }); 285 | } 286 | else 287 | { 288 | triggerCallback(insertError); 289 | } 290 | } 291 | }); 292 | } 293 | 294 | 295 | private function onTransactionCommitted(error:Error):void 296 | { 297 | dispatchEvent(new BreezeMigrationEvent(BreezeMigrationEvent.FINISH)); 298 | 299 | triggerCallback(error); 300 | } 301 | 302 | 303 | private function triggerCallback(error:Error = null):void 304 | { 305 | var callback:Function = _callback; 306 | _callback = null; 307 | if(callback != null) 308 | { 309 | callback(error); 310 | } 311 | } 312 | 313 | } 314 | 315 | } 316 | -------------------------------------------------------------------------------- /src/breezedb/migrations/breezedb_internal.as: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2017 Digital Strawberry LLC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | * 24 | */ 25 | 26 | package breezedb.migrations 27 | { 28 | 29 | internal namespace breezedb_internal = "https://getbreeze.io/breezedb"; 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/breezedb/models/BreezeModel.as: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2017 Digital Strawberry LLC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | * 24 | */ 25 | 26 | package breezedb.models 27 | { 28 | import breezedb.BreezeDb; 29 | import breezedb.queries.BreezeQueryReference; 30 | 31 | import flash.errors.IllegalOperationError; 32 | 33 | import flash.events.EventDispatcher; 34 | import flash.utils.describeType; 35 | import flash.utils.getQualifiedClassName; 36 | 37 | import org.kuwamoto.Inflect; 38 | 39 | /** 40 | * Base class for custom database models. 41 | */ 42 | public class BreezeModel extends EventDispatcher 43 | { 44 | /** 45 | * @private 46 | */ 47 | protected var _databaseName:String = null; 48 | 49 | 50 | /** 51 | * @private 52 | */ 53 | protected var _tableName:String = null; 54 | 55 | 56 | /** 57 | * @private 58 | */ 59 | protected var _primaryKey:String = "id"; 60 | 61 | 62 | /** 63 | * @private 64 | */ 65 | protected var _exists:Boolean = false; 66 | 67 | 68 | /** 69 | * @private 70 | */ 71 | protected var _autoIncrementId:Boolean = true; 72 | 73 | 74 | /** 75 | * Creates new instance of the model. 76 | * 77 | * @param initialValues A key-value Object (where keys represent column names) used 78 | * to initialize the model's properties. 79 | */ 80 | public function BreezeModel(initialValues:Object = null) 81 | { 82 | super(null); 83 | 84 | _databaseName = BreezeDb.DEFAULT_DB; 85 | 86 | if(initialValues != null) 87 | { 88 | populateFromObject(initialValues, false); 89 | } 90 | } 91 | 92 | 93 | /** 94 | * 95 | * 96 | * Public API 97 | * 98 | * 99 | */ 100 | 101 | 102 | /** 103 | * Helper method that retrieves an instance of BreezeModelQueryBuilder for the given model class. 104 | * 105 | * @param modelClass The model to retrieve the builder for. Must be a subclass 106 | * of BreezeModel class. 107 | * @return Instance of BreezeModelQueryBuilder associated with the given model. 108 | */ 109 | public static function query(modelClass:Class):BreezeModelQueryBuilder 110 | { 111 | return new BreezeModelQueryBuilder(modelClass); 112 | } 113 | 114 | 115 | /** 116 | * Saves this model to the database. If it exists, its values will be updated. 117 | * 118 | * @param callback Function that is triggered when the query is completed. The saved model is returned 119 | * to the callback as the second argument. 120 | * 121 | * 122 | * var photo:Photo = new Photo(); 123 | * photo.title = "Sunset"; 124 | * photo.save(callback); 125 | * function callback(error:Error, photo:Photo):void 126 | * { 127 | * 128 | * }; 129 | * 130 | * 131 | * @return BreezeQueryReference object that allows cancelling the request callback. 132 | */ 133 | public function save(callback:Function = null):BreezeQueryReference 134 | { 135 | var modelClass:Class = Object(this).constructor as Class; 136 | return new BreezeModelQueryBuilder(modelClass).save(this, callback); 137 | } 138 | 139 | 140 | /** 141 | * Removes this model from the database. 142 | * 143 | * @param callback Function that is triggered when the query is completed. 144 | * 145 | * 146 | * BreezeModelQueryBuilder.query(Photo).find(1, function(findError:Error, photo:Photo):void 147 | * { 148 | * if(photo != null) 149 | * { 150 | * photo.remove(function(removeError:Error):void 151 | * { 152 | * 153 | * }); 154 | * } 155 | * }); 156 | * 157 | * 158 | * @return BreezeQueryReference object that allows cancelling the request callback. 159 | */ 160 | public function remove(callback:Function = null):BreezeQueryReference 161 | { 162 | var modelClass:Class = Object(this).constructor as Class; 163 | if(primaryKey == null || !(primaryKey in this)) 164 | { 165 | throw new IllegalOperationError("The model " + modelClass + " has no primary key set."); 166 | } 167 | return new BreezeModelQueryBuilder(modelClass).removeByKey(this[primaryKey], callback).queryReference; 168 | } 169 | 170 | 171 | /** 172 | * 173 | * 174 | * Internal / Private API 175 | * 176 | * 177 | */ 178 | 179 | 180 | /** 181 | * @private 182 | */ 183 | internal function populateFromObject(values:Object, exists:Boolean = true):void 184 | { 185 | for(var property:String in values) 186 | { 187 | if(property in this) 188 | { 189 | this[property] = values[property]; 190 | } 191 | } 192 | 193 | setExists(exists); 194 | } 195 | 196 | 197 | /** 198 | * @private 199 | */ 200 | internal function toKeyValue(omitPrimaryKey:Boolean = false):Object 201 | { 202 | var result:Object = {}; 203 | 204 | var description:XML = describeType(this); 205 | var variables:XMLList = description..variable; 206 | for each(var variable:XML in variables) 207 | { 208 | var column:String = variable.@name; 209 | if((column == '') || (omitPrimaryKey && (primaryKey == column))) 210 | { 211 | continue; 212 | } 213 | 214 | result[column] = this[column]; 215 | } 216 | 217 | return result; 218 | } 219 | 220 | 221 | /** 222 | * @private 223 | */ 224 | internal function setExists(value:Boolean):void 225 | { 226 | _exists = value; 227 | } 228 | 229 | 230 | /** 231 | * 232 | * 233 | * Getters / Setters 234 | * 235 | * 236 | */ 237 | 238 | 239 | private function get className():String 240 | { 241 | var className:String = getQualifiedClassName(this); 242 | var index:int = className.lastIndexOf("::"); 243 | if(index >= 0) 244 | { 245 | className = className.slice(index + 2); 246 | } 247 | return className; 248 | } 249 | 250 | 251 | /** 252 | * Returns the model's table name. 253 | */ 254 | public function get tableName():String 255 | { 256 | if(_tableName != null) 257 | { 258 | return _tableName; 259 | } 260 | 261 | var regExp:RegExp = /(^[a-z]|[A-Z0-9])[a-z]*/g; 262 | var className:String = this.className; 263 | var result:Array = className.match(regExp); 264 | 265 | if(result != null && result.length > 0) 266 | { 267 | className = result.join("_"); 268 | } 269 | 270 | className = className.toLowerCase(); 271 | 272 | _tableName = Inflect.pluralize(className); 273 | return _tableName; 274 | } 275 | 276 | 277 | /** 278 | * Returns the model's database name. 279 | */ 280 | public function get databaseName():String 281 | { 282 | return _databaseName; 283 | } 284 | 285 | 286 | /** 287 | * Returns the name of the model's primary key. 288 | */ 289 | public function get primaryKey():String 290 | { 291 | return _primaryKey; 292 | } 293 | 294 | 295 | /** 296 | * Returns true if the model exists in the database. 297 | */ 298 | public function get exists():Boolean 299 | { 300 | return _exists; 301 | } 302 | 303 | 304 | /** 305 | * Returns true if the model has an auto-incrementing id. 306 | */ 307 | public function get autoIncrementId():Boolean 308 | { 309 | return _autoIncrementId; 310 | } 311 | } 312 | 313 | } 314 | -------------------------------------------------------------------------------- /src/breezedb/models/BreezeModelQueryBuilder.as: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2017 Digital Strawberry LLC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | * 24 | */ 25 | 26 | package breezedb.models 27 | { 28 | import breezedb.BreezeDb; 29 | import breezedb.IBreezeDatabase; 30 | import breezedb.collections.Collection; 31 | import breezedb.queries.BreezeQueryBuilder; 32 | import breezedb.queries.BreezeQueryReference; 33 | import breezedb.queries.BreezeSQLResult; 34 | import breezedb.utils.Callback; 35 | import breezedb.utils.GarbagePrevention; 36 | 37 | import flash.errors.IllegalOperationError; 38 | 39 | /** 40 | * Class providing API to run queries on a table associated with the given model. 41 | */ 42 | public class BreezeModelQueryBuilder extends BreezeQueryBuilder 43 | { 44 | private var _model:BreezeModel; 45 | private var _modelClass:Class; 46 | 47 | /** 48 | * Creates a new builder and associates it with a table of the given model. 49 | * 50 | * @param modelClass The model used to obtain database and table against which the queries will be executed. 51 | */ 52 | public function BreezeModelQueryBuilder(modelClass:Class) 53 | { 54 | _modelClass = modelClass; 55 | _model = new modelClass(); 56 | var db:IBreezeDatabase = BreezeDb.getDb(_model.databaseName); 57 | super(db, _model.tableName); 58 | } 59 | 60 | 61 | /** 62 | * 63 | * 64 | * Public API 65 | * 66 | * 67 | */ 68 | 69 | 70 | /** 71 | * @inheritDoc 72 | */ 73 | override public function fetch(callback:* = null):BreezeQueryBuilder 74 | { 75 | if(_callbackProxy == null || _callbackProxy != onFirstCompleted) 76 | { 77 | _callbackProxy = onFetchCompleted; 78 | } 79 | return super.fetch(callback); 80 | } 81 | 82 | 83 | /** 84 | * Finds models that match the given primary keys. 85 | * 86 | * @param primaryKeys Either a single primary key or Array of primary keys. 87 | * @param callback This parameter can be one of the following: 88 | * 111 | * 112 | * @return Instance of BreezeQueryBuilder allowing you to obtain the query reference 113 | * or execute the query at later time if it was delayed. 114 | */ 115 | public function find(primaryKeys:*, callback:* = null):BreezeQueryBuilder 116 | { 117 | if(primaryKeys == null) 118 | { 119 | throw new ArgumentError("Parameter primaryKeys cannot be null."); 120 | } 121 | 122 | if(_model.primaryKey == null) 123 | { 124 | throw new IllegalOperationError("The model " + _modelClass + " has no primary key set."); 125 | } 126 | 127 | // Fetch all the records whose id matches one of the value in the given array 128 | if(primaryKeys is Array) 129 | { 130 | return whereIn(_model.primaryKey, primaryKeys).fetch(callback); 131 | } 132 | 133 | // We are looking for a single value so use the callback proxy of the 'first' method 134 | _callbackProxy = onFirstCompleted; 135 | return where(_model.primaryKey, primaryKeys).fetch(callback); 136 | } 137 | 138 | 139 | /** 140 | * Returns the first model that matches the given values. If match is not found, a new model instance 141 | * with those values is returned. Note this instance is not saved to the database. 142 | * You will need to call the model's save method. 143 | * 144 | * @param values Key-value object specifying column names and values that will be used to find the matching model. 145 | * @param callback Function that is triggered when the query is completed. 146 | * 147 | * 148 | * // Find or return new instance of Photo model with title "Sunset" 149 | * var modelBuilder:BreezeModelQueryBuilder = new BreezeModelQueryBuilder(Photo); 150 | * modelBuilder.firstOrNew({ title: "Sunset" }, callback); 151 | * function callback(error:Error, photo:Photo):void 152 | * { 153 | * }; 154 | * 155 | * 156 | * @see #firstOrCreate() 157 | */ 158 | public function firstOrNew(values:Object, callback:Function = null):void 159 | { 160 | firstOrInit(values, callback); 161 | } 162 | 163 | 164 | /** 165 | * Returns the first model that matches the given values. If match is not found, a new model instance 166 | * with those values is returned and saved to the database. 167 | * 168 | * @param values Key-value object specifying column names and values that will be used to find the matching model. 169 | * @param callback Function that is triggered when the query is completed. 170 | * 171 | * 172 | * // Find or create new instance of Photo model with title "Sunset" 173 | * var modelBuilder:BreezeModelQueryBuilder = new BreezeModelQueryBuilder(Photo); 174 | * modelBuilder.firstOrNew({ title: "Sunset" }, callback); 175 | * function callback(error:Error, photo:Photo):void 176 | * { 177 | * if(error == null) 178 | * { 179 | * trace(photo.exists); // true 180 | * } 181 | * }; 182 | * 183 | * 184 | * @see #firstOrNew() 185 | */ 186 | public function firstOrCreate(values:Object, callback:Function = null):void 187 | { 188 | firstOrInit(values, callback, true); 189 | } 190 | 191 | 192 | /** 193 | * Removes all the models that match the given primary keys. 194 | * 195 | * @param primaryKeys Either a single primary key or Array of primary keys. 196 | * @param callback Function that is triggered when the query is completed. 197 | * 198 | * 199 | * // Remove photos with id of 1 and 2 200 | * var modelBuilder:BreezeModelQueryBuilder = new BreezeModelQueryBuilder(Photo); 201 | * modelBuilder.removeByKey([1, 2], callback); 202 | * function callback(error:Error):void 203 | * { 204 | * if(error == null) 205 | * { 206 | * 207 | * } 208 | * }; 209 | * 210 | * 211 | * @return Instance of BreezeQueryBuilder allowing you to obtain the query reference 212 | * or execute the query at later time if it was delayed. 213 | */ 214 | public function removeByKey(primaryKeys:*, callback:* = null):BreezeQueryBuilder 215 | { 216 | if(primaryKeys == null) 217 | { 218 | throw new ArgumentError("Parameter primaryKeys cannot be null."); 219 | } 220 | 221 | if(_model.primaryKey == null || !(_model.primaryKey in _model)) 222 | { 223 | throw new IllegalOperationError("The model " + _modelClass + " has no primary key set."); 224 | } 225 | 226 | if(primaryKeys is Array) 227 | { 228 | whereIn(_model.primaryKey, primaryKeys); 229 | } 230 | else 231 | { 232 | where(_model.primaryKey, primaryKeys); 233 | } 234 | 235 | return remove(callback); 236 | } 237 | 238 | 239 | /** 240 | * 241 | * 242 | * Internal / Private API 243 | * 244 | * 245 | */ 246 | 247 | 248 | private function getTypedCollection(collection:Collection):Collection 249 | { 250 | var castCollection:Collection = new Collection(); 251 | 252 | // Cast each Object to model object 253 | for(var i:int = 0; i < collection.length; i++) 254 | { 255 | var model:BreezeModel = new _modelClass(); 256 | model.populateFromObject(collection[i]); 257 | castCollection.add(model); 258 | } 259 | 260 | return castCollection; 261 | } 262 | 263 | 264 | /** 265 | * Internal implementation for 'firstOrNew' and 'firstOrCreate'. 266 | */ 267 | private function firstOrInit(values:Object, callback:Function = null, saveToDatabase:Boolean = false):void 268 | { 269 | if(values == null) 270 | { 271 | throw new ArgumentError("Parameter values cannot be null."); 272 | } 273 | 274 | // Add 'where' clause for each key-value 275 | for(var key:String in values) 276 | { 277 | where(key, values[key]); 278 | } 279 | 280 | var self:BreezeModelQueryBuilder = this; 281 | 282 | // Retrieve the first model matching the given values 283 | first(function(firstError:Error, model:BreezeModel):void 284 | { 285 | // Match not found, create new model 286 | if(model == null) 287 | { 288 | model = new _modelClass(); 289 | model.populateFromObject(values, false); 290 | 291 | // Save the model first then trigger the callback 292 | if(saveToDatabase) 293 | { 294 | GarbagePrevention.instance.add(self); 295 | model.save(function(saveError:Error, savedModel:BreezeModel):void 296 | { 297 | GarbagePrevention.instance.remove(self); 298 | Callback.call(callback, [saveError, model]); 299 | }); 300 | return; 301 | } 302 | } 303 | 304 | // Create the model with the next available id 305 | if(!model.exists && model.autoIncrementId && !hasSetId(model)) 306 | { 307 | model[model.primaryKey] = _db.connection.lastInsertRowID + 1; 308 | } 309 | Callback.call(callback, [firstError, model]); 310 | }); 311 | } 312 | 313 | 314 | /** 315 | * @private 316 | */ 317 | internal function save(model:BreezeModel, callback:Function = null):BreezeQueryReference 318 | { 319 | _model = model; 320 | 321 | // Perform update 322 | if(model.exists) 323 | { 324 | // We need the primary key to do that 325 | if(model.primaryKey == null || !(model.primaryKey in model)) 326 | { 327 | throw new IllegalOperationError("Cannot update model " + model + " when the primary key is unknown."); 328 | } 329 | 330 | _callbackProxy = onUpdateViaSaveCompleted; 331 | return where(model.primaryKey, model[model.primaryKey]) 332 | .update(model.toKeyValue(), callback) 333 | .queryReference; 334 | } 335 | 336 | // Perform insertGetId 337 | _callbackProxy = onInsertViaSaveCompleted; 338 | 339 | // Omit the primary key in the insert statement to have one assigned automatically via auto-increment 340 | var omitPrimaryKey:Boolean = (model.autoIncrementId) && !hasSetId(model); 341 | return insertGetId(model.toKeyValue(omitPrimaryKey), callback).queryReference; 342 | } 343 | 344 | 345 | private function hasSetId(model:BreezeModel):Boolean 346 | { 347 | return !((model.primaryKey != null) && (model.primaryKey in model) && (model[model.primaryKey] is Number) && (model[model.primaryKey] < 1)); 348 | } 349 | 350 | 351 | /** 352 | * 353 | * Proxy callbacks 354 | * 355 | * Cast query response to model's class. 356 | * 357 | */ 358 | 359 | 360 | /** 361 | * @private 362 | */ 363 | override protected function onFirstCompleted(error:Error, results:Collection):void 364 | { 365 | _callbackProxy = null; 366 | 367 | var result:Object = (results.length > 0) ? results[0] : null; 368 | var model:BreezeModel = null; 369 | if(result != null) 370 | { 371 | model = new _modelClass(); 372 | model.populateFromObject(result); 373 | } 374 | finishProxiedQuery([error, model]); 375 | } 376 | 377 | 378 | /** 379 | * @private 380 | */ 381 | override protected function onChunkCompleted(error:Error, results:Collection):void 382 | { 383 | var castCollection:Collection = getTypedCollection(results); 384 | super.onChunkCompleted(error, castCollection); 385 | } 386 | 387 | 388 | /** 389 | * @private 390 | */ 391 | protected function onFetchCompleted(error:Error, results:Collection):void 392 | { 393 | _callbackProxy = null; 394 | 395 | var castCollection:Collection = getTypedCollection(results); 396 | finishProxiedQuery([error, castCollection]); 397 | } 398 | 399 | 400 | /** 401 | * @private 402 | */ 403 | protected function onUpdateViaSaveCompleted(error:Error, rowsAffected:int):void 404 | { 405 | _callbackProxy = null; 406 | 407 | finishProxiedQuery([error, _model]); 408 | } 409 | 410 | 411 | /** 412 | * @private 413 | */ 414 | protected function onInsertViaSaveCompleted(error:Error, result:BreezeSQLResult):void 415 | { 416 | _callbackProxy = null; 417 | 418 | if(error == null) 419 | { 420 | if(_model.primaryKey != null && 421 | _model.autoIncrementId && 422 | _model.hasOwnProperty(_model.primaryKey) && 423 | (_model[_model.primaryKey] is Number)) 424 | { 425 | _model[_model.primaryKey] = result.lastInsertRowID; 426 | } 427 | _model.setExists(true); 428 | } 429 | finishProxiedQuery([error, _model]); 430 | } 431 | } 432 | 433 | } 434 | -------------------------------------------------------------------------------- /src/breezedb/queries/BreezeJoinStatement.as: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2017 Digital Strawberry LLC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | * 24 | */ 25 | 26 | package breezedb.queries 27 | { 28 | 29 | internal class BreezeJoinStatement 30 | { 31 | public static const INNER_JOIN:String = "INNER JOIN"; 32 | public static const LEFT_OUTER_JOIN:String = "LEFT OUTER JOIN"; 33 | public static const CROSS_JOIN:String = "CROSS JOIN"; 34 | 35 | private var _type:String; 36 | private var _tableName:String; 37 | private var _predicate:String; 38 | 39 | public function BreezeJoinStatement(type:String, tableName:String, predicate:String = null) 40 | { 41 | _type = type; 42 | _tableName = tableName; 43 | _predicate = predicate; 44 | } 45 | 46 | 47 | public function get type():String 48 | { 49 | return _type; 50 | } 51 | 52 | 53 | public function get tableName():String 54 | { 55 | return _tableName; 56 | } 57 | 58 | 59 | public function get predicate():String 60 | { 61 | return _predicate; 62 | } 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /src/breezedb/queries/BreezeQueryReference.as: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2017 Digital Strawberry LLC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | * 24 | */ 25 | 26 | package breezedb.queries 27 | { 28 | import flash.events.Event; 29 | import flash.events.EventDispatcher; 30 | 31 | /** 32 | * Class providing API that allows cancelling callback of executed query. 33 | */ 34 | public class BreezeQueryReference extends EventDispatcher 35 | { 36 | /** 37 | * Name for event that is dispatched when the query is cancelled. 38 | */ 39 | public static const CANCEL:String = "cancel"; 40 | 41 | private var _rawQuery:BreezeRawQuery; 42 | 43 | 44 | /** 45 | * @private 46 | */ 47 | public function BreezeQueryReference(rawQuery:BreezeRawQuery) 48 | { 49 | _rawQuery = rawQuery; 50 | } 51 | 52 | 53 | /** 54 | * Prevents the query callback from being triggered. Note that this does not stop 55 | * the actual SQL query from running, it only stops the callback from being called. 56 | */ 57 | public function cancel():void 58 | { 59 | _rawQuery.cancel(); 60 | dispatchEvent(new Event(CANCEL)); 61 | } 62 | 63 | 64 | /** 65 | * Returns true if the query is completed. 66 | */ 67 | public function get isCompleted():Boolean 68 | { 69 | return _rawQuery.isCompleted; 70 | } 71 | 72 | 73 | /** 74 | * Returns true if the query is cancelled. 75 | */ 76 | public function get isCancelled():Boolean 77 | { 78 | return _rawQuery.isCancelled; 79 | } 80 | } 81 | 82 | } 83 | -------------------------------------------------------------------------------- /src/breezedb/queries/BreezeQueryResult.as: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2017 Digital Strawberry LLC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | * 24 | */ 25 | 26 | package breezedb.queries 27 | { 28 | import flash.data.SQLResult; 29 | 30 | /** 31 | * Class providing access to results of a single query when executing multiple SQL statements. 32 | */ 33 | public class BreezeQueryResult extends BreezeSQLResult 34 | { 35 | private var _error:Error; 36 | 37 | 38 | /** 39 | * @private 40 | */ 41 | public function BreezeQueryResult(result:SQLResult, error:Error) 42 | { 43 | super(result); 44 | 45 | _error = error; 46 | } 47 | 48 | 49 | /** 50 | * An error that occurred while executing the query, or null if there is no error. 51 | */ 52 | public function get error():Error 53 | { 54 | return _error; 55 | } 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /src/breezedb/queries/BreezeQueryRunner.as: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2017 Digital Strawberry LLC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | * 24 | */ 25 | 26 | package breezedb.queries 27 | { 28 | import breezedb.IBreezeDatabase; 29 | import breezedb.utils.GarbagePrevention; 30 | 31 | import flash.events.Event; 32 | 33 | /** 34 | * Base class for classes that create and run SQL queries. 35 | */ 36 | public class BreezeQueryRunner 37 | { 38 | /** 39 | * @private 40 | */ 41 | internal static const MULTI_QUERY_RAW:int = 0; 42 | 43 | /** 44 | * @private 45 | */ 46 | internal static const MULTI_QUERY_FAIL_ON_ERROR:int = 1; 47 | 48 | /** 49 | * @private 50 | */ 51 | internal static const MULTI_QUERY_TRANSACTION:int = 2; 52 | 53 | /** 54 | * @private 55 | */ 56 | internal static const QUERY_RAW:int = 0; 57 | 58 | /** 59 | * @private 60 | */ 61 | internal static const QUERY_SELECT:int = 1; 62 | 63 | /** 64 | * @private 65 | */ 66 | internal static const QUERY_DELETE:int = 2; 67 | 68 | /** 69 | * @private 70 | */ 71 | internal static const QUERY_INSERT:int = 3; 72 | 73 | /** 74 | * @private 75 | */ 76 | internal static const QUERY_UPDATE:int = 4; 77 | 78 | /** 79 | * @private 80 | */ 81 | protected var _db:IBreezeDatabase; 82 | 83 | /** 84 | * @private 85 | */ 86 | protected var _queryString:String; 87 | 88 | /** 89 | * @private 90 | */ 91 | protected var _queryType:int; 92 | 93 | /** 94 | * @private 95 | */ 96 | protected var _queryParams:Object; 97 | 98 | /** 99 | * @private 100 | */ 101 | protected var _queryReference:BreezeQueryReference; 102 | 103 | /** 104 | * @private 105 | */ 106 | protected var _multiQueryMethod:int; 107 | 108 | /** 109 | * @private 110 | * Reference to the original callback, if callback proxy is used. 111 | */ 112 | protected var _originalCallback:Function; 113 | 114 | /** 115 | * @private 116 | * Callback used in place of the provided callback. Useful when the query response 117 | * needs further processing, e.g. during query builder's chunk call. 118 | */ 119 | protected var _callbackProxy:Function; 120 | 121 | 122 | /** 123 | * @private 124 | */ 125 | public function BreezeQueryRunner(db:IBreezeDatabase) 126 | { 127 | if(db == null) 128 | { 129 | throw new ArgumentError("Parameter db cannot be null."); 130 | } 131 | 132 | _db = db; 133 | _queryParams = null; 134 | _queryType = QUERY_RAW; 135 | _multiQueryMethod = MULTI_QUERY_TRANSACTION; 136 | } 137 | 138 | 139 | /** 140 | * Executes the query, if it was delayed initially. 141 | * 142 | * @param callback Function that is triggered when the query is completed. The function's signature 143 | * depends on the original query being executed. Refer to the documentation of the method 144 | * used to create the query. 145 | * @return Reference to the executed query. 146 | */ 147 | public function exec(callback:Function = null):BreezeQueryReference 148 | { 149 | if(_queryReference != null) 150 | { 151 | return _queryReference; 152 | } 153 | 154 | // Check if there are multiple statements 155 | var queries:Array = _queryString.split(";"); 156 | 157 | // Remove empty queries 158 | for(var i:int = 0; i < queries.length; ) 159 | { 160 | var queryString:String = queries[i]; 161 | if(!(/\S/.test(queryString))) 162 | { 163 | queries.removeAt(i); 164 | continue; 165 | } 166 | ++i; 167 | } 168 | 169 | if(_callbackProxy != null) 170 | { 171 | _originalCallback = callback; 172 | callback = _callbackProxy; 173 | 174 | GarbagePrevention.instance.add(this); 175 | } 176 | 177 | // Run multi query if there are multiple statements 178 | if(queries.length > 1) 179 | { 180 | switch(_multiQueryMethod) 181 | { 182 | case MULTI_QUERY_RAW: 183 | _queryReference = _db.multiQuery(queries, _queryParams, callback); 184 | break; 185 | case MULTI_QUERY_FAIL_ON_ERROR: 186 | _queryReference = _db.multiQueryFailOnError(queries, _queryParams, callback); 187 | break; 188 | case MULTI_QUERY_TRANSACTION: 189 | _queryReference = _db.multiQueryTransaction(queries, _queryParams, callback); 190 | break; 191 | } 192 | listenToQueryCancel(); 193 | return _queryReference; 194 | } 195 | 196 | _queryString = queries.join(";"); 197 | _queryString += ";"; 198 | 199 | switch(_queryType) 200 | { 201 | case QUERY_RAW: 202 | _queryReference = _db.query(_queryString, _queryParams, callback); 203 | break; 204 | case QUERY_SELECT: 205 | _queryReference = _db.select(_queryString, _queryParams, callback); 206 | break; 207 | case QUERY_DELETE: 208 | _queryReference = _db.remove(_queryString, _queryParams, callback); 209 | break; 210 | case QUERY_INSERT: 211 | _queryReference = _db.insert(_queryString, _queryParams, callback); 212 | break; 213 | case QUERY_UPDATE: 214 | _queryReference = _db.update(_queryString, _queryParams, callback); 215 | break; 216 | } 217 | listenToQueryCancel(); 218 | return _queryReference; 219 | } 220 | 221 | 222 | /** 223 | * 224 | * 225 | * Private API 226 | * 227 | * 228 | */ 229 | 230 | 231 | private function listenToQueryCancel():void 232 | { 233 | // If we are using a proxy, we need to remove this object from GarbagePrevention 234 | // when the query is cancelled, since the proxy will not be triggered 235 | if(_callbackProxy != null) 236 | { 237 | _queryReference.addEventListener(BreezeQueryReference.CANCEL, onQueryCancelled, false, 0, true); 238 | } 239 | } 240 | 241 | 242 | private function onQueryCancelled(event:Event):void 243 | { 244 | _queryReference.removeEventListener(BreezeQueryReference.CANCEL, onQueryCancelled); 245 | GarbagePrevention.instance.remove(this); 246 | } 247 | 248 | 249 | /** 250 | * @private 251 | */ 252 | protected function finishProxiedQuery(params:Array):* 253 | { 254 | _queryReference.removeEventListener(BreezeQueryReference.CANCEL, onQueryCancelled); 255 | GarbagePrevention.instance.remove(this); 256 | 257 | if(!_queryReference.isCancelled && _originalCallback != null) 258 | { 259 | params = (params == null) ? null : params.slice(0, _originalCallback.length); 260 | 261 | return _originalCallback.apply(_originalCallback, params); 262 | } 263 | } 264 | 265 | 266 | /** 267 | * @private 268 | */ 269 | internal function setMultiQueryMethod(value:int):void 270 | { 271 | _multiQueryMethod = value; 272 | } 273 | 274 | 275 | /** 276 | * @private 277 | */ 278 | internal function get database():IBreezeDatabase 279 | { 280 | return _db; 281 | } 282 | 283 | 284 | /** 285 | * @private 286 | */ 287 | internal function get parameters():Object 288 | { 289 | return _queryParams; 290 | } 291 | 292 | 293 | /** 294 | * 295 | * 296 | * Getters / Setters 297 | * 298 | * 299 | */ 300 | 301 | 302 | /** 303 | * The SQL query to be executed. 304 | */ 305 | public function get queryString():String 306 | { 307 | return _queryString; 308 | } 309 | 310 | 311 | /** 312 | * Reference to the query that is being executed. It is null if the query execution is delayed. 313 | */ 314 | public function get queryReference():BreezeQueryReference 315 | { 316 | return _queryReference; 317 | } 318 | 319 | } 320 | 321 | } 322 | -------------------------------------------------------------------------------- /src/breezedb/queries/BreezeSQLMultiStatement.as: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2017 Digital Strawberry LLC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | * 24 | */ 25 | 26 | package breezedb.queries 27 | { 28 | import breezedb.BreezeDb; 29 | import breezedb.IBreezeDatabase; 30 | import breezedb.collections.Collection; 31 | import breezedb.events.BreezeQueryEvent; 32 | import breezedb.events.BreezeSQLStatementEvent; 33 | import breezedb.utils.Callback; 34 | import breezedb.utils.GarbagePrevention; 35 | 36 | import flash.data.SQLResult; 37 | import flash.data.SQLStatement; 38 | import flash.errors.IllegalOperationError; 39 | import flash.events.EventDispatcher; 40 | 41 | internal class BreezeSQLMultiStatement extends EventDispatcher implements ISQLStatement 42 | { 43 | private var _isRunning:Boolean; 44 | private var _currentIndex:int = -1; 45 | private var _currentRawQuery:String; 46 | private var _failOnError:Boolean; 47 | private var _transaction:Boolean; 48 | 49 | // True if this multi-statement is in control of the current transaction 50 | private var _transactionControl:Boolean; 51 | 52 | private var _db:IBreezeDatabase; 53 | private var _callback:Function; 54 | private var _queries:Array; 55 | private var _results:Vector.; 56 | private var _fatalError:Error; 57 | 58 | 59 | public function BreezeSQLMultiStatement(failOnError:Boolean = true, transaction:Boolean = false, callback:Function = null) 60 | { 61 | _failOnError = failOnError; 62 | _transaction = transaction; 63 | _callback = callback; 64 | 65 | _queries = []; 66 | _results = new []; 67 | } 68 | 69 | 70 | /** 71 | * 72 | * 73 | * Public API 74 | * 75 | * 76 | */ 77 | 78 | 79 | public function exec():void 80 | { 81 | if(_db == null) 82 | { 83 | throw new IllegalOperationError("Database must be set before executing the queries."); 84 | } 85 | 86 | if(_isRunning) 87 | { 88 | throw new Error("The execute statement can not be called while queries are running"); 89 | } 90 | 91 | _isRunning = true; 92 | 93 | if(_transaction && !_db.inTransaction) 94 | { 95 | _transactionControl = true; 96 | _db.beginTransaction(onTransactionBegan); 97 | return; 98 | } 99 | 100 | startExecution(); 101 | } 102 | 103 | 104 | /** 105 | * Adds a query to the list of queries to be executed. 106 | * 107 | * @param query Either a raw query (String) or delayed BreezeQueryRunner. 108 | * @param params Parameters for the raw query. 109 | * @param transaction true if the multi-statement will be run within a transaction. In that case, 110 | * any multi-query runners cannot run within a transaction. 111 | */ 112 | public function addQuery(query:*, params:Object = null, transaction:Boolean = false):void 113 | { 114 | // Raw query, create SQL statement 115 | if(query is String) 116 | { 117 | var statement:BreezeSQLStatement = new BreezeSQLStatement(onRawQueryCompleted); 118 | statement.text = query; 119 | if(params != null) 120 | { 121 | for(var key:String in params) 122 | { 123 | var paramKey:String = ((key.charAt(0) == ":") ? "" : ":") + key; 124 | statement.parameters[paramKey] = params[key]; 125 | } 126 | } 127 | _queries[_queries.length] = statement; 128 | } 129 | // Query runner is executed as is, no SQL statement is created for it 130 | // because the runner can execute multiple queries itself 131 | else if(query is BreezeQueryRunner) 132 | { 133 | // Run the query in transaction only if this multi-statement is not run in transaction 134 | BreezeQueryRunner(query).setMultiQueryMethod(transaction ? BreezeQueryRunner.MULTI_QUERY_FAIL_ON_ERROR : BreezeQueryRunner.MULTI_QUERY_TRANSACTION); 135 | _queries[_queries.length] = query; 136 | } 137 | else 138 | { 139 | throw new ArgumentError("Parameter query must be a String or BreezeQueryRunner"); 140 | } 141 | } 142 | 143 | 144 | public function setDatabase(db:IBreezeDatabase):void 145 | { 146 | _db = db; 147 | } 148 | 149 | 150 | /** 151 | * 152 | * 153 | * Private API 154 | * 155 | * 156 | */ 157 | 158 | 159 | private function startExecution():void 160 | { 161 | GarbagePrevention.instance.add(this); 162 | 163 | executeNextStatement(); 164 | } 165 | 166 | 167 | private function onRawQueryCompleted(error:Error, statement:SQLStatement):void 168 | { 169 | var result:BreezeQueryResult = new BreezeQueryResult(statement.getResult(), error); 170 | addResult(result); 171 | } 172 | 173 | 174 | private function onQueryRunnerCompleted(error:Error, queryResult:* = null):void 175 | { 176 | // Enable the statements queue again (if it was enabled at all) 177 | BreezeRawQuery.breezedb_internal::useQueryQueue = BreezeDb.isQueryQueueEnabled; 178 | 179 | var result:BreezeQueryResult = null; 180 | 181 | // Generic result 182 | if(queryResult is BreezeSQLResult) 183 | { 184 | result = new BreezeQueryResult(BreezeSQLResult(queryResult).sqlResult, error); 185 | } 186 | // SELECT result 187 | else if(queryResult is Collection) 188 | { 189 | result = new BreezeQueryResult(new SQLResult(Collection(queryResult).all), error); 190 | } 191 | // DELETE, UPDATE or aggregate result 192 | else if(queryResult is Number) 193 | { 194 | var rowsAffected:int = (queryResult is int) ? queryResult : 0; 195 | result = new BreezeQueryResult(new SQLResult([queryResult], rowsAffected), error); 196 | } 197 | // Multi-query result 198 | else if(queryResult is Vector.) 199 | { 200 | var multiResult:Vector. = queryResult as Vector.; 201 | if(multiResult.length > 0) 202 | { 203 | result = multiResult[0]; 204 | } 205 | } 206 | // Single object, e.g. when executing first() 207 | else if(queryResult != null) 208 | { 209 | result = new BreezeQueryResult(new SQLResult([queryResult]), error); 210 | } 211 | 212 | if(result == null) 213 | { 214 | result = new BreezeQueryResult(new SQLResult(), error); 215 | } 216 | 217 | addResult(result); 218 | } 219 | 220 | 221 | private function addResult(result:BreezeQueryResult):void 222 | { 223 | _results[_currentIndex] = result; 224 | 225 | // Dispatch event for each sub-query 226 | var eventType:String = (result.error == null) ? BreezeQueryEvent.SUCCESS : BreezeQueryEvent.ERROR; 227 | if(hasEventListener(eventType)) 228 | { 229 | dispatchEvent(new BreezeQueryEvent(eventType, result.error, result, _currentRawQuery)); 230 | } 231 | 232 | if(result.error != null && (_failOnError || _transaction)) 233 | { 234 | _fatalError = result.error; 235 | if(_transaction && _db.inTransaction && _transactionControl) 236 | { 237 | _db.rollBack(onTransactionEnded); 238 | return; 239 | } 240 | finalize(); 241 | return; 242 | } 243 | 244 | executeNextStatement(); 245 | } 246 | 247 | 248 | private function onTransactionBegan(error:Error):void 249 | { 250 | if(error == null) 251 | { 252 | startExecution(); 253 | } 254 | else 255 | { 256 | _fatalError = error; 257 | finalize(); 258 | } 259 | } 260 | 261 | 262 | private function onTransactionEnded(error:Error):void 263 | { 264 | if(error != null && _fatalError == null) 265 | { 266 | _fatalError = error; 267 | } 268 | finalize(); 269 | } 270 | 271 | 272 | private function executeNextStatement():void 273 | { 274 | if(_currentIndex >= _queries.length - 1) 275 | { 276 | if(_transaction && _db.inTransaction && _transactionControl) 277 | { 278 | _db.commit(onTransactionEnded); 279 | return; 280 | } 281 | 282 | finalize(); 283 | return; 284 | } 285 | 286 | var query:* = _queries[++_currentIndex]; 287 | 288 | // Execute SQL statement 289 | if(query is BreezeSQLStatement) 290 | { 291 | var statement:BreezeSQLStatement = query as BreezeSQLStatement; 292 | statement.sqlConnection = _db.connection; 293 | _currentRawQuery = statement.text; 294 | statement.exec(); 295 | } 296 | // Otherwise execute delayed query runner 297 | else 298 | { 299 | _currentRawQuery = BreezeQueryRunner(query).queryString; 300 | 301 | // This multi statement is already in the queue, we cannot queue 302 | // this runner's statements because they would never get executed 303 | BreezeRawQuery.breezedb_internal::useQueryQueue = false; 304 | BreezeQueryRunner(query).exec(onQueryRunnerCompleted); 305 | } 306 | } 307 | 308 | 309 | private function finalize():void 310 | { 311 | _isRunning = false; 312 | 313 | var result:Array = []; 314 | if(_failOnError || _transaction) 315 | { 316 | result[0] = _fatalError; 317 | } 318 | result[result.length] = _results; 319 | 320 | Callback.call(_callback, [result]); 321 | 322 | dispatchEvent(new BreezeSQLStatementEvent(BreezeSQLStatementEvent.COMPLETE)); 323 | 324 | GarbagePrevention.instance.remove(this); 325 | } 326 | } 327 | 328 | } 329 | -------------------------------------------------------------------------------- /src/breezedb/queries/BreezeSQLResult.as: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2017 Digital Strawberry LLC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | * 24 | */ 25 | 26 | package breezedb.queries 27 | { 28 | import breezedb.collections.Collection; 29 | 30 | import flash.data.SQLResult; 31 | 32 | /** 33 | * Class providing access to data returned as a response to execution of a SQL statement. 34 | */ 35 | public class BreezeSQLResult 36 | { 37 | private var _data:Collection; 38 | private var _result:SQLResult; 39 | 40 | 41 | /** 42 | * @private 43 | */ 44 | public function BreezeSQLResult(result:SQLResult) 45 | { 46 | _result = result; 47 | } 48 | 49 | 50 | /** 51 | * Indicates whether all the resulting data from a statement execution has been returned. 52 | */ 53 | public function get complete():Boolean 54 | { 55 | return (_result != null) ? _result.complete : false; 56 | } 57 | 58 | 59 | /** 60 | * Indicates how many rows were affected by the operation. Only changes that are directly specified by 61 | * an INSERT, UPDATE, or DELETE statement are counted. 62 | */ 63 | public function get rowsAffected():Number 64 | { 65 | return (_result != null) ? _result.rowsAffected : -1; 66 | } 67 | 68 | 69 | /** 70 | * The last generated row identifier generated by a SQL INSERT statement. 71 | */ 72 | public function get lastInsertRowID():Number 73 | { 74 | return (_result != null) ? _result.lastInsertRowID : -1; 75 | } 76 | 77 | 78 | /** 79 | * The data returned as a result of the statement execution, specifically when a SQL SELECT 80 | * statement is executed. 81 | * 82 | *

When a statement returns one or more rows this property is an array containing objects that 83 | * represent the rows of result data. Each object in the array has property names that correspond 84 | * to the result data set's column names.

85 | * 86 | *

The returned Collection is never null.

87 | */ 88 | public function get data():Collection 89 | { 90 | if(_data != null) 91 | { 92 | return _data; 93 | } 94 | 95 | if(_result != null && _result.data != null && _result.data.length > 0) 96 | { 97 | _data = Collection.fromArray(_result.data); 98 | return _data; 99 | } 100 | 101 | _data = new Collection(); 102 | return _data; 103 | } 104 | 105 | 106 | /** 107 | * Provides access to the original SQL result. 108 | */ 109 | internal function get sqlResult():SQLResult 110 | { 111 | return _result; 112 | } 113 | } 114 | 115 | } 116 | -------------------------------------------------------------------------------- /src/breezedb/queries/BreezeSQLStatement.as: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2017 Digital Strawberry LLC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | * 24 | */ 25 | 26 | package breezedb.queries 27 | { 28 | import breezedb.events.BreezeSQLStatementEvent; 29 | import breezedb.utils.Callback; 30 | import breezedb.utils.GarbagePrevention; 31 | 32 | import flash.data.SQLStatement; 33 | import flash.events.SQLErrorEvent; 34 | import flash.events.SQLEvent; 35 | import flash.net.Responder; 36 | 37 | internal class BreezeSQLStatement extends SQLStatement implements ISQLStatement 38 | { 39 | private var _callback:Function; 40 | 41 | 42 | public function BreezeSQLStatement(callback:Function) 43 | { 44 | _callback = callback; 45 | } 46 | 47 | 48 | /** 49 | * 50 | * 51 | * Public API 52 | * 53 | * 54 | */ 55 | 56 | 57 | public function exec():void 58 | { 59 | execute(); 60 | } 61 | 62 | 63 | override public function execute(prefetch:int = -1, responder:Responder = null):void 64 | { 65 | fixParameterMismatch(); 66 | 67 | addEventListener(SQLEvent.RESULT, onQuerySuccess, false, 0, true); 68 | addEventListener(SQLErrorEvent.ERROR, onQueryError, false, 0, true); 69 | 70 | GarbagePrevention.instance.add(this); 71 | 72 | super.execute(prefetch, responder); 73 | } 74 | 75 | 76 | /** 77 | * 78 | * 79 | * Private API 80 | * 81 | * 82 | */ 83 | 84 | 85 | /** 86 | * This method fixes the annoying "feature" in SQLite that only allows parameters that 87 | * are actually used within the query. 88 | */ 89 | private function fixParameterMismatch():void 90 | { 91 | for(var property:String in parameters) 92 | { 93 | var regex:RegExp = new RegExp(property + "(\\b)"); 94 | if(text.search(regex) == -1) 95 | { 96 | delete parameters[property]; 97 | } 98 | } 99 | } 100 | 101 | 102 | private function onQuerySuccess(event:SQLEvent):void 103 | { 104 | Callback.call(_callback, [null, this]); 105 | 106 | dispatchEvent(new BreezeSQLStatementEvent(BreezeSQLStatementEvent.COMPLETE)); 107 | 108 | GarbagePrevention.instance.remove(this); 109 | } 110 | 111 | 112 | private function onQueryError(event:SQLErrorEvent):void 113 | { 114 | Callback.call(_callback, [event.error, this]); 115 | 116 | dispatchEvent(new BreezeSQLStatementEvent(BreezeSQLStatementEvent.COMPLETE)); 117 | 118 | GarbagePrevention.instance.remove(this); 119 | } 120 | } 121 | 122 | } 123 | -------------------------------------------------------------------------------- /src/breezedb/queries/BreezeUnionStatement.as: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2017 Digital Strawberry LLC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | * 24 | */ 25 | 26 | package breezedb.queries 27 | { 28 | internal class BreezeUnionStatement 29 | { 30 | private var _query:BreezeQueryBuilder; 31 | private var _all:Boolean; 32 | 33 | public function BreezeUnionStatement(query:BreezeQueryBuilder, all:Boolean) 34 | { 35 | _query = query; 36 | _all = all; 37 | } 38 | 39 | 40 | public function get query():BreezeQueryBuilder 41 | { 42 | return _query; 43 | } 44 | 45 | 46 | public function get all():Boolean 47 | { 48 | return _all; 49 | } 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /src/breezedb/queries/IRawQuery.as: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2017 Digital Strawberry LLC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | * 24 | */ 25 | 26 | package breezedb.queries 27 | { 28 | /** 29 | * Interface providing API to execute raw queries. 30 | */ 31 | public interface IRawQuery 32 | { 33 | /** 34 | * Executes a query on the associated database. It is treated as a raw query, thus the result 35 | * is returned as a generic BreezeSQLResult object. 36 | * 37 | * @param rawQuery SQL query to execute. 38 | * @param params Optional query parameters, i.e. key-value Object. If query parameters 39 | * are not used, this parameter can specify a callback Function. 40 | * @param callback Function that is triggered when the query is completed. 41 | * 42 | * 43 | * BreezeDb.db.query("SELECT * FROM photos WHERE id > :id", { id: 2 }, onRawQueryCompleted); 44 | * 45 | * function onRawQueryCompleted(error:Error, result:BreezeSQLResult):void 46 | * { 47 | * if(error == null) 48 | * { 49 | * trace(result.data); // For SELECT queries 50 | * trace(result.rowsAffected); // For UPDATE, DELETE queries 51 | * } 52 | * }; 53 | * 54 | * 55 | * @return BreezeQueryReference object that allows cancelling the request callback. 56 | */ 57 | function query(rawQuery:String, params:* = null, callback:Function = null):BreezeQueryReference; 58 | 59 | 60 | /** 61 | * Executes a SELECT query on the associated database. The result is cast to a 62 | * Collection object. 63 | * 64 | * @param rawQuery SQL query to execute. 65 | * @param params Optional query parameters, i.e. key-value Object. If query parameters 66 | * are not used, this parameter can specify a callback Function. 67 | * @param callback Function that is triggered when the query is completed. 68 | * 69 | * 70 | * BreezeDb.db.select("SELECT id, title, views FROM photos", onSelectCompleted); 71 | * 72 | * function onSelectCompleted(error:Error, results:Collection):void 73 | * { 74 | * if(error == null) 75 | * { 76 | * trace(results); 77 | * } 78 | * }; 79 | * 80 | * 81 | * @return BreezeQueryReference object that allows cancelling the request callback. 82 | */ 83 | function select(rawQuery:String, params:* = null, callback:Function = null):BreezeQueryReference; 84 | 85 | 86 | /** 87 | * Executes an INSERT query on the associated database. 88 | * 89 | * @param rawQuery SQL query to execute. 90 | * @param params Optional query parameters, i.e. key-value Object. If query parameters 91 | * are not used, this parameter can specify a callback Function. 92 | * @param callback Function that is triggered when the query is completed. 93 | * 94 | * 95 | * BreezeDb.db.insert( 96 | * "INSERT INTO photos (title, views, downloads) VALUES (:title, :views, :downloads), 97 | * { title: "Mountains", views: 35, downloads: 10 }, 98 | * onInsertCompleted 99 | * ); 100 | * 101 | * function onInsertCompleted(error:Error):void 102 | * { 103 | * if(error == null) 104 | * { 105 | * // Insert was successful 106 | * } 107 | * }; 108 | * 109 | * 110 | * @return BreezeQueryReference object that allows cancelling the request callback. 111 | */ 112 | function insert(rawQuery:String, params:* = null, callback:Function = null):BreezeQueryReference; 113 | 114 | 115 | /** 116 | * Executes an UPDATE query on the associated database. The result is cast to 117 | * an int that provides information about the number of rows affected by the query. 118 | * 119 | * @param rawQuery SQL query to execute. 120 | * @param params Optional query parameters, i.e. key-value Object. If query parameters 121 | * are not used, this parameter can specify a callback Function. 122 | * @param callback Function that is triggered when the query is completed. 123 | * 124 | * 125 | * BreezeDb.db.update("UPDATE photos SET title = :title WHERE id = :id", { title: "Trees", id: 2 }, onUpdateCompleted); 126 | * 127 | * function onUpdateCompleted(error:Error, rowsAffected:int):void 128 | * { 129 | * if(error == null) 130 | * { 131 | * trace("Updated", rowsAffected, "row(s)"); 132 | * } 133 | * }; 134 | * 135 | * 136 | * @return BreezeQueryReference object that allows cancelling the request callback. 137 | */ 138 | function update(rawQuery:String, params:* = null, callback:Function = null):BreezeQueryReference; 139 | 140 | 141 | /** 142 | * Executes a DELETE query on the associated database. The result is cast to 143 | * an int that provides information about the number of rows deleted by the query. 144 | * 145 | * @param rawQuery SQL query to execute. 146 | * @param params Optional query parameters, i.e. key-value Object. If query parameters 147 | * are not used, this parameter can specify a callback Function. 148 | * @param callback Function that is triggered when the query is completed. 149 | * 150 | * 151 | * BreezeDb.db.remove("DELETE FROM photos WHERE title = :title", { title: "Camp Fire" }, onDeleteCompleted); 152 | * 153 | * function onDeleteCompleted(error:Error, rowsDeleted:int):void 154 | * { 155 | * if(error == null) 156 | * { 157 | * trace("Deleted", rowsDeleted, "row(s)"); 158 | * } 159 | * }; 160 | * 161 | * 162 | * @return BreezeQueryReference object that allows cancelling the request callback. 163 | */ 164 | function remove(rawQuery:String, params:* = null, callback:Function = null):BreezeQueryReference; 165 | 166 | 167 | /** 168 | * Executes multiple queries on the associated database. All queries are executed, regardless 169 | * of any errors that occur in earlier queries. 170 | * 171 | *

The result is cast to a list of BreezeQueryResult and the results are in 172 | * the same order as the executed queries. Each result contains an error and result objects.

173 | * 174 | * @param rawQueries List of SQL queries to execute. It can be either a raw query (String) 175 | * or delayed BreezeQueryRunner (super class of BreezeQueryBuilder). 176 | * Note all BreezeQueryRunner objects must use the same database connection. 177 | * @param params Optional query parameters, i.e. Array of key-value Objects 178 | * or null. If query parameters are not used, this parameter can specify 179 | * a callback Function. 180 | * @param callback Function that is triggered when the query is completed. 181 | * 182 | * 183 | * var query1:BreezeQueryBuilder = BreezeDb.db.table("photos").where("id", 1).update({ title: "Hills" }, BreezeDb.DELAY); 184 | * var query2:BreezeQueryBuilder = BreezeDb.db.table("photos").where("id", 2).fetch(BreezeDb.DELAY); 185 | * 186 | * BreezeDb.db.multiQuery( 187 | * [ 188 | * query1, 189 | * query2, 190 | * "SELECT id, title FROM photos WHERE title = :title" 191 | * ], 192 | * [null, null, { title: "Hills" }], 193 | * onMultiQueryCompleted 194 | * ); 195 | * 196 | * function onMultiQueryCompleted(results:Vector.<BreezeQueryResult>):void 197 | * { 198 | * for each(var result:BreezeQueryResult in results) 199 | * { 200 | * if(result.error == null) 201 | * { 202 | * trace(result.data); 203 | * } 204 | * } 205 | * }; 206 | * 207 | * 208 | * @return BreezeQueryReference object that allows cancelling the request callback. 209 | */ 210 | function multiQuery(rawQueries:Array, params:* = null, callback:Function = null):BreezeQueryReference; 211 | 212 | 213 | /** 214 | * Executes multiple queries on the associated database. If a query fails, the queries that follow 215 | * will not be executed. Successful queries are not rolled back. 216 | * 217 | *

The first callback parameter is an Error object that references the error that 218 | * caused the execution to stop. Additionally, a list of BreezeQueryResult is provided 219 | * and the results are in the same order as the executed queries. Each result contains an error 220 | * and result objects.

221 | * 222 | * @param rawQueries List of SQL queries to execute. It can be either a raw query (String) 223 | * or delayed BreezeQueryRunner (super class of BreezeQueryBuilder). 224 | * Note all BreezeQueryRunner objects must use the same database connection. 225 | * @param params Optional query parameters, i.e. Array of key-value Objects 226 | * or null. If query parameters are not used, this parameter can specify 227 | * a callback Function. 228 | * @param callback Function that is triggered when the query is completed. 229 | * 230 | * 231 | * BreezeDb.db.multiQueryFailOnError( 232 | * [ 233 | * "SELECT * FROM photos WHEREz", // syntax error, the second query will not be executed 234 | * "SELECT id, title FROM photos WHERE title = :title" 235 | * ], 236 | * [null, { title: "Hills" }], 237 | * onMultiQueryCompleted 238 | * ); 239 | * 240 | * function onMultiQueryCompleted(error:Error, results:Vector.<BreezeQueryResult>):void 241 | * { 242 | * trace(error); // SQLError 243 | * trace(results.length); // 1 244 | * }; 245 | * 246 | * 247 | * @return BreezeQueryReference object that allows cancelling the request callback. 248 | */ 249 | function multiQueryFailOnError(rawQueries:Array, params:* = null, callback:Function = null):BreezeQueryReference; 250 | 251 | 252 | /** 253 | * Executes multiple queries on the associated database. If a query fails, the queries that follow 254 | * will not be executed and the database is rolled back to the state before executing 255 | * the queries. 256 | * 257 | *

The first callback parameter is an Error object that references the error that 258 | * caused the execution to stop. Additionally, a list of BreezeQueryResult is provided 259 | * and the results are in the same order as the executed queries. Each result contains an error 260 | * and result objects.

261 | * 262 | * @param rawQueries List of SQL queries to execute. It can be either a raw query (String) 263 | * or delayed BreezeQueryRunner (super class of BreezeQueryBuilder). 264 | * Note all BreezeQueryRunner objects must use the same database connection. 265 | * @param params Optional query parameters, i.e. Array of key-value Objects 266 | * or null. If query parameters are not used, this parameter can specify 267 | * a callback Function. 268 | * @param callback Function that is triggered when the query is completed. 269 | * 270 | * 271 | * BreezeDb.db.multiQueryTransaction( 272 | * [ 273 | * "UPDATE photos SET title = :title", 274 | * "SELECT title FROM photos WHEREz id > 2" // syntax error, the previous UPDATE will be rolled back 275 | * ], 276 | * [{ title: "Hills" }], 277 | * onMultiQueryCompleted 278 | * ); 279 | * 280 | * function onMultiQueryCompleted(error:Error, results:Vector.<BreezeQueryResult>):void 281 | * { 282 | * trace(error); // SQLError 283 | * }; 284 | * 285 | * 286 | * @return BreezeQueryReference object that allows cancelling the request callback. 287 | */ 288 | function multiQueryTransaction(rawQueries:Array, params:* = null, callback:Function = null):BreezeQueryReference; 289 | } 290 | 291 | } 292 | -------------------------------------------------------------------------------- /src/breezedb/queries/ISQLStatement.as: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2017 Digital Strawberry LLC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | * 24 | */ 25 | 26 | package breezedb.queries 27 | { 28 | import flash.events.IEventDispatcher; 29 | 30 | /** 31 | * @private 32 | */ 33 | public interface ISQLStatement extends IEventDispatcher 34 | { 35 | 36 | function exec():void; 37 | 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/breezedb/queries/SQLStatementQueue.as: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2017 Digital Strawberry LLC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | * 24 | */ 25 | 26 | package breezedb.queries 27 | { 28 | import breezedb.IBreezeDatabase; 29 | import breezedb.events.BreezeDatabaseEvent; 30 | import breezedb.events.BreezeSQLStatementEvent; 31 | 32 | import flash.utils.Dictionary; 33 | 34 | internal class SQLStatementQueue 35 | { 36 | private static var _queues:Dictionary; 37 | 38 | private var _db:IBreezeDatabase; 39 | private var _currentStatement:ISQLStatement; 40 | private var _queue:Vector.; 41 | 42 | public function SQLStatementQueue(db:IBreezeDatabase) 43 | { 44 | _db = db; 45 | _db.addEventListener(BreezeDatabaseEvent.CLOSE_SUCCESS, onDatabaseClosed, false, 0, true); 46 | 47 | _queue = new []; 48 | } 49 | 50 | 51 | public static function forDatabase(db:IBreezeDatabase):SQLStatementQueue 52 | { 53 | if(_queues == null) 54 | { 55 | _queues = new Dictionary(); 56 | } 57 | 58 | // Existing queue 59 | if(db in _queues) 60 | { 61 | return _queues[db]; 62 | } 63 | 64 | // New queue 65 | var queue:SQLStatementQueue = new SQLStatementQueue(db); 66 | _queues[db] = queue; 67 | return queue; 68 | } 69 | 70 | 71 | public function add(statement:ISQLStatement):void 72 | { 73 | if(_queue.length == 0 && _currentStatement == null) 74 | { 75 | _currentStatement = statement; 76 | _currentStatement.addEventListener(BreezeSQLStatementEvent.COMPLETE, onStatementCompleted); 77 | _currentStatement.exec(); 78 | return; 79 | } 80 | 81 | _queue[_queue.length] = statement; 82 | } 83 | 84 | 85 | public function dispose():void 86 | { 87 | if(_currentStatement != null) 88 | { 89 | _currentStatement.removeEventListener(BreezeSQLStatementEvent.COMPLETE, onStatementCompleted); 90 | _currentStatement = null; 91 | } 92 | _db.removeEventListener(BreezeDatabaseEvent.CLOSE_SUCCESS, onDatabaseClosed); 93 | _db = null; 94 | } 95 | 96 | 97 | private function onStatementCompleted(event:BreezeSQLStatementEvent):void 98 | { 99 | _currentStatement.removeEventListener(BreezeSQLStatementEvent.COMPLETE, onStatementCompleted); 100 | _currentStatement = null; 101 | 102 | if(_queue.length > 0) 103 | { 104 | _currentStatement = _queue.shift(); 105 | _currentStatement.addEventListener(BreezeSQLStatementEvent.COMPLETE, onStatementCompleted); 106 | _currentStatement.exec(); 107 | } 108 | } 109 | 110 | 111 | private function onDatabaseClosed(event:BreezeDatabaseEvent):void 112 | { 113 | if(_queues != null) 114 | { 115 | var db:IBreezeDatabase = event.currentTarget as IBreezeDatabase; 116 | if(db in _queues) 117 | { 118 | var queue:SQLStatementQueue = _queues[db]; 119 | queue.dispose(); 120 | delete _queues[db]; 121 | } 122 | } 123 | } 124 | 125 | } 126 | 127 | } 128 | -------------------------------------------------------------------------------- /src/breezedb/queries/breezedb_internal.as: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2017 Digital Strawberry LLC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | * 24 | */ 25 | 26 | package breezedb.queries 27 | { 28 | 29 | internal namespace breezedb_internal = "https://getbreeze.io/breezedb"; 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/breezedb/schemas/ColumnDataType.as: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2017 Digital Strawberry LLC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | * 24 | */ 25 | 26 | package breezedb.schemas 27 | { 28 | 29 | internal class ColumnDataType 30 | { 31 | 32 | public static const INTEGER:int = 0; 33 | public static const TEXT:int = 1; 34 | public static const BLOB:int = 2; 35 | public static const NUMERIC:int = 3; 36 | public static const DATE:int = 4; 37 | public static const DATE_TIME:int = 5; 38 | 39 | 40 | internal static function toString(value:int):String 41 | { 42 | switch(value) 43 | { 44 | case INTEGER: 45 | return "INTEGER"; 46 | case TEXT: 47 | return "TEXT"; 48 | case BLOB: 49 | return "BLOB"; 50 | case NUMERIC: 51 | return "NUMERIC"; 52 | case DATE: 53 | return "DATE"; 54 | case DATE_TIME: 55 | return "DATETIME"; 56 | } 57 | throw new ArgumentError("Unknown data type value: " + value); 58 | } 59 | 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /src/breezedb/schemas/IColumnConstraint.as: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2017 Digital Strawberry LLC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | * 24 | */ 25 | 26 | package breezedb.schemas 27 | { 28 | 29 | /** 30 | * Interface providing API to add constraints on a column. 31 | */ 32 | public interface IColumnConstraint 33 | { 34 | /** 35 | * Adds a NOT NULL constraint on the column. 36 | * 37 | * @return Reference to IColumnConstraint allowing to chain additional constraints. 38 | */ 39 | function notNull():IColumnConstraint; 40 | 41 | 42 | /** 43 | * Adds a DEFAULT [value] constraint on the column. 44 | * 45 | * @return Reference to IColumnConstraint allowing to chain additional constraints. 46 | */ 47 | function defaultTo(value:*):IColumnConstraint; 48 | 49 | 50 | /** 51 | * Adds a DEFAULT NULL constraint on the column. 52 | * 53 | * @return Reference to IColumnConstraint allowing to chain additional constraints. 54 | */ 55 | function defaultNull():IColumnConstraint; 56 | 57 | 58 | /** 59 | * Adds a UNIQUE constraint on the column, ensuring that the column contains a unique value. 60 | * 61 | * @return Reference to IColumnConstraint allowing to chain additional constraints. 62 | */ 63 | function unique():IColumnConstraint; 64 | 65 | 66 | /** 67 | * Designates the column as primary key. 68 | * 69 | * @return Reference to IColumnConstraint allowing to chain additional constraints. 70 | */ 71 | function primary():IColumnConstraint; 72 | 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /src/breezedb/schemas/TableBlueprint.as: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2017 Digital Strawberry LLC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | * 24 | */ 25 | 26 | package breezedb.schemas 27 | { 28 | import flash.errors.IllegalOperationError; 29 | 30 | /** 31 | * Class providing API to create and edit table structure. 32 | */ 33 | public class TableBlueprint 34 | { 35 | /** 36 | * @private 37 | */ 38 | internal static const CREATE:int = 0; 39 | 40 | /** 41 | * @private 42 | */ 43 | internal static const ALTER:int = 1; 44 | 45 | private var _statement:int; 46 | private var _tableName:String; 47 | private var _columns:Vector.; 48 | private var _createIndex:String; 49 | private var _dropIndex:String; 50 | 51 | 52 | /** 53 | * @private 54 | */ 55 | public function TableBlueprint() 56 | { 57 | _columns = new []; 58 | } 59 | 60 | 61 | /** 62 | * Adds a new column with the given name and type INTEGER. 63 | * The column is created as follows: [name] INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, 64 | * additional constraints cannot be applied. 65 | * 66 | * @param columnName Name of the column. 67 | */ 68 | public function increments(columnName:String):void 69 | { 70 | addColumn(columnName, ColumnDataType.INTEGER) 71 | .autoIncrement() 72 | .primary() 73 | .notNull(); 74 | // No more constraints should be added to this column 75 | } 76 | 77 | 78 | /** 79 | * Adds a new column with the given name and type INTEGER. 80 | * 81 | * @param columnName Name of the column. 82 | * @return IColumnConstraint object that allows adding additional constraints on the column. 83 | */ 84 | public function integer(columnName:String):IColumnConstraint 85 | { 86 | return addColumn(columnName, ColumnDataType.INTEGER); 87 | } 88 | 89 | 90 | /** 91 | * Adds a new column with the given name and type INTEGER. 92 | * 93 | * @param columnName Name of the column. 94 | * @return IColumnConstraint object that allows adding additional constraints on the column. 95 | */ 96 | public function string(columnName:String):IColumnConstraint 97 | { 98 | return addColumn(columnName, ColumnDataType.TEXT); 99 | } 100 | 101 | 102 | /** 103 | * Adds a new column with the given name and type BLOB. 104 | * 105 | * @param columnName Name of the column. 106 | * @return IColumnConstraint object that allows adding additional constraints on the column. 107 | */ 108 | public function blob(columnName:String):IColumnConstraint 109 | { 110 | return addColumn(columnName, ColumnDataType.BLOB); 111 | } 112 | 113 | 114 | /** 115 | * Adds a new column with the given name and type INTEGER. 116 | * 117 | * @param columnName Name of the column. 118 | * @return IColumnConstraint object that allows adding additional constraints on the column. 119 | */ 120 | public function boolean(columnName:String):IColumnConstraint 121 | { 122 | return addColumn(columnName, ColumnDataType.INTEGER); 123 | } 124 | 125 | 126 | /** 127 | * Adds a new column with the given name and type NUMERIC. 128 | * 129 | * @param columnName Name of the column. 130 | * @return IColumnConstraint object that allows adding additional constraints on the column. 131 | */ 132 | public function number(columnName:String):IColumnConstraint 133 | { 134 | return addColumn(columnName, ColumnDataType.NUMERIC); 135 | } 136 | 137 | 138 | /** 139 | * Adds a new column with the given name and type DATE. 140 | * 141 | * @param columnName Name of the column. 142 | * @return IColumnConstraint object that allows adding additional constraints on the column. 143 | */ 144 | public function date(columnName:String):IColumnConstraint 145 | { 146 | return addColumn(columnName, ColumnDataType.DATE); 147 | } 148 | 149 | 150 | /** 151 | * Adds a new column with the given name and type DATETIME. 152 | * 153 | * @param columnName Name of the column. 154 | * @return IColumnConstraint object that allows adding additional constraints on the column. 155 | */ 156 | public function timestamp(columnName:String):IColumnConstraint 157 | { 158 | return addColumn(columnName, ColumnDataType.DATE_TIME); 159 | } 160 | 161 | 162 | /** 163 | * Creates primary key on one or multiple columns. You can only use this method when creating table. 164 | * 165 | * @param rest List of names (String) for existing columns on which the primary key will be created. 166 | */ 167 | public function primary(...rest):void 168 | { 169 | if(_statement == ALTER) 170 | { 171 | throw new IllegalOperationError("Primary key cannot be changed after the table is created."); 172 | } 173 | 174 | var length:int = rest.length; 175 | for(var i:int = 0; i < length; ++i) 176 | { 177 | var columnName:String = rest[i] as String; 178 | if(columnName == null) 179 | { 180 | throw new ArgumentError("The name of the column must be a String."); 181 | } 182 | 183 | var column:TableColumn = getColumn(columnName); 184 | if(column == null) 185 | { 186 | throw new Error("Cannot create primary key on non-existing column '" + columnName + "'."); 187 | } 188 | column.primary(); 189 | } 190 | } 191 | 192 | 193 | /** 194 | * Creates an index on the given column(s). 195 | * 196 | * @param columns Either a String (column name) or Array of Strings 197 | * (multiple column names) on which the index should be created. 198 | * @param indexName Optional index name. If not specified, it will default to index_{column_name}. 199 | * @param unique Similar to UNIQUE constraint, unique index prevents duplicate entries 200 | * in the column or combination of columns on which there's an index. 201 | */ 202 | public function index(columns:*, indexName:String = null, unique:Boolean = false):void 203 | { 204 | if(columns is String) 205 | { 206 | columns = [columns]; 207 | } 208 | 209 | if(!(columns is Array)) 210 | { 211 | throw new ArgumentError("Parameter columns must be either a String or Array."); 212 | } 213 | 214 | if((columns as Array).length == 0) 215 | { 216 | throw new ArgumentError("At least one column name must be specified."); 217 | } 218 | 219 | _createIndex = "CREATE " + (unique ? "UNIQUE " : "") + "INDEX IF NOT EXISTS "; 220 | 221 | var customIndexName:Boolean = indexName != null; 222 | if(!customIndexName) 223 | { 224 | indexName = "index_"; 225 | } 226 | 227 | var columnsString:String = "("; 228 | var length:int = columns.length; 229 | for(var i:int = 0; i < length; ++i) 230 | { 231 | var index:String = columns[i] as String; 232 | if(index == null) 233 | { 234 | throw new ArgumentError("The name of the column must be a String."); 235 | } 236 | 237 | if(i > 0) 238 | { 239 | columnsString += ", "; 240 | } 241 | columnsString += index; 242 | 243 | if(!customIndexName) 244 | { 245 | if(i > 0) 246 | { 247 | indexName += "_"; 248 | } 249 | indexName += index; 250 | } 251 | } 252 | columnsString += ")"; 253 | 254 | _createIndex += "[" + indexName + "]"; 255 | _createIndex += " ON " + _tableName + " "; 256 | _createIndex += columnsString + ";"; 257 | } 258 | 259 | 260 | /** 261 | * Removes index with the given name. You can only use this method when editing table. 262 | * 263 | * @param indexName Name of the index to remove. 264 | */ 265 | public function dropIndex(indexName:String):void 266 | { 267 | if(_statement == CREATE) 268 | { 269 | throw new IllegalOperationError("Index can be dropped only when editing table."); 270 | } 271 | 272 | if(indexName == null) 273 | { 274 | throw new ArgumentError("Parameter indexName cannot be null."); 275 | } 276 | 277 | _dropIndex = "DROP INDEX " + indexName + ";"; 278 | } 279 | 280 | 281 | /** 282 | * 283 | * 284 | * Private API 285 | * 286 | * 287 | */ 288 | 289 | 290 | private function addColumn(columnName:String, dataType:int):TableColumn 291 | { 292 | if(columnName == null) 293 | { 294 | throw new ArgumentError("Parameter columnName cannot be null."); 295 | } 296 | 297 | var newColumn:TableColumn = new TableColumn(columnName, dataType, _statement == CREATE); 298 | var index:int = 0; 299 | for each(var column:TableColumn in _columns) 300 | { 301 | if(column.name == newColumn.name) 302 | { 303 | break; 304 | } 305 | index++; 306 | } 307 | _columns[index] = newColumn; 308 | return newColumn; 309 | } 310 | 311 | 312 | private function getColumn(columnName:String):TableColumn 313 | { 314 | for each(var column:TableColumn in _columns) 315 | { 316 | if(column.name == columnName) 317 | { 318 | return column; 319 | } 320 | } 321 | return null; 322 | } 323 | 324 | 325 | /** 326 | * @private 327 | */ 328 | internal function setStatement(value:int):void 329 | { 330 | _statement = value; 331 | } 332 | 333 | 334 | /** 335 | * @private 336 | */ 337 | internal function setTable(tableName:String):void 338 | { 339 | _tableName = tableName; 340 | if(_tableName.indexOf("[") < 0) 341 | { 342 | _tableName = "[" + _tableName + "]"; 343 | } 344 | } 345 | 346 | 347 | /** 348 | * @private 349 | */ 350 | internal function get query():String 351 | { 352 | var result:String = ""; 353 | if(_columns.length > 0) 354 | { 355 | if(_statement == CREATE) 356 | { 357 | result = (_statement == CREATE) ? "CREATE TABLE IF NOT EXISTS " + _tableName + " (" : ""; 358 | } 359 | 360 | var primaryKeys:Vector. = this.primaryKeys; 361 | var hasCompositeKey:Boolean = primaryKeys.length > 1; 362 | var i:int = 0; 363 | for each(var column:TableColumn in _columns) 364 | { 365 | // Adding multiple columns requires a separate query for each column 366 | if(_statement == ALTER) 367 | { 368 | result += "ALTER TABLE " + _tableName + " ADD COLUMN "; 369 | } 370 | 371 | // Add comma or semicolon to separate the previous line 372 | if(_statement == CREATE && i++ > 0) 373 | { 374 | result += ", "; 375 | } 376 | 377 | result += column.getSQLText(!hasCompositeKey); 378 | 379 | if(_statement == ALTER) 380 | { 381 | result += ";"; 382 | } 383 | } 384 | 385 | // Add primary key on multiple fields if has composite key 386 | if(hasCompositeKey) 387 | { 388 | i = 0; 389 | result += ", PRIMARY KEY ("; 390 | for each(column in primaryKeys) 391 | { 392 | // Add comma to separate the previous line 393 | if(i++ > 0) 394 | { 395 | result += ", "; 396 | } 397 | result += column.name; 398 | } 399 | result += ")"; 400 | } 401 | if(_statement == CREATE) 402 | { 403 | result += ");"; 404 | } 405 | } 406 | 407 | // Add index statement if needed 408 | if(_createIndex != null) 409 | { 410 | result += _createIndex; 411 | } 412 | if(_dropIndex != null) 413 | { 414 | result += _dropIndex; 415 | } 416 | 417 | return result; 418 | } 419 | 420 | 421 | /** 422 | * Returns list of columns that are designated as a primary key. 423 | */ 424 | private function get primaryKeys():Vector. 425 | { 426 | var result:Vector. = new []; 427 | for each(var column:TableColumn in _columns) 428 | { 429 | if(column.isPrimaryKey) 430 | { 431 | result[result.length] = column; 432 | } 433 | } 434 | return result; 435 | } 436 | } 437 | 438 | } 439 | -------------------------------------------------------------------------------- /src/breezedb/schemas/TableColumn.as: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2017 Digital Strawberry LLC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | * 24 | */ 25 | 26 | package breezedb.schemas 27 | { 28 | import flash.errors.IllegalOperationError; 29 | 30 | internal class TableColumn implements IColumnConstraint 31 | { 32 | private var _name:String; 33 | private var _dataType:int; 34 | private var _creationMode:Boolean; 35 | 36 | private var _autoIncrement:Boolean; 37 | private var _notNull:Boolean; 38 | private var _defaultTo:* = null; 39 | private var _defaultNull:Boolean; 40 | private var _unique:Boolean; 41 | private var _primaryKey:Boolean; 42 | 43 | 44 | /** 45 | * @private 46 | */ 47 | public function TableColumn(name:String, dataType:int, creationMode:Boolean) 48 | { 49 | _name = name; 50 | if(_name.indexOf("[") < 0) 51 | { 52 | _name = "[" + _name + "]"; 53 | } 54 | _dataType = dataType; 55 | _creationMode = creationMode; 56 | } 57 | 58 | 59 | /** 60 | * Makes the column value to be auto-incremented. 61 | * 62 | * @return Reference to IColumnConstraint allowing to chain additional constraints. 63 | */ 64 | public function autoIncrement():IColumnConstraint 65 | { 66 | _autoIncrement = true; 67 | return this; 68 | } 69 | 70 | 71 | /** 72 | * @inheritDoc 73 | */ 74 | public function notNull():IColumnConstraint 75 | { 76 | _notNull = true; 77 | return this; 78 | } 79 | 80 | 81 | /** 82 | * @inheritDoc 83 | * @return 84 | */ 85 | public function defaultTo(value:*):IColumnConstraint 86 | { 87 | _defaultTo = value; 88 | _defaultNull = false; 89 | return this; 90 | } 91 | 92 | 93 | /** 94 | * @inheritDoc 95 | */ 96 | public function defaultNull():IColumnConstraint 97 | { 98 | _defaultNull = true; 99 | _defaultTo = null; 100 | return this; 101 | } 102 | 103 | 104 | /** 105 | * @inheritDoc 106 | */ 107 | public function unique():IColumnConstraint 108 | { 109 | _unique = true; 110 | return this; 111 | } 112 | 113 | 114 | /** 115 | * @inheritDoc 116 | */ 117 | public function primary():IColumnConstraint 118 | { 119 | if(!_creationMode) 120 | { 121 | throw new IllegalOperationError("Primary key cannot be changed after the table is created."); 122 | } 123 | 124 | _primaryKey = true; 125 | return this; 126 | } 127 | 128 | 129 | /** 130 | * @private 131 | */ 132 | internal function get isPrimaryKey():Boolean 133 | { 134 | return _primaryKey; 135 | } 136 | 137 | 138 | /** 139 | * @private 140 | */ 141 | internal function get name():String 142 | { 143 | return _name; 144 | } 145 | 146 | 147 | /** 148 | * @private 149 | * @param includePrimaryKey If the column is designated as primary key and this parameter is true 150 | * then the result text will contain PRIMARY KEY. The parameter should be false in cases 151 | * when there are multiple primary keys, which requires different SQL syntax. 152 | */ 153 | internal function getSQLText(includePrimaryKey:Boolean):String 154 | { 155 | var result:String = _name + " " + ColumnDataType.toString(_dataType); 156 | 157 | if(_primaryKey && includePrimaryKey) 158 | { 159 | result += " PRIMARY KEY"; 160 | } 161 | 162 | if(_autoIncrement) 163 | { 164 | result += " AUTOINCREMENT"; 165 | } 166 | 167 | if(_notNull) 168 | { 169 | result += " NOT NULL"; 170 | } 171 | 172 | if(_unique) 173 | { 174 | result += " UNIQUE"; 175 | } 176 | 177 | if(_defaultNull) 178 | { 179 | result += " DEFAULT (NULL)"; 180 | } 181 | else if(_defaultTo !== null) 182 | { 183 | result += " DEFAULT (" + defaultValue + ")"; 184 | } 185 | return result; 186 | } 187 | 188 | 189 | private function get defaultValue():* 190 | { 191 | if(_defaultTo is String) 192 | { 193 | return "'" + _defaultTo + "'"; 194 | } 195 | return _defaultTo; 196 | } 197 | } 198 | 199 | } 200 | -------------------------------------------------------------------------------- /src/breezedb/schemas/breezedb_internal.as: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2017 Digital Strawberry LLC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | * 24 | */ 25 | 26 | package breezedb.schemas 27 | { 28 | 29 | internal namespace breezedb_internal = "https://getbreeze.io/breezedb"; 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/breezedb/utils/Callback.as: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2017 Digital Strawberry LLC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | * 24 | */ 25 | 26 | package breezedb.utils 27 | { 28 | 29 | /** 30 | * @private 31 | */ 32 | public class Callback 33 | { 34 | 35 | public static function call(fn:Function, args:Array):Boolean 36 | { 37 | if(fn == null) 38 | { 39 | return false; 40 | } 41 | 42 | var numArgs:int = fn.length; 43 | for(var i:int = args.length; i < numArgs; ++i) 44 | { 45 | args[i] = null; 46 | } 47 | 48 | // There are less than 3 arguments most of the time, 49 | // so we call the method directly to avoid the 'slice' allocations 50 | 51 | switch(numArgs) 52 | { 53 | case 0: 54 | fn(); 55 | break; 56 | case 1: 57 | fn(args[0]); 58 | break; 59 | case 2: 60 | fn(args[0], args[1]); 61 | break; 62 | case 3: 63 | fn(args[0], args[1], args[2]); 64 | break; 65 | default: 66 | fn.apply(null, args.slice(0, numArgs)); 67 | break; 68 | } 69 | 70 | return true; 71 | } 72 | 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /src/breezedb/utils/GarbagePrevention.as: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2017 Digital Strawberry LLC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | * 24 | */ 25 | 26 | package breezedb.utils 27 | { 28 | 29 | /** 30 | * Utility class that prevents garbage collection on objects until told to delete them. 31 | * @private 32 | */ 33 | public class GarbagePrevention 34 | { 35 | private static var _instance:GarbagePrevention; 36 | 37 | private var _objects:Array = []; 38 | 39 | 40 | public function GarbagePrevention() 41 | { 42 | if(!_instance) 43 | { 44 | _instance = this; 45 | } 46 | else 47 | { 48 | throw new Error('GarbagePrevention is a singleton.'); 49 | } 50 | } 51 | 52 | 53 | public function add(object:*):void 54 | { 55 | _objects.push(object); 56 | } 57 | 58 | 59 | public function addOnce(object:*):void 60 | { 61 | if(!contains(object)) 62 | { 63 | add(object); 64 | } 65 | } 66 | 67 | 68 | public function remove(object:*):Boolean 69 | { 70 | var index:int = _objects.indexOf(object); 71 | if(index > -1) 72 | { 73 | _objects.removeAt(index); 74 | return true; 75 | } 76 | 77 | return false; 78 | } 79 | 80 | 81 | public function removeAll():void 82 | { 83 | _objects.length = 0; 84 | } 85 | 86 | 87 | public function contains(object:*):Boolean 88 | { 89 | return _objects.indexOf(object) > -1; 90 | } 91 | 92 | 93 | public static function get instance():GarbagePrevention 94 | { 95 | return _instance ? _instance : new GarbagePrevention(); 96 | } 97 | 98 | } 99 | 100 | } 101 | -------------------------------------------------------------------------------- /src/org/kuwamoto/Inflect.as: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) kuwamoto.org 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | * 24 | * http://kuwamoto.org/2007/12/17/improved-pluralizing-in-php-actionscript-and-ror/ 25 | * 26 | */ 27 | 28 | package org.kuwamoto 29 | { 30 | public class Inflect 31 | { 32 | private static var plural:Array = [ 33 | [/(quiz)$/i, "$1zes"], 34 | [/^(ox)$/i, "$1en"], 35 | [/([m|l])ouse$/i, "$1ice"], 36 | [/(matr|vert|ind)ix|ex$/i, "$1ices"], 37 | [/(x|ch|ss|sh)$/i, "$1es"], 38 | [/([^aeiouy]|qu)y$/i, "$1ies"], 39 | [/(hive)$/i, "$1s"], 40 | [/(?:([^f])fe|([lr])f)$/i, "$1$2ves"], 41 | [/(shea|lea|loa|thie)f$/i, "$1ves"], 42 | [/sis$/i, "ses"], 43 | [/([ti])um$/i, "$1a"], 44 | [/(tomat|potat|ech|her|vet)o$/i, "$1oes"], 45 | [/(bu)s$/i, "$1ses"], 46 | [/(alias|status)$/i, "$1es"], 47 | [/(octop)us$/i, "$1i"], 48 | [/(ax|test)is$/i, "$1es"], 49 | [/(us)$/i, "$1es"], 50 | [/s$/i, "s"], 51 | [/$/i, "s"] 52 | ]; 53 | 54 | private static var irregular:Array = [ 55 | ['move', 'moves'], 56 | ['foot', 'feet'], 57 | ['goose', 'geese'], 58 | ['sex', 'sexes'], 59 | ['child', 'children'], 60 | ['man', 'men'], 61 | ['tooth', 'teeth'], 62 | ['person', 'people'] 63 | ]; 64 | 65 | private static var uncountable:Array = [ 66 | 'sheep', 67 | 'fish', 68 | 'deer', 69 | 'series', 70 | 'species', 71 | 'money', 72 | 'rice', 73 | 'information', 74 | 'equipment' 75 | ]; 76 | 77 | 78 | public static function pluralize(string:String):String 79 | { 80 | var pattern:RegExp; 81 | var result:String; 82 | 83 | // save some time in the case that singular and plural are the same 84 | if(uncountable.indexOf(string.toLowerCase()) != -1) 85 | { 86 | return string; 87 | } 88 | 89 | // check for irregular singular forms 90 | var item:Array; 91 | for each (item in irregular) 92 | { 93 | pattern = new RegExp(item[0] + "$", "i"); 94 | result = item[1]; 95 | 96 | if(pattern.test(string)) 97 | { 98 | return string.replace(pattern, result); 99 | } 100 | } 101 | 102 | // check for matches using regular expressions 103 | for each (item in plural) 104 | { 105 | pattern = item[0]; 106 | result = item[1]; 107 | 108 | if(pattern.test(string)) 109 | { 110 | return string.replace(pattern, result); 111 | } 112 | } 113 | 114 | return string; 115 | } 116 | 117 | } 118 | } -------------------------------------------------------------------------------- /test/application.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | io.getbreeze.breezedb 5 | 6 | 7 | breezedb 8 | Breeze Db 9 | 0.0.1 10 | 2017 Digital Strawberry LLC 11 | 12 | 13 | breezedb.swf 14 | standard 15 | false 16 | true 17 | true 18 | cpu 19 | true 20 | landscape 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /test/lib/breezetest.swc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GetBreeze/breeze-db/e33ff31f447321146bae505879720e1e1fb805ef/test/lib/breezetest.swc -------------------------------------------------------------------------------- /test/src/Main.as: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2017 Digital Strawberry LLC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | * 24 | */ 25 | 26 | package 27 | { 28 | 29 | import breezetest.BreezeTest; 30 | import breezetest.BreezeTestEvent; 31 | 32 | import flash.desktop.NativeApplication; 33 | 34 | import flash.display.Sprite; 35 | import flash.text.TextField; 36 | 37 | import tests.TestDatabase; 38 | import tests.TestQueryQueue; 39 | import tests.migrations.TestMigrations; 40 | import tests.TestQueryBuilder; 41 | import tests.TestRawQuery; 42 | import tests.TestSchema; 43 | import tests.collections.TestCollection; 44 | import tests.models.TestModel; 45 | 46 | public class Main extends Sprite 47 | { 48 | private var _breezeTest:BreezeTest; 49 | public function Main() 50 | { 51 | var textField:TextField = new TextField(); 52 | textField.text = "Running tests..."; 53 | addChild(textField); 54 | 55 | _breezeTest = new BreezeTest(this); 56 | _breezeTest.addEventListener(BreezeTestEvent.TESTS_COMPLETE, onTestsComplete); 57 | _breezeTest.add([TestCollection, TestDatabase, TestRawQuery, TestQueryBuilder, TestSchema, TestMigrations, TestModel, TestQueryQueue]); 58 | _breezeTest.run(); 59 | } 60 | 61 | 62 | private function onTestsComplete(event:BreezeTestEvent):void 63 | { 64 | // Return error if tests failed 65 | NativeApplication.nativeApplication.exit(_breezeTest.success ? 0 : 1); 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /test/src/tests/TestQueryQueue.as: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2017 Digital Strawberry LLC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | * 24 | */ 25 | 26 | package tests 27 | { 28 | import breezedb.BreezeDb; 29 | import breezedb.IBreezeDatabase; 30 | import breezedb.collections.Collection; 31 | import breezedb.queries.BreezeQueryResult; 32 | import breezedb.schemas.TableBlueprint; 33 | 34 | import breezetest.Assert; 35 | import breezetest.async.Async; 36 | 37 | import flash.errors.SQLError; 38 | import flash.utils.setTimeout; 39 | 40 | public class TestQueryQueue 41 | { 42 | public var currentAsync:Async; 43 | 44 | private var _db:IBreezeDatabase; 45 | private var _completedQueries:String; 46 | 47 | private const _photo:Object = { title: "Mountains", views: 35, downloads: 10 }; 48 | private const _tableName:String = "photos"; 49 | 50 | 51 | public function setupClass(async:Async):void 52 | { 53 | async.timeout = 2000; 54 | 55 | BreezeDb.isQueryQueueEnabled = true; 56 | 57 | _completedQueries = ""; 58 | 59 | _db = BreezeDb.getDb("query-queue-test"); 60 | _db.setup(onDatabaseSetup); 61 | } 62 | 63 | 64 | private function onDatabaseSetup(error:Error):void 65 | { 66 | Assert.isNull(error); 67 | Assert.isTrue(_db.isSetup); 68 | 69 | // Create test table 70 | _db.schema.createTable(_tableName, function(table:TableBlueprint):void 71 | { 72 | table.increments("id"); 73 | table.string("title").defaultNull(); 74 | table.integer("views").defaultTo(0); 75 | table.integer("downloads").defaultTo(0); 76 | }, onTableCreated); 77 | } 78 | 79 | 80 | private function onTableCreated(error:Error):void 81 | { 82 | Assert.isNull(error); 83 | 84 | currentAsync.complete(); 85 | } 86 | 87 | 88 | public function testQueue(async:Async):void 89 | { 90 | async.timeout = 5000; 91 | 92 | // Multi insert 93 | var photos:Array = []; 94 | var numPhotos:int = 200; 95 | for(var i:int = 0; i < numPhotos; ++i) 96 | { 97 | photos[i] = _photo; 98 | } 99 | _db.table(_tableName).insert(photos, onInsertCompleted); 100 | 101 | // Multi query in transaction 102 | _db.multiQueryTransaction([ 103 | "UPDATE " + _tableName + " SET title = :title WHERE id = :id", 104 | "SELECT id, title FROM " + _tableName + " WHERE title = 'Hills'" 105 | ], [{ title: "Hills", id: 1 }], onMultiQueryCompleted); 106 | 107 | // Faulty query, must not cause roll back on previous transaction query 108 | _db.query("DROP TABLEz " + _tableName, onFaultyQueryCompleted); // forced error 109 | 110 | // Delayed query must not be added to the queue 111 | _db.table(_tableName).where("id", 1).remove(BreezeDb.DELAY); 112 | 113 | // Cancelled query must not block the queue 114 | _db.table(_tableName).where("id", 1).fetch().queryReference.cancel(); 115 | 116 | // Check query 117 | _db.select("SELECT id, title FROM " + _tableName + " WHERE id = :id", { id: 1 }, onCheckMultiQueryCompleted); 118 | } 119 | 120 | 121 | private function onInsertCompleted(error:Error):void 122 | { 123 | Assert.isNull(error); 124 | 125 | _completedQueries += "insert-"; 126 | } 127 | 128 | 129 | private function onMultiQueryCompleted(error:Error, results:Vector.):void 130 | { 131 | Assert.isNull(error); 132 | Assert.isNotNull(results); 133 | Assert.equals(2, results.length); 134 | 135 | _completedQueries += "multiQ1-"; 136 | 137 | // UPDATE result 138 | var result:BreezeQueryResult = results[0]; 139 | Assert.isNull(result.error); 140 | Assert.isNotNull(result); 141 | Assert.equals(1, result.rowsAffected); 142 | 143 | // SELECT result 144 | result = results[1]; 145 | Assert.isNull(result.error); 146 | Assert.isNotNull(result); 147 | Assert.isNotNull(result.data); 148 | Assert.equals(1, result.data.length); 149 | } 150 | 151 | 152 | private function onFaultyQueryCompleted(error:Error):void 153 | { 154 | Assert.isNotNull(error); 155 | Assert.isType(error, SQLError); 156 | 157 | _completedQueries += "multiQ2-"; 158 | } 159 | 160 | 161 | private function onCheckMultiQueryCompleted(error:Error, results:Collection):void 162 | { 163 | _completedQueries += "check"; 164 | 165 | Assert.isNull(error); 166 | Assert.isNotNull(results); 167 | Assert.equals(1, results.length); 168 | Assert.equals(1, results[0].id); 169 | Assert.equals("Hills", results[0].title); 170 | Assert.equals("insert-multiQ1-multiQ2-check", _completedQueries); 171 | 172 | currentAsync.complete(); 173 | } 174 | 175 | 176 | public function tearDownClass(async:Async):void 177 | { 178 | if(_db != null && _db.isSetup) 179 | { 180 | setTimeout(_db.close, 500, onDatabaseClosed); 181 | } 182 | } 183 | 184 | 185 | private function onDatabaseClosed(error:Error):void 186 | { 187 | Assert.isNull(error); 188 | 189 | if(_db.file != null && _db.file.exists) 190 | { 191 | _db.file.deleteFile(); 192 | } 193 | 194 | currentAsync.complete(); 195 | } 196 | 197 | } 198 | 199 | } 200 | -------------------------------------------------------------------------------- /test/src/tests/TestSchema.as: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2017 Digital Strawberry LLC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | * 24 | */ 25 | 26 | package tests 27 | { 28 | import breezedb.BreezeDb; 29 | import breezedb.IBreezeDatabase; 30 | import breezedb.schemas.TableBlueprint; 31 | 32 | import breezetest.Assert; 33 | 34 | import breezetest.async.Async; 35 | 36 | import flash.errors.IllegalOperationError; 37 | import flash.utils.setTimeout; 38 | 39 | public class TestSchema 40 | { 41 | 42 | public var currentAsync:Async; 43 | 44 | private var _db:IBreezeDatabase; 45 | 46 | 47 | public function setupClass(async:Async):void 48 | { 49 | async.timeout = 2000; 50 | 51 | _db = BreezeDb.getDb("schema-test"); 52 | _db.setup(onDatabaseSetup); 53 | } 54 | 55 | 56 | private function onDatabaseSetup(error:Error):void 57 | { 58 | Assert.isNull(error); 59 | Assert.isTrue(_db.isSetup); 60 | 61 | currentAsync.complete(); 62 | } 63 | 64 | 65 | public function testSchema(async:Async):void 66 | { 67 | async.timeout = 5000; 68 | 69 | Assert.throwsError(function():void 70 | { 71 | _db.schema.createTable(null, null); 72 | }, ArgumentError); 73 | 74 | _db.schema.createTable("photos", function (table:TableBlueprint):void 75 | { 76 | table.increments("id"); 77 | table.string("name"); 78 | table.integer("views").defaultTo(0); 79 | table.timestamp("created_at").defaultTo(0); 80 | table.index("name"); 81 | 82 | // Cannot drop index during table creation 83 | Assert.throwsError(function():void 84 | { 85 | table.dropIndex("views"); 86 | }, IllegalOperationError); 87 | }, onPhotosTableCreated); 88 | } 89 | 90 | 91 | private function onPhotosTableCreated(error:Error):void 92 | { 93 | Assert.isNull(error); 94 | 95 | Assert.throwsError(function():void 96 | { 97 | _db.schema.hasTable(null, onPhotosTableCreated); 98 | }, ArgumentError); 99 | 100 | Assert.throwsError(function():void 101 | { 102 | _db.schema.hasTable("", null); 103 | }, ArgumentError); 104 | 105 | _db.schema.hasTable("photos", hasPhotosTable); 106 | } 107 | 108 | 109 | private function hasPhotosTable(error:Error, hasTable:Boolean):void 110 | { 111 | Assert.isNull(error); 112 | Assert.isTrue(hasTable); 113 | 114 | _db.schema.hasTable("non-existing", hasNonExistingTable); 115 | } 116 | 117 | 118 | private function hasNonExistingTable(error:Error, hasTable:Boolean):void 119 | { 120 | Assert.isNull(error); 121 | Assert.isFalse(hasTable); 122 | 123 | checkColumnsExistence(); 124 | } 125 | 126 | 127 | private function checkColumnsExistence():void 128 | { 129 | Assert.throwsError(function():void 130 | { 131 | _db.schema.hasColumn("photos", null, checkColumnsExistence); 132 | }, ArgumentError); 133 | 134 | Assert.throwsError(function():void 135 | { 136 | _db.schema.hasColumn(null, "views", checkColumnsExistence); 137 | }, ArgumentError); 138 | 139 | Assert.throwsError(function():void 140 | { 141 | _db.schema.hasColumn("", "views", null); 142 | }, ArgumentError); 143 | 144 | _db.schema.hasColumn("photos", "name", hasNameColumn); 145 | } 146 | 147 | 148 | private function hasNameColumn(error:Error, hasColumn:Boolean):void 149 | { 150 | Assert.isNull(error); 151 | Assert.isTrue(hasColumn); 152 | 153 | _db.schema.hasColumn("photos", "views", hasViewsColumn); 154 | } 155 | 156 | 157 | private function hasViewsColumn(error:Error, hasColumn:Boolean):void 158 | { 159 | Assert.isNull(error); 160 | Assert.isTrue(hasColumn); 161 | 162 | _db.schema.hasColumn("photos", "id", hasIdColumn); 163 | } 164 | 165 | 166 | private function hasIdColumn(error:Error, hasColumn:Boolean):void 167 | { 168 | Assert.isNull(error); 169 | Assert.isTrue(hasColumn); 170 | 171 | _db.schema.hasColumn("photos", "non-existing", hasNonExistingColumn); 172 | } 173 | 174 | 175 | private function hasNonExistingColumn(error:Error, hasColumn:Boolean):void 176 | { 177 | Assert.isNull(error); 178 | Assert.isFalse(hasColumn); 179 | 180 | _db.schema.hasColumn("non-existing", "id", hasNonExistingTableAndColumn); 181 | } 182 | 183 | 184 | private function hasNonExistingTableAndColumn(error:Error, hasColumn:Boolean):void 185 | { 186 | Assert.isNull(error); 187 | Assert.isFalse(hasColumn); 188 | 189 | testEditTable(); 190 | } 191 | 192 | 193 | // private, called after creating the table 194 | private function testEditTable():void 195 | { 196 | Assert.throwsError(function():void 197 | { 198 | _db.schema.editTable(null, null); 199 | }, ArgumentError); 200 | 201 | _db.schema.editTable("photos", function (table:TableBlueprint):void 202 | { 203 | // Adding multiple new columns is not possible using standard SQLite syntax 204 | // but the library should handle it automatically under the hood 205 | table.string("newColumn1").defaultNull(); 206 | table.number("newColumn2").defaultTo(3.14); 207 | }, onPhotosTableEdited); 208 | } 209 | 210 | 211 | private function onPhotosTableEdited(error:Error):void 212 | { 213 | Assert.isNull(error); 214 | 215 | _db.schema.hasColumn("photos", "newColumn1", newColumn1Exists); 216 | } 217 | 218 | 219 | private function newColumn1Exists(error:Error, hasColumn:Boolean):void 220 | { 221 | Assert.isNull(error); 222 | Assert.isTrue(hasColumn); 223 | 224 | _db.schema.hasColumn("photos", "newColumn2", newColumn2Exists); 225 | } 226 | 227 | 228 | private function newColumn2Exists(error:Error, hasColumn:Boolean):void 229 | { 230 | Assert.isNull(error); 231 | Assert.isTrue(hasColumn); 232 | 233 | testEditExistingColumn(); 234 | } 235 | 236 | 237 | private function testEditExistingColumn():void 238 | { 239 | _db.schema.editTable("photos", function(table:TableBlueprint):void 240 | { 241 | // Cannot modify primary key 242 | Assert.throwsError(function():void 243 | { 244 | table.integer("newKey").primary(); 245 | }, IllegalOperationError); 246 | 247 | // Should not be able to edit existing column 248 | table.integer("name").notNull(); 249 | }, onExistingColumnEdited); 250 | } 251 | 252 | 253 | private function onExistingColumnEdited(error:Error):void 254 | { 255 | Assert.isNotNull(error); 256 | 257 | renameTable(); 258 | } 259 | 260 | 261 | private function renameTable():void 262 | { 263 | Assert.throwsError(function():void 264 | { 265 | _db.schema.renameTable(null, ""); 266 | }, ArgumentError); 267 | 268 | Assert.throwsError(function():void 269 | { 270 | _db.schema.renameTable("", null); 271 | }, ArgumentError); 272 | 273 | _db.schema.renameTable("photos", "pictures", onTableRenamed); 274 | } 275 | 276 | 277 | private function onTableRenamed(error:Error):void 278 | { 279 | Assert.isNull(error); 280 | 281 | _db.schema.hasTable("photos", hasOldTableName); 282 | } 283 | 284 | 285 | private function hasOldTableName(error:Error, hasTable:Boolean):void 286 | { 287 | Assert.isNull(error); 288 | Assert.isFalse(hasTable); 289 | 290 | _db.schema.hasTable("pictures", hasNewTableName); 291 | } 292 | 293 | 294 | private function hasNewTableName(error:Error, hasTable:Boolean):void 295 | { 296 | Assert.isNull(error); 297 | Assert.isTrue(hasTable); 298 | 299 | Assert.throwsError(function():void 300 | { 301 | _db.schema.renameTable("pictures", "photos; DROP TABLE photos", BreezeDb.DELAY); 302 | }, ArgumentError); 303 | 304 | dropTable(); 305 | } 306 | 307 | 308 | private function dropTable():void 309 | { 310 | Assert.throwsError(function():void 311 | { 312 | _db.schema.dropTable(null); 313 | }, ArgumentError); 314 | 315 | _db.schema.dropTable("pictures", onTableDropped); 316 | } 317 | 318 | 319 | private function onTableDropped(error:Error):void 320 | { 321 | Assert.isNull(error); 322 | 323 | _db.schema.hasTable("pictures", hasDroppedTable) 324 | } 325 | 326 | 327 | private function hasDroppedTable(error:Error, hasTable:Boolean):void 328 | { 329 | Assert.isNull(error); 330 | Assert.isFalse(hasTable); 331 | 332 | _db.schema.dropTable("pictures", onNonExistingTableDropped); 333 | } 334 | 335 | 336 | private function onNonExistingTableDropped(error:Error):void 337 | { 338 | Assert.isNotNull(error); 339 | 340 | _db.schema.dropTableIfExists("pictures", onNonExistingTableDroppedSilently); 341 | } 342 | 343 | 344 | private function onNonExistingTableDroppedSilently(error:Error):void 345 | { 346 | Assert.isNull(error); 347 | 348 | currentAsync.complete(); 349 | } 350 | 351 | 352 | public function tearDownClass(async:Async):void 353 | { 354 | if(_db != null && _db.isSetup) 355 | { 356 | setTimeout(_db.close, 500, onDatabaseClosed); 357 | } 358 | } 359 | 360 | 361 | private function onDatabaseClosed(error:Error):void 362 | { 363 | Assert.isNull(error); 364 | 365 | if(_db.file != null && _db.file.exists) 366 | { 367 | _db.file.deleteFile(); 368 | } 369 | 370 | currentAsync.complete(); 371 | } 372 | 373 | } 374 | 375 | } 376 | -------------------------------------------------------------------------------- /test/src/tests/migrations/Migration_Create_Table_Photos.as: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2017 Digital Strawberry LLC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | * 24 | */ 25 | 26 | package tests.migrations 27 | { 28 | import breezedb.IBreezeDatabase; 29 | import breezedb.migrations.BreezeMigration; 30 | import breezedb.schemas.TableBlueprint; 31 | 32 | public class Migration_Create_Table_Photos extends BreezeMigration 33 | { 34 | 35 | public function Migration_Create_Table_Photos() 36 | { 37 | super(); 38 | } 39 | 40 | 41 | override public function run(db:IBreezeDatabase):void 42 | { 43 | db.schema.createTable("photos", function (table:TableBlueprint):void 44 | { 45 | table.increments("id"); 46 | table.string("title").defaultNull(); 47 | table.integer("views").defaultTo(0); 48 | table.integer("downloads").defaultTo(0); 49 | table.integer("likes").defaultTo(0); 50 | table.date("creation_date"); 51 | }, 52 | function(error:Error):void 53 | { 54 | done(error == null); 55 | }); 56 | } 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /test/src/tests/migrations/Migration_Insert_Default_Photos.as: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2017 Digital Strawberry LLC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | * 24 | */ 25 | 26 | package tests.migrations 27 | { 28 | import breezedb.IBreezeDatabase; 29 | import breezedb.migrations.BreezeMigration; 30 | 31 | public class Migration_Insert_Default_Photos extends BreezeMigration 32 | { 33 | 34 | private const _photos:Array = [ 35 | { title: "Mountains", views: 35, downloads: 10, likes: 4, creation_date: new Date(2014, 1, 25) }, 36 | { title: "Flowers", views: 6, downloads: 6, likes: 6, creation_date: new Date(2015, 3, 3) }, 37 | { title: "Lake", views: 35, downloads: 0, likes: 0, creation_date: new Date(2016, 5, 19) } 38 | ]; 39 | 40 | public function Migration_Insert_Default_Photos() 41 | { 42 | super(); 43 | } 44 | 45 | 46 | override public function run(db:IBreezeDatabase):void 47 | { 48 | db.table("photos").insert(_photos, function(error:Error):void 49 | { 50 | done(error == null); 51 | }); 52 | } 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /test/src/tests/migrations/Migration_Invalid_Class.as: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2017 Digital Strawberry LLC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | * 24 | */ 25 | 26 | package tests.migrations 27 | { 28 | 29 | // Does not inherit BreezeMigration, must fail 30 | public class Migration_Invalid_Class 31 | { 32 | 33 | public function Migration_Invalid_Class() 34 | { 35 | } 36 | 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /test/src/tests/migrations/Migration_Unsuccessful.as: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2017 Digital Strawberry LLC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | * 24 | */ 25 | 26 | package tests.migrations 27 | { 28 | import breezedb.IBreezeDatabase; 29 | import breezedb.migrations.BreezeMigration; 30 | 31 | // Always failing migration 32 | public class Migration_Unsuccessful extends BreezeMigration 33 | { 34 | 35 | public function Migration_Unsuccessful() 36 | { 37 | super(); 38 | } 39 | 40 | 41 | override public function run(db:IBreezeDatabase):void 42 | { 43 | done(false); 44 | } 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /test/src/tests/migrations/TestMigrations.as: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2017 Digital Strawberry LLC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | * 24 | */ 25 | 26 | package tests.migrations 27 | { 28 | import breezedb.BreezeDb; 29 | import breezedb.IBreezeDatabase; 30 | import breezedb.collections.Collection; 31 | import breezedb.events.BreezeMigrationEvent; 32 | import breezedb.migrations.BreezeMigration; 33 | 34 | import breezetest.Assert; 35 | 36 | import breezetest.async.Async; 37 | 38 | import flash.utils.setTimeout; 39 | 40 | public class TestMigrations extends BreezeMigration 41 | { 42 | 43 | public var currentAsync:Async; 44 | private var _db:IBreezeDatabase; 45 | private var _migrationEvents:Vector.; 46 | private var _testRepeatMigrations:Boolean; 47 | private var _isRepeatedMigration:Boolean; 48 | private var _migrationFinished:Boolean; 49 | 50 | 51 | public function testSetupMigrations(async:Async):void 52 | { 53 | async.timeout = 3000; 54 | 55 | _migrationEvents = new []; 56 | _testRepeatMigrations = true; 57 | _isRepeatedMigration = false; 58 | _migrationFinished = false; 59 | 60 | _db = BreezeDb.getDb("setup-migrations"); 61 | _db.addEventListener(BreezeMigrationEvent.RUN_SUCCESS, onMigrationRan); 62 | _db.addEventListener(BreezeMigrationEvent.RUN_ERROR, onMigrationRan); 63 | _db.addEventListener(BreezeMigrationEvent.SKIP, onMigrationRan); 64 | _db.addEventListener(BreezeMigrationEvent.FINISH, onMigrationsFinished); 65 | _db.migrations = [Migration_Create_Table_Photos, Migration_Insert_Default_Photos]; 66 | _db.setup(onSetupWithMigrationsCompleted); 67 | } 68 | 69 | 70 | private function onSetupWithMigrationsCompleted(error:Error):void 71 | { 72 | Assert.isNull(error); 73 | Assert.isTrue(_db.isSetup); 74 | 75 | validateMigrations(); 76 | } 77 | 78 | 79 | private function validateMigrations():void 80 | { 81 | // Check that the BreezeMigrationEvent.FINISH event was dispatched 82 | Assert.isTrue(_migrationFinished); 83 | 84 | // Check the table has been created 85 | _db.schema.hasTable("photos", onCheckTableCompleted); 86 | } 87 | 88 | 89 | private function onCheckTableCompleted(error:Error, hasTable:Boolean):void 90 | { 91 | Assert.isNull(error); 92 | Assert.isTrue(hasTable); 93 | 94 | // Check the photos has been inserted 95 | _db.table("photos").fetch(onCheckInsertCompleted); 96 | } 97 | 98 | 99 | private function onCheckInsertCompleted(error:Error, results:Collection):void 100 | { 101 | Assert.isNull(error); 102 | Assert.isNotNull(results); 103 | Assert.equals(3, results.length); 104 | 105 | Assert.equals(1, results[0].id); 106 | Assert.equals("Mountains", results[0].title); 107 | Assert.equals(35, results[0].views); 108 | Assert.equals(10, results[0].downloads); 109 | Assert.equals(4, results[0].likes); 110 | 111 | Assert.equals(2, results[1].id); 112 | Assert.equals("Flowers", results[1].title); 113 | Assert.equals(6, results[1].views); 114 | Assert.equals(6, results[1].downloads); 115 | Assert.equals(6, results[1].likes); 116 | 117 | Assert.equals(3, results[2].id); 118 | Assert.equals("Lake", results[2].title); 119 | Assert.equals(35, results[2].views); 120 | Assert.equals(0, results[2].downloads); 121 | Assert.equals(0, results[2].likes); 122 | 123 | Assert.equals(2, _migrationEvents.length); 124 | var length:int = _migrationEvents.length; 125 | for(var i:int = 0; i < length; ++i) 126 | { 127 | if(_isRepeatedMigration) 128 | { 129 | Assert.equals(BreezeMigrationEvent.SKIP, _migrationEvents[i].type); 130 | } 131 | else 132 | { 133 | Assert.equals(BreezeMigrationEvent.RUN_SUCCESS, _migrationEvents[i].type); 134 | } 135 | } 136 | 137 | _migrationEvents.length = 0; 138 | 139 | _db.removeEventListener(BreezeMigrationEvent.RUN_SUCCESS, onMigrationRan); 140 | _db.removeEventListener(BreezeMigrationEvent.RUN_ERROR, onMigrationRan); 141 | _db.removeEventListener(BreezeMigrationEvent.SKIP, onMigrationRan); 142 | _db.removeEventListener(BreezeMigrationEvent.FINISH, onMigrationsFinished); 143 | 144 | setTimeout(_db.close, 500, onDbClosed); 145 | } 146 | 147 | 148 | private function onDbClosed(error:Error):void 149 | { 150 | Assert.isNull(error); 151 | 152 | // Try to run the same migrations again 153 | if(_testRepeatMigrations) 154 | { 155 | _testRepeatMigrations = false; 156 | _isRepeatedMigration = true; 157 | _db.addEventListener(BreezeMigrationEvent.RUN_SUCCESS, onMigrationRan); 158 | _db.addEventListener(BreezeMigrationEvent.RUN_ERROR, onMigrationRan); 159 | _db.addEventListener(BreezeMigrationEvent.SKIP, onMigrationRan); 160 | _db.addEventListener(BreezeMigrationEvent.FINISH, onMigrationsFinished); 161 | _db.setup(onSetupWithMigrationsCompleted); 162 | } 163 | else 164 | { 165 | _db.file.deleteFile(); 166 | 167 | currentAsync.complete(); 168 | } 169 | } 170 | 171 | 172 | public function testAfterSetupMigrations(async:Async):void 173 | { 174 | async.timeout = 3000; 175 | 176 | _migrationEvents = new []; 177 | _testRepeatMigrations = false; 178 | _isRepeatedMigration = false; 179 | _migrationFinished = false; 180 | 181 | _db = BreezeDb.getDb("after-setup-migrations"); 182 | _db.addEventListener(BreezeMigrationEvent.RUN_SUCCESS, onMigrationRan); 183 | _db.addEventListener(BreezeMigrationEvent.RUN_ERROR, onMigrationRan); 184 | _db.addEventListener(BreezeMigrationEvent.SKIP, onMigrationRan); 185 | _db.addEventListener(BreezeMigrationEvent.FINISH, onMigrationsFinished); 186 | _db.setup(onDbSetup); 187 | } 188 | 189 | 190 | private function onDbSetup(error:Error):void 191 | { 192 | Assert.isNull(error); 193 | Assert.isTrue(_db.isSetup); 194 | 195 | _db.runMigrations([Migration_Create_Table_Photos, Migration_Insert_Default_Photos], onAfterSetupMigrationsCompleted); 196 | } 197 | 198 | 199 | private function onAfterSetupMigrationsCompleted(error:Error):void 200 | { 201 | Assert.isNull(error); 202 | 203 | validateMigrations(); 204 | } 205 | 206 | 207 | private function onMigrationRan(event:BreezeMigrationEvent):void 208 | { 209 | _migrationEvents[_migrationEvents.length] = event; 210 | } 211 | 212 | 213 | private function onMigrationsFinished(event:BreezeMigrationEvent):void 214 | { 215 | _migrationFinished = true; 216 | } 217 | 218 | 219 | public function testInvalidMigrationClass(async:Async):void 220 | { 221 | async.timeout = 3000; 222 | 223 | _db = BreezeDb.getDb("invalid-migration-class"); 224 | _db.migrations = Migration_Invalid_Class; 225 | _db.setup(onInvalidMigrationClassDbSetup); 226 | } 227 | 228 | 229 | private function onInvalidMigrationClassDbSetup(error:Error):void 230 | { 231 | Assert.isNotNull(error); 232 | Assert.isType(error, ArgumentError); 233 | Assert.isFalse(_db.isSetup); 234 | 235 | _db.file.deleteFile(); 236 | 237 | currentAsync.complete(); 238 | } 239 | 240 | 241 | public function testUnsuccessfulMigration(async:Async):void 242 | { 243 | async.timeout = 3000; 244 | 245 | _db = BreezeDb.getDb("unsuccessful-migration"); 246 | _db.migrations = [Migration_Create_Table_Photos, Migration_Unsuccessful]; 247 | _db.setup(onUnsuccessfulMigrationDbSetup); 248 | } 249 | 250 | 251 | private function onUnsuccessfulMigrationDbSetup(error:Error):void 252 | { 253 | Assert.isNotNull(error); 254 | Assert.isFalse(_db.isSetup); 255 | 256 | // Check that the successful migration has not been committed 257 | _db.schema.hasTable("photos", onCheckMigrationRollBackCompleted); 258 | } 259 | 260 | 261 | private function onCheckMigrationRollBackCompleted(error:Error, hasTable:Boolean):void 262 | { 263 | Assert.isFalse(hasTable); 264 | 265 | _db.close(function(error:Error):void 266 | { 267 | _db.file.deleteFile(); 268 | 269 | currentAsync.complete(); 270 | }); 271 | } 272 | 273 | 274 | public function testInvalidMigrationArgument(async:Async):void 275 | { 276 | async.timeout = 3000; 277 | 278 | _db = BreezeDb.getDb("invalid-migration-argument"); 279 | _db.migrations = ["Invalid migration value"]; 280 | _db.setup(onInvalidMigrationArgumentDbSetup); 281 | } 282 | 283 | 284 | private function onInvalidMigrationArgumentDbSetup(error:Error):void 285 | { 286 | Assert.isNotNull(error); 287 | Assert.isFalse(_db.isSetup); 288 | 289 | _db.file.deleteFile(); 290 | 291 | currentAsync.complete(); 292 | } 293 | } 294 | 295 | } 296 | -------------------------------------------------------------------------------- /test/src/tests/models/CustomTableModel.as: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2017 Digital Strawberry LLC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | * 24 | */ 25 | 26 | package tests.models 27 | { 28 | import breezedb.models.BreezeModel; 29 | 30 | public class CustomTableModel extends BreezeModel 31 | { 32 | 33 | public function CustomTableModel() 34 | { 35 | super(); 36 | 37 | _tableName = "custom_table_name"; 38 | _databaseName = TestModel.DB_NAME; 39 | } 40 | 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /test/src/tests/models/Photo.as: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2017 Digital Strawberry LLC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | * 24 | */ 25 | 26 | package tests.models 27 | { 28 | import breezedb.models.BreezeModel; 29 | 30 | public class Photo extends BreezeModel 31 | { 32 | public var id:int; 33 | public var title:String; 34 | public var views:int; 35 | public var downloads:int; 36 | public var creation_date:Date; 37 | 38 | public function Photo() 39 | { 40 | super(); 41 | _databaseName = TestModel.DB_NAME; 42 | } 43 | 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /test/src/tests/models/PhotoAlbum.as: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2017 Digital Strawberry LLC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | * 24 | */ 25 | 26 | package tests.models 27 | { 28 | import breezedb.models.BreezeModel; 29 | 30 | public class PhotoAlbum extends BreezeModel 31 | { 32 | 33 | public function PhotoAlbum() 34 | { 35 | super(); 36 | _databaseName = TestModel.DB_NAME; 37 | } 38 | 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /test/src/tests/models/TestModel.as: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2017 Digital Strawberry LLC 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | * 24 | */ 25 | 26 | package tests.models 27 | { 28 | import breezedb.BreezeDb; 29 | import breezedb.IBreezeDatabase; 30 | import breezedb.collections.Collection; 31 | import breezedb.models.BreezeModel; 32 | import breezedb.schemas.TableBlueprint; 33 | 34 | import breezetest.Assert; 35 | import breezetest.async.Async; 36 | 37 | import flash.utils.setTimeout; 38 | 39 | public class TestModel 40 | { 41 | // Used by custom models 42 | public static const DB_NAME:String = "test-model"; 43 | 44 | public var currentAsync:Async; 45 | 46 | private var _db:IBreezeDatabase; 47 | 48 | private const _photos:Array = [ 49 | { title: "Mountains", views: 35, downloads: 10, creation_date: new Date(2014, 1, 25) }, 50 | { title: "Flowers", views: 6, downloads: 6, creation_date: new Date(2015, 3, 3) }, 51 | { title: "Lake", views: 35, downloads: 0, creation_date: new Date(2016, 5, 19) }, 52 | { title: "Camp Fire", views: 13, downloads: 13, creation_date: new Date(2016, 8, 27) } 53 | ]; 54 | private const _photosTable:String = "photos"; 55 | 56 | 57 | public function setupClass(async:Async):void 58 | { 59 | async.timeout = 3000; 60 | 61 | _db = BreezeDb.getDb(DB_NAME); 62 | _db.setup(onDatabaseSetup); 63 | } 64 | 65 | 66 | private function onDatabaseSetup(error:Error):void 67 | { 68 | Assert.isNull(error); 69 | Assert.isTrue(_db.isSetup); 70 | 71 | _db.schema.createTable(_photosTable, function (table:TableBlueprint):void 72 | { 73 | table.increments("id"); 74 | table.string("title").defaultNull(); 75 | table.integer("views").defaultTo(0); 76 | table.integer("downloads").defaultTo(0); 77 | table.date("creation_date").defaultNull(); 78 | }, onTableCreated); 79 | } 80 | 81 | 82 | private function onTableCreated(error:Error):void 83 | { 84 | Assert.isNull(error); 85 | 86 | // Insert photos 87 | _db.table(_photosTable).insert(_photos, onPhotosInserted); 88 | } 89 | 90 | 91 | private function onPhotosInserted(error:Error):void 92 | { 93 | Assert.isNull(error); 94 | 95 | currentAsync.complete(); 96 | } 97 | 98 | 99 | public function testTableName():void 100 | { 101 | var photo:Photo = new Photo(); 102 | Assert.equals("photos", photo.tableName); 103 | 104 | var photoAlbum:PhotoAlbum = new PhotoAlbum(); 105 | Assert.equals("photo_albums", photoAlbum.tableName); 106 | 107 | var customTable:CustomTableModel = new CustomTableModel(); 108 | Assert.equals("custom_table_name", customTable.tableName); 109 | } 110 | 111 | 112 | public function testSave(async:Async):void 113 | { 114 | async.timeout = 3000; 115 | 116 | // Save new photo 117 | var photo:Photo = new Photo(); 118 | photo.id = 6; 119 | photo.title = "Hills"; 120 | photo.views = 7; 121 | photo.downloads = 3; 122 | photo.creation_date = new Date(2016, 7, 7); 123 | photo.save(onNewPhotoSaved) 124 | } 125 | 126 | 127 | private function onNewPhotoSaved(error:Error, photo:Photo):void 128 | { 129 | Assert.isNull(error); 130 | Assert.isNotNull(photo); 131 | Assert.equals(6, photo.id); 132 | Assert.equals("Hills", photo.title); 133 | Assert.equals(7, photo.views); 134 | Assert.equals(3, photo.downloads); 135 | Assert.isNotNull(photo.creation_date); 136 | Assert.equals(2016, photo.creation_date.fullYear); 137 | Assert.equals(7, photo.creation_date.month); 138 | Assert.equals(7, photo.creation_date.date); 139 | 140 | // Update the photo via save 141 | photo.title = "Great Smoky Mountains"; 142 | photo.views = 13; 143 | photo.downloads = 10; 144 | photo.save(onPhotoUpdated); 145 | } 146 | 147 | 148 | private function onPhotoUpdated(error:Error, photo:Photo):void 149 | { 150 | Assert.isNull(error); 151 | Assert.isNotNull(photo); 152 | Assert.equals(6, photo.id); 153 | Assert.equals("Great Smoky Mountains", photo.title); 154 | Assert.equals(13, photo.views); 155 | Assert.equals(10, photo.downloads); 156 | Assert.isNotNull(photo.creation_date); 157 | Assert.equals(2016, photo.creation_date.fullYear); 158 | Assert.equals(7, photo.creation_date.month); 159 | Assert.equals(7, photo.creation_date.date); 160 | 161 | currentAsync.complete(); 162 | } 163 | 164 | 165 | public function testFirstAndRemove(async:Async):void 166 | { 167 | async.timeout = 3000; 168 | 169 | BreezeModel.query(Photo).first(onFirstPhotoRetrieved); 170 | } 171 | 172 | 173 | private function onFirstPhotoRetrieved(error:Error, photo:Photo):void 174 | { 175 | Assert.isNull(error); 176 | Assert.isNotNull(photo); 177 | 178 | Assert.equals(1, photo.id); 179 | Assert.equals("Mountains", photo.title); 180 | Assert.equals(35, photo.views); 181 | Assert.equals(10, photo.downloads); 182 | 183 | photo.remove(onFirstPhotoDeleted); 184 | } 185 | 186 | 187 | private function onFirstPhotoDeleted(error:Error):void 188 | { 189 | Assert.isNull(error); 190 | 191 | BreezeModel.query(Photo).where("id", 1).fetch(onPhotoDeleteCheckCompleted); 192 | } 193 | 194 | 195 | private function onPhotoDeleteCheckCompleted(error:Error, results:Collection):void 196 | { 197 | Assert.isNull(error); 198 | Assert.isNotNull(results); 199 | Assert.equals(0, results.length); 200 | 201 | currentAsync.complete(); 202 | } 203 | 204 | 205 | public function testFirstOrNew(async:Async):void 206 | { 207 | async.timeout = 3000; 208 | 209 | BreezeModel.query(Photo).firstOrNew({ id: 5, title: "Sunrise" }, onFirstOrNewCompleted); 210 | } 211 | 212 | 213 | private function onFirstOrNewCompleted(error:Error, photo:Photo):void 214 | { 215 | Assert.isNull(error); 216 | Assert.isNotNull(photo); 217 | 218 | Assert.equals(5, photo.id); 219 | Assert.equals("Sunrise", photo.title); 220 | Assert.equals(0, photo.views); 221 | Assert.equals(0, photo.downloads); 222 | Assert.isFalse(photo.exists); 223 | 224 | // Check that the photo is not in the database 225 | BreezeModel.query(Photo).where("id", 5).fetch(onFirstOrNewCheckCompleted); 226 | } 227 | 228 | 229 | private function onFirstOrNewCheckCompleted(error:Error, results:Collection):void 230 | { 231 | Assert.isNull(error); 232 | Assert.isNotNull(results); 233 | Assert.equals(0, results.length); 234 | 235 | BreezeModel.query(Photo).firstOrNew({ title: "Sunrise" }, onFirstOrNewWithoutIdCompleted); 236 | } 237 | 238 | 239 | private function onFirstOrNewWithoutIdCompleted(error:Error, photo:Photo):void 240 | { 241 | Assert.isNull(error); 242 | Assert.isNotNull(photo); 243 | 244 | // The photo should have auto-incremented id, non-zero 245 | Assert.isTrue(photo.id != 0); 246 | Assert.equals("Sunrise", photo.title); 247 | Assert.equals(0, photo.views); 248 | Assert.equals(0, photo.downloads); 249 | Assert.isFalse(photo.exists); 250 | 251 | // Check that the photo is not in the database 252 | BreezeModel.query(Photo).where("id", photo.id).fetch(onFirstOrNewWithoutIdCheckCompleted); 253 | } 254 | 255 | 256 | private function onFirstOrNewWithoutIdCheckCompleted(error:Error, results:Collection):void 257 | { 258 | Assert.isNull(error); 259 | Assert.isNotNull(results); 260 | Assert.equals(0, results.length); 261 | 262 | currentAsync.complete(); 263 | } 264 | 265 | 266 | public function testFirstOrCreate(async:Async):void 267 | { 268 | async.timeout = 3000; 269 | 270 | BreezeModel.query(Photo).firstOrCreate({ id: 20, title: "Sunset", views: 10 }, onFirstOrCreateCompleted); 271 | } 272 | 273 | 274 | private function onFirstOrCreateCompleted(error:Error, photo:Photo):void 275 | { 276 | Assert.isNull(error); 277 | Assert.isNotNull(photo); 278 | 279 | Assert.equals(20, photo.id); 280 | Assert.equals("Sunset", photo.title); 281 | Assert.equals(10, photo.views); 282 | Assert.equals(0, photo.downloads); 283 | Assert.isTrue(photo.exists); 284 | 285 | // Check that the photo is in the database 286 | BreezeModel.query(Photo).where("id", 20).fetch(onFirstOrCreateCheckCompleted); 287 | } 288 | 289 | 290 | private function onFirstOrCreateCheckCompleted(error:Error, results:Collection):void 291 | { 292 | Assert.isNull(error); 293 | Assert.isNotNull(results); 294 | Assert.equals(1, results.length); 295 | 296 | Assert.isType(results[0], Photo); 297 | 298 | var photo:Photo = results[0] as Photo; 299 | 300 | Assert.equals(20, photo.id); 301 | Assert.equals("Sunset", photo.title); 302 | Assert.equals(10, photo.views); 303 | Assert.equals(0, photo.downloads); 304 | 305 | // Save new photo without specifying the id (it must auto-increment) 306 | BreezeModel.query(Photo).firstOrCreate({ title: "Cloudy Sky" }, onFirstOrCreateWithoutIdCompleted); 307 | } 308 | 309 | 310 | private function onFirstOrCreateWithoutIdCompleted(error:Error, photo:Photo):void 311 | { 312 | Assert.isNull(error); 313 | Assert.isNotNull(photo); 314 | 315 | Assert.equals(21, photo.id); 316 | Assert.equals("Cloudy Sky", photo.title); 317 | Assert.isTrue(photo.exists); 318 | 319 | // Check that the photo is in the database 320 | BreezeModel.query(Photo).where("id", 21).fetch(onFirstOrCreateWithoutIdCheckCompleted); 321 | } 322 | 323 | 324 | private function onFirstOrCreateWithoutIdCheckCompleted(error:Error, results:Collection):void 325 | { 326 | Assert.isNull(error); 327 | Assert.isNotNull(results); 328 | Assert.equals(1, results.length); 329 | 330 | Assert.isType(results[0], Photo); 331 | 332 | var photo:Photo = results[0] as Photo; 333 | 334 | Assert.equals(21, photo.id); 335 | Assert.equals("Cloudy Sky", photo.title); 336 | Assert.equals(0, photo.views); 337 | Assert.equals(0, photo.downloads); 338 | 339 | currentAsync.complete(); 340 | } 341 | 342 | 343 | public function testFindAndRemoveByKey(async:Async):void 344 | { 345 | async.timeout = 3000; 346 | 347 | // Check that all photos that are about to be removed are in the database 348 | BreezeModel.query(Photo).find(2, onFindSinglePhotoCompleted); 349 | } 350 | 351 | 352 | private function onFindSinglePhotoCompleted(error:Error, photo:Photo):void 353 | { 354 | Assert.isNull(error); 355 | Assert.isNotNull(photo); 356 | 357 | Assert.equals(2, photo.id); 358 | Assert.equals("Flowers", photo.title); 359 | Assert.equals(6, photo.views); 360 | Assert.equals(6, photo.downloads); 361 | 362 | BreezeModel.query(Photo).find([3, 4], onFindMultiplePhotosCompleted); 363 | } 364 | 365 | 366 | private function onFindMultiplePhotosCompleted(error:Error, results:Collection):void 367 | { 368 | Assert.isNull(error); 369 | Assert.isNotNull(results); 370 | Assert.equals(2, results.length); 371 | 372 | var length:int = results.length; 373 | for(var i:int = 0; i < length; ++i) 374 | { 375 | Assert.isType(results[i], Photo); 376 | Assert.equals(i + 3, Photo(results[i]).id); 377 | } 378 | 379 | // Remove photo with id of 2 380 | BreezeModel.query(Photo).removeByKey(2, onPhoto2Removed); 381 | } 382 | 383 | 384 | private function onPhoto2Removed(error:Error):void 385 | { 386 | Assert.isNull(error); 387 | 388 | // Check the photo with id of 2 was removed 389 | BreezeModel.query(Photo).find(2, onPhoto2RemoveCheckCompleted); 390 | } 391 | 392 | 393 | private function onPhoto2RemoveCheckCompleted(error:Error, photo:Photo):void 394 | { 395 | Assert.isNull(error); 396 | Assert.isNull(photo); 397 | 398 | // Remove photos with id of 3 and 4 399 | BreezeModel.query(Photo).removeByKey([3, 4], onPhoto3And4Removed); 400 | } 401 | 402 | 403 | private function onPhoto3And4Removed(error:Error):void 404 | { 405 | Assert.isNull(error); 406 | 407 | // Check the photos with id of 2 and 3 were removed 408 | BreezeModel.query(Photo).find([2, 3], onPhoto2And3RemoveCheckCompleted); 409 | } 410 | 411 | 412 | private function onPhoto2And3RemoveCheckCompleted(error:Error, results:Collection):void 413 | { 414 | Assert.isNull(error); 415 | Assert.isNotNull(results); 416 | Assert.equals(0, results.length); 417 | 418 | currentAsync.complete(); 419 | } 420 | 421 | 422 | public function tearDownClass(async:Async):void 423 | { 424 | if(_db != null && _db.isSetup) 425 | { 426 | setTimeout(_db.close, 500, onDatabaseClosed); 427 | } 428 | } 429 | 430 | 431 | private function onDatabaseClosed(error:Error):void 432 | { 433 | Assert.isNull(error); 434 | 435 | if(_db.file != null && _db.file.exists) 436 | { 437 | _db.file.deleteFile(); 438 | } 439 | 440 | currentAsync.complete(); 441 | } 442 | 443 | } 444 | 445 | } 446 | -------------------------------------------------------------------------------- /test/test.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | --------------------------------------------------------------------------------