Index: setup.py
===================================================================
--- setup.py	(revision 18049)
+++ setup.py	(working copy)
@@ -21,5 +21,4 @@
             "sqlquery.macro = sqlquery.macro"
         ]
     },
-    install_requires = ['pymills']
 )
Index: sqlquery/macro.py
===================================================================
--- sqlquery/macro.py	(revision 18049)
+++ sqlquery/macro.py	(working copy)
@@ -1,23 +1,15 @@
 # -*- coding: utf-8 -*-
 
 import inspect
-from StringIO import StringIO
+import re
 
 from trac.config import Option
-from trac.core import *
-from trac.db.api import get_column_names
-from trac.web.chrome import web_context
+from trac.core import Component, implements
+from trac.db.api import DatabaseManager, get_column_names
+from trac.util.html import tag
 from trac.wiki.macros import IWikiMacroProvider
-from trac.wiki.formatter import format_to_html
 
-try:
-    from pymills.db import Connection
-except ImportError:
-    from pymills.dbapi import Connection
-from pymills.datatypes import OrderedDict
-from pymills.table import Table, Header, Row, Cell
 
-
 class SqlQueryMacro(Component):
     """
     A macro to execute an SQL query against a
@@ -47,61 +39,83 @@
         if args is None:
             return "No query defined!"
 
-        sql = str(args).strip()
+        sql = unicode(args).strip()
+        if not re.match(r'\s*SELECT\s', sql, re.I):
+            raise ValueError('Only SELECT query is allowed')
 
+        def execute_query(cnx):
+            cursor = cnx.cursor()
+            cursor.execute(sql)
+            records = cursor.fetchall()
+            fields = get_column_names(cursor)
+            return records, fields
+
         if self.uri:
-            db = Connection(self.uri)
+            dbm = SqlQueryDatabaseManager(self.env)
+            connector, kwargs = dbm.get_connector()
+            cnx = connector.get_connection(**kwargs)
             try:
-                records = db.do(sql)
+                records, fields = execute_query(cnx)
             finally:
-                db.rollback()
-                db.close()
-            if records:
-                fields = [x for x in records[0].keys()
-                            if not x.startswith("__") and not x.endswith("__")]
+                cnx.rollback()
+                cnx.close()
         else:
             with self.env.db_query as db:
-                cursor = db.cursor()
-                cursor.execute(sql)
-                records = cursor.fetchall()
-                fields = get_column_names(cursor)
+                records, fields = execute_query(db)
 
-        if records:
-            headers = [Header(f) for f in fields]
-            groups = OrderedDict()
+        if not records:
+            return tag.div('No results')
+
+        try:
+            group_idx = fields.index('__group__')
+        except ValueError:
+            groups = {None: records}
+            group_vals = [None]
+        else:
+            groups = {}
+            group_vals = []
             for record in records:
-                style = ""
+                group = record[group_idx]
+                if group not in groups:
+                    group_vals.append(group)
+                    groups[group] = []
+                groups[group].append(record)
 
-                if "__color__" in record:
-                    style += "background-color: %s" % record["__color__"]
-                    record.remove("__color__")
+        div = tag.div()
+        for group in group_vals:
+            if group is not None:
+                div.append(tag.h3(group))
+            table = tag.table(class_='wiki')
+            thead = tag.thead(tag.tr(tag.th(field)
+                              for field in fields
+                              if field not in ('__color__', '__group__')))
+            tbody = tag.tbody()
+            for record in groups[group]:
+                cells = []
+                style = None
+                for idx, field in enumerate(fields):
+                    value = record[idx]
+                    if field == '__color__':
+                        if isinstance(value, basestring) and ';' not in value:
+                            style = 'background-color:' + value
+                        continue
+                    if field == '__group__':
+                        continue
+                    if value is None:
+                        cell = tag.td('NULL')
+                    elif isinstance(value, (int, long, float)):
+                        cell = tag.td('%g' % value, style='text-align:right')
+                    else:
+                        cell = tag.td(value)
+                    cells.append(cell)
+                tbody.append(tag.tr(cells, style=style))
+            table.append([thead, tbody])
+            div.append(table)
+        return div
 
-                if "__group__" in record:
-                    group = record["__group__"]
-                    record.remove("__group__")
-                    row = Row([Cell(v) for v in record], style=style)
-                    if group not in groups:
-                        groups[group] = []
-                    groups[group].append(row)
-                else:
-                    row = Row([Cell(v) for v in record], style=style)
-                    if None not in groups:
-                        groups[None] = []
-                    groups[None].append(row)
 
-            s = StringIO()
-            for group, rows in groups.iteritems():
-                t = Table(headers, rows, cls="wiki")
-                t.refresh()
-                if group:
-                    s.write("=== %s ===\n" % group)
-                s.write("{{{#!html\n")
-                s.write(t.toHTML())
-                s.write("\n}}}\n")
+class SqlQueryDatabaseManager(DatabaseManager):
 
-            v = s.getvalue()
-            s.close()
-            context = web_context(formatter.req)
-            return format_to_html(self.env, context, v)
-        else:
-            return "No results"
+    @property
+    def connection_uri(self):
+        return SqlQueryMacro(self.env).uri
