Please read the documentation in the Sql_lib itelsf if something is unclear.
This Description may not contain all features of the Builder. Most usages should be possible in an intuitive way, so just try if it already works like you think it should work.
All parameters are documented in the lib itself.
*Please Read it*.
You may also take a look at the *SqlLib_tests* as it contains many possible ways to use the SqlBuilder. (By the way this tests use the UnitTest_lib for unittesting. It may be something you could use somewhere else, too...)
== Why
== Why
=== Prepared Statements
=== Prepared Statements
Prepared Statements should always be used because of
Prepared Statements should *always* be used because of
* Security (Sql injection): If you are used to something like
* *Security* (Sql injection): If you are used to something like
`"select * from PERSON where PERSONID = '" + persId + "'"`
`"select * from PERSON where PERSONID = '" + persId + "'"`
you *WILL* forget to use prepared statements if it is really nessecary:
you *WILL* forget to use prepared statements if it is really nessecary:
`"select * from PERSON where FIRSTNAME = '" + userInput + "'"`
`"select * from PERSON where FIRSTNAME = '" + userInput + "'"`
...
@@ -245,6 +249,54 @@ pCondition can be a simple string or a SqlBuilder containing a condition. (only
...
@@ -245,6 +249,54 @@ pCondition can be a simple string or a SqlBuilder containing a condition. (only
orderBy(pFields) just adds a order by to the sql
orderBy(pFields) just adds a order by to the sql
the parameter can be filled the same way as .select(pFields)
the parameter can be filled the same way as .select(pFields)
=== db. function wrappers
==== select-functions
There are some wrappers for db. functions directly in the SqlBuilder mainly for convenience and to prevent sending selects like "select FIRSTNAME from PERSON where 1 = 2" to the dbms.
Note: you can still use the db. functions if you like.
cell
arrayRow
arrayColumn
arrayPage
table
tablePage
All of them have an extra parameter pExecuteOnlyIfConditionExists, no pAlias and no pSQL.
* pExecuteOnlyIfConditionExists is a boolean which defaults to false
- If it is false and the builder currently has no condition (e.g. because of *IfSet's), the executed select will also contain no condition -> selects all
- If it is true the select will only be executed if there is a condition. Else it will return "" or [] based on which method you used.
This is to prevent sending selects like "select FIRSTNAME from PERSON where 1 = 2" to the dbms
-> Note: if not all of your conditions are *IfSet's, this case will never happen, as the Builder always contains a condition in this case. -> you can ommit the param in most cases
cell is a special case as it contains another param: pFallbackValue
I added it, because in the basic is often a count(*):
// The conditionProcesss doesn't support prepared statements. So .build() is currently not possible.
// The conditionProcesss doesn't support prepared statements. So .build() is currently not possible.
// using .toString() resolves all conditions and builds the finished select as string.
// using .toString() resolves all conditions and builds the finished select as string.
result.string(cond.toString());
result.string(cond.toString());
----
----
\ No newline at end of file
== SqlCondition to SqlBuilder conversion help
The SqlCondition is deprecated and removed completely in Basic 2020.
So you have to:
* replace all SqlCondition usages by the SqlBuilder
* if you haven't used it before and use code like ...'" + myVal + "'...
START TO USIE IT. (See 1. Why)
* if you find something which cannot be built by the SqlBuilder -> new Featureticket for Basic
For the first point some advice:
It is not easily possible to replace the SqlCondition directly by the SqlBuilder. There are too many differences.
=== Differences SqlCondition -> SqlBuilder
Here a list of the main differences:
==== Instanciation
*SqlCondition*
new SqlCondition(...)
SqlCondition.begin(...)
*SqlBuilder*
new SqlBuilder(...)
newSelect(...)
newWhere(...)
*Iformation*
Why no SqlBuilder.begin(...):
Because this was needed when we had a older jscript-engine in Adito.
It was for writing the next methods directly after creation.
e.g.
[source,js]
----
SqlBuilder.begin(...)
.where(..)
----
Now, with a newer Rhino jscript-engine it is possible to write
e.g.
[source,js]
----
new SqlBuilder(...)
.where(...)
----
So this workaround is not needed anymore.
==== the new .where
*SqlCondition*
doesn't have this
*SqlBuilder*
.where(...)
*Iformation*
The .where was a feedback I got while creating the SqlBuilder.
It exists just for semantic reasons (see documentation of where above).
It is simply more similar to a normal SQL-string if the first condtion uses .where()
Notes for SqlCondition to SqlBuilder conversion:
* It may happen that you forget to use .where as first condition. In this case you will get an error explaining the problem.
* Sometimes it can be a problem, because the first condition you add is wraped in a if. (Then you would need a check if the where is already called and use .and for the next one else use .where... -> thats bad)
Solution: just add a empty .where() or use newWhere(). This won't add a condition but you can continue with .and / .or without any problem.
==== and / or
*SqlCondition*
has several of these
*SqlBuilder*
.where
.whereIfSet
.and / .or
.andIfSet / .orIfSet
*Iformation*
One of the main Problems with the SqlCondition was that no one knows which of the .and / .or methods does what. (It was everything documented but no one reads the documentation...)
And it was inconsistent in some cases.
Basically you can put everything into .and / .or / .where
just returns the condition, nothing else, even if the sqlBuilder contains more.
*SqlBuilder: build(alternativeCond)*
Note: often alternativeCond was used. In most cases this is not needed:
- If you have at least one condition without IfSet, it will never use alternativeCond because it will throw an error before.
- if you have only *IfSet and use "1=1" the "1=1" isn't needed, because no condition at all also selects everything
- This is often used in conditionProcesses. There you should always select everything, and not nothing, as Adito may add additional conditions to it (for e.g. permissions or selecting only one specific id).
* SqlCondition: translate(alternativeCond)
*SqlBuilder: toString(alternativeCond)*
Only use this if you really need a string. Use .build() if you can use prepared statements!
=== Recommended steps for conversion
Search for "SqlConditon" for each find:
* See if it is used as condition or if there is somewhere a .buildSql with a full select.
* If it's a condition you may use newWhere(...) / newWhereIfSet(...).
* If it's a select you may use
[source,js]
----
newSelect(...)
.from(...)
(.join(...))
.where(...)
...
----
* Build your condition, think if you need *IfSet or not (e.g. if it's an essential condition).
* If there is a db.table, db.cell, etc. consider to use the .table, .cell, .array methods from the sqlBuilder itself:
[source,js]
----
var myData = newSelect(...)
.from(...)
.join(...)
.where(...)
.table()
----
* If you are in an conditionProcess, use .toString instead of .translate
if there is a alternativeCondition, think, if you really need it.
* after all you can use the basic as reference as there is everything replaced.