James B. Orlin

157 papers A* 17A 2B 8C 1Journal 121Unranked 2
YearRankTypeTitle / Venue / Authors
2026 J jnl
CoRR
Christoph Grüne, Berit Johannes, James B. Orlin, Lasse Wulf
2026 A* conf
SODA
Daniel Dadush, James B. Orlin, Aaron Sidford, László A. Végh
2025 J jnl
CoRR
Daniel Dadush, James B. Orlin, Aaron Sidford, László A. Végh
2025 J jnl
INFORMS J. Optim.
Nathan Atkinson, Scott C. Ganz, Dorit S. Hochbaum, James B. Orlin
2023 J jnl
J. ACM
James B. Orlin, László A. Végh
2023 J jnl
CoRR
Nathan Atkinson, Scott C. Ganz, Dorit S. Hochbaum, James B. Orlin
2021 J jnl
Networks
James B. Orlin, Xiao-Yue Gong
2021 A* conf
SODA
James B. Orlin, László A. Végh
2021 B conf
WG
Eranda Çela, Bettina Klinz, Stefan Lendl, James B. Orlin, Gerhard J. Woeginger, Lasse Wulf
2020 J jnl
CoRR
James B. Orlin, László A. Végh
2020 conf
SOSA
Louis L. Chen, Will Ma, James B. Orlin, David Simchi-Levi
2019 J jnl
CoRR
James B. Orlin, Xiao-Yue Gong
2018 J jnl
Discret. Optim.
Nir Halman, Giacomo Nannicini, James B. Orlin
2018 J jnl
Discret. Appl. Math.
James B. Orlin, K. Subramani, Piotr Wojciechowski
2018 J jnl
Math. Program.
James B. Orlin, Andreas S. Schulz, Rajan Udwani
2018 ch.
Handbook of Approximation Algorithms and Metaheuristics (1)
Ravindra K. Ahuja, Özlem Ergun, James B. Orlin, Abraham P. Punnen
2017 A* conf
SODA
James B. Orlin, Antonio Sedeño-Noda
2016 J jnl
Networks
Imke Joormann, James B. Orlin, Marc E. Pfetsch
2016 J jnl
Oper. Res. Lett.
Dimitris Bertsimas, Ebrahim Nasrabadi, James B. Orlin
2016 B conf
IPCO
James B. Orlin, Andreas S. Schulz, Rajan Udwani
2015 J jnl
SIAM J. Optim.
Nir Halman, Giacomo Nannicini, James B. Orlin
2015 J jnl
CoRR
James B. Orlin, Andreas S. Schulz, Rajan Udwani
2014 J jnl
SIAM J. Discret. Math.
Nir Halman, Diego Klabjan, Chung-Lun Li, James B. Orlin, David Simchi-Levi
2013 A conf
ESA
Nir Halman, Giacomo Nannicini, James B. Orlin
2013 J jnl
Networks
James B. Orlin, Balachandran Vaidyanathan
2013 A* conf
STOC
James B. Orlin
2013 J jnl
Inf. Process. Lett.
Edith Elkind, James B. Orlin
2013 J jnl
CoRR
Dimitris Bertsimas, Ebrahim Nasrabadi, James B. Orlin
2013 J jnl
CoRR
Ebrahim Nasrabadi, James B. Orlin
2013 J jnl
Networks
Dorit S. Hochbaum, James B. Orlin
2012 J jnl
Oper. Res.
Mehdi Ghiyasvand, James B. Orlin
2012 J jnl
Oper. Res.
Nir Halman, James B. Orlin, David Simchi-Levi
2011 J jnl
Oper. Res.
Woonghee Tim Huh, Retsef Levi, Paat Rusmevichientong, James B. Orlin
2011 J jnl
Ann. Oper. Res.
Martin Milanic, James B. Orlin, Gábor Rudolf
2011 J jnl
IEEE/ACM Trans. Netw.
Murali S. Kodialam, T. V. Lakshman, James B. Orlin, Sudipta Sengupta
2010 J jnl
J. Discrete Algorithms
James B. Orlin, Kamesh Madduri, K. Subramani, Matthew D. Williamson
2010 conf
Equilibrium Computation
James B. Orlin
2010 A* conf
STOC
James B. Orlin
2010 J jnl
Discret. Math. Algorithms Appl.
Moshe Dror, James B. Orlin, Michael Zhu
2009 J jnl
Math. Oper. Res.
Nir Halman, Diego Klabjan, Mohamed Mostagir, James B. Orlin, David Simchi-Levi
2009 J jnl
Math. Program.
James B. Orlin
2009 A* conf
SODA
Satoru Iwata, James B. Orlin
2009 J jnl
Oper. Res.
Onur Seref, Ravindra K. Ahuja, James B. Orlin
2009 B conf
WADS
James B. Orlin, Abraham P. Punnen, Andreas S. Schulz
2009 ch.
Encyclopedia of Optimization
Ravindra K. Ahuja, Thomas L. Magnanti, James B. Orlin
2009 ch.
Encyclopedia of Optimization
Ravindra K. Ahuja, Thomas L. Magnanti, James B. Orlin
2009 J jnl
IEEE/ACM Trans. Netw.
Murali S. Kodialam, T. V. Lakshman, James B. Orlin, Sudipta Sengupta
2008 B conf
IPCO
James B. Orlin
2008 J jnl
Networks
Agustín Bompadre, James B. Orlin
2008 J jnl
SIAM J. Discret. Math.
Moshe Dror, James B. Orlin
2008 A* conf
SODA
Nir Halman, Diego Klabjan, Chung-Lun Li, James B. Orlin, David Simchi-Levi
2008 J jnl
Comput. Oper. Res.
Mahesh Kumar, James B. Orlin
2008 J jnl
Discret. Appl. Math.
Edmund K. Burke, Moshe Dror, James B. Orlin
2008 J jnl
Transp. Sci.
Balachandran Vaidyanathan, Ravindra K. Ahuja, James B. Orlin
2008 J jnl
Discret. Optim.
James B. Orlin, Andreas S. Schulz, Sudipta Sengupta
2007 B conf
IPCO
James B. Orlin
2007 J jnl
INFORMS J. Comput.
Ravindra K. Ahuja, Jon Goodstein, Amit Mukherjee, James B. Orlin, Dushyant Sharma
2007 J jnl
Oper. Res.
Ravindra K. Ahuja, Arvind Kumar, Krishna C. Jha, James B. Orlin
2007 J jnl
Oper. Res.
Dritan Nace, James B. Orlin
2007 J jnl
IEEE J. Sel. Areas Commun.
Murali S. Kodialam, T. V. Lakshman, James B. Orlin, Sudipta Sengupta
2007 J jnl
INFORMS J. Comput.
Ravindra K. Ahuja, Krishna C. Jha, James B. Orlin, Dushyant Sharma
2007 ch.
Handbook of Approximation Algorithms and Metaheuristics
Özlem Ergun, Abraham P. Punnen, James B. Orlin, Ravindra K. Ahuja
2006 A* conf
INFOCOM
Murali S. Kodialam, T. V. Lakshman, James B. Orlin, Sudipta Sengupta
2006 J jnl
Discret. Optim.
Özlem Ergun, James B. Orlin
2006 J jnl
J. Heuristics
Özlem Ergun, James B. Orlin, Abran Steele-Feldman
2006 J jnl
Oper. Res. Lett.
Özlem Ergun, James B. Orlin
2006 J jnl
Discret. Optim.
Agustín Bompadre, Moshe Dror, James B. Orlin
2006 J jnl
J. ACM
János Csirik, David S. Johnson, Claire Kenyon, James B. Orlin, Peter W. Shor, Richard R. Weber
2006 A* conf
INFOCOM
Murali S. Kodialam, T. V. Lakshman, James B. Orlin, Sudipta Sengupta
2006 J jnl
Int. J. Comput. Geom. Appl.
Moshe Dror, Yusin Lee, James B. Orlin, Valentin Polishchuk
2006 C conf
PATAT
Carol Meyers, James B. Orlin
2005 J jnl
Int. Trans. Oper. Res.
Robert G. Bland, James B. Orlin
2005 J jnl
Math. Program.
Ramkumar Ramaswamy, James B. Orlin, Nilopal Chakravarti
2005 J jnl
Transp. Sci.
Ravindra K. Ahuja, Jian Liu, James B. Orlin, Dushyant Sharma, Larry A. Shughart
2005 B conf
IPCO
Agustín Bompadre, James B. Orlin
2004 J jnl
Algorithmica
Ravindra K. Ahuja, Dorit S. Hochbaum, James B. Orlin
2004 J jnl
Manag. Sci.
Ravindra K. Ahuja, James B. Orlin, Stefano Pallottino, Maria Paola Scaparra, Maria Grazia Scutellà
2004 J jnl
Networks
Ravindra K. Ahuja, Jian Liu, James B. Orlin, Jon Goodstein, Amit Mukherjee
2004 J jnl
SIAM J. Comput.
James B. Orlin, Abraham P. Punnen, Andreas S. Schulz
2004 A* conf
SODA
James B. Orlin, Abraham P. Punnen, Andreas S. Schulz
2004 J jnl
Math. Program.
James B. Orlin, Dushyant Sharma
2003 J jnl
Oper. Res. Lett.
Ravindra K. Ahuja, James B. Orlin, Dushyant Sharma
2003 J jnl
Networks
Ravindra K. Ahuja, James B. Orlin, Stefano Pallottino, Maria Grazia Scutellà
2003 J jnl
Manag. Sci.
Ravindra K. Ahuja, Dorit S. Hochbaum, James B. Orlin
2002 J jnl
Oper. Res. Lett.
Ravindra K. Ahuja, James B. Orlin, Prabha Sharma, P. T. Sokkalingam
2002 J jnl
Discret. Appl. Math.
Ravindra K. Ahuja, Özlem Ergun, James B. Orlin, Abraham P. Punnen
2002 A conf
ESA
Koen M. J. De Bontridder, B. J. Lageweg, Jan Karel Lenstra, James B. Orlin, Leen Stougie
2002 J jnl
Networks
Ravindra K. Ahuja, James B. Orlin
2002 J jnl
CoRR
Neal E. Young, Robert Endre Tarjan, James B. Orlin
2002 J jnl
Transp. Sci.
Ravindra K. Ahuja, James B. Orlin, Stefano Pallottino, Maria Grazia Scutellà
2002 J jnl
Networks
Charu C. Aggarwal, James B. Orlin
2002 J jnl
CoRR
János Csirik, David S. Johnson, Claire Kenyon, James B. Orlin, Peter W. Shor, Richard R. Weber
2001 J jnl
Oper. Res.
Ravindra K. Ahuja, James B. Orlin
2001 J jnl
Oper. Res.
Ravindra K. Ahuja, James B. Orlin
2001 J jnl
Math. Program.
Ravindra K. Ahuja, James B. Orlin, Dushyant Sharma
2000 J jnl
J. Algorithms
Ravindra K. Ahuja, James B. Orlin
2000 J jnl
Comput. Oper. Res.
Ravindra K. Ahuja, James B. Orlin, Ashish Tiwari
2000 J jnl
Networks
P. T. Sokkalingam, Ravindra K. Ahuja, James B. Orlin
2000 A* conf
STOC
János Csirik, David S. Johnson, Claire Kenyon, James B. Orlin, Peter W. Shor, Richard R. Weber
2000 J jnl
SIAM J. Discret. Math.
Lisa Fleischer, James B. Orlin
2000 A* conf
STOC
James B. Orlin, Andreas S. Schulz, Sudipta Sengupta
1999 ch.
Handbook of Discrete and Combinatorial Mathematics
James B. Orlin, Ravindra K. Ahuja, David Simchi-Levi, Sunil Chopra, Bruce L. Golden, B. K. Kaku
1999 J jnl
Oper. Res.
P. T. Sokkalingam, Ravindra K. Ahuja, James B. Orlin
1999 B conf
IPCO
Ravindra K. Ahuja, Dorit S. Hochbaum, James B. Orlin
1998 J jnl
Oper. Res.
Rina R. Schneur, James B. Orlin
1998 J jnl
Math. Program.
Charu C. Aggarwal, Ravindra K. Ahuja, Jianxiu Hao, James B. Orlin
1997 J jnl
Oper. Res.
Paul Mireault, James B. Orlin, Rakesh V. Vohra
1997 J jnl
Math. Program.
James B. Orlin
1997 J jnl
INFORMS J. Comput.
Ravindra K. Ahuja, James B. Orlin
1997 J jnl
Oper. Res. Lett.
Ravindra K. Ahuja, James B. Orlin
1997 J jnl
Oper. Res.
Charu C. Aggarwal, James B. Orlin, Ray P. Tai
1997 J jnl
Math. Oper. Res.
Donald Goldfarb, Zhiying Jin, James B. Orlin
1996 A* conf
SODA
James B. Orlin
1996 J jnl
INFORMS J. Comput.
James B. Orlin
1996 J jnl
INFORMS J. Comput.
Ravindra K. Ahuja, James B. Orlin
1995 J jnl
Networks
Ravindra K. Ahuja, James B. Orlin
1994 J jnl
J. Algorithms
Jianxiu Hao, James B. Orlin
1994 J jnl
Math. Program.
Dimitris Bertsimas, James B. Orlin
1994 J jnl
SIAM J. Comput.
Ravindra K. Ahuja, James B. Orlin, Clifford Stein, Robert Endre Tarjan
1993 J jnl
Oper. Res.
James B. Orlin
1993 J jnl
Math. Program.
Shinji Mizuno, Romesh Saigal, James B. Orlin
1993 J jnl
Networks
Mark Hartmann, James B. Orlin
1993 book
Network flows - theory, algorithms and applications.
Ravindra K. Ahuja, Thomas L. Magnanti, James B. Orlin
1993 J jnl
Oper. Res. Lett.
James B. Orlin, Clifford Stein
1993 J jnl
Math. Program.
James B. Orlin, Serge A. Plotkin, Éva Tardos
1993 J jnl
Discret. Appl. Math.
Randy Shull, Alan Shuchat, James B. Orlin, Marianne Lepp
1992 A* conf
SODA
Jianxiu Hao, James B. Orlin
1992 B conf
IPCO
Dimitris Bertsimas, James B. Orlin
1992 J jnl
Math. Program.
Ravindra K. Ahuja, Andrew V. Goldberg, James B. Orlin, Robert Endre Tarjan
1992 J jnl
Math. Program.
James B. Orlin, Ravindra K. Ahuja
1992 J jnl
Oper. Res.
Ravindra K. Ahuja, James B. Orlin
1991 J jnl
Networks
Neal E. Young, Robert Endre Tarjan, James B. Orlin
1991 A* conf
SODA
Murali S. Kodialam, James B. Orlin
1991 J jnl
SIAM Rev.
Ravindra K. Ahuja, Thomas L. Magnanti, James B. Orlin
1990 J jnl
J. ACM
Ravindra K. Ahuja, Kurt Mehlhorn, James B. Orlin, Robert Endre Tarjan
1990 J jnl
Math. Program.
James B. Orlin, John H. Vande Vate
1989 J jnl
Oper. Res.
Ravindra K. Ahuja, James B. Orlin
1989 J jnl
SIAM J. Comput.
Ravindra K. Ahuja, James B. Orlin, Robert Endre Tarjan
1989 J jnl
Discret. Appl. Math.
Randy Shull, James B. Orlin, Alan Shuchat, Marianne L. Gardner
1988 A* conf
STOC
James B. Orlin
1988 J jnl
Math. Program.
Thomas L. Magnanti, James B. Orlin
1985 J jnl
Networks
Stephen C. Graves, James B. Orlin
1985 J jnl
Math. Program.
James B. Orlin, Uriel G. Rothblum
1985 J jnl
Oper. Res.
Amiya K. Chakravarty, James B. Orlin, Uriel G. Rothblum
1985 J jnl
J. Algorithms
Zevi Miller, James B. Orlin
1985 J jnl
Math. Program.
Robert M. Freund, James B. Orlin
1985 J jnl
Oper. Res.
James B. Orlin
1984 J jnl
Math. Oper. Res.
James B. Orlin
1983 J jnl
Networks
James B. Orlin
1983 J jnl
Networks
James B. Orlin
1983 J jnl
Math. Program.
James B. Orlin
1982 J jnl
Math. Program.
James B. Orlin
1982 J jnl
Oper. Res.
James B. Orlin
1981 J jnl
Discret. Appl. Math.
Richard M. Karp, James B. Orlin
1981 A* conf
STOC
James B. Orlin
1980 J jnl
Oper. Res.
John J. Bartholdi III, James B. Orlin, H. Donald Ratliff
1978 J jnl
J. Comb. Theory B
James B. Orlin
redb/extractors/decompiler/DecompileAPK.py
← Index redb/extractors/decompiler/DecompileAPK.py python
"""APK Code Analysis Extractor.

Decompiles and disassembles APK DEX bytecode at the method level,
producing per-method content and reference records analogous to
the Binary Ninja code_binja_* tables.

Uses androguard + JADX + apktool to replicate Binary Ninja analysis
depth for Android applications.
"""

import gc
import hashlib
import inspect
import logging
import os
import threading
import time
from datetime import datetime, timezone
from typing import Any, Dict, Optional

from redb.extractors.decompiler.apk.analyzer import APKCodeAnalyzer
from redb.extractors.enum import Tag
from redb.extractors.extractor import Extractor


class DecompileAPK(Extractor):
    """APK code analysis extractor — produces multi-table ClickHouse export.

    Follows the same pattern as DecompileBinja for consistency.
    """

    def __init__(
        self,
        filepath,
        log,
        exporters=None,
        index_prefix=None,
        known_benign=False,
        known_malicious=False,
        filetype=None,
        decompile_modules=None,
    ):
        super().__init__(
            filepath,
            log,
            exporters,
            index_prefix,
            known_benign=known_benign,
            known_malicious=known_malicious,
        )
        self.log.debug(inspect.currentframe().f_code.co_name)
        self.analysis_results = None
        self.analyzer = None
        self.filetype = filetype or "apk"
        self.decompile_modules = decompile_modules or {"all"}

        try:
            self.APK_DECOMPILE_TIMEOUT = int(
                os.getenv("APK_DECOMPILE_TIMEOUT", "600")
            )
        except ValueError:
            self.log.warning(
                "Invalid APK_DECOMPILE_TIMEOUT value, using default of 600 seconds"
            )
            self.APK_DECOMPILE_TIMEOUT = 600

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.cleanup_run()

    def calculate_md5(self, input_str):
        """Calculate MD5 hash of a string."""
        return hashlib.md5(input_str.encode("utf-8")).hexdigest()

    def cleanup_run(self):
        """Clean up after analysis."""
        try:
            if self.analyzer:
                self.analyzer.cleanup()
                self.analyzer = None
            gc.collect()
        except Exception as e:
            self.log.error(f"Error in cleanup: {e}")

    def analyze_apk(self) -> Optional[Dict[str, Any]]:
        """Run APK code analysis and return results."""
        self.log.debug("Starting APK code analysis")
        try:
            self.analyzer = APKCodeAnalyzer(
                filepath=self.filepath,
                timeout=self.APK_DECOMPILE_TIMEOUT,
                log=self.log,
                decompile_modules=self.decompile_modules,
            )
            results = self.analyzer.extract()
            return results
        except Exception as e:
            self.log.error(f"Error in APK code analysis: {e}")
            import traceback
            self.log.error(f"Traceback: {traceback.format_exc()}")
            return None
        finally:
            self.cleanup_run()

    def extract(self):
        """Extract and process all analysis results.

        Uses daemon thread with timeout, same pattern as DecompileBinja.
        """
        self.log.debug(inspect.currentframe().f_code.co_name)

        extraction_completed = False
        extraction_result = False
        extraction_error = None

        def do_extraction():
            nonlocal extraction_completed, extraction_result, extraction_error
            try:
                results = self.analyze_apk()
                if not results:
                    extraction_result = False
                else:
                    self.analysis_results = results
                    self.analysis_results["sha256"] = self.sha256
                    self.analysis_results["sha1"] = self.sha1
                    self.analysis_results["md5"] = self.md5
                    extraction_result = True
            except Exception as e:
                extraction_error = e
                extraction_result = False
            finally:
                extraction_completed = True

        extraction_thread = threading.Thread(target=do_extraction)
        extraction_thread.daemon = True
        extraction_thread.start()

        start_time = time.time()
        while (
            not extraction_completed
            and (time.time() - start_time) < self.APK_DECOMPILE_TIMEOUT
        ):
            time.sleep(1)

        if not extraction_completed:
            self.log.error(
                f"APK extraction timed out after {self.APK_DECOMPILE_TIMEOUT} seconds"
            )
            self.cleanup_run()
            return None

        if extraction_error:
            self.log.error(f"Error in APK extraction: {extraction_error}")
            return None

        return self.analysis_results if extraction_result else None

    def prepare_export_data(self, exporter_type: str) -> Any:
        """Prepare data for database export."""
        self.log.debug(inspect.currentframe().f_code.co_name)
        if not self.analysis_results:
            return None

        if exporter_type == "ClickHouseExporter":
            now = datetime.now(timezone.utc)
            export = {"multi_table": True}

            # Table 1: Decompiled method content
            if self.analysis_results.get("decompiled_content"):
                export["decompiled_content"] = {
                    "table": "code_apk_decompiled_methods_content",
                    "data": [
                        [
                            f["decompiled_method_hash"],
                            f["decompiled_method"],
                            f.get("decompiled_method_type", "UNKNOWN"),
                            1 if f.get("decompiled_has_string_encryption") else 0,
                            1 if f.get("decompiled_has_reflection_calls") else 0,
                            1 if f.get("decompiled_excessive_goto_count") else 0,
                            now,
                        ]
                        for f in self.analysis_results["decompiled_content"]
                    ],
                    "column_names": [
                        "decompiled_method_hash",
                        "decompiled_method",
                        "decompiled_method_type",
                        "decompiled_has_string_encryption",
                        "decompiled_has_reflection_calls",
                        "decompiled_excessive_goto_count",
                        "analysis_date",
                    ],
                    "column_type_names": [
                        "FixedString(64)",
                        "String",
                        "Enum8('USER'=1, 'LIBRARY'=2, 'UNKNOWN'=5)",
                        "UInt8",
                        "UInt8",
                        "UInt8",
                        "DateTime64(3, 'UTC')",
                    ],
                }

            # Table 2: Decompiled method references
            if self.analysis_results.get("decompiled_refs"):
                export["decompiled_refs"] = {
                    "table": "code_apk_decompiled_methods_references",
                    "data": [
                        [
                            self.analysis_results["sha256"],
                            f["decompiled_method_hash"],
                            f.get("smali_method_hash"),
                            f.get("decompiled_class_name", ""),
                            f.get("decompiled_method_name", ""),
                            f.get("decompiled_method_signature", ""),
                            f.get("decompiled_method_prototype", ""),
                            f.get("functions_caller", []),
                            f.get("functions_call", []),
                            now,
                        ]
                        for f in self.analysis_results["decompiled_refs"]
                    ],
                    "column_names": [
                        "sha256",
                        "decompiled_method_hash",
                        "smali_method_hash",
                        "decompiled_class_name",
                        "decompiled_method_name",
                        "decompiled_method_signature",
                        "decompiled_method_prototype",
                        "functions_caller",
                        "functions_call",
                        "analysis_date",
                    ],
                    "column_type_names": [
                        "FixedString(64)",
                        "FixedString(64)",
                        "Nullable(FixedString(64))",
                        "LowCardinality(String)",
                        "LowCardinality(String)",
                        "String",
                        "String",
                        "Array(String)",
                        "Array(String)",
                        "DateTime64(3, 'UTC')",
                    ],
                }

            # Table 3: Smali method content
            if self.analysis_results.get("smali_content"):
                export["smali_content"] = {
                    "table": "code_apk_smali_methods_content",
                    "data": [
                        [
                            f["smali_method_hash"],
                            f["smali_method"],
                            f.get("smali_method_type", "UNKNOWN"),
                            f.get("smali_instructions_count", 0),
                            f.get("smali_register_count", 0),
                            1 if f.get("smali_has_string_encryption") else 0,
                            1 if f.get("smali_has_reflection_calls") else 0,
                            1 if f.get("smali_excessive_goto_count") else 0,
                            f.get("smali_flattened_score", 0.0),
                            f.get("smali_mba_score", 0.0),
                            now,
                        ]
                        for f in self.analysis_results["smali_content"]
                    ],
                    "column_names": [
                        "smali_method_hash",
                        "smali_method",
                        "smali_method_type",
                        "smali_instructions_count",
                        "smali_register_count",
                        "smali_has_string_encryption",
                        "smali_has_reflection_calls",
                        "smali_excessive_goto_count",
                        "smali_flattened_score",
                        "smali_mba_score",
                        "analysis_date",
                    ],
                    "column_type_names": [
                        "FixedString(64)",
                        "String",
                        "Enum8('USER'=1, 'LIBRARY'=2, 'UNKNOWN'=5)",
                        "UInt32",
                        "UInt16",
                        "UInt8",
                        "UInt8",
                        "UInt8",
                        "Float64",
                        "Float64",
                        "DateTime64(3, 'UTC')",
                    ],
                }

            # Table 4: Smali method references
            if self.analysis_results.get("smali_refs"):
                export["smali_refs"] = {
                    "table": "code_apk_smali_methods_references",
                    "data": [
                        [
                            self.analysis_results["sha256"],
                            f["smali_method_hash"],
                            f.get("decompiled_method_hash"),
                            f.get("smali_class_name", ""),
                            f.get("smali_method_name", ""),
                            f.get("smali_method_signature", ""),
                            now,
                        ]
                        for f in self.analysis_results["smali_refs"]
                    ],
                    "column_names": [
                        "sha256",
                        "smali_method_hash",
                        "decompiled_method_hash",
                        "smali_class_name",
                        "smali_method_name",
                        "smali_method_signature",
                        "analysis_date",
                    ],
                    "column_type_names": [
                        "FixedString(64)",
                        "FixedString(64)",
                        "Nullable(FixedString(64))",
                        "LowCardinality(String)",
                        "LowCardinality(String)",
                        "String",
                        "DateTime64(3, 'UTC')",
                    ],
                }

            # Table 5: Method similarity metrics (content-based fuzzy matching)
            if self.analysis_results.get("similarity_metrics"):
                export["method_similarity_metrics"] = {
                    "table": "code_apk_method_similarity_metrics",
                    "data": [
                        [
                            f["smali_method_hash"],
                            f.get("ssdeep_smali"),
                            f.get("tlsh_smali"),
                            f.get("ssdeep_smali_normalized"),
                            f.get("tlsh_smali_normalized"),
                            f.get("minhash", []),
                            now,
                        ]
                        for f in self.analysis_results["similarity_metrics"]
                    ],
                    "column_names": [
                        "smali_method_hash",
                        "ssdeep_smali",
                        "tlsh_smali",
                        "ssdeep_smali_normalized",
                        "tlsh_smali_normalized",
                        "minhash",
                        "analysis_date",
                    ],
                    "column_type_names": [
                        "FixedString(64)",
                        "Nullable(String)",
                        "Nullable(FixedString(72))",
                        "Nullable(String)",
                        "Nullable(FixedString(72))",
                        "Array(UInt8)",
                        "DateTime64(3, 'UTC')",
                    ],
                }

            # Table 5b: CFG method features (structural/topological)
            if self.analysis_results.get("cfg"):
                export["cfg_methods"] = {
                    "table": "code_apk_cfg_methods",
                    "data": [
                        [
                            cfg["smali_method_hash"],
                            cfg["cfg_topology_hash"],
                            cfg["block_count"],
                            cfg["edge_count"],
                            cfg.get("cfg_instructions_count", 0),
                            cfg.get("call_count", 0),
                            cfg["cyclomatic_complexity"],
                            cfg.get("loop_count", 0),
                            cfg.get("max_depth", 0),
                            cfg.get("max_fan_out", 0),
                            cfg.get("md_index_topdown", 0),
                            cfg.get("md_index_bottomup", 0),
                            cfg.get("prime_product_smali", 0),
                            cfg.get("cfg_feature_tlsh"),
                            cfg.get("wl_minhash", []),
                            cfg.get("bb_features", []),
                            cfg.get("cfg_adjacency", []),
                            now,
                        ]
                        for cfg in self.analysis_results["cfg"]
                        if cfg is not None
                    ],
                    "column_names": [
                        "smali_method_hash",
                        "cfg_topology_hash",
                        "block_count",
                        "edge_count",
                        "cfg_instructions_count",
                        "call_count",
                        "cyclomatic_complexity",
                        "loop_count",
                        "max_depth",
                        "max_fan_out",
                        "md_index_topdown",
                        "md_index_bottomup",
                        "prime_product_smali",
                        "cfg_feature_tlsh",
                        "wl_minhash",
                        "bb_features",
                        "cfg_adjacency",
                        "analysis_date",
                    ],
                    "column_type_names": [
                        "FixedString(64)",
                        "FixedString(16)",
                        "UInt16",
                        "UInt16",
                        "UInt32",
                        "UInt16",
                        "UInt16",
                        "UInt16",
                        "UInt16",
                        "UInt16",
                        "UInt64",
                        "UInt64",
                        "UInt64",
                        "Nullable(FixedString(72))",
                        "Array(UInt8)",
                        "Array(Array(UInt16))",
                        "Array(UInt32)",
                        "DateTime64(3, 'UTC')",
                    ],
                }

            # Table 6: Strings — reuse code_binja_strings_raw for cross-format correlation
            # DEX strings are MUTF-8; string_raw = string since no encoding difference
            if self.analysis_results.get("strings"):
                export["strings_raw"] = {
                    "table": "code_binja_strings_raw",
                    "data": [
                        [
                            self.analysis_results["sha256"],
                            s["string"],
                            s["string"],  # string_raw = string (MUTF-8 decoded to UTF-8)
                            s.get("string_encoding", "UTF8"),
                            s.get("string_offset", 0),
                            s.get("string_length", len(s["string"])),
                            s.get("string_length", len(s["string"])),  # string_raw_length = string_length
                            s.get("string_entropy", 0.0),
                        ]
                        for s in self.analysis_results["strings"]
                    ],
                    "column_names": [
                        "sha256",
                        "string",
                        "string_raw",
                        "string_encoding",
                        "string_offset",
                        "string_length",
                        "string_raw_length",
                        "string_entropy",
                    ],
                    "column_type_names": [
                        "FixedString(64)",
                        "String",
                        "String",
                        "LowCardinality(String)",
                        "UInt64",
                        "UInt32",
                        "UInt32",
                        "Float32",
                    ],
                }

            # Table 7: Analysis errors
            if self.analysis_results.get("analysis_errors"):
                export["analysis_errors"] = {
                    "table": "code_apk_analysis_errors",
                    "data": [
                        [
                            self.analysis_results["sha256"],
                            f.get("class_name"),
                            f.get("method_name"),
                            f.get("error_location", "unknown"),
                            f.get("error_message", ""),
                            f.get("error_type", "unknown"),
                            self.calculate_md5(
                                f"{f.get('error_message', '')}"
                                f"{f.get('class_name', '')}"
                                f"{f.get('method_name', '')}"
                                f"{f.get('error_location', 'unknown')}"
                            ),
                            "new",
                            now,
                        ]
                        for f in self.analysis_results["analysis_errors"]
                    ],
                    "column_names": [
                        "sha256",
                        "class_name",
                        "method_name",
                        "error_location",
                        "error_message",
                        "error_type",
                        "error_hash",
                        "status",
                        "analysis_date",
                    ],
                    "column_type_names": [
                        "FixedString(64)",
                        "Nullable(String)",
                        "Nullable(String)",
                        "LowCardinality(String)",
                        "Nullable(String)",
                        "Nullable(String)",
                        "FixedString(32)",
                        "Enum8('new'=1, 'investigating'=2, 'fixed'=3, 'wontfix'=4)",
                        "DateTime64(3, 'UTC')",
                    ],
                }

            return export

        return None

    def tag(self) -> str:
        """Return the tag for this extractor."""
        return Tag.APK_DECOMPILED.value

    def get_clickhouse_table(self) -> str:
        """Not used directly as we're handling multiple tables."""
        pass