typealias TaskDBModel = V2.TaskDBModel
typealias TapRegistrationDBModel = V2.TapRegistrationDBModel
enum V2 {
class TaskDBModel: CoreStoreObject {
let testName = Value.Required<String>("testName", initial: "")
let remark = Value.Optional<String>("remark")
let date = Value.Required<Date>("date", initial: Date())
let taps = Relationship.ToManyUnordered<V2.TapRegistrationDBModel>("taps", inverse: { $0.task })
let age = Value.Optional<Int>("age")
let sex = Value.Optional<String>("sex")
}
class TapRegistrationDBModel: CoreStoreObject {
let milliseconds = Value.Optional<Int32>("milliseconds", initial: 0)
let date = Value.Required<Date>("date", initial: Date())
let task = Relationship.ToOne<V2.TaskDBModel>("task")
}
}
enum V1 {
class TaskDBModel: CoreStoreObject {
let testName = Value.Required<String>("testName", initial: "")
let remark = Value.Optional<String>("remark")
let date = Value.Required<Date>("date", initial: Date())
let taps = Relationship.ToManyUnordered<V1.TapRegistrationDBModel>("taps", inverse: { $0.task })
}
class TapRegistrationDBModel: CoreStoreObject {
let milliseconds = Value.Optional<Int32>("milliseconds", initial: 0)
let date = Value.Required<Date>("date", initial: Date())
let task = Relationship.ToOne<V1.TaskDBModel>("task")
}
}
This used to be the initialization code before(on V5.0):
First, your versionLock for V2's TapRegistration seem to be the same with V1, which shouldn't be the case.
Second, check your usage of String(describing: Task.self). I don't recommend using non-static strings for entity names because they will break if you refactor your types.
If none of those are the issue, I'm afraid this may be caused by your initialization of dates. (I haven't proved this but I wouldn't be surprised if it was the cause)
The initial: argument here should be a statically reproducible value (e.g. Date.distantPast), not Date(), which creates the date instance during the time the code was run.
@JohnEstropia commented on GitHub (Oct 14, 2018):
I am not sure but I'll throw out some ideas.
First, your `versionLock` for V2's `TapRegistration` seem to be the same with V1, which shouldn't be the case.
Second, check your usage of `String(describing: Task.self)`. I don't recommend using non-static strings for entity names because they will break if you refactor your types.
If none of those are the issue, I'm afraid this may be caused by your initialization of `dates`. (I haven't proved this but I wouldn't be surprised if it was the cause)
```swift
let date = Value.Required<Date>("date", initial: Date())
```
The `initial:` argument here should be a statically reproducible value (e.g. `Date.distantPast`), not `Date()`, which creates the date instance during the time the code was run.
I'm new to CoreStore myself, but I hit a similar issue when using synchronous migration with CoreStoreObjects. Try switching to the asynchronous CoreStore.addStorage() call instead and see if the problem goes away for you.
I still see get the Core Data error logs on the console, but the migration does proceed correctly. I just chalked those up to spurious logging due to opening an out-of-date store prior to then beginning migration.
@scogeo commented on GitHub (Oct 15, 2018):
I'm new to CoreStore myself, but I hit a similar issue when using synchronous migration with `CoreStoreObject`s. Try switching to the asynchronous `CoreStore.addStorage()` call instead and see if the problem goes away for you.
I still see get the Core Data error logs on the console, but the migration does proceed correctly. I just chalked those up to spurious logging due to opening an out-of-date store prior to then beginning migration.
@JohnEstropia The versionLock for TapRegistration is the one I got from the output of CoreStore itself. So maybe there is a bug there?
I've changed the String(describing: Task.self) to static strings.
And I've changed the date code to:
let date = Value.Required<Date>("date", initial: Date(timeIntervalSince1970: 0))
And still I'm getting those errors.
@scogeo I've tried with the asynchronous CoreStore.addStorage() call but still the same results. A simple call like CoreStore.fetchAll(From<TaskDBModel>()) fails. It returnsnil
@Miggets7 commented on GitHub (Oct 15, 2018):
@JohnEstropia The `versionLock` for `TapRegistration` is the one I got from the output of CoreStore itself. So maybe there is a bug there?
I've changed the `String(describing: Task.self`) to static strings.
And I've changed the date code to:
```
let date = Value.Required<Date>("date", initial: Date(timeIntervalSince1970: 0))
```
And still I'm getting those errors.
@scogeo I've tried with the asynchronous `CoreStore.addStorage()` call but still the same results. A simple call like `CoreStore.fetchAll(From<TaskDBModel>())` fails. It returns`nil`
The versionLock for TapRegistration is the one I got from the output of CoreStore itself. So maybe there is a bug there?
Can you try commenting out the versionLock arguments for both V1 and V2 and check if the hashes are the same?
@JohnEstropia commented on GitHub (Oct 15, 2018):
@Miggets7
> The versionLock for TapRegistration is the one I got from the output of CoreStore itself. So maybe there is a bug there?
Can you try commenting out the `versionLock` arguments for both V1 and V2 and check if the hashes are the same?
🔸 [CoreStore: Notice] CoreStoreSchema.swift:188 init(modelVersion:entityConfigurations:versionLock:)
↪︎ These are hashes for the 'CoreStoreSchema' with version name "V1". Copy the dictionary below and pass it to the 'CoreStoreSchema' initializer's "versionLock" argument:
versionLock: [
"TapRegistration": [0xfd077bcfe64c4992, 0x6d06a0cd48c6ac9c, 0x8977f8d6cc0d5c14, 0x3d9c007916290238],
"Task": [0xd4c806a92e336b77, 0x1eeab56711d8e7d8, 0x6ed6e2b670cb5d13, 0x99c812c97e60dd80]
]
🔸 [CoreStore: Notice] CoreStoreSchema.swift:188 init(modelVersion:entityConfigurations:versionLock:)
↪︎ These are hashes for the 'CoreStoreSchema' with version name "V2". Copy the dictionary below and pass it to the 'CoreStoreSchema' initializer's "versionLock" argument:
versionLock: [
"TapRegistration": [0xfd077bcfe64c4992, 0x6d06a0cd48c6ac9c, 0x8977f8d6cc0d5c14, 0x3d9c007916290238],
"Task": [0xcf35773200b21f75, 0xce61aef165810847, 0x1a435a2d66adaabe, 0x1483319388071899]
]
@Miggets7 commented on GitHub (Oct 15, 2018):
@JohnEstropia These are the `versionLock` results:
```
🔸 [CoreStore: Notice] CoreStoreSchema.swift:188 init(modelVersion:entityConfigurations:versionLock:)
↪︎ These are hashes for the 'CoreStoreSchema' with version name "V1". Copy the dictionary below and pass it to the 'CoreStoreSchema' initializer's "versionLock" argument:
versionLock: [
"TapRegistration": [0xfd077bcfe64c4992, 0x6d06a0cd48c6ac9c, 0x8977f8d6cc0d5c14, 0x3d9c007916290238],
"Task": [0xd4c806a92e336b77, 0x1eeab56711d8e7d8, 0x6ed6e2b670cb5d13, 0x99c812c97e60dd80]
]
🔸 [CoreStore: Notice] CoreStoreSchema.swift:188 init(modelVersion:entityConfigurations:versionLock:)
↪︎ These are hashes for the 'CoreStoreSchema' with version name "V2". Copy the dictionary below and pass it to the 'CoreStoreSchema' initializer's "versionLock" argument:
versionLock: [
"TapRegistration": [0xfd077bcfe64c4992, 0x6d06a0cd48c6ac9c, 0x8977f8d6cc0d5c14, 0x3d9c007916290238],
"Task": [0xcf35773200b21f75, 0xce61aef165810847, 0x1a435a2d66adaabe, 0x1483319388071899]
]
```
@Miggets7 Oops, sorry I've been misreading the entities. The TapRegistration didn't have attribute changes so the same hash should be fine.
Couple of things I'd like to clarify:
do{tryCoreStore.addStorageAndWait(SQLiteStore(fileName:"Vigilantia.sqlite",localStorageOptions:.allowSynchronousLightweightMigration))}catch{print("error setting up storage: \(error)")}
Is error setting up storage: actually being reached here?
Also when you tried to use the asynchronous CoreStore.addStorage() method, were you getting a .failure result from the completion block?
@JohnEstropia commented on GitHub (Oct 15, 2018):
@Miggets7 Oops, sorry I've been misreading the entities. The TapRegistration didn't have attribute changes so the same hash should be fine.
Couple of things I'd like to clarify:
```swift
do {
try CoreStore.addStorageAndWait(SQLiteStore(fileName: "Vigilantia.sqlite", localStorageOptions: .allowSynchronousLightweightMigration))
}
catch {
print("error setting up storage: \(error)")
}
```
Is `error setting up storage:` actually being reached here?
Also when you tried to use the asynchronous `CoreStore.addStorage()` method, were you getting a `.failure` result from the completion block?
@JohnEstropia
It seems to be working now with the CoreStore.addStorage() call. It does throw an exeption in NSPersistentStoreCoordinator+Setup.swift here:
But it retuns a success call. It seems the data also seems right and running tha app a second time doens't throw any errors. But the completion still return an error object:
Right now it seems I can use this without any problem, so I guess this issue could be closed?
@Miggets7 commented on GitHub (Oct 15, 2018):
@JohnEstropia
It seems to be working now with the `CoreStore.addStorage()` call. It does throw an exeption in NSPersistentStoreCoordinator+Setup.swift here:
```
@nonobjc
internal func addPersistentStoreSynchronously(_ storeType: String, configuration: ModelConfiguration, URL storeURL: URL?, options: [AnyHashable: Any]?) throws -> NSPersistentStore {
return try self.performSynchronously {
do {
return try self.addPersistentStore(
ofType: storeType,
configurationName: configuration,
at: storeURL,
options: options
)
}
catch {
throw CoreStoreError(error)
}
}
}
```
But it retuns a success call. It seems the data also seems right and running tha app a second time doens't throw any errors. But the completion still return an error object:
```
Printing description of error.differentStorageExistsAtURL.existingPersistentStoreURL:
▿ (CoreStore.SQLiteStore) (
.configuration = nil;
.storeOptions = 2 key-value(s) [
"_NSBinaryStoreInsecureDecodingCompatibilityOption" = true;
"NSSQLitePragmasOption" = 1 key-value(s) [
"journal_mode" = "WAL";
];
];
.fileURL = "file:///var/mobile/Containers/Data/Application/C261FF7A-FDA1-49FF-AE48-B7C63C00CB07/Library/Application%20Support/com.appbriek.vigilancebuddy/Vigilantia.sqlite";
.migrationMappingProviders = 0 item(s) [];
.localStorageOptions = [.none];
.fileSize = 32768;
)
▿ _url : (CoreStore.SQLiteStore) (
.configuration = nil;
.storeOptions = 2 key-value(s) [
"_NSBinaryStoreInsecureDecodingCompatibilityOption" = true;
"NSSQLitePragmasOption" = 1 key-value(s) [
"journal_mode" = "WAL";
];
];
.fileURL = "file:///var/mobile/Containers/Data/Application/C261FF7A-FDA1-49FF-AE48-B7C63C00CB07/Library/Application%20Support/com.appbriek.vigilancebuddy/Vigilantia.sqlite";
.migrationMappingProviders = 0 item(s) [];
.localStorageOptions = [.none];
.fileSize = 32768;
)
```
Right now it seems I can use this without any problem, so I guess this issue could be closed?
Just a brief followup to the above comment after some brief investigation on my own prototype. You can suppress the Core Data log messages caused by the throw from the call to addPresistentStore mentioned by @Miggets7 by explicitly declaring a simple CustomSchemaMappingProvider. This will cause a different code path to be taken and avoid the throw and error logs during migration.
@scogeo commented on GitHub (Oct 15, 2018):
Just a brief followup to the above comment after some brief investigation on my own prototype. You can suppress the Core Data log messages caused by the throw from the call to `addPresistentStore` mentioned by @Miggets7 by explicitly declaring a simple `CustomSchemaMappingProvider`. This will cause a different code path to be taken and avoid the throw and error logs during migration.
In this example, something like this should work:
```swift
let storage = SQLiteStore(
fileName: "Vigilantia.sqlite",
migrationMappingProviders: [
CustomSchemaMappingProvider(
from: "V1",
to: "V2",
entityMappings: [
.transformEntity(sourceEntity: "Task", destinationEntity: "Task", transformer: CustomSchemaMappingProvider.CustomMapping.inferredTransformation),
.copyEntity(sourceEntity: "TapRegistration", destinationEntity: "TapRegistration")
]
)
]
)
```
Ah, I see. There is actually a quirk in lightweight migrations where it fails in addPersistentStore(), but succeeds when using the inferred mapping model that it should have used internally in addPersistentStore(). You'll find that logic here:
I'll look for a way to silent these error logs in this case.
@scogeo Thanks for the suggestion to use CustomSchemaMappingProvider. While this would work for your data, there is a tradeoff in memory use here as lightweight migration uses batched SQL queries internally as much as it can, while CustomSchemaMappingProvider recreates all objects one by one. If you have small data it should be more or less the same. (On a separate note, if your models are expected to succeed with an inferred mapping, you can omit the CustomSchemaMappingProvider's entityMappings argument)
@JohnEstropia commented on GitHub (Oct 16, 2018):
Ah, I see. There is actually a quirk in lightweight migrations where it fails in `addPersistentStore()`, but succeeds when using the inferred mapping model that it should have used internally in `addPersistentStore()`. You'll find that logic here:
<img width="828" alt="screen shot 2018-10-16 at 10 24 54" src="https://user-images.githubusercontent.com/3029684/46987135-c3973400-d12d-11e8-86aa-b76586f56f8b.png">
I'll look for a way to silent these error logs in this case.
@scogeo Thanks for the suggestion to use `CustomSchemaMappingProvider`. While this would work for your data, there is a tradeoff in memory use here as lightweight migration uses batched SQL queries internally as much as it can, while `CustomSchemaMappingProvider` recreates all objects one by one. If you have small data it should be more or less the same. (On a separate note, if your models are expected to succeed with an inferred mapping, you can omit the `CustomSchemaMappingProvider`'s `entityMappings` argument)
@JohnEstropia thank you for looking into the problem further, it would be nice to resolve it so I can use the implicit lightweight migration without any errors in the console logs.
Really enjoying CoreStore so far though!
@scogeo commented on GitHub (Oct 17, 2018):
@JohnEstropia thank you for looking into the problem further, it would be nice to resolve it so I can use the implicit lightweight migration without any errors in the console logs.
Really enjoying CoreStore so far though!
I'm closing this issue now, thanks for all the input.
To future developers who would hit this issue, please note that "lightweight migration" somehow has two types in Core Data: one that would succeed synchronously, and one that needs to run an NSInferredMappingModel, which means synchronous migration would not work. I have added a new error CoreStoreError.asynchronousMigrationRequired(localStoreURL:NSError:) thrown from addStorageAndWait() which would indicate this case.
@JohnEstropia commented on GitHub (Dec 5, 2018):
I'm closing this issue now, thanks for all the input.
To future developers who would hit this issue, please note that "lightweight migration" somehow has two types in Core Data: one that would succeed synchronously, and one that needs to run an `NSInferredMappingModel`, which means synchronous migration would not work. I have added a new error `CoreStoreError.asynchronousMigrationRequired(localStoreURL:NSError:)` thrown from `addStorageAndWait()` which would indicate this case.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Originally created by @Miggets7 on GitHub (Oct 12, 2018).
Hi John,
I would like to begin with sayring that I absolutly love CoreStore! It's an awesome project and very nice to use.
I'm having trouble though migrating my models. I'm using v5.3.1 and this is the error log:
And this is initialization code:
And the model code:
This used to be the initialization code before(on V5.0):
Can you tell why it isn't working?
@JohnEstropia commented on GitHub (Oct 14, 2018):
I am not sure but I'll throw out some ideas.
First, your
versionLockfor V2'sTapRegistrationseem to be the same with V1, which shouldn't be the case.Second, check your usage of
String(describing: Task.self). I don't recommend using non-static strings for entity names because they will break if you refactor your types.If none of those are the issue, I'm afraid this may be caused by your initialization of
dates. (I haven't proved this but I wouldn't be surprised if it was the cause)The
initial:argument here should be a statically reproducible value (e.g.Date.distantPast), notDate(), which creates the date instance during the time the code was run.@scogeo commented on GitHub (Oct 15, 2018):
I'm new to CoreStore myself, but I hit a similar issue when using synchronous migration with
CoreStoreObjects. Try switching to the asynchronousCoreStore.addStorage()call instead and see if the problem goes away for you.I still see get the Core Data error logs on the console, but the migration does proceed correctly. I just chalked those up to spurious logging due to opening an out-of-date store prior to then beginning migration.
@Miggets7 commented on GitHub (Oct 15, 2018):
@JohnEstropia The
versionLockforTapRegistrationis the one I got from the output of CoreStore itself. So maybe there is a bug there?I've changed the
String(describing: Task.self) to static strings.And I've changed the date code to:
And still I'm getting those errors.
@scogeo I've tried with the asynchronous
CoreStore.addStorage()call but still the same results. A simple call likeCoreStore.fetchAll(From<TaskDBModel>())fails. It returnsnil@JohnEstropia commented on GitHub (Oct 15, 2018):
@Miggets7
Can you try commenting out the
versionLockarguments for both V1 and V2 and check if the hashes are the same?@Miggets7 commented on GitHub (Oct 15, 2018):
@JohnEstropia These are the
versionLockresults:@JohnEstropia commented on GitHub (Oct 15, 2018):
@Miggets7 Oops, sorry I've been misreading the entities. The TapRegistration didn't have attribute changes so the same hash should be fine.
Couple of things I'd like to clarify:
Is
error setting up storage:actually being reached here?Also when you tried to use the asynchronous
CoreStore.addStorage()method, were you getting a.failureresult from the completion block?@Miggets7 commented on GitHub (Oct 15, 2018):
@JohnEstropia
It seems to be working now with the
CoreStore.addStorage()call. It does throw an exeption in NSPersistentStoreCoordinator+Setup.swift here:But it retuns a success call. It seems the data also seems right and running tha app a second time doens't throw any errors. But the completion still return an error object:
Right now it seems I can use this without any problem, so I guess this issue could be closed?
@scogeo commented on GitHub (Oct 15, 2018):
Just a brief followup to the above comment after some brief investigation on my own prototype. You can suppress the Core Data log messages caused by the throw from the call to
addPresistentStorementioned by @Miggets7 by explicitly declaring a simpleCustomSchemaMappingProvider. This will cause a different code path to be taken and avoid the throw and error logs during migration.In this example, something like this should work:
@JohnEstropia commented on GitHub (Oct 16, 2018):
Ah, I see. There is actually a quirk in lightweight migrations where it fails in
addPersistentStore(), but succeeds when using the inferred mapping model that it should have used internally inaddPersistentStore(). You'll find that logic here:I'll look for a way to silent these error logs in this case.
@scogeo Thanks for the suggestion to use
CustomSchemaMappingProvider. While this would work for your data, there is a tradeoff in memory use here as lightweight migration uses batched SQL queries internally as much as it can, whileCustomSchemaMappingProviderrecreates all objects one by one. If you have small data it should be more or less the same. (On a separate note, if your models are expected to succeed with an inferred mapping, you can omit theCustomSchemaMappingProvider'sentityMappingsargument)@scogeo commented on GitHub (Oct 17, 2018):
@JohnEstropia thank you for looking into the problem further, it would be nice to resolve it so I can use the implicit lightweight migration without any errors in the console logs.
Really enjoying CoreStore so far though!
@JohnEstropia commented on GitHub (Dec 5, 2018):
I'm closing this issue now, thanks for all the input.
To future developers who would hit this issue, please note that "lightweight migration" somehow has two types in Core Data: one that would succeed synchronously, and one that needs to run an
NSInferredMappingModel, which means synchronous migration would not work. I have added a new errorCoreStoreError.asynchronousMigrationRequired(localStoreURL:NSError:)thrown fromaddStorageAndWait()which would indicate this case.