1 /*
2  * Copyright (c) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #define LOG_TAG "RdbPredicates"
16 #include "rdb_predicates.h"
17 
18 #include "logger.h"
19 #include "string_utils.h"
20 
21 namespace OHOS {
22 namespace NativeRdb {
23 using namespace OHOS::Rdb;
24 
RdbPredicates(const std::string & tableName)25 RdbPredicates::RdbPredicates(const std::string &tableName) : AbsRdbPredicates(tableName)
26 {
27     InitialParam();
28 }
29 
GetJoinClause() const30 std::string RdbPredicates::GetJoinClause() const
31 {
32     return joinTableNames.empty() ? "" : ProcessJoins();
33 }
34 
35 /**
36  * Adds a {@code cross join} condition to a SQL statement.
37  */
CrossJoin(const std::string & tableName)38 RdbPredicates *RdbPredicates::CrossJoin(const std::string &tableName)
39 {
40     return Join(JoinType::CROSS, tableName);
41 }
42 
43 /**
44  * Adds an {@code inner join} condition to a SQL statement.
45  */
InnerJoin(const std::string & tableName)46 RdbPredicates *RdbPredicates::InnerJoin(const std::string &tableName)
47 {
48     return Join(JoinType::INNER, tableName);
49 }
50 
51 /**
52  * Adds a {@code left outer join} condition to a SQL statement.
53  */
LeftOuterJoin(const std::string & tableName)54 RdbPredicates *RdbPredicates::LeftOuterJoin(const std::string &tableName)
55 {
56     return Join(JoinType::LEFT, tableName);
57 }
58 /**
59  * Adds a condition to a SQL statement.
60  */
Join(int join,const std::string & tableName)61 RdbPredicates *RdbPredicates::Join(int join, const std::string &tableName)
62 {
63     if (tableName.empty()) {
64         LOG_WARN("RdbPredicates join failed: table name is null or empty.");
65         return this;
66     }
67 
68     joinTypes.push_back(GetGrammar(join));
69     joinTableNames.push_back(tableName);
70     joinCount++;
71     return this;
72 }
73 
74 /**
75  * Adds a {@code using} condition to the predicate. This method is similar to {@code using} of the SQL statement.
76  */
Using(const std::vector<std::string> & fields)77 RdbPredicates *RdbPredicates::Using(const std::vector<std::string> &fields)
78 {
79     if (fields.size() == 0) {
80         LOG_WARN("RdbPredicates Using failed : clauses is null.");
81         return this;
82     }
83     if (joinCount <= 0) {
84         LOG_WARN("No active join operation before using.");
85         return this;
86     }
87     while (joinCount > 1) {
88         joinConditions.push_back("");
89         joinCount--;
90     }
91     joinCount--;
92     joinConditions.push_back(StringUtils::SurroundWithFunction("USING", ",", fields));
93     return this;
94 }
95 
96 /**
97  * Adds an {@code on} condition to the predicate.
98  */
On(const std::vector<std::string> & clauses)99 RdbPredicates *RdbPredicates::On(const std::vector<std::string> &clauses)
100 {
101     if (clauses.size() == 0) {
102         LOG_WARN("RdbPredicates on failed : clauses is null.");
103         return this;
104     }
105     if (joinCount <= 0) {
106         LOG_WARN("No active join operation before on.");
107         return this;
108     }
109     while (joinCount > 1) {
110         joinConditions.push_back("");
111         joinCount--;
112     }
113     joinCount--;
114     joinConditions.push_back(StringUtils::SurroundWithFunction("ON", "AND", clauses));
115     return this;
116 }
117 
ProcessJoins() const118 std::string RdbPredicates::ProcessJoins() const
119 {
120     std::string builder;
121     size_t size = joinTableNames.size();
122     for (size_t i = 0; i < size; i++) {
123         if (i != 0) {
124             builder = builder + " ";
125         }
126         builder = builder + joinTypes[i] + " " + joinTableNames[i];
127         if (joinConditions[i] != "") {
128             builder = builder + " " + joinConditions[i];
129         }
130     }
131     return builder;
132 }
133 
GetGrammar(int type) const134 std::string RdbPredicates::GetGrammar(int type) const
135 {
136     if (type == INNER) {
137         return "INNER JOIN";
138     }
139     if (type == LEFT) {
140         return "LEFT OUTER JOIN";
141     }
142     return "CROSS JOIN";
143 }
144 } // namespace NativeRdb
145 } // namespace OHOS