2 * Copyright (c) 2016 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
24 #include "keychain/securityd/SecDbItem.h"
25 #include <utilities/SecDb.h>
27 #define CKKSNilToNSNull(obj) \
30 o ? o : [NSNull null]; \
33 #define CKKSIsNull(x) \
36 ((y == nil) || ([y isEqual:[NSNull null]])); \
38 #define CKKSUnbase64NullableString(x) (!CKKSIsNull(x) ? [[NSData alloc] initWithBase64EncodedString:x options:0] : nil)
40 NS_ASSUME_NONNULL_BEGIN
42 // A holder of a possibly-present string value.
43 // Also includes some convenience methods for parsing the string in different manners.
44 // If the value is nil, then the convenience methods return nil (or false/0).
45 @interface CKKSSQLResult
: NSObject
46 - (instancetype
)init
:(NSString
* _Nullable
)value
;
49 - (NSInteger
)asNSInteger
;
50 - (NSString
* _Nullable
)asString
;
51 - (NSNumber
* _Nullable
)asNSNumberInteger
;
52 - (NSDate
* _Nullable
)asISO8601Date
;
53 - (NSData
* _Nullable
)asBase64DecodedData
;
56 @interface CKKSSQLDatabaseObject
: NSObject
<NSCopying
>
58 @
property (copy
) NSDictionary
<NSString
*, NSString
*>* originalSelfWhereClause
;
60 - (bool)saveToDatabase
:(NSError
* _Nullable __autoreleasing
* _Nullable
)error
;
61 - (bool)saveToDatabaseWithConnection
:(SecDbConnectionRef _Nullable
)conn
62 error
:(NSError
* _Nullable __autoreleasing
* _Nullable
)error
;
63 - (bool)deleteFromDatabase
:(NSError
* _Nullable __autoreleasing
* _Nullable
)error
;
64 + (bool)deleteAll
:(NSError
* _Nullable __autoreleasing
* _Nullable
)error
;
66 // Load the object from the database, and error if it doesn't exist
67 + (instancetype _Nullable
)fromDatabaseWhere
:(NSDictionary
*)whereDict error
:(NSError
* _Nullable __autoreleasing
* _Nullable
)error
;
69 // Load the object from the database, and return nil if it doesn't exist
70 + (instancetype _Nullable
)tryFromDatabaseWhere
:(NSDictionary
*)whereDict
71 error
:(NSError
* _Nullable __autoreleasing
* _Nullable
)error
;
73 + (NSArray
*)all
:(NSError
* _Nullable __autoreleasing
* _Nullable
)error
;
74 + (NSArray
*)allWhere
:(NSDictionary
* _Nullable
)whereDict error
:(NSError
* _Nullable __autoreleasing
* _Nullable
)error
;
76 // Like all() above, but with limits on how many will return
77 + (NSArray
*)fetch
:(size_t)count error
:(NSError
* _Nullable __autoreleasing
* _Nullable
)error
;
78 + (NSArray
*)fetch
:(size_t)count
79 where
:(NSDictionary
* _Nullable
)whereDict
80 error
:(NSError
* _Nullable __autoreleasing
* _Nullable
)error
;
81 + (NSArray
*)fetch
:(size_t)count
82 where
:(NSDictionary
* _Nullable
)whereDict
83 orderBy
:(NSArray
* _Nullable
)orderColumns
84 error
:(NSError
* _Nullable __autoreleasing
* _Nullable
)error
;
87 + (bool)saveToDatabaseTable
:(NSString
*)table
88 row
:(NSDictionary
*)row
89 connection
:(SecDbConnectionRef _Nullable
)dbconn
90 error
:(NSError
* _Nullable __autoreleasing
* _Nullable
)error
;
91 + (bool)deleteFromTable
:(NSString
*)table
92 where
:(NSDictionary
* _Nullable
)whereDict
93 connection
:(SecDbConnectionRef _Nullable
)dbconn
94 error
:(NSError
* _Nullable __autoreleasing
* _Nullable
)error
;
96 + (bool)queryDatabaseTable
:(NSString
*)table
97 where
:(NSDictionary
* _Nullable
)whereDict
98 columns
:(NSArray
*)names
99 groupBy
:(NSArray
* _Nullable
)groupColumns
100 orderBy
:(NSArray
* _Nullable
)orderColumns
102 processRow
:(void (^)(NSDictionary
<NSString
*, CKKSSQLResult
*>*))processRow
103 error
:(NSError
* _Nullable __autoreleasing
* _Nullable
)error
;
105 + (bool)queryMaxValueForField
:(NSString
*)maxField
106 inTable
:(NSString
*)table
107 where
:(NSDictionary
* _Nullable
)whereDict
108 columns
:(NSArray
*)names
109 processRow
:(void (^)(NSDictionary
<NSString
*, CKKSSQLResult
*>*))processRow
;
111 // Note: if you don't use the SQLDatabase methods of loading yourself,
112 // make sure you call this directly after loading.
113 - (instancetype
)memoizeOriginalSelfWhereClause
;
115 + (NSString
*)quotedString
:(NSString
*)string
;
117 #pragma mark - Subclasses must implement the following:
119 // Given a row from the database, make this object
120 + (instancetype _Nullable
)fromDatabaseRow
:(NSDictionary
<NSString
*, CKKSSQLResult
*>*)row
;
122 // Return the columns, in order, that this row wants to fetch
123 + (NSArray
<NSString
*>*)sqlColumns
;
125 // Return the table name for objects of this class
126 + (NSString
*)sqlTable
;
128 // Return the columns and values, in order, that this row wants to save
129 - (NSDictionary
<NSString
*, NSString
*>*)sqlValues
;
131 // Return a set of key-value pairs that will uniquely find This Row in the table
132 - (NSDictionary
<NSString
*, NSString
*>*)whereClauseToFindSelf
;
134 //- (instancetype)copyWithZone:(NSZone* _Nullable)zone;
137 // Helper class to use with where clauses
138 // If you pass in one of these in a where dictionary instead of a concrete value, columnName will be
139 // used directly, instead of binding as a named parameter. Therefore, it's essential to use
140 // compile-time constants for both fields.
142 typedef NS_ENUM(uint64_t, CKKSSQLWhereComparator
) {
143 CKKSSQLWhereComparatorEquals
= 1,
144 CKKSSQLWhereComparatorNotEquals
= 2,
145 CKKSSQLWhereComparatorGreaterThan
= 3,
146 CKKSSQLWhereComparatorLessThan
= 4,
149 NSString
* CKKSSQLWhereComparatorAsString(CKKSSQLWhereComparator comparator
);
151 // This typedef is to ensure that CKKSSQLWhereColumn can only ever produce static strings
152 typedef NS_ENUM(uint64_t, CKKSSQLWhereColumnName
) {
153 CKKSSQLWhereColumnNameUUID
= 1,
154 CKKSSQLWhereColumnNameParentKeyUUID
= 2,
156 NSString
* CKKSSQLWhereColumnNameAsString(CKKSSQLWhereColumnName columnName
);
158 @interface CKKSSQLWhereColumn
: NSObject
159 @property CKKSSQLWhereComparator sqlOp
;
160 @property CKKSSQLWhereColumnName columnName
;
161 - (instancetype
)initWithOperation
:(CKKSSQLWhereComparator
)op columnName
:(CKKSSQLWhereColumnName
)column
;
162 + (instancetype
)op
:(CKKSSQLWhereComparator
)op column
:(CKKSSQLWhereColumnName
)columnName
;
165 // Unlike CKKSSQLWhereColumn, this will insert the value as a parameter in a prepared statement
166 // but gives you the flexbility to inject a sqlOp. sqlOp must be a compile-time constant.
167 @interface CKKSSQLWhereValue
: NSObject
168 @property CKKSSQLWhereComparator sqlOp
;
169 @property NSString
* value
;
170 - (instancetype
)initWithOperation
:(CKKSSQLWhereComparator
)op value
:(NSString
*)value
;
171 + (instancetype
)op
:(CKKSSQLWhereComparator
)op value
:(NSString
*)value
;
175 NS_ASSUME_NONNULL_END