sbSQLSelectBuilder.cpp
Go to the documentation of this file.
1 /*
2 //
3 // BEGIN SONGBIRD GPL
4 //
5 // This file is part of the Songbird web player.
6 //
7 // Copyright(c) 2005-2008 POTI, Inc.
8 // http://songbirdnest.com
9 //
10 // This file may be licensed under the terms of of the
11 // GNU General Public License Version 2 (the "GPL").
12 //
13 // Software distributed under the License is distributed
14 // on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either
15 // express or implied. See the GPL for the specific language
16 // governing rights and limitations.
17 //
18 // You should have received a copy of the GPL along with this
19 // program. If not, go to http://www.gnu.org/licenses/gpl.html
20 // or write to the Free Software Foundation, Inc.,
21 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 //
23 // END SONGBIRD GPL
24 //
25 */
26 
27 #include "sbSQLSelectBuilder.h"
28 #include "sbSQLWhereBuilder.h"
29 #include "sbSQLBuilderCriterion.h"
30 
34 
36  mIsDistinct(PR_FALSE)
37 {
38  MOZ_COUNT_CTOR(sbSQLSelectBuilder);
39 }
40 
42 {
43  MOZ_COUNT_DTOR(sbSQLSelectBuilder);
44 }
45 
46 NS_IMETHODIMP
47 sbSQLSelectBuilder::GetBaseTableName(nsAString& aBaseTableName)
48 {
49  aBaseTableName.Assign(mBaseTableName);
50  return NS_OK;
51 }
52 NS_IMETHODIMP
53 sbSQLSelectBuilder::SetBaseTableName(const nsAString& aBaseTableName)
54 {
55  mBaseTableName.Assign(aBaseTableName);
56  return NS_OK;
57 }
58 
59 NS_IMETHODIMP
60 sbSQLSelectBuilder::GetBaseTableAlias(nsAString& aBaseTableAlias)
61 {
62  aBaseTableAlias.Assign(mBaseTableAlias);
63  return NS_OK;
64 }
65 NS_IMETHODIMP
66 sbSQLSelectBuilder::SetBaseTableAlias(const nsAString& aBaseTableAlias)
67 {
68  mBaseTableAlias.Assign(aBaseTableAlias);
69  return NS_OK;
70 }
71 
72 NS_IMETHODIMP
73 sbSQLSelectBuilder::GetDistinct(PRBool *aDistinct)
74 {
75  *aDistinct = mIsDistinct;
76  return NS_OK;
77 }
78 NS_IMETHODIMP
79 sbSQLSelectBuilder::SetDistinct(PRBool aDistinct)
80 {
81  mIsDistinct = aDistinct;
82  return NS_OK;
83 }
84 
85 NS_IMETHODIMP
86 sbSQLSelectBuilder::AddColumn(const nsAString& aTableName,
87  const nsAString& aColumnName)
88 {
89  sbColumnInfo* ci = mOutputColumns.AppendElement();
90  NS_ENSURE_TRUE(ci, NS_ERROR_OUT_OF_MEMORY);
91 
92  ci->tableName = aTableName;
93  ci->columnName = aColumnName;
94 
95  return NS_OK;
96 }
97 
98 NS_IMETHODIMP
99 sbSQLSelectBuilder::ClearColumns()
100 {
101  mOutputColumns.Clear();
102 
103  return NS_OK;
104 }
105 
106 NS_IMETHODIMP
107 sbSQLSelectBuilder::AddOrder(const nsAString& aTableName,
108  const nsAString& aColumnName,
109  PRBool aAscending)
110 {
111  sbOrderInfo* oi = mOrders.AppendElement();
112  NS_ENSURE_TRUE(oi, NS_ERROR_OUT_OF_MEMORY);
113 
114  oi->tableName = aTableName;
115  oi->columnName = aColumnName;
116  oi->ascending = aAscending;
117  oi->random = PR_FALSE;
118 
119  return NS_OK;
120 }
121 
122 NS_IMETHODIMP
123 sbSQLSelectBuilder::AddRandomOrder()
124 {
125  sbOrderInfo* oi = mOrders.AppendElement();
126  NS_ENSURE_TRUE(oi, NS_ERROR_OUT_OF_MEMORY);
127 
128  oi->random = PR_TRUE;
129  oi->ascending = PR_FALSE; // unused, but don't leave it uninitialized
130 
131  return NS_OK;
132 }
133 
134 NS_IMETHODIMP
135 sbSQLSelectBuilder::AddGroupBy(const nsAString& aTableName,
136  const nsAString& aColumnName)
137 {
138  sbGroupInfo* gi = mGroups.AppendElement();
139  NS_ENSURE_TRUE(gi, NS_ERROR_OUT_OF_MEMORY);
140 
141  gi->tableName = aTableName;
142  gi->columnName = aColumnName;
143 
144  return NS_OK;
145 }
146 
147 NS_IMETHODIMP
149 {
151  mBaseTableName.Truncate();
152  mBaseTableAlias.Truncate();
153  mIsDistinct = PR_FALSE;
154  mOutputColumns.Clear();
155  mOrders.Clear();
156  mGroups.Clear();
157 
158  return NS_OK;
159 }
160 
161 NS_IMETHODIMP
162 sbSQLSelectBuilder::ToString(nsAString& _retval)
163 {
164  nsresult rv;
165  nsAutoString buff;
166 
167  // Start with a select...
168  buff.AssignLiteral("select ");
169 
170  if (mIsDistinct) {
171  buff.AppendLiteral("distinct ");
172  }
173 
174  // Append output column names
175  PRUint32 len = mOutputColumns.Length();
176  for (PRUint32 i = 0; i < len; i++) {
177  const sbColumnInfo& ci = mOutputColumns[i];
178  if (!ci.tableName.IsEmpty()) {
179  buff.Append(ci.tableName);
180  buff.AppendLiteral(".");
181  }
182  buff.Append(ci.columnName);
183  if (i + 1 < len) {
184  buff.AppendLiteral(", ");
185  }
186  }
187 
188  // Append the from clause including the base table, subqueries, and joins
189  buff.AppendLiteral(" from ");
190  buff.Append(mBaseTableName);
191  if (!mBaseTableAlias.IsEmpty()) {
192  buff.AppendLiteral(" as ");
193  buff.Append(mBaseTableAlias);
194  }
195 
196  len = mSubqueries.Length();
197  for (PRUint32 i = 0; i < len; i++) {
198  const sbSubqueryInfo& sq = mSubqueries[i];
199  buff.AppendLiteral(", ( ");
200  nsAutoString str;
201  sq.subquery->ToString(str);
202  buff.Append(str);
203  buff.AppendLiteral(" )");
204  if (!sq.alias.IsEmpty()) {
205  buff.AppendLiteral(" as ");
206  buff.Append(sq.alias);
207  }
208  }
209 
210  len = mJoins.Length();
211  for (PRUint32 i = 0; i < len; i++) {
212  const sbJoinInfo& ji = mJoins[i];
213  switch(ji.type) {
215  /* default is inner */
216  break;
218  buff.AppendLiteral(" left");
219  break;
221  buff.AppendLiteral(" left outer");
222  break;
223  default:
224  NS_NOTREACHED("Unknown Join Type");
225  }
226  buff.AppendLiteral(" join ");
227  if (ji.subquery) {
228  buff.AppendLiteral("(");
229  nsAutoString str;
230  ji.subquery->ToString(str);
231  buff.Append(str);
232  buff.AppendLiteral(")");
233  }
234  else {
235  buff.Append(ji.joinedTableName);
236  }
237  if (!ji.joinedTableAlias.IsEmpty()) {
238  buff.AppendLiteral(" as ");
239  buff.Append(ji.joinedTableAlias);
240  }
241  buff.AppendLiteral(" on ");
242  if (ji.criterion) {
243  nsAutoString str;
244  static_cast<sbSQLBuilderCriterionBase*>(ji.criterion.get())->ToString(str);
245  buff.Append(str);
246  }
247  else {
249  buff.AppendLiteral("+");
250  }
251  buff.Append(ji.joinToTableName);
252  buff.AppendLiteral(".");
253  buff.Append(ji.joinToColumnName);
254  buff.AppendLiteral(" = ");
256  buff.AppendLiteral("+");
257  }
258  if (!ji.joinedTableAlias.IsEmpty()) {
259  buff.Append(ji.joinedTableAlias);
260  buff.AppendLiteral(".");
261  }
262  else {
263  if (!ji.joinedTableName.IsEmpty()) {
264  buff.Append(ji.joinedTableName);
265  buff.AppendLiteral(".");
266  }
267  }
268  buff.Append(ji.joinedColumnName);
269  }
270  }
271 
272  rv = AppendWhere(buff);
273  NS_ENSURE_SUCCESS(rv, rv);
274 
275  // Append group by clause
276  len = mGroups.Length();
277  if (len > 0) {
278  buff.AppendLiteral(" group by ");
279  for (PRUint32 i = 0; i < len; i++) {
280  const sbGroupInfo& gi = mGroups[i];
281  if (!gi.tableName.IsEmpty()) {
282  buff.Append(gi.tableName);
283  buff.AppendLiteral(".");
284  }
285  buff.Append(gi.columnName);
286  if (i + 1 < len) {
287  buff.AppendLiteral(", ");
288  }
289  }
290  }
291 
292  // Append order by clause
293  len = mOrders.Length();
294  if (len > 0) {
295  buff.AppendLiteral(" order by ");
296  for (PRUint32 i = 0; i < len; i++) {
297  const sbOrderInfo& oi = mOrders[i];
298  if (oi.random) {
299  buff.AppendLiteral("random()");
300  } else {
301  if (!oi.tableName.IsEmpty()) {
302  buff.Append(oi.tableName);
303  buff.AppendLiteral(".");
304  }
305  buff.Append(oi.columnName);
306  if (oi.ascending) {
307  buff.AppendLiteral(" asc");
308  }
309  else {
310  buff.AppendLiteral(" desc");
311  }
312  }
313  if (i + 1 < len) {
314  buff.AppendLiteral(", ");
315  }
316  }
317  }
318 
319  // Add limit and offset
320  if(mLimit >= 0 || mLimitIsParameter) {
321  buff.AppendLiteral(" limit ");
322  if(mLimitIsParameter) {
323  buff.AppendLiteral("?");
324  }
325  else {
326  buff.AppendInt(mLimit);
327  }
328  }
329 
330  if(mOffset >= 0 || mOffsetIsParameter) {
331  buff.AppendLiteral(" offset ");
332  if(mOffsetIsParameter) {
333  buff.AppendLiteral("?");
334  }
335  else {
336  buff.AppendInt(mOffset);
337  }
338  }
339 
340  _retval.Assign(buff);
341  return NS_OK;
342 }
343 
nsTArray< sbSubqueryInfo > mSubqueries
PRPackedBool requiresJoinFromIndexUsageFix
return NS_OK
nsCOMPtr< sbISQLSelectBuilder > subquery
nsresult AppendWhere(nsAString &aBuffer)
NS_DECL_SBISQLSELECTBUILDER NS_IMETHOD ToString(nsAString &_result)
Interface for building SELECT statements.
const unsigned long JOIN_LEFT_OUTER
const unsigned long JOIN_INNER
nsCOMPtr< sbISQLSelectBuilder > subquery
const unsigned long JOIN_LEFT
nsTArray< sbJoinInfo > mJoins
PRPackedBool requiresJoinToIndexUsageFix
nsCOMPtr< sbISQLBuilderCriterion > criterion
_getSelectedPageStyle s i
NS_IMPL_ISUPPORTS_INHERITED1(sbSQLSelectBuilder, sbSQLWhereBuilder, sbISQLSelectBuilder) sbSQLSelectBuilder