/wheels/model/adapters/Base.cfc

http://cfwheels.googlecode.com/ · ColdFusion CFScript · 273 lines · 246 code · 20 blank · 7 comment · 40 complexity · 268edfaed10ee5a51e31131a6b33c682 MD5 · raw file

  1. <cfcomponent output="false">
  2. <cfinclude template="../../global/cfml.cfm">
  3. <cffunction name="init" access="public" returntype="any" output="false">
  4. <cfargument name="datasource" type="string" required="true">
  5. <cfargument name="username" type="string" required="true">
  6. <cfargument name="password" type="string" required="true">
  7. <cfset variables.instance.connection = arguments>
  8. <cfreturn this>
  9. </cffunction>
  10. <cffunction name="$tableName" returntype="string" access="public" output="false">
  11. <cfargument name="list" type="string" required="true">
  12. <cfargument name="action" type="string" required="true">
  13. <cfscript>
  14. var loc = {};
  15. loc.returnValue = "";
  16. loc.iEnd = ListLen(arguments.list);
  17. for (loc.i=1; loc.i <= loc.iEnd; loc.i++)
  18. {
  19. loc.iItem = ListGetAt(arguments.list, loc.i);
  20. if (arguments.action == "remove")
  21. loc.iItem = ListRest(loc.iItem, "."); // removes table names
  22. loc.returnValue = ListAppend(loc.returnValue, loc.iItem);
  23. }
  24. </cfscript>
  25. <cfreturn loc.returnValue>
  26. </cffunction>
  27. <cffunction name="$columnAlias" returntype="string" access="public" output="false">
  28. <cfargument name="list" type="string" required="true">
  29. <cfargument name="action" type="string" required="true">
  30. <cfscript>
  31. var loc = {};
  32. loc.returnValue = "";
  33. loc.iEnd = ListLen(arguments.list);
  34. for (loc.i=1; loc.i <= loc.iEnd; loc.i++)
  35. {
  36. loc.iItem = ListGetAt(arguments.list, loc.i);
  37. if (Find(" AS ", loc.iItem))
  38. {
  39. loc.sort = "";
  40. if (Right(loc.iItem, 4) == " ASC" || Right(loc.iItem, 5) == " DESC")
  41. {
  42. loc.sort = " " & Reverse(SpanExcluding(Reverse(loc.iItem), " "));
  43. loc.iItem = Mid(loc.iItem, 1, Len(loc.iItem)-Len(loc.sort));
  44. }
  45. loc.alias = Reverse(SpanExcluding(Reverse(loc.iItem), " "));
  46. if (arguments.action == "keep")
  47. loc.iItem = loc.alias; // keeps the alias only
  48. else if (arguments.action == "remove")
  49. loc.iItem = Replace(loc.iItem, " AS " & loc.alias, ""); // removes the alias
  50. loc.iItem = loc.iItem & loc.sort;
  51. }
  52. loc.returnValue = ListAppend(loc.returnValue, loc.iItem);
  53. }
  54. </cfscript>
  55. <cfreturn loc.returnValue>
  56. </cffunction>
  57. <cffunction name="$removeColumnAliasesInOrderClause" returntype="array" access="public" output="false">
  58. <cfargument name="sql" type="array" required="true">
  59. <cfscript>
  60. var loc = {};
  61. loc.returnValue = arguments.sql;
  62. if (IsSimpleValue(loc.returnValue[ArrayLen(loc.returnValue)]) && Left(loc.returnValue[ArrayLen(loc.returnValue)], 9) == "ORDER BY ")
  63. {
  64. // remove the column aliases from the order by clause (this is passed in so that we can handle sub queries with calculated properties)
  65. loc.pos = ArrayLen(loc.returnValue);
  66. loc.orderByClause = ReplaceNoCase(loc.returnValue[loc.pos], "ORDER BY ", "");
  67. loc.returnValue[loc.pos] = "ORDER BY " & $columnAlias(list=loc.orderByClause, action="remove");
  68. }
  69. </cfscript>
  70. <cfreturn loc.returnValue>
  71. </cffunction>
  72. <cffunction name="$addColumnsToSelectAndGroupBy" returntype="array" access="public" output="false">
  73. <cfargument name="sql" type="array" required="true">
  74. <cfscript>
  75. var loc = {};
  76. loc.returnValue = arguments.sql;
  77. if (IsSimpleValue(loc.returnValue[ArrayLen(loc.returnValue)]) && Left(loc.returnValue[ArrayLen(loc.returnValue)], 8) IS "ORDER BY" && IsSimpleValue(loc.returnValue[ArrayLen(loc.returnValue)-1]) && Left(loc.returnValue[ArrayLen(loc.returnValue)-1], 8) IS "GROUP BY")
  78. {
  79. loc.iEnd = ListLen(loc.returnValue[ArrayLen(loc.returnValue)]);
  80. for (loc.i=1; loc.i <= loc.iEnd; loc.i++)
  81. {
  82. loc.item = Trim(ReplaceNoCase(ReplaceNoCase(ReplaceNoCase(ListGetAt(loc.returnValue[ArrayLen(loc.returnValue)], loc.i), "ORDER BY ", ""), " ASC", ""), " DESC", ""));
  83. if (!ListFindNoCase(ReplaceNoCase(loc.returnValue[ArrayLen(loc.returnValue)-1], "GROUP BY ", ""), loc.item))
  84. loc.returnValue[ArrayLen(loc.returnValue)-1] = ListAppend(loc.returnValue[ArrayLen(loc.returnValue)-1], loc.item);
  85. if (!ListFindNoCase(ReplaceNoCase(loc.returnValue[1], "SELECT ", ""), loc.item))
  86. loc.returnValue[1] = ListAppend(loc.returnValue[1], loc.item);
  87. }
  88. }
  89. </cfscript>
  90. <cfreturn loc.returnValue>
  91. </cffunction>
  92. <cffunction name="$getColumns" returntype="query" access="public" output="false" hint="retrieves all the column information from a table">
  93. <cfargument name="tableName" type="string" required="true" hint="the table to retrieve column information for">
  94. <cfscript>
  95. var loc = {};
  96. loc.args = duplicate(variables.instance.connection);
  97. loc.args.table = arguments.tableName;
  98. if (application.wheels.showErrorInformation)
  99. {
  100. try
  101. {
  102. loc.columns = $getColumnInfo(argumentCollection=loc.args);
  103. }
  104. catch (Any e)
  105. {
  106. $throw(type="Wheels.TableNotFound", message="The `#arguments.tableName#` table could not be found in the database.", extendedInfo="Add a table named `#arguments.tableName#` to your database or tell Wheels to use a different table for this model. For example you can tell a `user` model to use a table called `tbl_users` by creating a `User.cfc` file in the `models` folder, creating an `init` method inside it and then calling `table(""tbl_users"")` from within it.");
  107. }
  108. }
  109. else
  110. {
  111. loc.columns = $getColumnInfo(argumentCollection=loc.args);
  112. }
  113. </cfscript>
  114. <cfreturn loc.columns>
  115. </cffunction>
  116. <cffunction name="$getValidationType" returntype="string" access="public" output="false">
  117. <cfargument name="type" type="string" required="true">
  118. <cfswitch expression="#arguments.type#">
  119. <cfcase value="cf_sql_real,cf_sql_numeric,cf_sql_float,cf_sql_decimal,cf_sql_double" delimiters=",">
  120. <cfreturn "float">
  121. </cfcase>
  122. <cfcase value="cf_sql_tinyint,cf_sql_smallint,cf_sql_integer,cf_sql_bigint" delimiters=",">
  123. <cfreturn "integer">
  124. </cfcase>
  125. <cfcase value="cf_sql_char,cf_sql_varchar" delimiters=",">
  126. <cfreturn "string">
  127. </cfcase>
  128. <cfcase value="cf_sql_date,cf_sql_timestamp,cf_sql_time" delimiters=",">
  129. <cfreturn "datetime">
  130. </cfcase>
  131. <cfdefaultcase>
  132. <cfreturn "">
  133. </cfdefaultcase>
  134. </cfswitch>
  135. </cffunction>
  136. <cffunction name="$cleanInStatmentValue" returntype="string" access="public" output="false">
  137. <cfargument name="statement" type="string" required="true">
  138. <cfscript>
  139. var loc = {};
  140. loc.delim = ",";
  141. if (Find("'", arguments.statement))
  142. {
  143. loc.delim = "','";
  144. arguments.statement = RemoveChars(arguments.statement, 1, 1);
  145. arguments.statement = reverse(RemoveChars(reverse(arguments.statement), 1, 1));
  146. arguments.statement = Replace(arguments.statement, "''", "'", "all");
  147. }
  148. arguments.statement = ReplaceNoCase(arguments.statement, loc.delim, chr(7), "all");
  149. </cfscript>
  150. <cfreturn arguments.statement>
  151. </cffunction>
  152. <cffunction name="$CFQueryParameters" returntype="struct" access="public" output="false">
  153. <cfargument name="settings" type="struct" required="true">
  154. <cfscript>
  155. var loc = {};
  156. loc.params = {};
  157. loc.params.cfsqltype = arguments.settings.type;
  158. loc.params.value = arguments.settings.value;
  159. if (StructKeyExists(arguments.settings, "null"))
  160. {
  161. loc.params.null = arguments.settings.null;
  162. }
  163. if (StructKeyExists(arguments.settings, "scale") AND arguments.settings.scale GT 0)
  164. {
  165. loc.params.scale = arguments.settings.scale;
  166. }
  167. if (StructKeyExists(arguments.settings, "list") AND arguments.settings.list)
  168. {
  169. loc.params.list = arguments.settings.list;
  170. loc.params.separator = chr(7);
  171. loc.params.value = $cleanInStatmentValue(loc.params.value);
  172. }
  173. if (!IsBinary(loc.params.value) && loc.params.value eq "null")
  174. {
  175. loc.params.useNull = true;
  176. }
  177. </cfscript>
  178. <cfreturn loc.params>
  179. </cffunction>
  180. <cffunction name="$performQuery" returntype="struct" access="public" output="false">
  181. <cfargument name="sql" type="array" required="true">
  182. <cfargument name="parameterize" type="boolean" required="true">
  183. <cfargument name="limit" type="numeric" required="false" default="0">
  184. <cfargument name="offset" type="numeric" required="false" default="0">
  185. <cfargument name="connection" type="struct" required="false" default="#variables.instance.connection#">
  186. <cfargument name="$primaryKey" type="string" required="false" default="">
  187. <cfscript>
  188. var loc = {};
  189. var query = {};
  190. loc.returnValue = {};
  191. loc.args = duplicate(arguments.connection);
  192. loc.args.result = "loc.result";
  193. loc.args.name = "query.name";
  194. if (StructKeyExists(loc.args, "username") && !Len(loc.args.username))
  195. {
  196. StructDelete(loc.args, "username", false);
  197. }
  198. if (StructKeyExists(loc.args, "password") && !Len(loc.args.password))
  199. {
  200. StructDelete(loc.args, "password", false);
  201. }
  202. // set queries in Railo to not preserve single quotes on the entire
  203. // cfquery block (we'll handle this individually in the SQL statement instead)
  204. if (application.wheels.serverName == "Railo")
  205. loc.args.psq = false;
  206. // overloaded arguments are settings for the query
  207. loc.orgArgs = duplicate(arguments);
  208. StructDelete(loc.orgArgs, "sql", false);
  209. StructDelete(loc.orgArgs, "parameterize", false);
  210. StructDelete(loc.orgArgs, "limit", false);
  211. StructDelete(loc.orgArgs, "offset", false);
  212. StructDelete(loc.orgArgs, "$primaryKey", false);
  213. StructAppend(loc.args, loc.orgArgs, true);
  214. </cfscript>
  215. <cfquery attributeCollection="#loc.args#"><cfloop array="#arguments.sql#" index="loc.i"><cfif IsStruct(loc.i)><cfset loc.queryParamAttributes = $CFQueryParameters(loc.i)><cfif StructKeyExists(loc.queryParamAttributes, "useNull")>NULL<cfelseif StructKeyExists(loc.queryParamAttributes, "list")><cfif arguments.parameterize>(<cfqueryparam attributeCollection="#loc.queryParamAttributes#">)<cfelse>(#PreserveSingleQuotes(loc.i.value)#)</cfif><cfelse><cfif arguments.parameterize><cfqueryparam attributeCollection="#loc.queryParamAttributes#"><cfelse>#$quoteValue(loc.i.value)#</cfif></cfif><cfelse><cfset loc.i = Replace(PreserveSingleQuotes(loc.i), "[[comma]]", ",", "all")>#PreserveSingleQuotes(loc.i)#</cfif>#chr(13)##chr(10)#</cfloop><cfif arguments.limit>LIMIT #arguments.limit#<cfif arguments.offset>#chr(13)##chr(10)#OFFSET #arguments.offset#</cfif></cfif></cfquery>
  216. <cfscript>
  217. if (StructKeyExists(query, "name"))
  218. loc.returnValue.query = query.name;
  219. // get/set the primary key value if necessary
  220. // will be done on insert statement involving auto-incremented primary keys when Railo/ACF cannot retrieve it for us
  221. // this happens on non-supported databases (example: H2) and drivers (example: jTDS)
  222. loc.$id = $identitySelect(queryAttributes=loc.args, result=loc.result, primaryKey=arguments.$primaryKey);
  223. if (StructKeyExists(loc, "$id"))
  224. StructAppend(loc.result, loc.$id);
  225. loc.returnValue.result = loc.result;
  226. </cfscript>
  227. <cfreturn loc.returnValue>
  228. </cffunction>
  229. <cffunction name="$getColumnInfo" returntype="query" access="public" output="false">
  230. <cfargument name="table" type="string" required="true">
  231. <cfargument name="datasource" type="string" required="true">
  232. <cfargument name="username" type="string" required="true">
  233. <cfargument name="password" type="string" required="true">
  234. <cfset arguments.type = "columns">
  235. <cfreturn $dbinfo(argumentCollection=arguments)>
  236. </cffunction>
  237. <cffunction name="$quoteValue" returntype="string" access="public" output="false">
  238. <cfargument name="str" type="string" required="true" hint="string to quote">
  239. <cfscript>
  240. if (!IsNumeric(arguments.str))
  241. {
  242. arguments.str = "'#arguments.str#'";
  243. }
  244. return arguments.str;
  245. </cfscript>
  246. </cffunction>
  247. <cffunction name="$tableAliasForJoin" returntype="string" access="public" output="false">
  248. <cfargument name="table" type="string" required="true">
  249. <cfargument name="alias" type="string" required="true">
  250. <cfreturn "#arguments.table# AS #arguments.alias#">
  251. </cffunction>
  252. <cfinclude template="../../plugins/injection.cfm">
  253. </cfcomponent>