Skip to content
This repository
Browse code

Work towards refactoring the code to make it more test-able.

Started refactoring tests to use Mocha + Sinon + Chai instead of Vows.
  • Loading branch information...
commit bb007a77f590058c7f0e6562f866b08ebdda45cc 1 parent 2c047e5
Ramesh Nair authored
97  docs/squel.html
@@ -80,60 +80,62 @@
80 80
             <span class="k">if</span> <span class="s">&quot;&quot;</span> <span class="o">isnt</span> <span class="nx">nodeStr</span></pre></div>             </td>           </tr>                               <tr id="section-17">             <td class="docs">               <div class="pilwrap">                 <a class="pilcrow" href="#section-17">&#182;</a>               </div>               <p>if this isn't first expression then add the operator</p>             </td>             <td class="code">               <div class="highlight"><pre>                <span class="k">if</span> <span class="s">&quot;&quot;</span> <span class="o">isnt</span> <span class="nx">str</span> <span class="k">then</span> <span class="nx">str</span> <span class="o">+=</span> <span class="s">&quot; &quot;</span> <span class="o">+</span> <span class="nx">child</span><span class="p">.</span><span class="nx">type</span> <span class="o">+</span> <span class="s">&quot; &quot;</span>
81 81
                 <span class="nx">str</span> <span class="o">+=</span> <span class="nx">nodeStr</span>
82 82
         <span class="nx">str</span></pre></div>             </td>           </tr>                               <tr id="section-18">             <td class="docs">               <div class="pilwrap">                 <a class="pilcrow" href="#section-18">&#182;</a>               </div>               <p>Default builder options.</p>             </td>             <td class="code">               <div class="highlight"><pre><span class="nv">DefaultInsertBuilderOptions = DefaultUpdateBuilderOptions =</span></pre></div>             </td>           </tr>                               <tr id="section-19">             <td class="docs">               <div class="pilwrap">                 <a class="pilcrow" href="#section-19">&#182;</a>               </div>               <p>If true then field values will not be rendered inside quotes so as to allow for field value placeholders (for
83  
-parameterized querying).</p>             </td>             <td class="code">               <div class="highlight"><pre>    <span class="nv">usingValuePlaceholders: </span><span class="kc">false</span></pre></div>             </td>           </tr>                               <tr id="section-20">             <td class="docs">               <div class="pilwrap">                 <a class="pilcrow" href="#section-20">&#182;</a>               </div>               <p>Get class name of given object.</p>             </td>             <td class="code">               <div class="highlight"><pre><span class="nv">getObjectClassName = </span><span class="nf">(obj) -&gt;</span>
  83
+parameterized querying).</p>             </td>             <td class="code">               <div class="highlight"><pre>    <span class="nv">usingValuePlaceholders: </span><span class="kc">false</span></pre></div>             </td>           </tr>                               <tr id="section-20">             <td class="docs">               <div class="pilwrap">                 <a class="pilcrow" href="#section-20">&#182;</a>               </div>               <p>Base class for all query builders</p>             </td>             <td class="code">               <div class="highlight"><pre><span class="k">class</span> <span class="nx">QueryBuilder</span></pre></div>             </td>           </tr>                               <tr id="section-21">             <td class="docs">               <div class="pilwrap">                 <a class="pilcrow" href="#section-21">&#182;</a>               </div>               <p>Get class name of given object.</p>             </td>             <td class="code">               <div class="highlight"><pre>  <span class="nv">_getObjectClassName: </span><span class="nf">(obj) -&gt;</span>
84 84
     <span class="k">if</span> <span class="nx">obj</span> <span class="o">&amp;&amp;</span> <span class="nx">obj</span><span class="p">.</span><span class="nx">constructor</span> <span class="o">&amp;&amp;</span> <span class="nx">obj</span><span class="p">.</span><span class="nx">constructor</span><span class="p">.</span><span class="nx">toString</span>
85  
-        <span class="nv">arr = </span><span class="nx">obj</span><span class="p">.</span><span class="nx">constructor</span><span class="p">.</span><span class="nx">toString</span><span class="p">().</span><span class="nx">match</span> <span class="sr">/function\s*(\w+)/</span><span class="p">;</span>
86  
-        <span class="k">if</span> <span class="nx">arr</span> <span class="o">&amp;&amp;</span> <span class="nx">arr</span><span class="p">.</span><span class="nx">length</span> <span class="o">is</span> <span class="mi">2</span>
87  
-            <span class="k">return</span> <span class="nx">arr</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
88  
-    <span class="k">return</span> <span class="kc">undefined</span></pre></div>             </td>           </tr>                               <tr id="section-21">             <td class="docs">               <div class="pilwrap">                 <a class="pilcrow" href="#section-21">&#182;</a>               </div>               <p>Sanitize the given condition.</p>             </td>             <td class="code">               <div class="highlight"><pre><span class="nv">ExpressionClassName = </span><span class="nx">getObjectClassName</span><span class="p">(</span><span class="k">new</span> <span class="nx">Expression</span><span class="p">())</span>
89  
-<span class="nv">sanitizeCondition = </span><span class="nf">(condition) -&gt;</span>
  85
+      <span class="nv">arr = </span><span class="nx">obj</span><span class="p">.</span><span class="nx">constructor</span><span class="p">.</span><span class="nx">toString</span><span class="p">().</span><span class="nx">match</span> <span class="sr">/function\s*(\w+)/</span><span class="p">;</span>
  86
+      <span class="k">if</span> <span class="nx">arr</span> <span class="o">&amp;&amp;</span> <span class="nx">arr</span><span class="p">.</span><span class="nx">length</span> <span class="o">is</span> <span class="mi">2</span>
  87
+        <span class="k">return</span> <span class="nx">arr</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
  88
+    <span class="k">return</span> <span class="kc">undefined</span></pre></div>             </td>           </tr>                               <tr id="section-22">             <td class="docs">               <div class="pilwrap">                 <a class="pilcrow" href="#section-22">&#182;</a>               </div>               <p>Sanitize the given condition.</p>             </td>             <td class="code">               <div class="highlight"><pre>  <span class="nv">_sanitizeCondition: </span><span class="nf">(condition) -&gt;</span>
90 89
     <span class="nv">t = </span><span class="k">typeof</span> <span class="nx">condition</span>
91  
-    <span class="k">if</span> <span class="nx">ExpressionClassName</span> <span class="o">isnt</span> <span class="nx">getObjectClassName</span><span class="p">(</span><span class="nx">condition</span><span class="p">)</span> <span class="o">and</span> <span class="s">&quot;string&quot;</span> <span class="o">isnt</span> <span class="nx">t</span>
92  
-        <span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span> <span class="s">&quot;condition must be a string or Expression instance&quot;</span></pre></div>             </td>           </tr>                               <tr id="section-22">             <td class="docs">               <div class="pilwrap">                 <a class="pilcrow" href="#section-22">&#182;</a>               </div>               <p>If it's an expression builder instance then convert it to string form.</p>             </td>             <td class="code">               <div class="highlight"><pre>    <span class="k">if</span> <span class="s">&quot;Expression&quot;</span> <span class="o">is</span> <span class="nx">t</span>
93  
-        <span class="nv">condition = </span><span class="nx">condition</span><span class="p">.</span><span class="nx">toString</span><span class="p">()</span>
94  
-    <span class="nx">condition</span></pre></div>             </td>           </tr>                               <tr id="section-23">             <td class="docs">               <div class="pilwrap">                 <a class="pilcrow" href="#section-23">&#182;</a>               </div>               <p>Sanitize the given name.
95  
-The 'type' parameter is used to construct a meaningful error message in case validation fails.</p>             </td>             <td class="code">               <div class="highlight"><pre><span class="nv">sanitizeName = </span><span class="nf">(value, type) -&gt;</span>
  90
+    <span class="nv">c = </span><span class="nx">@_getObjectClassName</span><span class="p">(</span><span class="nx">condition</span><span class="p">)</span>
  91
+
  92
+    <span class="k">if</span> <span class="s">&#39;Expression&#39;</span> <span class="o">isnt</span> <span class="nx">c</span> <span class="o">and</span> <span class="s">&quot;string&quot;</span> <span class="o">isnt</span> <span class="nx">t</span>
  93
+      <span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span> <span class="s">&quot;condition must be a string or Expression instance&quot;</span></pre></div>             </td>           </tr>                               <tr id="section-23">             <td class="docs">               <div class="pilwrap">                 <a class="pilcrow" href="#section-23">&#182;</a>               </div>               <p>If it's an expression builder instance then convert it to string form.</p>             </td>             <td class="code">               <div class="highlight"><pre>    <span class="k">if</span> <span class="s">&#39;Expression&#39;</span> <span class="o">is</span> <span class="nx">t</span> <span class="o">or</span> <span class="s">&#39;Expression&#39;</span> <span class="o">is</span> <span class="nx">c</span>
  94
+      <span class="nv">condition = </span><span class="nx">condition</span><span class="p">.</span><span class="nx">toString</span><span class="p">()</span>
  95
+    <span class="nx">condition</span></pre></div>             </td>           </tr>                               <tr id="section-24">             <td class="docs">               <div class="pilwrap">                 <a class="pilcrow" href="#section-24">&#182;</a>               </div>               <p>Sanitize the given name.
  96
+The 'type' parameter is used to construct a meaningful error message in case validation fails.</p>             </td>             <td class="code">               <div class="highlight"><pre>  <span class="nv">_sanitizeName: </span><span class="nf">(value, type) -&gt;</span>
96 97
     <span class="k">if</span> <span class="s">&quot;string&quot;</span> <span class="o">isnt</span> <span class="k">typeof</span> <span class="nx">value</span>
97  
-        <span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span> <span class="s">&quot;</span><span class="si">#{</span><span class="nx">type</span><span class="si">}</span><span class="s"> must be a string&quot;</span>
  98
+      <span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span> <span class="s">&quot;</span><span class="si">#{</span><span class="nx">type</span><span class="si">}</span><span class="s"> must be a string&quot;</span>
98 99
     <span class="nx">value</span>
99 100
 
100  
-<span class="nv">sanitizeField = </span><span class="nf">(item) -&gt;</span> <span class="nx">sanitizeName</span> <span class="nx">item</span><span class="p">,</span> <span class="s">&quot;field name&quot;</span>
101  
-<span class="nv">sanitizeTable = </span><span class="nf">(item) -&gt;</span> <span class="nx">sanitizeName</span> <span class="nx">item</span><span class="p">,</span> <span class="s">&quot;table name&quot;</span>
102  
-<span class="nv">sanitizeAlias = </span><span class="nf">(item) -&gt;</span> <span class="nx">sanitizeName</span> <span class="nx">item</span><span class="p">,</span> <span class="s">&quot;alias&quot;</span></pre></div>             </td>           </tr>                               <tr id="section-24">             <td class="docs">               <div class="pilwrap">                 <a class="pilcrow" href="#section-24">&#182;</a>               </div>               <p>Sanitize the given limit/offset value.</p>             </td>             <td class="code">               <div class="highlight"><pre><span class="nv">sanitizeLimitOffset = </span><span class="nf">(value) -&gt;</span>
  101
+  <span class="nv">_sanitizeField: </span><span class="nf">(item) -&gt;</span> <span class="nx">@_sanitizeName</span> <span class="nx">item</span><span class="p">,</span> <span class="s">&quot;field name&quot;</span>
  102
+  <span class="nv">_sanitizeTable: </span><span class="nf">(item) -&gt;</span> <span class="nx">@_sanitizeName</span> <span class="nx">item</span><span class="p">,</span> <span class="s">&quot;table name&quot;</span>
  103
+  <span class="nv">_sanitizeAlias: </span><span class="nf">(item) -&gt;</span> <span class="nx">@_sanitizeName</span> <span class="nx">item</span><span class="p">,</span> <span class="s">&quot;alias&quot;</span></pre></div>             </td>           </tr>                               <tr id="section-25">             <td class="docs">               <div class="pilwrap">                 <a class="pilcrow" href="#section-25">&#182;</a>               </div>               <p>Sanitize the given limit/offset value.</p>             </td>             <td class="code">               <div class="highlight"><pre>  <span class="nv">_sanitizeLimitOffset: </span><span class="nf">(value) -&gt;</span>
103 104
     <span class="nv">value = </span><span class="nb">parseInt</span><span class="p">(</span><span class="nx">value</span><span class="p">)</span>
104 105
     <span class="k">if</span> <span class="mi">0</span> <span class="o">&gt;</span> <span class="nx">value</span>
105  
-        <span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span> <span class="s">&quot;limit/offset must be &gt;=0&quot;</span>
106  
-    <span class="nx">value</span></pre></div>             </td>           </tr>                               <tr id="section-25">             <td class="docs">               <div class="pilwrap">                 <a class="pilcrow" href="#section-25">&#182;</a>               </div>               <p>Santize the given field value</p>             </td>             <td class="code">               <div class="highlight"><pre><span class="nv">sanitizeValue = </span><span class="nf">(item) -&gt;</span>
  106
+      <span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span> <span class="s">&quot;limit/offset must be &gt;=0&quot;</span>
  107
+    <span class="nx">value</span></pre></div>             </td>           </tr>                               <tr id="section-26">             <td class="docs">               <div class="pilwrap">                 <a class="pilcrow" href="#section-26">&#182;</a>               </div>               <p>Santize the given field value</p>             </td>             <td class="code">               <div class="highlight"><pre>  <span class="nv">_sanitizeValue: </span><span class="nf">(item) -&gt;</span>
107 108
     <span class="nv">t = </span><span class="k">typeof</span> <span class="nx">item</span>
108 109
     <span class="k">if</span> <span class="kc">null</span> <span class="o">isnt</span> <span class="nx">item</span> <span class="o">and</span> <span class="s">&quot;string&quot;</span> <span class="o">isnt</span> <span class="nx">t</span> <span class="o">and</span> <span class="s">&quot;number&quot;</span> <span class="o">isnt</span> <span class="nx">t</span> <span class="o">and</span> <span class="s">&quot;boolean&quot;</span> <span class="o">isnt</span> <span class="nx">t</span>
109  
-        <span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span> <span class="s">&quot;field value must be a string, number, boolean or null&quot;</span>
110  
-    <span class="nx">item</span></pre></div>             </td>           </tr>                               <tr id="section-26">             <td class="docs">               <div class="pilwrap">                 <a class="pilcrow" href="#section-26">&#182;</a>               </div>               <p>Format the given field value for inclusion into the query string</p>
  110
+      <span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span> <span class="s">&quot;field value must be a string, number, boolean or null&quot;</span>
  111
+    <span class="nx">item</span></pre></div>             </td>           </tr>                               <tr id="section-27">             <td class="docs">               <div class="pilwrap">                 <a class="pilcrow" href="#section-27">&#182;</a>               </div>               <p>Format the given field value for inclusion into the query string</p>
111 112
 
112  
-<p>options: see DefaultBuilderOptions</p>             </td>             <td class="code">               <div class="highlight"><pre><span class="nv">formatValue = </span><span class="nf">(value, options) -&gt;</span>
  113
+<p>options: see DefaultBuilderOptions</p>             </td>             <td class="code">               <div class="highlight"><pre>  <span class="nv">_formatValue: </span><span class="nf">(value, options) -&gt;</span>
113 114
     <span class="k">if</span> <span class="kc">null</span> <span class="o">is</span> <span class="nx">value</span>
114  
-        <span class="nv">value = </span><span class="s">&quot;NULL&quot;</span>
  115
+      <span class="nv">value = </span><span class="s">&quot;NULL&quot;</span>
115 116
     <span class="k">else</span> <span class="k">if</span> <span class="s">&quot;boolean&quot;</span> <span class="o">is</span> <span class="k">typeof</span> <span class="nx">value</span>
116  
-        <span class="nv">value = </span><span class="k">if</span> <span class="nx">value</span> <span class="k">then</span> <span class="s">&quot;TRUE&quot;</span> <span class="k">else</span> <span class="s">&quot;FALSE&quot;</span>
  117
+      <span class="nv">value = </span><span class="k">if</span> <span class="nx">value</span> <span class="k">then</span> <span class="s">&quot;TRUE&quot;</span> <span class="k">else</span> <span class="s">&quot;FALSE&quot;</span>
117 118
     <span class="k">else</span> <span class="k">if</span> <span class="s">&quot;number&quot;</span> <span class="o">isnt</span> <span class="k">typeof</span> <span class="nx">value</span>
118  
-        <span class="k">if</span> <span class="kc">false</span> <span class="o">is</span> <span class="nx">options</span><span class="p">.</span><span class="nx">usingValuePlaceholders</span>
119  
-            <span class="nv">value = </span><span class="s">&quot;&#39;</span><span class="si">#{</span><span class="nx">value</span><span class="si">}</span><span class="s">&#39;&quot;</span>
120  
-    <span class="nx">value</span></pre></div>             </td>           </tr>                               <tr id="section-27">             <td class="docs">               <div class="pilwrap">                 <a class="pilcrow" href="#section-27">&#182;</a>               </div>               <p>Base class for all query builders</p>             </td>             <td class="code">               <div class="highlight"><pre><span class="k">class</span> <span class="nx">QueryBuilder</span></pre></div>             </td>           </tr>                               <tr id="section-28">             <td class="docs">               <div class="pilwrap">                 <a class="pilcrow" href="#section-28">&#182;</a>               </div>               <p>Base class for query builders which support WHERE, ORDER and LIMIT clauses.</p>             </td>             <td class="code">               <div class="highlight"><pre><span class="k">class</span> <span class="nx">WhereOrderLimit</span> <span class="k">extends</span> <span class="nx">QueryBuilder</span>
  119
+      <span class="k">if</span> <span class="o">not</span> <span class="nx">options</span> <span class="o">or</span> <span class="kc">false</span> <span class="o">is</span> <span class="nx">options</span><span class="p">.</span><span class="nx">usingValuePlaceholders</span>
  120
+        <span class="nv">value = </span><span class="s">&quot;&#39;</span><span class="si">#{</span><span class="nx">value</span><span class="si">}</span><span class="s">&#39;&quot;</span>
  121
+    <span class="nx">value</span></pre></div>             </td>           </tr>                               <tr id="section-28">             <td class="docs">               <div class="pilwrap">                 <a class="pilcrow" href="#section-28">&#182;</a>               </div>               <p>Base class for query builders which support WHERE, ORDER and LIMIT clauses.</p>             </td>             <td class="code">               <div class="highlight"><pre><span class="k">class</span> <span class="nx">WhereOrderLimit</span> <span class="k">extends</span> <span class="nx">QueryBuilder</span>
121 122
     <span class="nv">wheres: </span><span class="kc">null</span>
122 123
     <span class="nv">orders: </span><span class="kc">null</span>
123 124
     <span class="nv">limits: </span><span class="kc">null</span>
124 125
 
125 126
     <span class="nv">constructor: </span><span class="o">-&gt;</span>
  127
+        <span class="k">super</span>
126 128
         <span class="vi">@wheres = </span><span class="p">[]</span>
127 129
         <span class="vi">@orders = </span><span class="p">[]</span></pre></div>             </td>           </tr>                               <tr id="section-29">             <td class="docs">               <div class="pilwrap">                 <a class="pilcrow" href="#section-29">&#182;</a>               </div>               <p>Add a WHERE condition.</p>
128 130
 
129 131
 <p>When the final query is constructed all the WHERE conditions are combined using the intersection (AND) operator.</p>             </td>             <td class="code">               <div class="highlight"><pre>    <span class="nv">where: </span><span class="p">(</span><span class="nx">condition</span><span class="p">)</span> <span class="o">=&gt;</span>
130  
-        <span class="nv">condition = </span><span class="nx">sanitizeCondition</span><span class="p">(</span><span class="nx">condition</span><span class="p">)</span>
  132
+        <span class="nv">condition = </span><span class="nx">@_sanitizeCondition</span><span class="p">(</span><span class="nx">condition</span><span class="p">)</span>
131 133
         <span class="k">if</span> <span class="s">&quot;&quot;</span> <span class="o">isnt</span> <span class="nx">condition</span>
132 134
             <span class="nx">@wheres</span><span class="p">.</span><span class="nx">push</span> <span class="nx">condition</span>
133 135
         <span class="nx">@</span></pre></div>             </td>           </tr>                               <tr id="section-30">             <td class="docs">               <div class="pilwrap">                 <a class="pilcrow" href="#section-30">&#182;</a>               </div>               <p>Add an ORDER BY transformation for the given field in the given order.</p>
134 136
 
135 137
 <p>To specify descending order pass false for the 'asc' parameter.</p>             </td>             <td class="code">               <div class="highlight"><pre>    <span class="nv">order: </span><span class="p">(</span><span class="nx">field</span><span class="p">,</span> <span class="nv">asc = </span><span class="kc">true</span><span class="p">)</span> <span class="o">=&gt;</span>
136  
-        <span class="nv">field = </span><span class="nx">sanitizeField</span> <span class="nx">field</span>
  138
+        <span class="nv">field = </span><span class="nx">@_sanitizeField</span><span class="p">(</span><span class="nx">field</span><span class="p">)</span>
137 139
         <span class="nx">@orders</span><span class="p">.</span><span class="nx">push</span>
138 140
             <span class="nv">field: </span><span class="nx">field</span>
139 141
             <span class="nv">dir: </span><span class="k">if</span> <span class="nx">asc</span> <span class="k">then</span> <span class="s">&quot;ASC&quot;</span> <span class="k">else</span> <span class="s">&quot;DESC&quot;</span>
@@ -141,7 +143,7 @@
141 143
 
142 144
 <p>Call this will override the previously set limit for this query. Also note that Passing 0 for 'max' will remove
143 145
 the limit.</p>             </td>             <td class="code">               <div class="highlight"><pre>    <span class="nv">limit: </span><span class="p">(</span><span class="nx">max</span><span class="p">)</span> <span class="o">=&gt;</span>
144  
-        <span class="nv">max = </span><span class="nx">sanitizeLimitOffset</span> <span class="nx">max</span>
  146
+        <span class="nv">max = </span><span class="nx">@_sanitizeLimitOffset</span><span class="p">(</span><span class="nx">max</span><span class="p">)</span>
145 147
         <span class="vi">@limits = </span><span class="nx">max</span>
146 148
         <span class="nx">@</span></pre></div>             </td>           </tr>                               <tr id="section-32">             <td class="docs">               <div class="pilwrap">                 <a class="pilcrow" href="#section-32">&#182;</a>               </div>               <p>Get string representation of WHERE clause, if any</p>             </td>             <td class="code">               <div class="highlight"><pre>    <span class="nv">whereString: </span><span class="o">=&gt;</span>
147 149
         <span class="k">if</span> <span class="mi">0</span> <span class="o">&lt;</span> <span class="nx">@wheres</span><span class="p">.</span><span class="nx">length</span>
@@ -174,9 +176,9 @@
174 176
 <p>'condition' is an optional condition (containing an SQL expression) for the JOIN. If this is an instance of
175 177
 an expression builder then it will only get evaluated during the final query string construction phase in
176 178
 toString().</p>             </td>             <td class="code">               <div class="highlight"><pre>    <span class="vi">@_join = </span><span class="p">(</span><span class="nx">type</span><span class="p">,</span> <span class="nx">table</span><span class="p">,</span> <span class="nx">alias</span><span class="p">,</span> <span class="nx">condition</span><span class="p">)</span> <span class="o">=&gt;</span>
177  
-      <span class="nv">table = </span><span class="nx">sanitizeTable</span><span class="p">(</span><span class="nx">table</span><span class="p">)</span>
178  
-      <span class="nv">alias = </span><span class="nx">sanitizeAlias</span><span class="p">(</span><span class="nx">alias</span><span class="p">)</span> <span class="k">if</span> <span class="nx">alias</span>
179  
-      <span class="nv">condition = </span><span class="nx">sanitizeCondition</span><span class="p">(</span><span class="nx">condition</span><span class="p">)</span> <span class="k">if</span> <span class="nx">condition</span>
  179
+      <span class="nv">table = </span><span class="nx">@_sanitizeTable</span><span class="p">(</span><span class="nx">table</span><span class="p">)</span>
  180
+      <span class="nv">alias = </span><span class="nx">@_sanitizeAlias</span><span class="p">(</span><span class="nx">alias</span><span class="p">)</span> <span class="k">if</span> <span class="nx">alias</span>
  181
+      <span class="nv">condition = </span><span class="nx">@_sanitizeCondition</span><span class="p">(</span><span class="nx">condition</span><span class="p">)</span> <span class="k">if</span> <span class="nx">condition</span>
180 182
 
181 183
       <span class="nx">@joins</span><span class="p">.</span><span class="nx">push</span>
182 184
         <span class="nv">type: </span><span class="nx">type</span>
@@ -216,8 +218,8 @@
216 218
         <span class="nx">@</span></pre></div>             </td>           </tr>                               <tr id="section-44">             <td class="docs">               <div class="pilwrap">                 <a class="pilcrow" href="#section-44">&#182;</a>               </div>               <p>Read data from the given table.</p>
217 219
 
218 220
 <p>An alias may also be specified for the table.</p>             </td>             <td class="code">               <div class="highlight"><pre>    <span class="nv">from: </span><span class="p">(</span><span class="nx">table</span><span class="p">,</span> <span class="nv">alias = </span><span class="kc">null</span><span class="p">)</span> <span class="o">=&gt;</span>
219  
-        <span class="nv">table = </span><span class="nx">sanitizeTable</span><span class="p">(</span><span class="nx">table</span><span class="p">)</span>
220  
-        <span class="nv">alias = </span><span class="nx">sanitizeAlias</span><span class="p">(</span><span class="nx">alias</span><span class="p">)</span> <span class="k">if</span> <span class="nx">alias</span>
  221
+        <span class="nv">table = </span><span class="nx">@_sanitizeTable</span><span class="p">(</span><span class="nx">table</span><span class="p">)</span>
  222
+        <span class="nv">alias = </span><span class="nx">@_sanitizeAlias</span><span class="p">(</span><span class="nx">alias</span><span class="p">)</span> <span class="k">if</span> <span class="nx">alias</span>
221 223
 
222 224
         <span class="nx">@froms</span><span class="p">.</span><span class="nx">push</span>
223 225
             <span class="nv">name: </span><span class="nx">table</span>
@@ -228,20 +230,20 @@
228 230
 e.g. DATE_FORMAT(a.started, "%H")</p>
229 231
 
230 232
 <p>An alias may also be specified for this field.</p>             </td>             <td class="code">               <div class="highlight"><pre>    <span class="nv">field: </span><span class="p">(</span><span class="nx">field</span><span class="p">,</span> <span class="nv">alias = </span><span class="kc">null</span><span class="p">)</span> <span class="o">=&gt;</span>
231  
-        <span class="nv">field = </span><span class="nx">sanitizeField</span><span class="p">(</span><span class="nx">field</span><span class="p">)</span>
232  
-        <span class="nv">alias = </span><span class="nx">sanitizeAlias</span><span class="p">(</span><span class="nx">alias</span><span class="p">)</span> <span class="k">if</span> <span class="nx">alias</span>
  233
+        <span class="nv">field = </span><span class="nx">@_sanitizeField</span><span class="p">(</span><span class="nx">field</span><span class="p">)</span>
  234
+        <span class="nv">alias = </span><span class="nx">@_sanitizeAlias</span><span class="p">(</span><span class="nx">alias</span><span class="p">)</span> <span class="k">if</span> <span class="nx">alias</span>
233 235
 
234 236
         <span class="nx">@fields</span><span class="p">.</span><span class="nx">push</span>
235 237
             <span class="nv">field: </span><span class="nx">field</span>
236 238
             <span class="nv">alias: </span><span class="nx">alias</span>
237 239
         <span class="nx">@</span></pre></div>             </td>           </tr>                               <tr id="section-46">             <td class="docs">               <div class="pilwrap">                 <a class="pilcrow" href="#section-46">&#182;</a>               </div>               <p>Add a GROUP BY transformation for the given field.</p>             </td>             <td class="code">               <div class="highlight"><pre>    <span class="nv">group: </span><span class="p">(</span><span class="nx">field</span><span class="p">)</span> <span class="o">=&gt;</span>
238  
-        <span class="nv">field = </span><span class="nx">sanitizeField</span> <span class="nx">field</span>
  240
+        <span class="nv">field = </span><span class="nx">@_sanitizeField</span><span class="p">(</span><span class="nx">field</span><span class="p">)</span>
239 241
         <span class="nx">@groups</span><span class="p">.</span><span class="nx">push</span> <span class="nx">field</span>
240 242
         <span class="nx">@</span></pre></div>             </td>           </tr>                               <tr id="section-47">             <td class="docs">               <div class="pilwrap">                 <a class="pilcrow" href="#section-47">&#182;</a>               </div>               <p>Set the OFFSET transformation.</p>
241 243
 
242 244
 <p>Call this will override the previously set offset for this query. Also note that Passing 0 for 'max' will remove
243 245
 the offset.</p>             </td>             <td class="code">               <div class="highlight"><pre>    <span class="nv">offset: </span><span class="p">(</span><span class="nx">start</span><span class="p">)</span> <span class="o">=&gt;</span>
244  
-        <span class="nv">start = </span><span class="nx">sanitizeLimitOffset</span> <span class="nx">start</span>
  246
+        <span class="nv">start = </span><span class="nx">@_sanitizeLimitOffset</span><span class="p">(</span><span class="nx">start</span><span class="p">)</span>
245 247
         <span class="vi">@offsets = </span><span class="nx">start</span>
246 248
         <span class="nx">@</span></pre></div>             </td>           </tr>                               <tr id="section-48">             <td class="docs">               <div class="pilwrap">                 <a class="pilcrow" href="#section-48">&#182;</a>               </div>               <p>Get the final fully constructed query string.</p>             </td>             <td class="code">               <div class="highlight"><pre>    <span class="nv">toString: </span><span class="o">=&gt;</span></pre></div>             </td>           </tr>                               <tr id="section-49">             <td class="docs">               <div class="pilwrap">                 <a class="pilcrow" href="#section-49">&#182;</a>               </div>               <p>basic checks</p>             </td>             <td class="code">               <div class="highlight"><pre>        <span class="k">if</span> <span class="mi">0</span> <span class="o">&gt;=</span> <span class="nx">@froms</span><span class="p">.</span><span class="nx">length</span>
247 249
             <span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span> <span class="s">&quot;from() needs to be called&quot;</span>
@@ -279,16 +281,16 @@
279 281
         <span class="vi">@options = </span><span class="nx">_extend</span> <span class="p">{},</span> <span class="nx">DefaultUpdateBuilderOptions</span><span class="p">,</span> <span class="nx">options</span></pre></div>             </td>           </tr>                               <tr id="section-61">             <td class="docs">               <div class="pilwrap">                 <a class="pilcrow" href="#section-61">&#182;</a>               </div>               <p>Update the given table.</p>
280 282
 
281 283
 <p>An alias may also be specified for the table.</p>             </td>             <td class="code">               <div class="highlight"><pre>    <span class="nv">table: </span><span class="p">(</span><span class="nx">table</span><span class="p">,</span> <span class="nv">alias = </span><span class="kc">null</span><span class="p">)</span> <span class="o">=&gt;</span>
282  
-        <span class="nv">table = </span><span class="nx">sanitizeTable</span><span class="p">(</span><span class="nx">table</span><span class="p">)</span>
283  
-        <span class="nv">alias = </span><span class="nx">sanitizeAlias</span><span class="p">(</span><span class="nx">alias</span><span class="p">)</span> <span class="k">if</span> <span class="nx">alias</span>
  284
+        <span class="nv">table = </span><span class="nx">@_sanitizeTable</span><span class="p">(</span><span class="nx">table</span><span class="p">)</span>
  285
+        <span class="nv">alias = </span><span class="nx">@_sanitizeAlias</span><span class="p">(</span><span class="nx">alias</span><span class="p">)</span> <span class="k">if</span> <span class="nx">alias</span>
284 286
 
285 287
         <span class="nx">@tables</span><span class="p">.</span><span class="nx">push</span>
286 288
             <span class="nv">name: </span><span class="nx">table</span>
287 289
             <span class="nv">alias: </span><span class="nx">alias</span>
288 290
         <span class="nx">@</span></pre></div>             </td>           </tr>                               <tr id="section-62">             <td class="docs">               <div class="pilwrap">                 <a class="pilcrow" href="#section-62">&#182;</a>               </div>               <p>Update the given field with the given value.
289 291
 This will override any previously set value for the given field.</p>             </td>             <td class="code">               <div class="highlight"><pre>    <span class="nv">set: </span><span class="p">(</span><span class="nx">field</span><span class="p">,</span> <span class="nx">value</span><span class="p">)</span> <span class="o">=&gt;</span>
290  
-        <span class="nv">field = </span><span class="nx">sanitizeField</span> <span class="nx">field</span>
291  
-        <span class="nv">value = </span><span class="nx">sanitizeValue</span> <span class="nx">value</span>
  292
+        <span class="nv">field = </span><span class="nx">@_sanitizeField</span><span class="p">(</span><span class="nx">field</span><span class="p">)</span>
  293
+        <span class="nv">value = </span><span class="nx">@_sanitizeValue</span><span class="p">(</span><span class="nx">value</span><span class="p">)</span>
292 294
         <span class="nx">@fields</span><span class="p">[</span><span class="nx">field</span><span class="p">]</span> <span class="o">=</span> <span class="nx">value</span>
293 295
         <span class="nx">@</span></pre></div>             </td>           </tr>                               <tr id="section-63">             <td class="docs">               <div class="pilwrap">                 <a class="pilcrow" href="#section-63">&#182;</a>               </div>               <p>Get the final fully constructed query string.</p>             </td>             <td class="code">               <div class="highlight"><pre>    <span class="nv">toString: </span><span class="o">=&gt;</span></pre></div>             </td>           </tr>                               <tr id="section-64">             <td class="docs">               <div class="pilwrap">                 <a class="pilcrow" href="#section-64">&#182;</a>               </div>               <p>basic checks</p>             </td>             <td class="code">               <div class="highlight"><pre>        <span class="k">if</span> <span class="mi">0</span> <span class="o">&gt;=</span> <span class="nx">@tables</span><span class="p">.</span><span class="nx">length</span> <span class="k">then</span> <span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span> <span class="s">&quot;table() needs to be called&quot;</span>
294 296
         <span class="nv">fieldNames = </span><span class="p">(</span><span class="nx">field</span> <span class="k">for</span> <span class="nx">own</span> <span class="nx">field</span> <span class="k">of</span> <span class="nx">@fields</span><span class="p">)</span>
@@ -303,7 +305,7 @@
303 305
         <span class="nx">ret</span> <span class="o">+=</span> <span class="nx">tables</span></pre></div>             </td>           </tr>                               <tr id="section-66">             <td class="docs">               <div class="pilwrap">                 <a class="pilcrow" href="#section-66">&#182;</a>               </div>               <p>fields</p>             </td>             <td class="code">               <div class="highlight"><pre>        <span class="nv">fields = </span><span class="s">&quot;&quot;</span>
304 306
         <span class="k">for</span> <span class="nx">field</span> <span class="k">in</span> <span class="nx">fieldNames</span>
305 307
             <span class="nx">fields</span> <span class="o">+=</span> <span class="s">&quot;, &quot;</span> <span class="k">if</span> <span class="s">&quot;&quot;</span> <span class="o">isnt</span> <span class="nx">fields</span>
306  
-            <span class="nx">fields</span> <span class="o">+=</span> <span class="s">&quot;</span><span class="si">#{</span><span class="nx">field</span><span class="si">}</span><span class="s"> = </span><span class="si">#{</span><span class="nx">formatValue</span><span class="p">(</span><span class="nx">@fields</span><span class="p">[</span><span class="nx">field</span><span class="p">],</span> <span class="nx">@options</span><span class="p">)</span><span class="si">}</span><span class="s">&quot;</span>
  308
+            <span class="nx">fields</span> <span class="o">+=</span> <span class="s">&quot;</span><span class="si">#{</span><span class="nx">field</span><span class="si">}</span><span class="s"> = </span><span class="si">#{</span><span class="nx">@_formatValue</span><span class="p">(</span><span class="nx">@fields</span><span class="p">[</span><span class="nx">field</span><span class="p">],</span> <span class="nx">@options</span><span class="p">)</span><span class="si">}</span><span class="s">&quot;</span>
307 309
         <span class="nx">ret</span> <span class="o">+=</span> <span class="s">&quot; SET </span><span class="si">#{</span><span class="nx">fields</span><span class="si">}</span><span class="s">&quot;</span></pre></div>             </td>           </tr>                               <tr id="section-67">             <td class="docs">               <div class="pilwrap">                 <a class="pilcrow" href="#section-67">&#182;</a>               </div>               <p>where</p>             </td>             <td class="code">               <div class="highlight"><pre>        <span class="nx">ret</span> <span class="o">+=</span> <span class="nx">@whereString</span><span class="p">()</span></pre></div>             </td>           </tr>                               <tr id="section-68">             <td class="docs">               <div class="pilwrap">                 <a class="pilcrow" href="#section-68">&#182;</a>               </div>               <p>order by</p>             </td>             <td class="code">               <div class="highlight"><pre>        <span class="nx">ret</span> <span class="o">+=</span> <span class="nx">@orderString</span><span class="p">()</span></pre></div>             </td>           </tr>                               <tr id="section-69">             <td class="docs">               <div class="pilwrap">                 <a class="pilcrow" href="#section-69">&#182;</a>               </div>               <p>limit</p>             </td>             <td class="code">               <div class="highlight"><pre>        <span class="nx">ret</span> <span class="o">+=</span> <span class="nx">@limitString</span><span class="p">()</span>
308 310
 
309 311
         <span class="nx">ret</span></pre></div>             </td>           </tr>                               <tr id="section-70">             <td class="docs">               <div class="pilwrap">                 <a class="pilcrow" href="#section-70">&#182;</a>               </div>               <p>A DELETE query builder.</p>
@@ -313,7 +315,7 @@
313 315
 <p>All the build methods in this object return the object instance for chained method calling purposes.</p>             </td>             <td class="code">               <div class="highlight"><pre><span class="k">class</span> <span class="nx">Delete</span> <span class="k">extends</span> <span class="nx">JoinWhereOrderLimit</span>
314 316
     <span class="nv">table: </span><span class="kc">null</span></pre></div>             </td>           </tr>                               <tr id="section-71">             <td class="docs">               <div class="pilwrap">                 <a class="pilcrow" href="#section-71">&#182;</a>               </div>               <p>The table to delete from.
315 317
 Calling this will override any previously set value.</p>             </td>             <td class="code">               <div class="highlight"><pre>    <span class="nv">from: </span><span class="p">(</span><span class="nx">table</span><span class="p">)</span> <span class="o">=&gt;</span>
316  
-        <span class="nv">table = </span><span class="nx">sanitizeTable</span><span class="p">(</span><span class="nx">table</span><span class="p">)</span>
  318
+        <span class="nv">table = </span><span class="nx">@_sanitizeTable</span><span class="p">(</span><span class="nx">table</span><span class="p">)</span>
317 319
         <span class="vi">@table = </span><span class="nx">table</span>
318 320
         <span class="nx">@</span></pre></div>             </td>           </tr>                               <tr id="section-72">             <td class="docs">               <div class="pilwrap">                 <a class="pilcrow" href="#section-72">&#182;</a>               </div>               <p>Get the final fully constructed query string.</p>             </td>             <td class="code">               <div class="highlight"><pre>    <span class="nv">toString: </span><span class="o">=&gt;</span></pre></div>             </td>           </tr>                               <tr id="section-73">             <td class="docs">               <div class="pilwrap">                 <a class="pilcrow" href="#section-73">&#182;</a>               </div>               <p>basic checks</p>             </td>             <td class="code">               <div class="highlight"><pre>        <span class="k">if</span> <span class="o">not</span> <span class="nx">@table</span> <span class="k">then</span> <span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span> <span class="s">&quot;from() needs to be called&quot;</span>
319 321
 
@@ -327,15 +329,16 @@
327 329
     <span class="nv">table: </span><span class="kc">null</span>
328 330
     <span class="nv">fields: </span><span class="kc">null</span>
329 331
     <span class="nv">options: </span><span class="kc">null</span></pre></div>             </td>           </tr>                               <tr id="section-79">             <td class="docs">               <div class="pilwrap">                 <a class="pilcrow" href="#section-79">&#182;</a>               </div>               <p>options: see DefaultBuilderOptions</p>             </td>             <td class="code">               <div class="highlight"><pre>    <span class="nv">constructor: </span><span class="nf">(options) -&gt;</span>
  332
+        <span class="k">super</span>
330 333
         <span class="vi">@fields = </span><span class="p">{}</span>
331 334
         <span class="vi">@options = </span><span class="nx">_extend</span> <span class="p">{},</span> <span class="nx">DefaultInsertBuilderOptions</span><span class="p">,</span> <span class="nx">options</span></pre></div>             </td>           </tr>                               <tr id="section-80">             <td class="docs">               <div class="pilwrap">                 <a class="pilcrow" href="#section-80">&#182;</a>               </div>               <p>The table to insert into.
332 335
 This will override any previously set value.</p>             </td>             <td class="code">               <div class="highlight"><pre>    <span class="nv">into: </span><span class="p">(</span><span class="nx">table</span><span class="p">)</span> <span class="o">=&gt;</span>
333  
-        <span class="nv">table = </span><span class="nx">sanitizeTable</span><span class="p">(</span><span class="nx">table</span><span class="p">)</span>
  336
+        <span class="nv">table = </span><span class="nx">@_sanitizeTable</span><span class="p">(</span><span class="nx">table</span><span class="p">)</span>
334 337
         <span class="vi">@table = </span><span class="nx">table</span>
335 338
         <span class="nx">@</span></pre></div>             </td>           </tr>                               <tr id="section-81">             <td class="docs">               <div class="pilwrap">                 <a class="pilcrow" href="#section-81">&#182;</a>               </div>               <p>Set the given field to the given value.
336 339
 This will override any previously set value for the given field.</p>             </td>             <td class="code">               <div class="highlight"><pre>    <span class="nv">set: </span><span class="p">(</span><span class="nx">field</span><span class="p">,</span> <span class="nx">value</span><span class="p">)</span> <span class="o">=&gt;</span>
337  
-        <span class="nv">field = </span><span class="nx">sanitizeField</span> <span class="nx">field</span>
338  
-        <span class="nv">value = </span><span class="nx">sanitizeValue</span> <span class="nx">value</span>
  340
+        <span class="nv">field = </span><span class="nx">@_sanitizeField</span><span class="p">(</span><span class="nx">field</span><span class="p">)</span>
  341
+        <span class="nv">value = </span><span class="nx">@_sanitizeValue</span><span class="p">(</span><span class="nx">value</span><span class="p">)</span>
339 342
         <span class="nx">@fields</span><span class="p">[</span><span class="nx">field</span><span class="p">]</span> <span class="o">=</span> <span class="nx">value</span>
340 343
         <span class="nx">@</span></pre></div>             </td>           </tr>                               <tr id="section-82">             <td class="docs">               <div class="pilwrap">                 <a class="pilcrow" href="#section-82">&#182;</a>               </div>               <p>Get the final fully constructed query string.</p>             </td>             <td class="code">               <div class="highlight"><pre>    <span class="nv">toString: </span><span class="o">=&gt;</span></pre></div>             </td>           </tr>                               <tr id="section-83">             <td class="docs">               <div class="pilwrap">                 <a class="pilcrow" href="#section-83">&#182;</a>               </div>               <p>basic checks</p>             </td>             <td class="code">               <div class="highlight"><pre>        <span class="k">if</span> <span class="o">not</span> <span class="nx">@table</span> <span class="k">then</span> <span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span> <span class="s">&quot;into() needs to be called&quot;</span>
341 344
         <span class="nv">fieldNames = </span><span class="p">(</span><span class="nx">name</span> <span class="k">for</span> <span class="nx">own</span> <span class="nx">name</span> <span class="k">of</span> <span class="nx">@fields</span><span class="p">)</span>
@@ -345,7 +348,7 @@
345 348
             <span class="nx">fields</span> <span class="o">+=</span> <span class="s">&quot;, &quot;</span> <span class="k">if</span> <span class="s">&quot;&quot;</span> <span class="o">isnt</span> <span class="nx">fields</span>
346 349
             <span class="nx">fields</span> <span class="o">+=</span> <span class="nx">field</span>
347 350
             <span class="nx">values</span> <span class="o">+=</span> <span class="s">&quot;, &quot;</span> <span class="k">if</span> <span class="s">&quot;&quot;</span> <span class="o">isnt</span> <span class="nx">values</span>
348  
-            <span class="nx">values</span> <span class="o">+=</span> <span class="nx">formatValue</span><span class="p">(</span><span class="nx">@fields</span><span class="p">[</span><span class="nx">field</span><span class="p">],</span> <span class="nx">@options</span><span class="p">)</span>
  351
+            <span class="nx">values</span> <span class="o">+=</span> <span class="nx">@_formatValue</span><span class="p">(</span><span class="nx">@fields</span><span class="p">[</span><span class="nx">field</span><span class="p">],</span> <span class="nx">@options</span><span class="p">)</span>
349 352
 
350 353
         <span class="s">&quot;INSERT INTO </span><span class="si">#{</span><span class="nx">@table</span><span class="si">}</span><span class="s"> (</span><span class="si">#{</span><span class="nx">fields</span><span class="si">}</span><span class="s">) VALUES (</span><span class="si">#{</span><span class="nx">values</span><span class="si">}</span><span class="s">)&quot;</span></pre></div>             </td>           </tr>                               <tr id="section-85">             <td class="docs">               <div class="pilwrap">                 <a class="pilcrow" href="#section-85">&#182;</a>               </div>               <p>Export everything as easily usable methods.</p>             </td>             <td class="code">               <div class="highlight"><pre><span class="nv">_export = </span><span class="p">{</span>
351 354
     <span class="nv">expr: </span><span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">Expression</span>
7  package.json
@@ -12,8 +12,11 @@
12 12
 		"coffee-script": "1.3",
13 13
 		"docco": "0.3",
14 14
 		"uglify-js": "1.3",
15  
-		"vows": "0.6"
16  
-	},
  15
+		"vows": "0.6",
  16
+    "mocha": "1.6.0",
  17
+    "chai": "1.3.0",
  18
+    "sinon": "1.5.0"
  19
+},
17 20
 	"keywords": ["sql", "database", "rdbms"],
18 21
 	"main": "squel",
19 22
 	"repository" :{
179  squel.js
@@ -27,7 +27,7 @@ OTHER DEALINGS IN THE SOFTWARE.
27 27
 
28 28
 
29 29
 (function() {
30  
-  var DefaultInsertBuilderOptions, DefaultUpdateBuilderOptions, Delete, Expression, ExpressionClassName, Insert, JoinWhereOrderLimit, QueryBuilder, Select, Update, WhereOrderLimit, formatValue, getObjectClassName, sanitizeAlias, sanitizeCondition, sanitizeField, sanitizeLimitOffset, sanitizeName, sanitizeTable, sanitizeValue, _export, _extend,
  30
+  var DefaultInsertBuilderOptions, DefaultUpdateBuilderOptions, Delete, Expression, Insert, JoinWhereOrderLimit, QueryBuilder, Select, Update, WhereOrderLimit, _export, _extend,
31 31
     __slice = [].slice,
32 32
     __hasProp = {}.hasOwnProperty,
33 33
     __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
@@ -167,83 +167,82 @@ OTHER DEALINGS IN THE SOFTWARE.
167 167
     usingValuePlaceholders: false
168 168
   };
169 169
 
170  
-  getObjectClassName = function(obj) {
171  
-    var arr;
172  
-    if (obj && obj.constructor && obj.constructor.toString) {
173  
-      arr = obj.constructor.toString().match(/function\s*(\w+)/);
174  
-      if (arr && arr.length === 2) {
175  
-        return arr[1];
176  
-      }
177  
-    }
178  
-    return void 0;
179  
-  };
180  
-
181  
-  ExpressionClassName = getObjectClassName(new Expression());
  170
+  QueryBuilder = (function() {
182 171
 
183  
-  sanitizeCondition = function(condition) {
184  
-    var t;
185  
-    t = typeof condition;
186  
-    if (ExpressionClassName !== getObjectClassName(condition) && "string" !== t) {
187  
-      throw new Error("condition must be a string or Expression instance");
188  
-    }
189  
-    if ("Expression" === t) {
190  
-      condition = condition.toString();
191  
-    }
192  
-    return condition;
193  
-  };
  172
+    function QueryBuilder() {}
194 173
 
195  
-  sanitizeName = function(value, type) {
196  
-    if ("string" !== typeof value) {
197  
-      throw new Error("" + type + " must be a string");
198  
-    }
199  
-    return value;
200  
-  };
  174
+    QueryBuilder.prototype._getObjectClassName = function(obj) {
  175
+      var arr;
  176
+      if (obj && obj.constructor && obj.constructor.toString) {
  177
+        arr = obj.constructor.toString().match(/function\s*(\w+)/);
  178
+        if (arr && arr.length === 2) {
  179
+          return arr[1];
  180
+        }
  181
+      }
  182
+      return void 0;
  183
+    };
201 184
 
202  
-  sanitizeField = function(item) {
203  
-    return sanitizeName(item, "field name");
204  
-  };
  185
+    QueryBuilder.prototype._sanitizeCondition = function(condition) {
  186
+      var c, t;
  187
+      t = typeof condition;
  188
+      c = this._getObjectClassName(condition);
  189
+      if ('Expression' !== c && "string" !== t) {
  190
+        throw new Error("condition must be a string or Expression instance");
  191
+      }
  192
+      if ('Expression' === t || 'Expression' === c) {
  193
+        condition = condition.toString();
  194
+      }
  195
+      return condition;
  196
+    };
205 197
 
206  
-  sanitizeTable = function(item) {
207  
-    return sanitizeName(item, "table name");
208  
-  };
  198
+    QueryBuilder.prototype._sanitizeName = function(value, type) {
  199
+      if ("string" !== typeof value) {
  200
+        throw new Error("" + type + " must be a string");
  201
+      }
  202
+      return value;
  203
+    };
209 204
 
210  
-  sanitizeAlias = function(item) {
211  
-    return sanitizeName(item, "alias");
212  
-  };
  205
+    QueryBuilder.prototype._sanitizeField = function(item) {
  206
+      return this._sanitizeName(item, "field name");
  207
+    };
213 208
 
214  
-  sanitizeLimitOffset = function(value) {
215  
-    value = parseInt(value);
216  
-    if (0 > value) {
217  
-      throw new Error("limit/offset must be >=0");
218  
-    }
219  
-    return value;
220  
-  };
  209
+    QueryBuilder.prototype._sanitizeTable = function(item) {
  210
+      return this._sanitizeName(item, "table name");
  211
+    };
221 212
 
222  
-  sanitizeValue = function(item) {
223  
-    var t;
224  
-    t = typeof item;
225  
-    if (null !== item && "string" !== t && "number" !== t && "boolean" !== t) {
226  
-      throw new Error("field value must be a string, number, boolean or null");
227  
-    }
228  
-    return item;
229  
-  };
  213
+    QueryBuilder.prototype._sanitizeAlias = function(item) {
  214
+      return this._sanitizeName(item, "alias");
  215
+    };
230 216
 
231  
-  formatValue = function(value, options) {
232  
-    if (null === value) {
233  
-      value = "NULL";
234  
-    } else if ("boolean" === typeof value) {
235  
-      value = value ? "TRUE" : "FALSE";
236  
-    } else if ("number" !== typeof value) {
237  
-      if (false === options.usingValuePlaceholders) {
238  
-        value = "'" + value + "'";
  217
+    QueryBuilder.prototype._sanitizeLimitOffset = function(value) {
  218
+      value = parseInt(value);
  219
+      if (0 > value) {
  220
+        throw new Error("limit/offset must be >=0");
239 221
       }
240  
-    }
241  
-    return value;
242  
-  };
  222
+      return value;
  223
+    };
243 224
 
244  
-  QueryBuilder = (function() {
  225
+    QueryBuilder.prototype._sanitizeValue = function(item) {
  226
+      var t;
  227
+      t = typeof item;
  228
+      if (null !== item && "string" !== t && "number" !== t && "boolean" !== t) {
  229
+        throw new Error("field value must be a string, number, boolean or null");
  230
+      }
  231
+      return item;
  232
+    };
245 233
 
246  
-    function QueryBuilder() {}
  234
+    QueryBuilder.prototype._formatValue = function(value, options) {
  235
+      if (null === value) {
  236
+        value = "NULL";
  237
+      } else if ("boolean" === typeof value) {
  238
+        value = value ? "TRUE" : "FALSE";
  239
+      } else if ("number" !== typeof value) {
  240
+        if (!options || false === options.usingValuePlaceholders) {
  241
+          value = "'" + value + "'";
  242
+        }
  243
+      }
  244
+      return value;
  245
+    };
247 246
 
248 247
     return QueryBuilder;
249 248
 
@@ -271,12 +270,13 @@ OTHER DEALINGS IN THE SOFTWARE.
271 270
       this.order = __bind(this.order, this);
272 271
 
273 272
       this.where = __bind(this.where, this);
  273
+      WhereOrderLimit.__super__.constructor.apply(this, arguments);
274 274
       this.wheres = [];
275 275
       this.orders = [];
276 276
     }
277 277
 
278 278
     WhereOrderLimit.prototype.where = function(condition) {
279  
-      condition = sanitizeCondition(condition);
  279
+      condition = this._sanitizeCondition(condition);
280 280
       if ("" !== condition) {
281 281
         this.wheres.push(condition);
282 282
       }
@@ -287,7 +287,7 @@ OTHER DEALINGS IN THE SOFTWARE.
287 287
       if (asc == null) {
288 288
         asc = true;
289 289
       }
290  
-      field = sanitizeField(field);
  290
+      field = this._sanitizeField(field);
291 291
       this.orders.push({
292 292
         field: field,
293 293
         dir: asc ? "ASC" : "DESC"
@@ -296,7 +296,7 @@ OTHER DEALINGS IN THE SOFTWARE.
296 296
     };
297 297
 
298 298
     WhereOrderLimit.prototype.limit = function(max) {
299  
-      max = sanitizeLimitOffset(max);
  299
+      max = this._sanitizeLimitOffset(max);
300 300
       this.limits = max;
301 301
       return this;
302 302
     };
@@ -359,12 +359,12 @@ OTHER DEALINGS IN THE SOFTWARE.
359 359
       var _this = this;
360 360
       JoinWhereOrderLimit.__super__.constructor.apply(this, arguments);
361 361
       this._join = function(type, table, alias, condition) {
362  
-        table = sanitizeTable(table);
  362
+        table = _this._sanitizeTable(table);
363 363
         if (alias) {
364  
-          alias = sanitizeAlias(alias);
  364
+          alias = _this._sanitizeAlias(alias);
365 365
         }
366 366
         if (condition) {
367  
-          condition = sanitizeCondition(condition);
  367
+          condition = _this._sanitizeCondition(condition);
368 368
         }
369 369
         _this.joins.push({
370 370
           type: type,
@@ -479,9 +479,9 @@ OTHER DEALINGS IN THE SOFTWARE.
479 479
       if (alias == null) {
480 480
         alias = null;
481 481
       }
482  
-      table = sanitizeTable(table);
  482
+      table = this._sanitizeTable(table);
483 483
       if (alias) {
484  
-        alias = sanitizeAlias(alias);
  484
+        alias = this._sanitizeAlias(alias);
485 485
       }
486 486
       this.froms.push({
487 487
         name: table,
@@ -494,9 +494,9 @@ OTHER DEALINGS IN THE SOFTWARE.
494 494
       if (alias == null) {
495 495
         alias = null;
496 496
       }
497  
-      field = sanitizeField(field);
  497
+      field = this._sanitizeField(field);
498 498
       if (alias) {
499  
-        alias = sanitizeAlias(alias);
  499
+        alias = this._sanitizeAlias(alias);
500 500
       }
501 501
       this.fields.push({
502 502
         field: field,
@@ -506,13 +506,13 @@ OTHER DEALINGS IN THE SOFTWARE.
506 506
     };
507 507
 
508 508
     Select.prototype.group = function(field) {
509  
-      field = sanitizeField(field);
  509
+      field = this._sanitizeField(field);
510 510
       this.groups.push(field);
511 511
       return this;
512 512
     };
513 513
 
514 514
     Select.prototype.offset = function(start) {
515  
-      start = sanitizeLimitOffset(start);
  515
+      start = this._sanitizeLimitOffset(start);
516 516
       this.offsets = start;
517 517
       return this;
518 518
     };
@@ -604,9 +604,9 @@ OTHER DEALINGS IN THE SOFTWARE.
604 604
       if (alias == null) {
605 605
         alias = null;
606 606
       }
607  
-      table = sanitizeTable(table);
  607
+      table = this._sanitizeTable(table);
608 608
       if (alias) {
609  
-        alias = sanitizeAlias(alias);
  609
+        alias = this._sanitizeAlias(alias);
610 610
       }
611 611
       this.tables.push({
612 612
         name: table,
@@ -616,8 +616,8 @@ OTHER DEALINGS IN THE SOFTWARE.
616 616
     };
617 617
 
618 618
     Update.prototype.set = function(field, value) {
619  
-      field = sanitizeField(field);
620  
-      value = sanitizeValue(value);
  619
+      field = this._sanitizeField(field);
  620
+      value = this._sanitizeValue(value);
621 621
       this.fields[field] = value;
622 622
       return this;
623 623
     };
@@ -660,7 +660,7 @@ OTHER DEALINGS IN THE SOFTWARE.
660 660
         if ("" !== fields) {
661 661
           fields += ", ";
662 662
         }
663  
-        fields += "" + field + " = " + (formatValue(this.fields[field], this.options));
  663
+        fields += "" + field + " = " + (this._formatValue(this.fields[field], this.options));
664 664
       }
665 665
       ret += " SET " + fields;
666 666
       ret += this.whereString();
@@ -687,7 +687,7 @@ OTHER DEALINGS IN THE SOFTWARE.
687 687
     Delete.prototype.table = null;
688 688
 
689 689
     Delete.prototype.from = function(table) {
690  
-      table = sanitizeTable(table);
  690
+      table = this._sanitizeTable(table);
691 691
       this.table = table;
692 692
       return this;
693 693
     };
@@ -725,19 +725,20 @@ OTHER DEALINGS IN THE SOFTWARE.
725 725
       this.set = __bind(this.set, this);
726 726
 
727 727
       this.into = __bind(this.into, this);
  728
+      Insert.__super__.constructor.apply(this, arguments);
728 729
       this.fields = {};
729 730
       this.options = _extend({}, DefaultInsertBuilderOptions, options);
730 731
     }
731 732
 
732 733
     Insert.prototype.into = function(table) {
733  
-      table = sanitizeTable(table);
  734
+      table = this._sanitizeTable(table);
734 735
       this.table = table;
735 736
       return this;
736 737
     };
737 738
 
738 739
     Insert.prototype.set = function(field, value) {
739  
-      field = sanitizeField(field);
740  
-      value = sanitizeValue(value);
  740
+      field = this._sanitizeField(field);
  741
+      value = this._sanitizeValue(value);
741 742
       this.fields[field] = value;
742 743
       return this;
743 744
     };
@@ -771,7 +772,7 @@ OTHER DEALINGS IN THE SOFTWARE.
771 772
         if ("" !== values) {
772 773
           values += ", ";
773 774
         }
774  
-        values += formatValue(this.fields[field], this.options);
  775
+        values += this._formatValue(this.fields[field], this.options);
775 776
       }
776 777
       return "INSERT INTO " + this.table + " (" + fields + ") VALUES (" + values + ")";
777 778
     };
2  squel.min.js
@@ -22,4 +22,4 @@ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22 22
 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 23
 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24 24
 OTHER DEALINGS IN THE SOFTWARE.
25  
-*/(function(){var e,t,n,r,i,s,o,u,a,f,l,c,h,p,d,v,m,g,y,b,w,E,S=[].slice,x={}.hasOwnProperty,T=function(e,t){return function(){return e.apply(t,arguments)}},N=function(e,t){function r(){this.constructor=e}for(var n in t)x.call(t,n)&&(e[n]=t[n]);return r.prototype=t.prototype,e.prototype=new r,e.__super__=t.prototype,e};E=function(){var e,t,n,r,i,s,o;e=arguments[0],n=2<=arguments.length?S.call(arguments,1):[];if(n)for(s=0,o=n.length;s<o;s++){r=n[s];if(r)for(t in r){if(!x.call(r,t))continue;i=r[t],e[t]=i}}return e},r=function(){function t(){this.toString=T(this.toString,this),this.or=T(this.or,this),this.and=T(this.and,this),this.end=T(this.end,this),this.or_begin=T(this.or_begin,this),this.and_begin=T(this.and_begin,this);var e=this;this.tree={parent:null,nodes:[]},this.current=this.tree,this._begin=function(t){var n;return n={type:t,parent:e.current,nodes:[]},e.current.nodes.push(n),e.current=e.current.nodes[e.current.nodes.length-1],e}}var e;return t.prototype.tree=null,t.prototype.current=null,t.prototype.and_begin=function(){return this._begin("AND")},t.prototype.or_begin=function(){return this._begin("OR")},t.prototype.end=function(){if(!this.current.parent)throw new Error("begin() needs to be called");return this.current=this.current.parent,this},t.prototype.and=function(e){if(!e||"string"!=typeof e)throw new Error("expr must be a string");return this.current.nodes.push({type:"AND",expr:e}),this},t.prototype.or=function(e){if(!e||"string"!=typeof e)throw new Error("expr must be a string");return this.current.nodes.push({type:"OR",expr:e}),this},t.prototype.toString=function(){if(null!==this.current.parent)throw new Error("end() needs to be called");return e(this.tree)},e=function(t){var n,r,i,s,o,u;i="",u=t.nodes;for(s=0,o=u.length;s<o;s++)n=u[s],n.expr!=null?r=n.expr:(r=e(n),""!==r&&(r="("+r+")")),""!==r&&(""!==i&&(i+=" "+n.type+" "),i+=r);return i},t}(),e=t={usingValuePlaceholders:!1},h=function(e){var t;if(e&&e.constructor&&e.constructor.toString){t=e.constructor.toString().match(/function\s*(\w+)/);if(t&&t.length===2)return t[1]}return void 0},i=h(new r),d=function(e){var t;t=typeof e;if(i!==h(e)&&"string"!==t)throw new Error("condition must be a string or Expression instance");return"Expression"===t&&(e=e.toString()),e},g=function(e,t){if("string"!=typeof e)throw new Error(""+t+" must be a string");return e},v=function(e){return g(e,"field name")},y=function(e){return g(e,"table name")},p=function(e){return g(e,"alias")},m=function(e){e=parseInt(e);if(0>e)throw new Error("limit/offset must be >=0");return e},b=function(e){var t;t=typeof e;if(null!==e&&"string"!==t&&"number"!==t&&"boolean"!==t)throw new Error("field value must be a string, number, boolean or null");return e},c=function(e,t){return null===e?e="NULL":"boolean"==typeof e?e=e?"TRUE":"FALSE":"number"!=typeof e&&!1===t.usingValuePlaceholders&&(e="'"+e+"'"),e},u=function(){function e(){}return e}(),l=function(e){function t(){this.limitString=T(this.limitString,this),this.orderString=T(this.orderString,this),this.whereString=T(this.whereString,this),this.limit=T(this.limit,this),this.order=T(this.order,this),this.where=T(this.where,this),this.wheres=[],this.orders=[]}return N(t,e),t.prototype.wheres=null,t.prototype.orders=null,t.prototype.limits=null,t.prototype.where=function(e){return e=d(e),""!==e&&this.wheres.push(e),this},t.prototype.order=function(e,t){return t==null&&(t=!0),e=v(e),this.orders.push({field:e,dir:t?"ASC":"DESC"}),this},t.prototype.limit=function(e){return e=m(e),this.limits=e,this},t.prototype.whereString=function(){return 0<this.wheres.length?" WHERE ("+this.wheres.join(") AND (")+")":""},t.prototype.orderString=function(){var e,t,n,r,i;if(0<this.orders.length){t="",i=this.orders;for(n=0,r=i.length;n<r;n++)e=i[n],""!==t&&(t+=", "),t+=""+e.field+" "+e.dir;return" ORDER BY "+t}return""},t.prototype.limitString=function(){return this.limits?" LIMIT "+this.limits:""},t}(u),o=function(e){function t(){this.joinString=T(this.joinString,this),this.outer_join=T(this.outer_join,this),this.right_join=T(this.right_join,this),this.left_join=T(this.left_join,this),this.join=T(this.join,this);var e=this;t.__super__.constructor.apply(this,arguments),this._join=function(t,n,r,i){return n=y(n),r&&(r=p(r)),i&&(i=d(i)),e.joins.push({type:t,table:n,alias:r,condition:i}),e}}return N(t,e),t.prototype.joins=null,t.prototype.join=function(e,t,n){return t==null&&(t=null),n==null&&(n=null),this._join("INNER",e,t,n)},t.prototype.left_join=function(e,t,n){return t==null&&(t=null),n==null&&(n=null),this._join("LEFT",e,t,n)},t.prototype.right_join=function(e,t,n){return t==null&&(t=null),n==null&&(n=null),this._join("RIGHT",e,t,n)},t.prototype.outer_join=function(e,t,n){return t==null&&(t=null),n==null&&(n=null),this._join("OUTER",e,t,n)},t.prototype.joinString=function(){var e,t,n,r,i;t="",i=this.joins||[];for(n=0,r=i.length;n<r;n++)e=i[n],t+=" "+e.type+" JOIN "+e.table,e.alias&&(t+=" `"+e.alias+"`"),e.condition&&(t+=" ON ("+e.condition+")");return t},t}(l),a=function(e){function t(){this.toString=T(this.toString,this),this.offset=T(this.offset,this),this.group=T(this.group,this),this.field=T(this.field,this),this.from=T(this.from,this),this.distinct=T(this.distinct,this),t.__super__.constructor.apply(this,arguments),this.froms=[],this.fields=[],this.joins=[],this.groups=[]}return N(t,e),t.prototype.froms=null,t.prototype.fields=null,t.prototype.groups=null,t.prototype.offsets=null,t.prototype.useDistinct=!1,t.prototype.distinct=function(){return this.useDistinct=!0,this},t.prototype.from=function(e,t){return t==null&&(t=null),e=y(e),t&&(t=p(t)),this.froms.push({name:e,alias:t}),this},t.prototype.field=function(e,t){return t==null&&(t=null),e=v(e),t&&(t=p(t)),this.fields.push({field:e,alias:t}),this},t.prototype.group=function(e){return e=v(e),this.groups.push(e),this},t.prototype.offset=function(e){return e=m(e),this.offsets=e,this},t.prototype.toString=function(){var e,t,n,r,i,s,o,u,a,f,l,c,h,p,d,v;if(0>=this.froms.length)throw new Error("from() needs to be called");i="SELECT ",this.useDistinct&&(i+="DISTINCT "),n="",p=this.fields;for(u=0,l=p.length;u<l;u++)t=p[u],""!==n&&(n+=", "),n+=t.field,t.alias&&(n+=' AS "'+t.alias+'"');i+=""===n?"*":n,o="",d=this.froms;for(a=0,c=d.length;a<c;a++)s=d[a],""!==o&&(o+=", "),o+=s.name,s.alias&&(o+=" `"+s.alias+"`");i+=" FROM "+o,i+=this.joinString(),i+=this.whereString();if(0<this.groups.length){r="",v=this.groups;for(f=0,h=v.length;f<h;f++)e=v[f],""!==r&&(r+=", "),r+=e;i+=" GROUP BY "+r}return i+=this.orderString(),i+=this.limitString(),this.offsets&&(i+=" OFFSET "+this.offsets),i},t}(o),f=function(e){function n(e){this.toString=T(this.toString,this),this.set=T(this.set,this),this.table=T(this.table,this),n.__super__.constructor.apply(this,arguments),this.tables=[],this.fields={},this.options=E({},t,e)}return N(n,e),n.prototype.tables=null,n.prototype.fields=null,n.prototype.options=null,n.prototype.table=function(e,t){return t==null&&(t=null),e=y(e),t&&(t=p(t)),this.tables.push({name:e,alias:t}),this},n.prototype.set=function(e,t){return e=v(e),t=b(t),this.fields[e]=t,this},n.prototype.toString=function(){var e,t,n,r,i,s,o,u,a,f,l;if(0>=this.tables.length)throw new Error("table() needs to be called");t=function(){var t,n;t=this.fields,n=[];for(e in t){if(!x.call(t,e))continue;n.push(e)}return n}.call(this);if(0>=t.length)throw new Error("set() needs to be called");r="UPDATE ",s="",l=this.tables;for(o=0,a=l.length;o<a;o++)i=l[o],""!==s&&(s+=", "),s+=i.name,i.alias&&(s+=" AS `"+i.alias+"`");r+=s,n="";for(u=0,f=t.length;u<f;u++)e=t[u],""!==n&&(n+=", "),n+=""+e+" = "+c(this.fields[e],this.options);return r+=" SET "+n,r+=this.whereString(),r+=this.orderString(),r+=this.limitString(),r},n}(l),n=function(e){function t(){return this.toString=T(this.toString,this),this.from=T(this.from,this),t.__super__.constructor.apply(this,arguments)}return N(t,e),t.prototype.table=null,t.prototype.from=function(e){return e=y(e),this.table=e,this},t.prototype.toString=function(){var e;if(!this.table)throw new Error("from() needs to be called");return e="DELETE FROM "+this.table,e+=this.joinString(),e+=this.whereString(),e+=this.orderString(),e+=this.limitString(),e},t}(o),s=function(t){function n(t){this.toString=T(this.toString,this),this.set=T(this.set,this),this.into=T(this.into,this),this.fields={},this.options=E({},e,t)}return N(n,t),n.prototype.table=null,n.prototype.fields=null,n.prototype.options=null,n.prototype.into=function(e){return e=y(e),this.table=e,this},n.prototype.set=function(e,t){return e=v(e),t=b(t),this.fields[e]=t,this},n.prototype.toString=function(){var e,t,n,r,i,s,o;if(!this.table)throw new Error("into() needs to be called");t=function(){var e,t;e=this.fields,t=[];for(r in e){if(!x.call(e,r))continue;t.push(r)}return t}.call(this);if(0>=t.length)throw new Error("set() needs to be called");n="",i="";for(s=0,o=t.length;s<o;s++)e=t[s],""!==n&&(n+=", "),n+=e,""!==i&&(i+=", "),i+=c(this.fields[e],this.options);return"INSERT INTO "+this.table+" ("+n+") VALUES ("+i+")"},n}(u),w={expr:function(){return new r},select:function(){return new a},update:function(e){return new f(e)},insert:function(e){return new s(e)},"delete":function(){return new n},Expression:r,QueryBuilder:u,Select:a,Update:f,Insert:s,Delete:n},typeof module!="undefined"&&module!==null&&(module.exports=w),typeof window!="undefined"&&window!==null&&(window.squel=w)}).call(this);
  25
+*/(function(){var e,t,n,r,i,s,o,u,a,f,l,c,h=[].slice,p={}.hasOwnProperty,d=function(e,t){return function(){return e.apply(t,arguments)}},v=function(e,t){function r(){this.constructor=e}for(var n in t)p.call(t,n)&&(e[n]=t[n]);return r.prototype=t.prototype,e.prototype=new r,e.__super__=t.prototype,e};c=function(){var e,t,n,r,i,s,o;e=arguments[0],n=2<=arguments.length?h.call(arguments,1):[];if(n)for(s=0,o=n.length;s<o;s++){r=n[s];if(r)for(t in r){if(!p.call(r,t))continue;i=r[t],e[t]=i}}return e},r=function(){function t(){this.toString=d(this.toString,this),this.or=d(this.or,this),this.and=d(this.and,this),this.end=d(this.end,this),this.or_begin=d(this.or_begin,this),this.and_begin=d(this.and_begin,this);var e=this;this.tree={parent:null,nodes:[]},this.current=this.tree,this._begin=function(t){var n;return n={type:t,parent:e.current,nodes:[]},e.current.nodes.push(n),e.current=e.current.nodes[e.current.nodes.length-1],e}}var e;return t.prototype.tree=null,t.prototype.current=null,t.prototype.and_begin=function(){return this._begin("AND")},t.prototype.or_begin=function(){return this._begin("OR")},t.prototype.end=function(){if(!this.current.parent)throw new Error("begin() needs to be called");return this.current=this.current.parent,this},t.prototype.and=function(e){if(!e||"string"!=typeof e)throw new Error("expr must be a string");return this.current.nodes.push({type:"AND",expr:e}),this},t.prototype.or=function(e){if(!e||"string"!=typeof e)throw new Error("expr must be a string");return this.current.nodes.push({type:"OR",expr:e}),this},t.prototype.toString=function(){if(null!==this.current.parent)throw new Error("end() needs to be called");return e(this.tree)},e=function(t){var n,r,i,s,o,u;i="",u=t.nodes;for(s=0,o=u.length;s<o;s++)n=u[s],n.expr!=null?r=n.expr:(r=e(n),""!==r&&(r="("+r+")")),""!==r&&(""!==i&&(i+=" "+n.type+" "),i+=r);return i},t}(),e=t={usingValuePlaceholders:!1},o=function(){function e(){}return e.prototype._getObjectClassName=function(e){var t;if(e&&e.constructor&&e.constructor.toString){t=e.constructor.toString().match(/function\s*(\w+)/);if(t&&t.length===2)return t[1]}return void 0},e.prototype._sanitizeCondition=function(e){var t,n;n=typeof e,t=this._getObjectClassName(e);if("Expression"!==t&&"string"!==n)throw new Error("condition must be a string or Expression instance");if("Expression"===n||"Expression"===t)e=e.toString();return e},e.prototype._sanitizeName=function(e,t){if("string"!=typeof e)throw new Error(""+t+" must be a string");return e},e.prototype._sanitizeField=function(e){return this._sanitizeName(e,"field name")},e.prototype._sanitizeTable=function(e){return this._sanitizeName(e,"table name")},e.prototype._sanitizeAlias=function(e){return this._sanitizeName(e,"alias")},e.prototype._sanitizeLimitOffset=function(e){e=parseInt(e);if(0>e)throw new Error("limit/offset must be >=0");return e},e.prototype._sanitizeValue=function(e){var t;t=typeof e;if(null!==e&&"string"!==t&&"number"!==t&&"boolean"!==t)throw new Error("field value must be a string, number, boolean or null");return e},e.prototype._formatValue=function(e,t){return null===e?e="NULL":"boolean"==typeof e?e=e?"TRUE":"FALSE":"number"!=typeof e&&(!t||!1===t.usingValuePlaceholders)&&(e="'"+e+"'"),e},e}(),f=function(e){function t(){this.limitString=d(this.limitString,this),this.orderString=d(this.orderString,this),this.whereString=d(this.whereString,this),this.limit=d(this.limit,this),this.order=d(this.order,this),this.where=d(this.where,this),t.__super__.constructor.apply(this,arguments),this.wheres=[],this.orders=[]}return v(t,e),t.prototype.wheres=null,t.prototype.orders=null,t.prototype.limits=null,t.prototype.where=function(e){return e=this._sanitizeCondition(e),""!==e&&this.wheres.push(e),this},t.prototype.order=function(e,t){return t==null&&(t=!0),e=this._sanitizeField(e),this.orders.push({field:e,dir:t?"ASC":"DESC"}),this},t.prototype.limit=function(e){return e=this._sanitizeLimitOffset(e),this.limits=e,this},t.prototype.whereString=function(){return 0<this.wheres.length?" WHERE ("+this.wheres.join(") AND (")+")":""},t.prototype.orderString=function(){var e,t,n,r,i;if(0<this.orders.length){t="",i=this.orders;for(n=0,r=i.length;n<r;n++)e=i[n],""!==t&&(t+=", "),t+=""+e.field+" "+e.dir;return" ORDER BY "+t}return""},t.prototype.limitString=function(){return this.limits?" LIMIT "+this.limits:""},t}(o),s=function(e){function t(){this.joinString=d(this.joinString,this),this.outer_join=d(this.outer_join,this),this.right_join=d(this.right_join,this),this.left_join=d(this.left_join,this),this.join=d(this.join,this);var e=this;t.__super__.constructor.apply(this,arguments),this._join=function(t,n,r,i){return n=e._sanitizeTable(n),r&&(r=e._sanitizeAlias(r)),i&&(i=e._sanitizeCondition(i)),e.joins.push({type:t,table:n,alias:r,condition:i}),e}}return v(t,e),t.prototype.joins=null,t.prototype.join=function(e,t,n){return t==null&&(t=null),n==null&&(n=null),this._join("INNER",e,t,n)},t.prototype.left_join=function(e,t,n){return t==null&&(t=null),n==null&&(n=null),this._join("LEFT",e,t,n)},t.prototype.right_join=function(e,t,n){return t==null&&(t=null),n==null&&(n=null),this._join("RIGHT",e,t,n)},t.prototype.outer_join=function(e,t,n){return t==null&&(t=null),n==null&&(n=null),this._join("OUTER",e,t,n)},t.prototype.joinString=function(){var e,t,n,r,i;t="",i=this.joins||[];for(n=0,r=i.length;n<r;n++)e=i[n],t+=" "+e.type+" JOIN "+e.table,e.alias&&(t+=" `"+e.alias+"`"),e.condition&&(t+=" ON ("+e.condition+")");return t},t}(f),u=function(e){function t(){this.toString=d(this.toString,this),this.offset=d(this.offset,this),this.group=d(this.group,this),this.field=d(this.field,this),this.from=d(this.from,this),this.distinct=d(this.distinct,this),t.__super__.constructor.apply(this,arguments),this.froms=[],this.fields=[],this.joins=[],this.groups=[]}return v(t,e),t.prototype.froms=null,t.prototype.fields=null,t.prototype.groups=null,t.prototype.offsets=null,t.prototype.useDistinct=!1,t.prototype.distinct=function(){return this.useDistinct=!0,this},t.prototype.from=function(e,t){return t==null&&(t=null),e=this._sanitizeTable(e),t&&(t=this._sanitizeAlias(t)),this.froms.push({name:e,alias:t}),this},t.prototype.field=function(e,t){return t==null&&(t=null),e=this._sanitizeField(e),t&&(t=this._sanitizeAlias(t)),this.fields.push({field:e,alias:t}),this},t.prototype.group=function(e){return e=this._sanitizeField(e),this.groups.push(e),this},t.prototype.offset=function(e){return e=this._sanitizeLimitOffset(e),this.offsets=e,this},t.prototype.toString=function(){var e,t,n,r,i,s,o,u,a,f,l,c,h,p,d,v;if(0>=this.froms.length)throw new Error("from() needs to be called");i="SELECT ",this.useDistinct&&(i+="DISTINCT "),n="",p=this.fields;for(u=0,l=p.length;u<l;u++)t=p[u],""!==n&&(n+=", "),n+=t.field,t.alias&&(n+=' AS "'+t.alias+'"');i+=""===n?"*":n,o="",d=this.froms;for(a=0,c=d.length;a<c;a++)s=d[a],""!==o&&(o+=", "),o+=s.name,s.alias&&(o+=" `"+s.alias+"`");i+=" FROM "+o,i+=this.joinString(),i+=this.whereString();if(0<this.groups.length){r="",v=this.groups;for(f=0,h=v.length;f<h;f++)e=v[f],""!==r&&(r+=", "),r+=e;i+=" GROUP BY "+r}return i+=this.orderString(),i+=this.limitString(),this.offsets&&(i+=" OFFSET "+this.offsets),i},t}(s),a=function(e){function n(e){this.toString=d(this.toString,this),this.set=d(this.set,this),this.table=d(this.table,this),n.__super__.constructor.apply(this,arguments),this.tables=[],this.fields={},this.options=c({},t,e)}return v(n,e),n.prototype.tables=null,n.prototype.fields=null,n.prototype.options=null,n.prototype.table=function(e,t){return t==null&&(t=null),e=this._sanitizeTable(e),t&&(t=this._sanitizeAlias(t)),this.tables.push({name:e,alias:t}),this},n.prototype.set=function(e,t){return e=this._sanitizeField(e),t=this._sanitizeValue(t),this.fields[e]=t,this},n.prototype.toString=function(){var e,t,n,r,i,s,o,u,a,f,l;if(0>=this.tables.length)throw new Error("table() needs to be called");t=function(){var t,n;t=this.fields,n=[];for(e in t){if(!p.call(t,e))continue;n.push(e)}return n}.call(this);if(0>=t.length)throw new Error("set() needs to be called");r="UPDATE ",s="",l=this.tables;for(o=0,a=l.length;o<a;o++)i=l[o],""!==s&&(s+=", "),s+=i.name,i.alias&&(s+=" AS `"+i.alias+"`");r+=s,n="";for(u=0,f=t.length;u<f;u++)e=t[u],""!==n&&(n+=", "),n+=""+e+" = "+this._formatValue(this.fields[e],this.options);return r+=" SET "+n,r+=this.whereString(),r+=this.orderString(),r+=this.limitString(),r},n}(f),n=function(e){function t(){return this.toString=d(this.toString,this),this.from=d(this.from,this),t.__super__.constructor.apply(this,arguments)}return v(t,e),t.prototype.table=null,t.prototype.from=function(e){return e=this._sanitizeTable(e),this.table=e,this},t.prototype.toString=function(){var e;if(!this.table)throw new Error("from() needs to be called");return e="DELETE FROM "+this.table,e+=this.joinString(),e+=this.whereString(),e+=this.orderString(),e+=this.limitString(),e},t}(s),i=function(t){function n(t){this.toString=d(this.toString,this),this.set=d(this.set,this),this.into=d(this.into,this),n.__super__.constructor.apply(this,arguments),this.fields={},this.options=c({},e,t)}return v(n,t),n.prototype.table=null,n.prototype.fields=null,n.prototype.options=null,n.prototype.into=function(e){return e=this._sanitizeTable(e),this.table=e,this},n.prototype.set=function(e,t){return e=this._sanitizeField(e),t=this._sanitizeValue(t),this.fields[e]=t,this},n.prototype.toString=function(){var e,t,n,r,i,s,o;if(!this.table)throw new Error("into() needs to be called");t=function(){var e,t;e=this.fields,t=[];for(r in e){if(!p.call(e,r))continue;t.push(r)}return t}.call(this);if(0>=t.length)throw new Error("set() needs to be called");n="",i="";for(s=0,o=t.length;s<o;s++)e=t[s],""!==n&&(n+=", "),n+=e,""!==i&&(i+=", "),i+=this._formatValue(this.fields[e],this.options);return"INSERT INTO "+this.table+" ("+n+") VALUES ("+i+")"},n}(o),l={expr:function(){return new r},select:function(){return new u},update:function(e){return new a(e)},insert:function(e){return new i(e)},"delete":function(){return new n},Expression:r,QueryBuilder:o,Select:u,Update:a,Insert:i,Delete:n},typeof module!="undefined"&&module!==null&&(module.exports=l),typeof window!="undefined"&&window!==null&&(window.squel=l)}).call(this);
119  src/squel.coffee
@@ -145,66 +145,69 @@ DefaultInsertBuilderOptions = DefaultUpdateBuilderOptions =
145 145
 
146 146
 
147 147
 
148  
-# Get class name of given object.
149  
-getObjectClassName = (obj) ->
  148
+
  149
+# Base class for all query builders
  150
+class QueryBuilder
  151
+  # Get class name of given object.
  152
+  _getObjectClassName: (obj) ->
150 153
     if obj && obj.constructor && obj.constructor.toString
151  
-        arr = obj.constructor.toString().match /function\s*(\w+)/;
152  
-        if arr && arr.length is 2
153  
-            return arr[1]
  154
+      arr = obj.constructor.toString().match /function\s*(\w+)/;
  155
+      if arr && arr.length is 2
  156
+        return arr[1]
154 157
     return undefined
155 158
 
156  
-# Sanitize the given condition.
157  
-ExpressionClassName = getObjectClassName(new Expression())
158  
-sanitizeCondition = (condition) ->
  159
+  # Sanitize the given condition.
  160
+  _sanitizeCondition: (condition) ->
159 161
     t = typeof condition
160  
-    if ExpressionClassName isnt getObjectClassName(condition) and "string" isnt t
161  
-        throw new Error "condition must be a string or Expression instance"
  162
+    c = @_getObjectClassName(condition)
  163
+
  164
+    if 'Expression' isnt c and "string" isnt t
  165
+      throw new Error "condition must be a string or Expression instance"
162 166
     # If it's an expression builder instance then convert it to string form.
163  
-    if "Expression" is t
164  
-        condition = condition.toString()
  167
+    if 'Expression' is t or 'Expression' is c
  168
+      condition = condition.toString()
165 169
     condition
166 170
 
167  
-# Sanitize the given name.
168  
-# The 'type' parameter is used to construct a meaningful error message in case validation fails.
169  
-sanitizeName = (value, type) ->
  171
+
  172
+  # Sanitize the given name.
  173
+  # The 'type' parameter is used to construct a meaningful error message in case validation fails.
  174
+  _sanitizeName: (value, type) ->
170 175
     if "string" isnt typeof value
171  
-        throw new Error "#{type} must be a string"
  176
+      throw new Error "#{type} must be a string"
172 177
     value
173 178
 
174  
-sanitizeField = (item) -> sanitizeName item, "field name"
175  
-sanitizeTable = (item) -> sanitizeName item, "table name"
176  
-sanitizeAlias = (item) -> sanitizeName item, "alias"
  179
+  _sanitizeField: (item) -> @_sanitizeName item, "field name"
  180
+  _sanitizeTable: (item) -> @_sanitizeName item, "table name"
  181
+  _sanitizeAlias: (item) -> @_sanitizeName item, "alias"
177 182
 
178  
-# Sanitize the given limit/offset value.
179  
-sanitizeLimitOffset = (value) ->
  183
+  # Sanitize the given limit/offset value.
  184
+  _sanitizeLimitOffset: (value) ->
180 185
     value = parseInt(value)
181 186
     if 0 > value
182  
-        throw new Error "limit/offset must be >=0"
  187
+      throw new Error "limit/offset must be >=0"
183 188
     value
184 189
 
185  
-# Santize the given field value
186  
-sanitizeValue = (item) ->
  190
+  # Santize the given field value
  191
+  _sanitizeValue: (item) ->
187 192
     t = typeof item
188 193
     if null isnt item and "string" isnt t and "number" isnt t and "boolean" isnt t
189  
-        throw new Error "field value must be a string, number, boolean or null"
  194
+      throw new Error "field value must be a string, number, boolean or null"
190 195
     item
191 196
 
192  
-# Format the given field value for inclusion into the query string
193  
-#
194  
-# options: see DefaultBuilderOptions
195  
-formatValue = (value, options) ->
  197
+  # Format the given field value for inclusion into the query string
  198
+  #
  199
+  # options: see DefaultBuilderOptions
  200
+  _formatValue: (value, options) ->
196 201
     if null is value
197  
-        value = "NULL"
  202
+      value = "NULL"
198 203
     else if "boolean" is typeof value
199  
-        value = if value then "TRUE" else "FALSE"
  204
+      value = if value then "TRUE" else "FALSE"
200 205
     else if "number" isnt typeof value
201  
-        if false is options.usingValuePlaceholders
202  
-            value = "'#{value}'"
  206
+      if not options or false is options.usingValuePlaceholders
  207
+        value = "'#{value}'"
203 208
     value
204 209
 
205 210
 
206  
-# Base class for all query builders
207  
-class QueryBuilder
208 211
 
209 212
 
210 213
 # Base class for query builders which support WHERE, ORDER and LIMIT clauses.
@@ -214,6 +217,7 @@ class WhereOrderLimit extends QueryBuilder
214 217
     limits: null
215 218
 
216 219
     constructor: ->
  220
+        super
217 221
         @wheres = []
218 222
         @orders = []
219 223
 
@@ -222,7 +226,7 @@ class WhereOrderLimit extends QueryBuilder
222 226
     #
223 227
     # When the final query is constructed all the WHERE conditions are combined using the intersection (AND) operator.
224 228
     where: (condition) =>
225  
-        condition = sanitizeCondition(condition)
  229
+        condition = @_sanitizeCondition(condition)
226 230
         if "" isnt condition
227 231
             @wheres.push condition
228 232
         @
@@ -232,7 +236,7 @@ class WhereOrderLimit extends QueryBuilder
232 236
     #
233 237
     # To specify descending order pass false for the 'asc' parameter.
234 238
     order: (field, asc = true) =>
235  
-        field = sanitizeField field
  239
+        field = @_sanitizeField(field)
236 240
         @orders.push
237 241
             field: field
238 242
             dir: if asc then "ASC" else "DESC"
@@ -244,7 +248,7 @@ class WhereOrderLimit extends QueryBuilder
244 248
     # Call this will override the previously set limit for this query. Also note that Passing 0 for 'max' will remove
245 249
     # the limit.
246 250
     limit: (max) =>
247  
-        max = sanitizeLimitOffset max
  251
+        max = @_sanitizeLimitOffset(max)
248 252
         @limits = max
249 253
         @
250 254
 
@@ -294,9 +298,9 @@ class JoinWhereOrderLimit extends WhereOrderLimit
294 298
     # an expression builder then it will only get evaluated during the final query string construction phase in
295 299
     # toString().
296 300
     @_join = (type, table, alias, condition) =>
297  
-      table = sanitizeTable(table)
298  
-      alias = sanitizeAlias(alias) if alias
299  
-      condition = sanitizeCondition(condition) if condition
  301
+      table = @_sanitizeTable(table)
  302
+      alias = @_sanitizeAlias(alias) if alias
  303
+      condition = @_sanitizeCondition(condition) if condition
300 304
 
301 305
       @joins.push
302 306
         type: type
@@ -370,8 +374,8 @@ class Select extends JoinWhereOrderLimit
370 374
     #
371 375
     # An alias may also be specified for the table.
372 376
     from: (table, alias = null) =>
373  
-        table = sanitizeTable(table)
374  
-        alias = sanitizeAlias(alias) if alias
  377
+        table = @_sanitizeTable(table)
  378
+        alias = @_sanitizeAlias(alias) if alias
375 379
 
376 380
         @froms.push
377 381
             name: table
@@ -386,8 +390,8 @@ class Select extends JoinWhereOrderLimit
386 390
     #
387 391
     # An alias may also be specified for this field.
388 392
     field: (field, alias = null) =>
389  
-        field = sanitizeField(field)
390  
-        alias = sanitizeAlias(alias) if alias
  393
+        field = @_sanitizeField(field)
  394
+        alias = @_sanitizeAlias(alias) if alias
391 395
 
392 396
         @fields.push
393 397
             field: field
@@ -398,7 +402,7 @@ class Select extends JoinWhereOrderLimit
398 402
 
399 403
     # Add a GROUP BY transformation for the given field.
400 404
     group: (field) =>
401  
-        field = sanitizeField field
  405
+        field = @_sanitizeField(field)
402 406
         @groups.push field
403 407
         @
404 408
 
@@ -408,7 +412,7 @@ class Select extends JoinWhereOrderLimit
408 412
     # Call this will override the previously set offset for this query. Also note that Passing 0 for 'max' will remove
409 413
     # the offset.
410 414
     offset: (start) =>
411  
-        start = sanitizeLimitOffset start
  415
+        start = @_sanitizeLimitOffset(start)
412 416
         @offsets = start
413 417
         @
414 418
 
@@ -491,8 +495,8 @@ class Update extends WhereOrderLimit
491 495
     #
492 496
     # An alias may also be specified for the table.
493 497
     table: (table, alias = null) =>
494  
-        table = sanitizeTable(table)
495  
-        alias = sanitizeAlias(alias) if alias
  498
+        table = @_sanitizeTable(table)
  499
+        alias = @_sanitizeAlias(alias) if alias
496 500
 
497 501
         @tables.push
498 502
             name: table
@@ -502,8 +506,8 @@ class Update extends WhereOrderLimit
502 506
     # Update the given field with the given value.
503 507
     # This will override any previously set value for the given field.
504 508
     set: (field, value) =>
505  
-        field = sanitizeField field
506  
-        value = sanitizeValue value
  509
+        field = @_sanitizeField(field)
  510
+        value = @_sanitizeValue(value)
507 511
         @fields[field] = value
508 512
         @
509 513
 
@@ -530,7 +534,7 @@ class Update extends WhereOrderLimit
530 534
         fields = ""
531 535
         for field in fieldNames
532 536
             fields += ", " if "" isnt fields
533  
-            fields += "#{field} = #{formatValue(@fields[field], @options)}"
  537
+            fields += "#{field} = #{@_formatValue(@fields[field], @options)}"
534 538
         ret += " SET #{fields}"
535 539
 
536 540
         # where
@@ -558,7 +562,7 @@ class Delete extends JoinWhereOrderLimit
558 562
     # The table to delete from.
559 563
     # Calling this will override any previously set value.
560 564
     from: (table) =>
561  
-        table = sanitizeTable(table)
  565
+        table = @_sanitizeTable(table)
562 566
         @table = table
563 567
         @
564 568
 
@@ -597,6 +601,7 @@ class Insert extends QueryBuilder
597 601
 
598 602
     # options: see DefaultBuilderOptions
599 603
     constructor: (options) ->
  604
+        super
600 605
         @fields = {}
601 606
         @options = _extend {}, DefaultInsertBuilderOptions, options
602 607
 
@@ -604,15 +609,15 @@ class Insert extends QueryBuilder
604 609
     # The table to insert into.
605 610
     # This will override any previously set value.
606 611
     into: (table) =>
607  
-        table = sanitizeTable(table)
  612
+        table = @_sanitizeTable(table)
608 613
         @table = table
609 614
         @
610 615
 
611 616
     # Set the given field to the given value.
612 617
     # This will override any previously set value for the given field.
613 618
     set: (field, value) =>
614  
-        field = sanitizeField field
615  
-        value = sanitizeValue value
  619
+        field = @_sanitizeField(field)
  620
+        value = @_sanitizeValue(value)
616 621
         @fields[field] = value
617 622
         @
618 623
 
@@ -630,7 +635,7 @@ class Insert extends QueryBuilder
630 635
             fields += ", " if "" isnt fields
631 636
             fields += field
632 637
             values += ", " if "" isnt values
633  
-            values += formatValue(@fields[field], @options)
  638
+            values += @_formatValue(@fields[field], @options)
634 639
 
635 640
         "INSERT INTO #{@table} (#{fields}) VALUES (#{values})"
636 641
 
49  test/delete.test.coffee
... ...
@@ -0,0 +1,49 @@
  1
+###
  2
+Copyright (c) 2012 Ramesh Nair (hiddentao.com)
  3
+
  4
+Permission is hereby granted, free of charge, to any person
  5
+obtaining a copy of this software and associated documentation
  6
+files (the "Software"), to deal in the Software without
  7
+restriction, including without limitation the rights to use,
  8
+copy, modify, merge, publish, distribute, sublicense, and/or sell
  9
+copies of the Software, and to permit persons to whom the
  10
+Software is furnished to do so, subject to the following
  11
+conditions:
  12
+
  13
+The above copyright notice and this permission notice shall be
  14
+included in all copies or substantial portions of the Software.
  15
+
  16
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  17
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  18
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  19
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  20
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  21
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  22
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  23
+OTHER DEALINGS IN THE SOFTWARE.
  24
+###
  25
+
  26
+
  27
+{test, assert, expect, should} = require './testbase'
  28
+squel = require "../src/squel"
  29
+
  30
+
  31
+
  32
+test['DELETE query builder'] =
  33
+  'when the builder is initialized':
  34
+    beforeEach: ->
  35
+      @inst = squel.delete()
  36
+
  37
+    'toString() throws an error': ->
  38
+      test.mocker.spy(@inst, 'toString')
  39
+
  40
+      try
  41
+        @inst.toString()
  42
+      catch err
  43
+        assert.same err.toString(), 'Error: from() needs to be called'
  44
+      finally
  45
+        assert.ok @inst.toString.threw()
  46
+
  47
+
  48
+
  49
+module?.exports[require('path').basename(__filename)] = test
3  test/mocha.opts
... ...
@@ -0,0 +1,3 @@
  1
+--ui exports
  2
+--reporter spec
  3
+--compilers coffee:coffee-script
248  test/querybuilder.test.coffee
... ...
@@ -0,0 +1,248 @@
  1
+###
  2
+Copyright (c) 2012 Ramesh Nair (hiddentao.com)
  3
+
  4
+Permission is hereby granted, free of charge, to any person
  5
+obtaining a copy of this software and associated documentation
  6
+files (the "Software"), to deal in the Software without
  7
+restriction, including without limitation the rights to use,
  8
+copy, modify, merge, publish, distribute, sublicense, and/or sell
  9
+copies of the Software, and to permit persons to whom the
  10
+Software is furnished to do so, subject to the following
  11
+conditions:
  12
+
  13
+The above copyright notice and this permission notice shall be
  14
+included in all copies or substantial portions of the Software.
  15
+
  16
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  17
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  18
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  19
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  20
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  21
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  22
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  23
+OTHER DEALINGS IN THE SOFTWARE.
  24
+###
  25
+
  26
+
  27
+{test, assert, expect, should} = require './testbase'
  28
+squel = require "../src/squel"
  29
+
  30
+
  31
+
  32
+test['Query builder base class'] =
  33
+  beforeEach: ->
  34
+    @inst = new squel.QueryBuilder()
  35
+
  36
+  '_getObjectClassName': ->
  37
+    s = 'a string'
  38
+    b = new Object()
  39
+    c = new Error()
  40
+    d = 1
  41
+
  42
+    assert.same @inst._getObjectClassName(0), undefined
  43
+    assert.same @inst._getObjectClassName(true), 'Boolean'
  44
+    assert.same @inst._getObjectClassName(1.2), 'Number'
  45
+    assert.same @inst._getObjectClassName('a string'), 'String'
  46
+    assert.same @inst._getObjectClassName(new Object), 'Object'
  47
+    assert.same @inst._getObjectClassName(new Error), 'Error'
  48
+
  49
+  '_sanitizeCondition':
  50
+    beforeEach: ->
  51
+      test.mocker.spy @inst, '_getObjectClassName'
  52
+
  53
+    'if Expression': ->
  54
+      e = squel.expr()
  55
+      console.log typeof e
  56
+      assert.same "", @inst._sanitizeCondition(e)
  57
+      assert.ok @inst._getObjectClassName.calledWithExactly(e)
  58
+
  59
+    'if string': ->
  60
+      s = 'BLA BLA'
  61
+      assert.same 'BLA BLA', @inst._sanitizeCondition(s)
  62
+      assert.ok @inst._getObjectClassName.calledWithExactly(s)
  63
+
  64
+    'if neither Expression nor String': ->
  65
+      test.mocker.spy @inst, '_sanitizeCondition'
  66
+
  67
+      try
  68
+        @inst._sanitizeCondition(1)
  69
+      catch err
  70
+        assert.same err.toString(), 'Error: condition must be a string or Expression instance'
  71
+      finally
  72
+        assert.ok @inst._getObjectClassName.calledWithExactly(1)
  73
+        assert.ok @inst._sanitizeCondition.threw()
  74
+
  75
+  '_sanitizeName':
  76
+    beforeEach: ->
  77
+      test.mocker.spy @inst, '_sanitizeName'
  78
+
  79
+    'if string': ->
  80
+      assert.same 'bla', @inst._sanitizeName('bla')
  81
+
  82
+    'if boolean': ->
  83
+      try
  84
+        @inst._sanitizeName(true, 'bla')
  85
+      catch err
  86
+        assert.same err.toString(), 'Error: bla must be a string'
  87
+      finally
  88
+        assert.ok @inst._sanitizeName.threw()
  89
+
  90
+    'if integer': ->
  91
+      try
  92
+        @inst._sanitizeName(1)
  93
+      catch err
  94
+        assert.same err.toString(), 'Error: undefined must be a string'
  95
+      finally
  96
+        assert.ok @inst._sanitizeName.threw()
  97
+
  98
+    'if float': ->
  99
+      try
  100
+        @inst._sanitizeName(1.2, 'meh')
  101
+      catch err
  102
+        assert.same err.toString(), 'Error: meh must be a string'
  103
+      finally
  104
+        assert.ok @inst._sanitizeName.threw()
  105
+
  106
+    'if array': ->
  107
+      try
  108
+        @inst._sanitizeName([1], 'yes')
  109
+      catch err
  110
+        assert.same err.toString(), 'Error: yes must be a string'
  111
+      finally
  112
+        assert.ok @inst._sanitizeName.threw()
  113
+
  114
+    'if object': ->
  115
+      try
  116
+        @inst._sanitizeName(new Object, 'obj1')
  117
+      catch err
  118
+        assert.same err.toString(), 'Error: obj1 must be a string'
  119
+      finally
  120
+        assert.ok @inst._sanitizeName.threw()
  121
+
  122
+    'if null': ->
  123
+      try
  124
+        @inst._sanitizeName(null, 'obj1')
  125
+      catch err
  126
+        assert.same err.toString(), 'Error: obj1 must be a string'
  127
+      finally
  128
+        assert.ok @inst._sanitizeName.threw()
  129
+
  130
+    'if undefined': ->
  131
+      try
  132
+        @inst._sanitizeName(undefined, 'obj1')
  133
+      catch err
  134
+        assert.same err.toString(), 'Error: obj1 must be a string'
  135
+      finally
  136
+        assert.ok @inst._sanitizeName.threw()
  137
+
  138
+
  139
+  '_sanitizeField': ->
  140
+    test.mocker.spy @inst, '_sanitizeName'
  141
+
  142
+    assert.same 'abc', @inst._sanitizeField('abc')
  143
+
  144
+    assert.ok @inst._sanitizeName.calledWithExactly 'abc', 'field name'
  145
+
  146
+
  147
+  '_sanitizeTable': ->
  148
+    test.mocker.spy @inst, '_sanitizeName'
  149
+
  150
+    assert.same 'abc', @inst._sanitizeTable('abc')
  151
+
  152
+    assert.ok @inst._sanitizeName.calledWithExactly 'abc', 'table name'
  153
+
  154
+
  155
+  '_sanitizeAlias': ->
  156
+    test.mocker.spy @inst, '_sanitizeName'
  157
+
  158
+    assert.same 'abc', @inst._sanitizeAlias('abc')
  159
+
  160
+    assert.ok @inst._sanitizeName.calledWithExactly 'abc', 'alias'
  161
+
  162
+
  163
+  '_sanitizeLimitOffset':
  164
+    'number >= 0': ->
  165
+      assert.same 0, @inst._sanitizeLimitOffset 0
  166
+      assert.same 1, @inst._sanitizeLimitOffset 1
  167
+
  168
+    'number < 0': ->
  169
+      test.mocker.spy @inst, '_sanitizeLimitOffset'
  170
+
  171
+      try
  172
+        @inst._sanitizeLimitOffset -1
  173
+      catch err
  174
+        assert.same err.toString(), 'Error: limit/offset must be >=0'
  175
+      finally
  176
+        assert.ok @inst._sanitizeLimitOffset.threw()
  177
+
  178
+
  179
+  '_sanitizeValue':
  180
+    beforeEach: ->
  181
+      test.mocker.spy @inst, '_sanitizeValue'
  182
+
  183