    private String sanitizeColumnName(String input)
    {
        if (input == null) return "";
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < input.length(); i++)
        {
            char c = input.charAt(i);
            if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_' || c == '-')
            {
                sb.append(c);
            }
            else
            {
                sb.append('_');
            }
        }
        return sb.toString();
    }

    public List<__@@@TABLE@@@__> toList()
    {
        return toList(null);
    }

    public List<__@@@TABLE@@@__> toList(String[] columns)
    {
        List<__@@@TABLE@@@__> list = new ArrayList<>();
        orma_global_sqltolist_lock.lock();
        PreparedStatement statement = null;
        boolean selectAll = (columns == null || columns.length == 0);
        Set<String> selectedCols = new LinkedHashSet<>();
        if (!selectAll) {
            for (String c : columns) {
                if (c == null || c.length() == 0) continue;
                selectedCols.add(sanitizeColumnName(c.toLowerCase()));
            }
            if (selectedCols.isEmpty()) selectAll = true;
        }
        try
        {
            if (!selectAll)
            {
                StringBuilder cols = new StringBuilder();
                boolean firstColumn = true;
                for (String col : selectedCols)
                {
                    if (!firstColumn) cols.append(", ");
                    cols.append("\"").append(col).append("\"");
                    firstColumn = false;
                }
                if (this.sql_start != null && this.sql_start.contains("*"))
                {
                    this.sql_start = this.sql_start.replace("*", cols.toString());
                }
                else
                {
                    this.sql_start = "SELECT " + cols.toString() + " FROM \"" + this.getClass().getSimpleName() + "\"";
                }
            }

            final String sql = this.sql_start + " " + this.sql_where + " " + this.sql_orderby + " " + this.sql_limit;
            log_bindvars_where(sql, bind_where_count, bind_where_vars);
            final long t1 = System.currentTimeMillis();
            statement = sqldb.prepareStatement(sql);
            if (!set_bindvars_where(statement, bind_where_count, bind_where_vars))
            {
                try
                {
                    statement.close();
                }
                catch (Exception ignored)
                {
                }
                return null;
            }
            ResultSet rs = statement.executeQuery();
            final long t2 = System.currentTimeMillis();
            if (ORMA_LONG_RUNNING_TRACE)
            {
                if ((t2 - t1) > ORMA_LONG_RUNNING_MS)
                {
                    Log.i(TAG, "long running (" + (t2 - t1)+ " ms) sql=" + sql);
                }
            }
            final long t3 = System.currentTimeMillis();
            while (rs.next())
            {
