Giter Site home page Giter Site logo

ctpersistance's Issues

updateRecordList 异常

CTPersistanceTable+Update.m的方法
- (void)updateRecordList:(NSArray <NSObject <CTPersistanceRecordProtocol> *> *)recordList error:(NSError **)error,

若直接传入error值是nil或NULL,运行到这个方法会崩溃Thread 1: EXC_BAD_ACCESS (code=1, address=0x0),错误定位在29行 if (*error != nil) { ,若传入的error 为 &error 则正常。

CTPersistanceDatabasePool 中的一些问题

数据库链接池存在一些问题,我提一下:

  1. databaseWithName 方法构造链接时使用的 Key 与 closeDatabaseWithName 不一致,所以存在 closeDatabaseWithName 失败甚至 Crash 问题 (database 为 nil 无法响应 closeDatabase )
  2. 如果使用当前线程与 databaseName 为 Key ,那么多线程环境下同一数据库存在多个链接的可能,而 CT 本身并没有使用 WAL 模式所以可能存在同时写以及读写竞争问题
  3. 建议数据库链接池采用 databasePath 作为 Key (可能存在同名数据库,所以不能使用 databaseName),这样能保证同一个数据库只有一个链接
  4. 不要内部自动关闭数据库链接,而且当前关闭也存在问题(同一线程下创建的多个链接可能只会关闭第一个,而且未从 databaseList 中移除)。关闭链接操作交由上层处理。
  5. 如果用户手动删除数据库文件,但是没有关闭链接,则该情形属于使用不当,不作容错处理。

swift 项目中使用 cocoapods 集成 CTPersistance 编译出错

Hi casa,

我想在 Swift 项目中 尝试使用 CTPersistance,通过 cocoapods 集成后,编译出错:

error

error2

libsqlte3.tbd 添加了,我的 Podfile 是这样的:

platform :ios, '8.0'
use_frameworks! 

target 'CTPersistanceDemo' do
pod 'CTPersistance'
end

而集成其他的 objc 写的第三方 pod 都没问题,比如 JGProgressHUD

麻烦你看看,先谢谢了。

备注:

  1. cocoapods 从 0.36 这个版本开始就支持 Swift 了,并且支持在 Swift 项目中也集成 Objective-C 的 pod 参考
  2. 这里有个讨论,看看有无帮助。

3002漏了对结果进行判断吗?

/* 3002 */
NSDictionary *keyvalueList = @{@"migration1_0":@"this is migration"};
NSString *whereCondition = @":primaryKey > 0";
NSString *primaryKey = [table primaryKeyName];
NSDictionary *whereConditionParams = NSDictionaryOfVariableBindings(primaryKey);
[table updateKeyValueList:keyvalueList whereCondition:whereCondition whereConditionParams:whereConditionParams error:&error];

/* test 3003 */

Escape character of single quote doesn't work

Query Error:
Origin Query is : INSERT INTO BBCMessageDetailTable (id,isReaded,sendTime,fromId,toId,owner,msgType,orderId,orderType,peer,status,content) VALUES (NULL,'0','1467975653','16122','22','16122','0','157','2','22','2','I'm ');

Error Message is: near "m": syntax error

sqlite> INSERT INTO BBCMessageDetailTable (id,isReaded,sendTime,fromId,toId,owner,msgType,orderId,orderType,peer,status,content) VALUES (NULL,'0','1467975653','16122','22','16122','0','157','2','22','2','I'm ');
...> );
...> ');
Error: near "m": syntax error

sqlite> INSERT INTO BBCMessageDetailTable (id,isReaded,sendTime,fromId,toId,owner,msgType,orderId,orderType,peer,status,content) VALUES (NULL,'0','1467975653','16122','22','16122','0','157','2','22','2','I''m ');
sqlite> select * from BBCMessageDetailTable;
0|0|1467972148|22|Q really |16122|0|156|2|22|1|16122
1|0|1467972118|22|The best |16122|0|156|2|22|2|16122
2|0|1467975594|22|Even |16122|0|157|2|22|1|16122
3|0|1467975622|22|Do not |16122|0|157|2|22|1|16122
4|0|1467975653|22|Im |16122|0|157|2|22|2|16122
5|0|1467975653|22|I'm |16122|0|157|2|22|2|16122

objectRepresentationWithDictionary方法名的理由

从CTPersistanceRecordProtocol文件的的声明config your record with dictionary和CTPersistanceRecord的实现来看这个方法都偏向于是一个动作,是不是名称改成- (void)setPersistanceValuesForKeysWithDictionary:(NSDictionary *)keyedValues会更合适?还是这里这么命名是有其他深层的原因?

写long类型的数值到数据库,再次查询时被转换为int

在CTPersistanceQueryCommand.m中

                case SQLITE_INTEGER:
                {
                    int value = sqlite3_column_int(statement, i);
                    [result setObject:[NSNumber numberWithInt:value] forKey:columnName];
                    break;
                }

从数据库中读出的整形,被转化为NSNumber,不是通过@(num),而是通过[NSNumber numberWithInt:value]的方式。
目前遇到的问题是:
我把一个文件的大小存入数据库,size超过4GB(>32位,Int)。从数据库取出来的值出错了。

当主键是字符串时,根据主键查询会报错

错误信息的一部分“WHERE primaryKey = 987D5D73-4E98-49D5-A095-19610A3E8EEB
Error Message is: unrecognized token: "987D5D73"”

应该是“- (NSString *)stringWithSQLParams:(NSDictionary *)params”这个方法在拼接参数的使用没有把主键值用“''”单引号包起来的原因。
改成""... WHERE primaryKey = '987D5D73-4E98-49D5-A095-19610A3E8EEB' ”就好了

你好大神

我一直搞不懂一个问题,如果服务器将错误的数据类型返回给客户端(能使app崩溃),此时客户端将此数据保存了下来,那么对于app来说岂不是很危险。这种情况该怎么避免呢

如果有多个数据库,都有数据迁移的需求,如何配置CTPersistanceConfiguration.plist文件?

场景:我有多个业务模块,分别做成不同的私有Pod。其中每个业务模块都使用CTPersistance创建自己模块数据库,每个数据库也都有对应的Migrator。但是有个问题,CTPersistance提供的配置文件CTPersistanceConfiguration.plist只有一份,如果在私有库中的CTPersistanceConfiguration.plist文件配置,当合并到主工程时,如果主工程或者别的私有库也有CTPersistanceConfiguration.plist文件,那么就会出现文件重复。这样的场景下,即如果有分库的需求时,如何进行数据迁移的配置呢?

谢谢~~

数据异步操作崩溃

大神帮忙看下。
一个socket请求,返回数据保存到本地数据库,偶尔会崩溃,不知道什么问题

代码我贴一下:
1、请求数据
2017-07-11 2 54 10

2017-07-11 2 47 55

2、保存数据
2017-07-11 2 48 16

3、崩溃点
2017-07-11 2 48 24

报错信息:
2017-07-11 2 51 37

数据存储bug

当存储的字段为字符串类型,且字符串中有 ; 符号的时候, 会被safeSQLEncode 过滤掉,导致数据存储错误

update 操作可能出现问题

在进行数据库记录更新时,如果存在 BLOB 字段,那么可能出现问题。默认情形下,数据更新操作并不会调用 bindBlobWithStatement 函数,也就是说 sqlite3_bind_blob 不会被执行,这样会导致一个 BLOB 类型字段不会被更新,甚至被更新为 NULL。除非再额外调用一次 BLOB 类型字段 对应的更新操作。

// 该操作不会更新  BLOB 类型字段
[table updateRecord:record error:&error];

// 需要以下操作才能实现真正的更新
[table updateRecord:record error:&error];
[table updateValue:record.bleData forKey:@"bleData" primaryKeyValue:record.identifier error:&error];

不知道作者能否在后面对 updateRecord 进行补充?

常量声明忘加`const`了


static NSString * kCTPersisatanceConfigurationFileName
->
static NSString * const kCTPersisatanceConfigurationFileName

1.3.2数据查询失效

今天更新插件的时候升级到了1.3.2,发现数据库操作全都失效了。看了下楼主的提交更新才明白了又是之前那个''的问题。
针对这种 NSString *sqlString = @"SELECT * FROM ':tableName' WHERE conversationId = ':conversationId' ORDER BY messageTime DESC limit ':index',':count'";
语法,前面带:冒号的参数都增加了'',查询OK了
但是
NSArray *recordList = [self.contactInfoTable findAllWithKeyName:@"shortName" value:shortName error:&error];
这种查询又失效了,点进去看了一下,分类里面参数楼主没有加''
2016-11-25 4 38 22

这里似乎又回到了1.3.0的缺少''语法问题

之前的问题 #37 就是这个问题
数据库我不熟,语法也不太懂,只是测试出来是这个问题,楼主看下

更新还是有问题

类型绑定 addBindKey 函数在更新 BOOL 类型时还是会出现问题。理论上 SQLite 好像是没有 BOOL 类型的,所以绑定代码可以做出部分修改:

if ([bindValue isKindOfClass:[NSNumber class]]) {
    NSNumber *value = (NSNumber *)bindValue;

    valueType = @"INTEGER";
    
    if (strcmp(value.objCType, @encode(float)) == 0
       || strcmp(value.objCType, @encode(double)) == 0
       || strcmp(value.objCType, @encode(CGFloat)) == 0) {

        valueType = @"REAL";
    }
}

并去掉:

if ([valueType isEqualToString:@"BOOLEAN"]) {
        invocation = [NSInvocation invocationWithMethodSignature:[NSMutableArray instanceMethodSignatureForSelector:@selector(bindBooleanWithStatement:value:key:)]];
        invocation.target = self;
        invocation.selector = @selector(bindBooleanWithStatement:value:key:);
        [invocation setArgument:&bindValue atIndex:3];
        [invocation setArgument:&bindKey atIndex:4];
        [invocation retainArguments];
        [self addObject:invocation];
        return;
 }

不然会将 BOOL 类型更新为 NULL,然后你取出后变为 NSNULL,然后就出现运行时错误。

晚上先到这里吧,明天起床再说早点休息

当字段值为UUID格式的数据时,数据可插入,但是通过对应字段的值去查询,会查询不到数据

当Record中的某个字段为UUID格式 (如4885D273-C3C6-40AE-9504-A147C4B3ACFB),这条数据,可以插入到数据库,但是通过这个字段的值去查询的时候,查不到这个数据。

然后,我又测试了你的test案例,这种情况同样的是出现的,在insert的例子中
//Insert
NSError error = nil;
/
test 1001 */
TestTable *table = [[TestTable alloc] init];
TestRecord *record = [[TestRecord alloc] init];
record.age = @(1);
record.name = @"4885D273-C3C6-40AE-9504-A147C4B3ACFB";
record.tomas = @"1";
[table insertRecord:record error:&error];
if ([record.primaryKey integerValue] > 0) {
NSLog(@"1001 success");
} else {
NSException *exception = [[NSException alloc] init];
@throw exception;
}
//

//Fetch
error = nil;
NSArray *recordList = [table findAllWithKeyName:@"name" value:@"4885D273-C3C6-40AE-9504-A147C4B3ACFB" error:&error];
if (recordList.count == 0) {
NSException *exception = [[NSException alloc] init];
@throw exception;
} else {
NSLog(@"2021 success");
}

NSLog(@"End Fetch Test");

//

record中的name字段,在我的测试过程中,发现name为UUID格式时,或者也可以说不全为数字时,都是查询不到的,我不知道是不是我使用方式错误,遗漏了某些地方,还是这里是有bug的

update:
原来是这个问题,TEXT类型的数据,需要加‘’,否则如果出现像UUID这种格式的字符串,就无法判别,只拿到前面的那些数字...
不知道这算不算个问题,或者,你可以在你的NSString里面多加一个方法,预防一下这个问题的出现

多线程test 6002中table是在Async block外创建,但运行成功?

我在文档里看到
方法:

  • (void)performAsyncAction:(void (^)(void))action shouldWaitUntilDone:(BOOL)shouldWaitUntilDone;
    的注释里写到:
    you must always create CTPersistanceTable in action block, do not use outside table instance in this block
    但是在test 6002里面发现mainTestTable是在block外创建的,运行测试仍然成功。想问下这里是否与冲突?

空值对象的改进问题

对于数据库 NULL 值当前设计是在 fetchWithError 函数中将其设置为 [NSNull null] 单例对象。在 OC 环境下这种设计绝大多数情形下不会存在太大的问题,但是对于 Swift 混编环境来说该设计明显对 Optional 值不友好,使用不当存在潜在 Crash 问题。另一个是对于值对象来说:即使是 OC 环境,[NSNull null] 单例对象在动态转化为 long long 等值时存在 Runtime Crash (当然这个在插入记录的时候就存在使用不当,值类型不应使用空值,但是 CT Runtime 提供了这部分操作的能力 )。

如果我们将改部分处理代码改为:

case SQLITE_NULL:
        [result setObject:nil forKey:columnName];
        break;

可能对使用者来说更好一点。

另一个,空值改进的方法我觉得后期可以考虑一下:对 CTPersistanceTableProtocol 进行一个拓展,增加一个 columnDefaultValue 方法用于设置默认值。这样使用者可以通过该协议设置默认值从而避免空值对象问题,而不是在插值之前人为保证。

字符串做主键插入的问题

在插入新数据之后会强制把 lastInsertRowId设置为主键的值,但是这个值类型和数据是错误的, 请问该如何处理这种情况?

CTPersistanceDataBase没有提供自己定义数据库路径的接口

Hi,大神!我又来麻烦您了。现在我有一份数据库文件,它是在Bundle中的,是我用来记录了一些常量,其中表都是类似这样子的
image
其中StringForAppDisplay是给App显示用的,CodeForServer是和后台服务器交互用的。主要是为了解决同样的数据,App显示数据和后台交互数据的不同的问题。

之前是自己用FMDB写SQL来查,现在想复用CTPersistance中的查询功能。但是看CTPersistanceDataBase的源码发现,CTPersistance能操作的数据库都只是在App的Library文件夹中,并不能访问到Bundle中的数据库文件。

我想请教一下:
1、如果我想复用CTPersistance的查询功能访问Bundle中的数据库文件,有什么比较优雅的做法没?
2、我用bundle中的数据库文件记录这种常量的设计是否合理(之前我是用Plist做,但是考虑到Plist容易被别人解包直接拿到数据,而且每次加载需要把整个Plist加载进内存。于是我改成了数据库的方式。数据库有设置加密密码,提高了一些数据安全性。并且我有配合NSCache来解决多次重复查询需要大量时间的问题)?如果不合理能否帮忙给点建议?

谢谢。

whereCondition Bug

should differentiate key and value in whereCondition, and only string type of value should have semi-colon.

关于主键是字符串的问题

当主键是字符串的时候,在获取操作中有findAllWithKeyName可以进行查找。但是当需要通过主键删除一条记录的时候就没有相应的方法了,可不可以在删除deleteRecord的系列方法中也添加类似deleteRecordWithKeyName呢,会不会有其他隐患?

CTPersistanceRecord setValue:forKey:报错

- (BOOL)setPersistanceValue:(id)value forKey:(NSString *)key
{
    BOOL result = YES;
    NSString *setter = [NSString stringWithFormat:@"set%@%@:", [[key substringToIndex:1] capitalizedString], [key substringFromIndex:1]];
    if ([self respondsToSelector:NSSelectorFromString(setter)]) {
        if ([value isKindOfClass:[NSString class]]) {
            [self setValue:[value safeSQLDecode] forKey:key];
        } else if ([value isKindOfClass:[NSNull class]]) {
            [self setValue:nil forKey:key];
        } else {
            [self setValue:value forKey:key];
        }
    } else {
        result = NO;
    }

    return result;
}

在判断 [value isKindOfClass:[NSNull class]]分支里,value被设置为nil,导致crash

could not set nil as the value for the key 

情景:
新建migratorStep,实现

- (void)goUpWithQueryCommand:(CTPersistanceQueryCommand *)queryCommand error:(NSError *__autoreleasing *)error
{
  [[queryCommand addColumn:@"uploadFinishDate" columnInfo:@"INTEGER" tableName:@"LocalMovieTable"] executeWithError:error];
}

数据库中增加一个INTEGER类型的字段。数据库升级之后,由于新添字段,所以会走[value isKindOfClass:[NSNull class]]的分支,然而,这里uploadFinishDate并不是id类型,导致出错。

CTPersistanceTable没有Merge数据的API

我需要实现一个功能:向一个数据库表中merge数据。如果表中已有该数据就update数据,如果表中没有就insert数据。当前在CTPersistanceTable以及他的类目中没找到提供该功能的API,暂时打算自己写一个CTPersistanceTable+Merge的类目来实现。
希望大神后续有空能更新出该API。如果现有的API能解决这个需求,又不影响性能的话,也请不吝赐教。
多谢!

NSMutableArray+CTPersistanceBindValue中-addBindKey:bindValue:columnDescription有内存泄漏

以这段代码为例:

if ([valueType isEqualToString:@"INTEGER"]) {
        invocation = [NSInvocation invocationWithMethodSignature:[NSMutableArray instanceMethodSignatureForSelector:@selector(bindIntegerWithStatement:value:key:)]];
        invocation.target = self;
        invocation.selector = @selector(bindIntegerWithStatement:value:key:);
        [invocation setArgument:&bindValue atIndex:3];
        [invocation setArgument:&bindKey atIndex:4];
        [invocation retainArguments];
        [self addObject:invocation];
        return;
    }
invocation = [NSInvocation invocationWithMethodSignature:[NSMutableArray instanceMethodSignatureForSelector:@selector(bindIntegerWithStatement:value:key:)]];
invocation.target = self;

这两句造成了循环引用,建议转为单例调用

NSArray

Hello and thanks for the great source code.
I have a question. How can i handle an NSArray in the testrecord for example in your demo?
as i see it i need to add the column in the testtable.m file as well.
how will i add the array in the table?

thanks

CTPersistanceAsyncExecutor在Release下运行会死循环

while (shouldWait) {
}

这个循环语句在release下编译,编译器会认为shouldWait不会被修改而不会每次去取值,导致死循环。在shouldWait变量前声明volatile可解决。另外,为啥不直接用- (void)addOperations:(NSArray<NSOperation *> *)ops waitUntilFinished:(BOOL)wait?

同样是数据库更新错误

我使用一个 double 字段保存毫秒数时间戳,但是使用 updateRecord 进行操作时候发生异常错误,调用栈为:

  1. updateRecord
  2. updateKeyValueList primaryKeyValue
  3. NSString *valueString = [keyValueList bindToValueList:bindValueList];
  4. [bindValueList addBindKey:valueKey bindValue:value columnDescription:nil];

最终发现错误出现在:

NSString *valueType = [[[columnDescription componentsSeparatedByString:@" "] firstObject] uppercaseString];

if (valueType == nil) {
    if ([bindValue isKindOfClass:[NSNumber class]]) {
        valueType = @"INTEGER";
    } if ([bindValue isKindOfClass:[NSString class]]) {
            valueType = @"TEXT";
    } if ([bindValue isKindOfClass:[NSNull class]]) {
            valueType = @"INTEGER";
    } if ([bindValue isKindOfClass:[NSData class]]) {
         valueType = @"BLOB";
     }
 }

您将 double 类型重置为了整型从而导致,REAL 类型更新出现异常,根本原因在于所有调用 bindToValueList 都会存在这个问题。预估其他操作使用处也会存在问题。

CTPersistanceAsyncExecutor 线程安全

CTPersistanceAsyncExecutor 的 operationQueue 是不是应该在单例初始化的时候就初始化好?否则多线程同时调用这个单例会出问题。

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.