You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@chemistry.apache.org by lg...@apache.org on 2014/07/17 14:56:00 UTC
svn commit: r1611348 - in /chemistry/objectivecmis/trunk:
ObjectiveCMIS.xcodeproj/ ObjectiveCMIS/Bindings/ ObjectiveCMIS/Client/
ObjectiveCMISTests/
Author: lgross
Date: Thu Jul 17 12:55:59 2014
New Revision: 1611348
URL: http://svn.apache.org/r1611348
Log:
Added CMISQueryStatement to create proper escaped SQL statements
Added:
chemistry/objectivecmis/trunk/ObjectiveCMIS/Bindings/CMISQueryStatement.h
chemistry/objectivecmis/trunk/ObjectiveCMIS/Bindings/CMISQueryStatement.m
Modified:
chemistry/objectivecmis/trunk/ObjectiveCMIS.xcodeproj/project.pbxproj
chemistry/objectivecmis/trunk/ObjectiveCMIS/Client/CMISSession.h
chemistry/objectivecmis/trunk/ObjectiveCMIS/Client/CMISSession.m
chemistry/objectivecmis/trunk/ObjectiveCMISTests/ObjectiveCMISTests.m
Modified: chemistry/objectivecmis/trunk/ObjectiveCMIS.xcodeproj/project.pbxproj
URL: http://svn.apache.org/viewvc/chemistry/objectivecmis/trunk/ObjectiveCMIS.xcodeproj/project.pbxproj?rev=1611348&r1=1611347&r2=1611348&view=diff
==============================================================================
--- chemistry/objectivecmis/trunk/ObjectiveCMIS.xcodeproj/project.pbxproj (original)
+++ chemistry/objectivecmis/trunk/ObjectiveCMIS.xcodeproj/project.pbxproj Thu Jul 17 12:55:59 2014
@@ -21,6 +21,9 @@
/* End PBXAggregateTarget section */
/* Begin PBXBuildFile section */
+ 253F2D2F19741FAE006BA517 /* CMISQueryStatement.h in Headers */ = {isa = PBXBuildFile; fileRef = 253F2D2D19741FAE006BA517 /* CMISQueryStatement.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 253F2D3019741FAE006BA517 /* CMISQueryStatement.m in Sources */ = {isa = PBXBuildFile; fileRef = 253F2D2E19741FAE006BA517 /* CMISQueryStatement.m */; };
+ 255E7EE41975069500C683A0 /* CMISQueryStatement.m in Sources */ = {isa = PBXBuildFile; fileRef = 253F2D2E19741FAE006BA517 /* CMISQueryStatement.m */; };
258998DB18D73D5A0091BA96 /* CMISAce.h in Headers */ = {isa = PBXBuildFile; fileRef = 258998D718D73D5A0091BA96 /* CMISAce.h */; settings = {ATTRIBUTES = (Public, ); }; };
258998DC18D73D5A0091BA96 /* CMISAce.m in Sources */ = {isa = PBXBuildFile; fileRef = 258998D818D73D5A0091BA96 /* CMISAce.m */; };
258998DD18D73D5A0091BA96 /* CMISAcl.h in Headers */ = {isa = PBXBuildFile; fileRef = 258998D918D73D5A0091BA96 /* CMISAcl.h */; settings = {ATTRIBUTES = (Public, ); }; };
@@ -278,6 +281,8 @@
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
+ 253F2D2D19741FAE006BA517 /* CMISQueryStatement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CMISQueryStatement.h; path = Bindings/CMISQueryStatement.h; sourceTree = "<group>"; };
+ 253F2D2E19741FAE006BA517 /* CMISQueryStatement.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CMISQueryStatement.m; path = Bindings/CMISQueryStatement.m; sourceTree = "<group>"; };
258998D718D73D5A0091BA96 /* CMISAce.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CMISAce.h; path = Common/CMISAce.h; sourceTree = "<group>"; };
258998D818D73D5A0091BA96 /* CMISAce.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CMISAce.m; path = Common/CMISAce.m; sourceTree = "<group>"; };
258998D918D73D5A0091BA96 /* CMISAcl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CMISAcl.h; path = Common/CMISAcl.h; sourceTree = "<group>"; };
@@ -761,6 +766,8 @@
828072D315153EC100EF635C /* Bindings */ = {
isa = PBXGroup;
children = (
+ 8280730D1515405C00EF635C /* AtomPub */,
+ 5892CBE0192CB83800C7734A /* Browser */,
82AD4AEE15416A150012DDB6 /* CMISAclService.h */,
828073191515405C00EF635C /* CMISBinding.h */,
82AD4AE9154164290012DDB6 /* CMISBindingFactory.h */,
@@ -786,11 +793,13 @@
FE417D6015761A34009056AA /* CMISPropertyDefinition.m */,
4EA61BDF1564F73900C759E4 /* CMISQueryResult.h */,
4EA61BE01564F73900C759E4 /* CMISQueryResult.m */,
+ 253F2D2D19741FAE006BA517 /* CMISQueryStatement.h */,
+ 253F2D2E19741FAE006BA517 /* CMISQueryStatement.m */,
82AD4AF715416AC10012DDB6 /* CMISRelationshipService.h */,
5892CB7A192CB65D00C7734A /* CMISRelationshipTypeDefinition.h */,
5892CB7B192CB65D00C7734A /* CMISRelationshipTypeDefinition.m */,
- FE417D6815761A34009056C1 /* CMISRenditionData.m */,
FE417D6815761A34009056BF /* CMISRenditionData.h */,
+ FE417D6815761A34009056C1 /* CMISRenditionData.m */,
8276E157155E392A00344A29 /* CMISRepositoryService.h */,
5892CB7C192CB65D00C7734A /* CMISSecondaryTypeDefinition.h */,
5892CB7D192CB65D00C7734A /* CMISSecondaryTypeDefinition.m */,
@@ -799,8 +808,6 @@
5892CB7E192CB65D00C7734A /* CMISTypeDefinitionCache.h */,
5892CB7F192CB65D00C7734A /* CMISTypeDefinitionCache.m */,
8276E158155E392A00344A29 /* CMISVersioningService.h */,
- 8280730D1515405C00EF635C /* AtomPub */,
- 5892CBE0192CB83800C7734A /* Browser */,
);
name = Bindings;
sourceTree = "<group>";
@@ -919,6 +926,7 @@
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
+ 253F2D2F19741FAE006BA517 /* CMISQueryStatement.h in Headers */,
828072E51515403800EF635C /* CMISCollection.h in Headers */,
828072E71515403800EF635C /* CMISDocument.h in Headers */,
5892CBC9192CB7D900C7734A /* CMISAtomPubExtensionDataParserBase.h in Headers */,
@@ -1194,6 +1202,7 @@
82C1C63715348EC4009B7B3D /* CMISAtomPubNavigationService.m in Sources */,
5892CB85192CB65D00C7734A /* CMISRelationshipTypeDefinition.m in Sources */,
5892CB95192CB73D00C7734A /* CMISAtomPubObjectByIdUriBuilder.m in Sources */,
+ 253F2D3019741FAE006BA517 /* CMISQueryStatement.m in Sources */,
5892CBC0192CB7D900C7734A /* CMISAtomFeedParser.m in Sources */,
5892CBBE192CB7D900C7734A /* CMISAtomEntryWriter.m in Sources */,
82AD4AEC1541642A0012DDB6 /* CMISBindingFactory.m in Sources */,
@@ -1268,6 +1277,7 @@
files = (
828072C415153DE900EF635C /* ObjectiveCMISTests.m in Sources */,
75E7789D155BA59D00191BAE /* ObjectiveCMISTests+Environment.m in Sources */,
+ 255E7EE41975069500C683A0 /* CMISQueryStatement.m in Sources */,
4EA61BD91564F70C00C759E4 /* CMISStringInOutParameter.m in Sources */,
4EA61BDC1564F70C00C759E4 /* CMISURLUtil.m in Sources */,
4EA61BE31564F73900C759E4 /* CMISObjectList.m in Sources */,
Added: chemistry/objectivecmis/trunk/ObjectiveCMIS/Bindings/CMISQueryStatement.h
URL: http://svn.apache.org/viewvc/chemistry/objectivecmis/trunk/ObjectiveCMIS/Bindings/CMISQueryStatement.h?rev=1611348&view=auto
==============================================================================
--- chemistry/objectivecmis/trunk/ObjectiveCMIS/Bindings/CMISQueryStatement.h (added)
+++ chemistry/objectivecmis/trunk/ObjectiveCMIS/Bindings/CMISQueryStatement.h Thu Jul 17 12:55:59 2014
@@ -0,0 +1,170 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+#import <Foundation/Foundation.h>
+
+/**
+ * CMISQueryStatement.
+ * Sample code:
+ *
+ * CMISQueryStatement *qs =
+ * [[CMISQueryStatement alloc] initWithStatement:@"SELECT ?, ? FROM ? WHERE ? > ? AND IN_FOLDER(?) OR ? IN (?)"];
+ *
+ * [qs setPropertyAtIndex:1 property:@"cmis:document"];
+ * [qs setPropertyAtIndex:2 property:@"cmis:name"];
+ * [qs setTypeAtIndex:3 type:@"cmis:document"];
+ *
+ * [qs setPropertyAtIndex:4 property:@"cmis:creationDate];
+ * [qs setDateAtIndex:5 date:creationDate];
+ *
+ * [qs setStringAtIndex:6 string:cmisDocument.identifier];
+ *
+ * [qs setPropertyAtIndex:7 property:@"cmis:createdBy];
+ * [qs setStringAtIndex:4 string:@"8, bob, tom, lisa"];
+ *
+ * NSString *statement = [qs queryString];
+ */
+@interface CMISQueryStatement : NSObject
+
+/**
+ * Initialize Query Statement. Use ? to define placeholders
+ *
+ * @param statement
+ THe SQL statement
+ */
+- (id)initWithStatement:(NSString*)statement;
+
+/**
+ * Sets the designated parameter to the query name of the given type.
+ *
+ * @param parameterIndex
+ * the parameter index (one-based)
+ * @param type
+ * the object type
+ */
+- (void)setTypeAtIndex:(NSUInteger)parameterIndex type:(NSString*)type;
+
+/**
+ * Sets the designated parameter to the query name of the given property.
+ *
+ * @param parameterIndex
+ * the parameter index (one-based)
+ * @param propertyId
+ * the property ID
+ */
+- (void)setPropertyAtIndex:(NSUInteger)parameterIndex property:(NSString*)property;
+
+/**
+ * Sets the designated parameter to the given string.
+ *
+ * @param parameterIndex
+ * the parameter index (one-based)
+ * @param string
+ * the string
+ */
+- (void)setStringAtIndex:(NSUInteger)parameterIndex string:(NSString*)string;
+
+/**
+ * Sets the designated parameter to the given string. It does not escape
+ * backslashes ('\') in front of '%' and '_'.
+ *
+ * @param parameterIndex
+ * the parameter index (one-based)
+ * @param string
+ * the LIKE string
+ */
+- (void)setStringLikeAtIndex:(NSUInteger)parameterIndex string:(NSString*)string;
+
+/**
+ * Sets the designated parameter to the given string in a CMIS contains
+ * statement.
+ * <p>
+ * Note that the CMIS specification requires two levels of escaping. The
+ * first level escapes ', ", \ characters to \', \" and \\. The characters
+ * *, ? and - are interpreted as text search operators and are not escaped
+ * on first level. If *, ?, - shall be used as literals, they must be passed
+ * escaped with \*, \? and \- to this method.
+ * <p>
+ * For all statements in a CONTAINS() clause it is required to isolate those
+ * from a query statement. Therefore a second level escaping is performed.
+ * On the second level grammar ", ', - and \ are escaped with a \. See the
+ * spec for further details.
+ * <p>
+ * Summary (input --> first level escaping --> second level escaping and
+ * output): * --> * --> * ? --> ? --> ? - --> - --> - \ --> \\ --> \\\\ (for
+ * any other character following other than * ? -) \* --> \* --> \\* \? -->
+ * \? --> \\? \- --> \- --> \\- ' --> \' --> \\\' " --> \" --> \\\"
+ *
+ * @param parameterIndex
+ * the parameter index (one-based)
+ * @param string
+ * the CONTAINS string
+ */
+- (void)setStringContainsAtIndex:(NSUInteger)parameterIndex string:(NSString*)string;
+
+/**
+ * Sets the designated parameter to the given number.
+ *
+ * @param parameterIndex
+ * the parameter index (one-based)
+ * @param number
+ * the number
+ */
+- (void)setNumberAtIndex:(NSUInteger)parameterIndex number:(NSNumber*)number;
+
+/**
+ * Sets the designated parameter to the given URL.
+ *
+ * @param parameterIndex
+ * the parameter index (one-based)
+ * @param url
+ * the URL
+ */
+- (void)setUrlAtIndex:(NSUInteger)parameterIndex url:(NSURL*)url;
+
+/**
+ * Sets the designated parameter to the given boolean.
+ *
+ * @param parameterIndex
+ * the parameter index (one-based)
+ * @param boolean
+ * the boolean
+ */
+- (void)setBooleanAtIndex:(NSUInteger)parameterIndex boolean:(BOOL)boolean;
+
+/**
+ * Sets the designated parameter to the given DateTime value with the prefix
+ * 'TIMESTAMP '.
+ *
+ * @param parameterIndex
+ * the parameter index (one-based)
+ * @param date
+ * the DateTime value as NSDate object
+ */
+- (void)setDateTimeAtIndex:(NSUInteger)parameterIndex date:(NSDate*)date;
+
+
+/**
+ * Returns the query statement.
+ *
+ * @return the query statement
+ */
+- (NSString*)queryString;
+
+@end
Added: chemistry/objectivecmis/trunk/ObjectiveCMIS/Bindings/CMISQueryStatement.m
URL: http://svn.apache.org/viewvc/chemistry/objectivecmis/trunk/ObjectiveCMIS/Bindings/CMISQueryStatement.m?rev=1611348&view=auto
==============================================================================
--- chemistry/objectivecmis/trunk/ObjectiveCMIS/Bindings/CMISQueryStatement.m (added)
+++ chemistry/objectivecmis/trunk/ObjectiveCMIS/Bindings/CMISQueryStatement.m Thu Jul 17 12:55:59 2014
@@ -0,0 +1,212 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+#import "CMISQueryStatement.h"
+
+@interface CMISQueryStatement ()
+
+@property (nonatomic, strong) NSString* statement;
+@property (nonatomic, strong) NSMutableDictionary *parametersDictionary;
+
+@end
+
+@implementation CMISQueryStatement
+
+- (id)initWithStatement:(NSString*)statement {
+ self = [super init];
+ if (self) {
+ self.statement = statement;
+ self.parametersDictionary = [NSMutableDictionary dictionary];
+ }
+
+ return self;
+}
+
+- (void)setTypeAtIndex:(NSUInteger)parameterIndex type:(NSString*)type {
+ if (type && type.length > 0) {
+ [self.parametersDictionary setObject:[CMISQueryStatement escapeString:type withSurroundingQuotes:NO] forKey:[NSNumber numberWithInteger:parameterIndex]];
+ }
+}
+
+- (void)setPropertyAtIndex:(NSUInteger)parameterIndex property:(NSString*)property {
+ if (property && property.length > 0) {
+ [self.parametersDictionary setObject:[CMISQueryStatement escapeString:property withSurroundingQuotes:NO] forKey:[NSNumber numberWithInteger:parameterIndex]];
+ }
+}
+
+- (void)setNumberAtIndex:(NSUInteger)parameterIndex number:(NSNumber*)number {
+ if (number) {
+ [self.parametersDictionary setObject:number forKey:[NSNumber numberWithInteger:parameterIndex]];
+ }
+}
+
+- (void)setStringAtIndex:(NSUInteger)parameterIndex string:(NSString*)string {
+ if (string && string.length > 0) {
+ [self.parametersDictionary setObject:[CMISQueryStatement escapeString:string withSurroundingQuotes:YES] forKey:[NSNumber numberWithInteger:parameterIndex]];
+ }
+}
+
+- (void)setStringLikeAtIndex:(NSUInteger)parameterIndex string:(NSString*)string {
+ if (string && string.length > 0) {
+ [self.parametersDictionary setObject:[CMISQueryStatement escapeLike:string] forKey:[NSNumber numberWithInteger:parameterIndex]];
+ }
+}
+
+- (void)setStringContainsAtIndex:(NSUInteger)parameterIndex string:(NSString*)string {
+ if (string && string.length > 0) {
+ [self.parametersDictionary setObject:[CMISQueryStatement escapeContains:string] forKey:[NSNumber numberWithInteger:parameterIndex]];
+ }
+}
+
+- (void)setUrlAtIndex:(NSUInteger)parameterIndex url:(NSURL*)url {
+ if (url) {
+ NSError *error;
+ NSString *urlString = [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:&error];
+ if (!error && urlString && urlString.length >0) {
+ [self.parametersDictionary setObject:[CMISQueryStatement escapeString:urlString withSurroundingQuotes:YES] forKey:[NSNumber numberWithInteger:parameterIndex]];
+ }
+ }
+}
+
+- (void)setBooleanAtIndex:(NSUInteger)parameterIndex boolean:(BOOL)boolean {
+ NSString *booleanString;
+ if (boolean) {
+ booleanString = @"YES";
+ } else {
+ booleanString = @"NO";
+ }
+ [self.parametersDictionary setObject:booleanString forKey:[NSNumber numberWithInteger:parameterIndex]];
+}
+
+- (void)setDateTimeAtIndex:(NSUInteger)parameterIndex date:(NSDate*)date {
+ if (date) {
+ [self.parametersDictionary setObject:[NSString stringWithFormat:@"TIMESTAMP '%@'", [CMISQueryStatement convert:date]] forKey:[NSNumber numberWithInteger:parameterIndex]];
+ }
+}
+
+
+- (NSString*)queryString {
+ BOOL inStr = false;
+ NSUInteger parameterIndex = 0;
+
+ NSMutableString *retStr = [NSMutableString string];
+
+ for (NSUInteger i = 0; i < self.statement.length; i++) {
+ unichar c = [self.statement characterAtIndex:i];
+
+ if (c == '\'') {
+ if (inStr && [retStr characterAtIndex:i - 1] == '\\') {
+ inStr = true;
+ } else {
+ inStr = !inStr;
+ }
+ [retStr appendString:[NSString stringWithCharacters:&c length:1]];
+ } else if (c == '?' && !inStr) {
+ parameterIndex++;
+ NSObject *parameter = [self.parametersDictionary objectForKey:[NSNumber numberWithInteger:parameterIndex]];
+ NSString *paramValue = nil;
+ if ([parameter isKindOfClass:NSString.class]) {
+ paramValue = (NSString*)parameter;
+ } else if ([parameter isKindOfClass:NSNumber.class]) {
+ paramValue = [(NSNumber*)parameter stringValue];
+ }
+ if (paramValue) {
+ // Replace placeholder
+ [retStr appendString:paramValue];
+ }
+ } else {
+ [retStr appendString:[NSString stringWithCharacters:&c length:1]];
+ }
+ }
+
+ return retStr;
+}
+
+#pragma mark - Escaping methods
+
++ (NSString*)escapeString:(NSString*)string withSurroundingQuotes:(BOOL)quotes {
+ NSMutableString *escapedString = [NSMutableString string];
+ [escapedString appendString:quotes ? @"'" : @"" ];
+ for (NSUInteger i = 0; i < string.length; i++) {
+ unichar c = [string characterAtIndex:i];
+
+ if (c == '\'' || c == '\\') {
+ [escapedString appendString:@"\\"];
+ }
+
+ [escapedString appendString:[NSString stringWithCharacters:&c length:1]];
+ }
+
+ if (quotes) {
+ [escapedString appendString:@"\'"];
+ }
+
+ return escapedString;
+}
+
++ (NSString*)escapeLike:(NSString*)string {
+ NSMutableString *escapedString = [NSMutableString stringWithString:@"'"];
+ for (NSUInteger i = 0; i < string.length; i++) {
+ unichar c = [string characterAtIndex:i];
+
+ if (c == '\'') {
+ [escapedString appendString:@"\\"];
+ } else if (c == '\\') {
+ if (i + 1 < string.length && ([string characterAtIndex:(i + 1)] == '%' || [string characterAtIndex:(i + 1)] == '_')) {
+ // no additional back slash
+ } else {
+ [escapedString appendString:@"\\"];
+ }
+ }
+
+ [escapedString appendString:[NSString stringWithCharacters:&c length:1]];
+ }
+
+ [escapedString appendString:@"\'"];
+ return escapedString;
+}
+
++ (NSString*)escapeContains:(NSString*)string {
+ NSMutableString *escapedString = [NSMutableString stringWithString:@"'"];
+ for (NSUInteger i = 0; i < string.length; i++) {
+ unichar c = [string characterAtIndex:i];
+
+ if (c == '\\') {
+ [escapedString appendString:@"\\"];
+ } else if (c == '\'' || c == '\"') {
+ [escapedString appendString:@"\\\\\\"];
+ }
+
+ [escapedString appendString:[NSString stringWithCharacters:&c length:1]];
+ }
+
+ [escapedString appendString:@"\'"];
+ return escapedString;
+}
+
++ (NSString*)convert:(NSDate*)date {
+ NSDateFormatter* timeStampFormatter = [[NSDateFormatter alloc] init];
+ timeStampFormatter.dateFormat = @"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";
+ timeStampFormatter.calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
+ timeStampFormatter.timeZone = [NSTimeZone timeZoneWithName:@"GMT"];
+
+ return [timeStampFormatter stringFromDate:date];
+}
+
+@end
Modified: chemistry/objectivecmis/trunk/ObjectiveCMIS/Client/CMISSession.h
URL: http://svn.apache.org/viewvc/chemistry/objectivecmis/trunk/ObjectiveCMIS/Client/CMISSession.h?rev=1611348&r1=1611347&r2=1611348&view=diff
==============================================================================
--- chemistry/objectivecmis/trunk/ObjectiveCMIS/Client/CMISSession.h (original)
+++ chemistry/objectivecmis/trunk/ObjectiveCMIS/Client/CMISSession.h Thu Jul 17 12:55:59 2014
@@ -22,6 +22,7 @@
#import "CMISRepositoryInfo.h"
#import "CMISBinding.h"
#import "CMISFolder.h"
+#import "CMISQueryStatement.h"
@class CMISOperationContext;
@class CMISPagedResult;
@@ -114,14 +115,14 @@
- (CMISRequest*)retrieveTypeDefinition:(NSString *)typeId
completionBlock:(void (^)(CMISTypeDefinition *typeDefinition, NSError *error))completionBlock;
/**
- * Retrieves all objects matching the given cmis query.
+ * Retrieves all objects matching the given cmis query string.
* completionBlock returns the search results as a paged results object or nil if unsuccessful.
*/
- (CMISRequest*)query:(NSString *)statement searchAllVersions:(BOOL)searchAllVersion
completionBlock:(void (^)(CMISPagedResult *pagedResult, NSError *error))completionBlock;
/**
- * Retrieves all objects matching the given cmis query, as CMISQueryResult objects.
+ * Retrieves all objects matching the given cmis query string, as CMISQueryResult objects.
* and using the parameters provided in the operation context.
* completionBlock returns the search results as a paged results object or nil if unsuccessful.
*/
@@ -130,6 +131,22 @@
completionBlock:(void (^)(CMISPagedResult *pagedResult, NSError *error))completionBlock;
/**
+ * Retrieves all objects matching the given cmis query statement.
+ * completionBlock returns the search results as a paged results object or nil if unsuccessful.
+ */
+- (CMISRequest*)queryStatement:(CMISQueryStatement *)queryStatement searchAllVersions:(BOOL)searchAllVersion
+ completionBlock:(void (^)(CMISPagedResult *pagedResult, NSError *error))completionBlock;
+
+/**
+ * Retrieves all objects matching the given cmis query statement, as CMISQueryResult objects.
+ * and using the parameters provided in the operation context.
+ * completionBlock returns the search results as a paged results object or nil if unsuccessful.
+ */
+- (CMISRequest*)queryStatement:(CMISQueryStatement *)queryStatement searchAllVersions:(BOOL)searchAllVersion
+ operationContext:(CMISOperationContext *)operationContext
+ completionBlock:(void (^)(CMISPagedResult *pagedResult, NSError *error))completionBlock;
+
+/**
* Queries for a specific type of objects.
* Returns a paged result set, containing CMISObject instances.
* completionBlock returns the search results as a paged results object or nil if unsuccessful.
@@ -140,6 +157,18 @@
operationContext:(CMISOperationContext *)operationContext
completionBlock:(void (^)(CMISPagedResult *result, NSError *error))completionBlock;
+/**
+ * Queries for a specific type of objects.
+ * Pass where clause as query statement to ensure correct escaping
+ * Returns a paged result set, containing CMISObject instances.
+ * completionBlock returns the search results as a paged results object or nil if unsuccessful.
+ */
+- (CMISRequest*)queryObjectsWithTypeid:(NSString *)typeId
+ whereStatement:(CMISQueryStatement *)whereStatement
+ searchAllVersions:(BOOL)searchAllVersion
+ operationContext:(CMISOperationContext *)operationContext
+ completionBlock:(void (^)(CMISPagedResult *result, NSError *error))completionBlock;
+
/**
* Creates a folder in the provided folder.
Modified: chemistry/objectivecmis/trunk/ObjectiveCMIS/Client/CMISSession.m
URL: http://svn.apache.org/viewvc/chemistry/objectivecmis/trunk/ObjectiveCMIS/Client/CMISSession.m?rev=1611348&r1=1611347&r2=1611348&view=diff
==============================================================================
--- chemistry/objectivecmis/trunk/ObjectiveCMIS/Client/CMISSession.m (original)
+++ chemistry/objectivecmis/trunk/ObjectiveCMIS/Client/CMISSession.m Thu Jul 17 12:55:59 2014
@@ -274,9 +274,28 @@
}];
}
+- (CMISRequest*)queryStatement:(CMISQueryStatement *)queryStatement searchAllVersions:(BOOL)searchAllVersion
+ completionBlock:(void (^)(CMISPagedResult *pagedResult, NSError *error))completionBlock {
+ return [self query:[queryStatement queryString]
+ searchAllVersions:searchAllVersion
+ completionBlock:completionBlock];
+}
+
+- (CMISRequest*)queryStatement:(CMISQueryStatement *)queryStatement searchAllVersions:(BOOL)searchAllVersion
+ operationContext:(CMISOperationContext *)operationContext
+ completionBlock:(void (^)(CMISPagedResult *pagedResult, NSError *error))completionBlock {
+ return [self query:[queryStatement queryString]
+ searchAllVersions:searchAllVersion
+ operationContext:operationContext
+ completionBlock:completionBlock];
+}
+
- (CMISRequest*)query:(NSString *)statement searchAllVersions:(BOOL)searchAllVersion completionBlock:(void (^)(CMISPagedResult *pagedResult, NSError *error))completionBlock
{
- return [self query:statement searchAllVersions:searchAllVersion operationContext:[CMISOperationContext defaultOperationContext] completionBlock:completionBlock];
+ return [self query:statement
+ searchAllVersions:searchAllVersion
+ operationContext:[CMISOperationContext defaultOperationContext]
+ completionBlock:completionBlock];
}
- (CMISRequest*)query:(NSString *)statement searchAllVersions:(BOOL)searchAllVersion
@@ -403,10 +422,31 @@
}
- (CMISRequest*)queryObjectsWithTypeid:(NSString *)typeId
- whereClause:(NSString *)whereClause
- searchAllVersions:(BOOL)searchAllVersion
- operationContext:(CMISOperationContext *)operationContext
- completionBlock:(void (^)(CMISPagedResult *result, NSError *error))completionBlock
+ whereClause:(NSString *)whereClause
+ searchAllVersions:(BOOL)searchAllVersion
+ operationContext:(CMISOperationContext *)operationContext
+ completionBlock:(void (^)(CMISPagedResult *result, NSError *error))completionBlock
+{
+ return [self retrieveTypeDefinition:typeId
+ completionBlock:^(CMISTypeDefinition *typeDefinition, NSError *internalError) {
+ if (internalError != nil) {
+ NSError *error = [CMISErrors cmisError:internalError cmisErrorCode:kCMISErrorCodeRuntime];
+ completionBlock(nil, error);
+ } else {
+ [self queryObjectsWithTypeDefinition:typeDefinition
+ whereClause:whereClause
+ searchAllVersions:searchAllVersion
+ operationContext:operationContext
+ completionBlock:completionBlock];
+ }
+ }];
+}
+
+- (CMISRequest*)queryObjectsWithTypeid:(NSString *)typeId
+ whereStatement:(CMISQueryStatement *)whereStatement
+ searchAllVersions:(BOOL)searchAllVersion
+ operationContext:(CMISOperationContext *)operationContext
+ completionBlock:(void (^)(CMISPagedResult *result, NSError *error))completionBlock
{
return [self retrieveTypeDefinition:typeId
completionBlock:^(CMISTypeDefinition *typeDefinition, NSError *internalError) {
@@ -414,11 +454,11 @@
NSError *error = [CMISErrors cmisError:internalError cmisErrorCode:kCMISErrorCodeRuntime];
completionBlock(nil, error);
} else {
- [self queryObjectsWithTypeDefinition:typeDefinition
- whereClause:whereClause
- searchAllVersions:searchAllVersion
- operationContext:operationContext
- completionBlock:completionBlock];
+ [self queryObjectsWithTypeid:typeId
+ whereClause:[whereStatement queryString]
+ searchAllVersions:searchAllVersion
+ operationContext:operationContext
+ completionBlock:completionBlock];
}
}];
}
Modified: chemistry/objectivecmis/trunk/ObjectiveCMISTests/ObjectiveCMISTests.m
URL: http://svn.apache.org/viewvc/chemistry/objectivecmis/trunk/ObjectiveCMISTests/ObjectiveCMISTests.m?rev=1611348&r1=1611347&r2=1611348&view=diff
==============================================================================
--- chemistry/objectivecmis/trunk/ObjectiveCMISTests/ObjectiveCMISTests.m (original)
+++ chemistry/objectivecmis/trunk/ObjectiveCMISTests/ObjectiveCMISTests.m Thu Jul 17 12:55:59 2014
@@ -43,6 +43,7 @@
#import "CMISLog.h"
#import "CMISURLUtil.h"
#import "CMISMimeHelper.h"
+#import "CMISQueryStatement.h"
@interface ObjectiveCMISTests ()
@@ -2291,4 +2292,110 @@
XCTAssertEqualObjects(@"%C3%BC%C3%A4%C3%B6%C3%9C%C3%84%C3%96%C3%A9%C4%9F", [CMISURLUtil encodeUrlParameterValue:@"üäöÃÃÃéÄ"], @"wrong encoded url parameter value");
}
+- (void)testQueryStatementStaticQueries {
+ NSString *query;
+ CMISQueryStatement *st;
+
+ query = @"SELECT cmis:name FROM cmis:folder";
+ st = [[CMISQueryStatement alloc] initWithStatement:query];
+ XCTAssertEqualObjects(query, [st queryString], @"wrong encoded query statement");
+
+ query = @"SELECT * FROM cmis:document WHERE cmis:createdBy = \'admin\' AND abc:int = 42";
+ st = [[CMISQueryStatement alloc] initWithStatement:query];
+ XCTAssertEqualObjects(query, [st queryString], @"wrong encoded query statement");
+
+ query = @"SELECT * FROM cmis:document WHERE abc:test = 'x?z'";
+ st = [[CMISQueryStatement alloc] initWithStatement:query];
+ [st setStringAtIndex:1 string:@"y"];
+ XCTAssertEqualObjects(query, [st queryString], @"wrong encoded query statement");
+}
+
+- (void)testQueryStatementWherePlacholder {
+ NSString *query;
+ CMISQueryStatement *st;
+
+ // strings
+ query = @"SELECT * FROM cmis:document WHERE abc:string = ?";
+ st = [[CMISQueryStatement alloc] initWithStatement:query];
+ [st setStringAtIndex:1 string:@"test"];
+ XCTAssertEqualObjects(@"SELECT * FROM cmis:document WHERE abc:string = 'test'", [st queryString], @"wrong encoded query statement");
+
+ query = @"SELECT * FROM cmis:document WHERE abc:string = ?";
+ st = [[CMISQueryStatement alloc] initWithStatement:query];
+ [st setStringAtIndex:1 string:@"te'st"];
+ XCTAssertEqualObjects(@"SELECT * FROM cmis:document WHERE abc:string = 'te\\'st'", [st queryString], @"wrong encoded query statement");
+
+ // likes
+ query = @"SELECT * FROM cmis:document WHERE abc:string LIKE ?";
+ st = [[CMISQueryStatement alloc] initWithStatement:query];
+ [st setStringLikeAtIndex:1 string:@"%test%"];
+ XCTAssertEqualObjects(@"SELECT * FROM cmis:document WHERE abc:string LIKE '%test%'", [st queryString], @"wrong encoded query statement");
+
+ query = @"SELECT * FROM cmis:document WHERE abc:string LIKE ?";
+ st = [[CMISQueryStatement alloc] initWithStatement:query];
+ [st setStringLikeAtIndex:1 string:@"\\_test\\%blah\\\\blah"];
+ XCTAssertEqualObjects(@"SELECT * FROM cmis:document WHERE abc:string LIKE '\\_test\\%blah\\\\\\\\blah'", [st queryString], @"wrong encoded query statement");
+
+ // contains
+
+ // *, ? and - are treated as text search operators: 1st level escaping:
+ // none, 2nd level escaping: none
+ // \*, \? and \- are used as literals, 1st level escaping: none, 2nd
+ // level escaping: \\*, \\?, \\-
+ // ' and " are used as literals, 1st level escaping: \', \", 2nd level
+ // escaping: \\\', \\\",
+ // \ plus any other character, 1st level escaping \\ plus character, 2nd
+ // level: \\\\ plus character
+
+ query = @"SELECT * FROM cmis:document WHERE CONTAINS(?)";
+ st = [[CMISQueryStatement alloc] initWithStatement:query];
+ [st setStringContainsAtIndex:1 string:@"John's"];
+ XCTAssertEqualObjects(@"SELECT * FROM cmis:document WHERE CONTAINS('John\\\\\\'s')", [st queryString], @"wrong encoded query statement");
+ [st setStringContainsAtIndex:1 string:@"foo -bar"];
+ XCTAssertEqualObjects(@"SELECT * FROM cmis:document WHERE CONTAINS('foo -bar')", [st queryString], @"wrong encoded query statement");
+ [st setStringContainsAtIndex:1 string:@"foo*"];
+ XCTAssertEqualObjects(@"SELECT * FROM cmis:document WHERE CONTAINS('foo*')", [st queryString], @"wrong encoded query statement");
+ [st setStringContainsAtIndex:1 string:@"foo?"];
+ XCTAssertEqualObjects(@"SELECT * FROM cmis:document WHERE CONTAINS('foo?')", [st queryString], @"wrong encoded query statement");
+ [st setStringContainsAtIndex:1 string:@"foo\\-bar"];
+ XCTAssertEqualObjects(@"SELECT * FROM cmis:document WHERE CONTAINS('foo\\\\-bar')", [st queryString], @"wrong encoded query statement");
+ [st setStringContainsAtIndex:1 string:@"foo\\*"];
+ XCTAssertEqualObjects(@"SELECT * FROM cmis:document WHERE CONTAINS('foo\\\\*')", [st queryString], @"wrong encoded query statement");
+ [st setStringContainsAtIndex:1 string:@"foo\\?"];
+ XCTAssertEqualObjects(@"SELECT * FROM cmis:document WHERE CONTAINS('foo\\\\?')", [st queryString], @"wrong encoded query statement");
+ [st setStringContainsAtIndex:1 string:@"\"Cool\""];
+ XCTAssertEqualObjects(@"SELECT * FROM cmis:document WHERE CONTAINS('\\\\\\\"Cool\\\\\\\"')", [st queryString], @"wrong encoded query statement");
+ [st setStringContainsAtIndex:1 string:@"c:\\MyDcuments"];
+ XCTAssertEqualObjects(@"SELECT * FROM cmis:document WHERE CONTAINS('c:\\\\MyDcuments')", [st queryString], @"wrong encoded query statement");
+
+ // ids
+ query = @"SELECT * FROM cmis:document WHERE abc:id = ?";
+ st = [[CMISQueryStatement alloc] initWithStatement:query];
+ [st setStringAtIndex:1 string:@"123"];
+ XCTAssertEqualObjects(@"SELECT * FROM cmis:document WHERE abc:id = '123'", [st queryString], @"wrong encoded query statement");
+
+ // booleans
+ query = @"SELECT * FROM cmis:document WHERE abc:bool = ?";
+ st = [[CMISQueryStatement alloc] initWithStatement:query];
+ [st setBooleanAtIndex:1 boolean:YES];
+ XCTAssertEqualObjects(@"SELECT * FROM cmis:document WHERE abc:bool = YES", [st queryString], @"wrong encoded query statement");
+
+ // numbers
+ query = @"SELECT * FROM cmis:document WHERE abc:int = ? AND abc:int2 = 123";
+ st = [[CMISQueryStatement alloc] initWithStatement:query];
+ [st setNumberAtIndex:1 number:[NSNumber numberWithInt:42]];
+ XCTAssertEqualObjects(@"SELECT * FROM cmis:document WHERE abc:int = 42 AND abc:int2 = 123", [st queryString], @"wrong encoded query statement");
+
+ query = @"SELECT * FROM cmis:document WHERE abc:dateTime = ?";
+ st = [[CMISQueryStatement alloc] initWithStatement:query];
+ NSDateFormatter *df = [NSDateFormatter new];
+ [df setDateFormat:@"dd/MM/yyyy HH:mm:ss"];
+ //Create the GMT date
+ df.timeZone = [NSTimeZone timeZoneForSecondsFromGMT:0];
+ NSDate *date = [df dateFromString:@"02/02/2012 03:04:05"];
+
+ [st setDateTimeAtIndex:1 date:date];
+ XCTAssertEqualObjects(@"SELECT * FROM cmis:document WHERE abc:dateTime = TIMESTAMP '2012-02-02T03:04:05.000Z'", [st queryString], @"wrong encoded query statement");
+}
+
@end