sqlshell 0.1.6__py3-none-any.whl → 0.1.8__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of sqlshell might be problematic. Click here for more details.

@@ -0,0 +1 @@
1
+ # SQLShell resources package initialization
@@ -0,0 +1,53 @@
1
+ import os
2
+ from PIL import Image, ImageDraw, ImageFont
3
+
4
+ def create_sql_icon(output_path, size=256):
5
+ """Create a simple SQL icon"""
6
+ # Create a new image with a transparent background
7
+ img = Image.new('RGBA', (size, size), (0, 0, 0, 0))
8
+ draw = ImageDraw.Draw(img)
9
+
10
+ # Define colors
11
+ primary_color = (44, 62, 80, 255) # Dark blue-gray
12
+ secondary_color = (52, 152, 219, 255) # Bright blue
13
+ accent_color = (26, 188, 156, 255) # Teal
14
+
15
+ # Draw a rounded rectangle background
16
+ radius = size // 10
17
+ rect = [(size//8, size//8), (size - size//8, size - size//8)]
18
+ draw.rounded_rectangle(rect, radius, fill=primary_color)
19
+
20
+ # Try to load a font, fall back to default if not available
21
+ try:
22
+ font_size = size // 3
23
+ font = ImageFont.truetype("arial.ttf", font_size)
24
+ except IOError:
25
+ try:
26
+ font = ImageFont.truetype("DejaVuSans.ttf", font_size)
27
+ except IOError:
28
+ font = ImageFont.load_default()
29
+
30
+ # Draw SQL text
31
+ text = "SQL"
32
+ text_width, text_height = draw.textsize(text, font=font) if hasattr(draw, 'textsize') else font.getsize(text)
33
+ position = ((size - text_width) // 2, (size - text_height) // 2)
34
+ draw.text(position, text, fill=accent_color, font=font)
35
+
36
+ # Draw a small database icon
37
+ db_size = size // 4
38
+ db_x = size // 2 - db_size // 2
39
+ db_y = size // 2 + text_height // 2 + db_size // 2
40
+
41
+ # Draw database cylinder
42
+ draw.ellipse([(db_x, db_y - db_size//3), (db_x + db_size, db_y)], fill=secondary_color)
43
+ draw.ellipse([(db_x, db_y + db_size//3), (db_x + db_size, db_y + db_size//1.5)], fill=secondary_color)
44
+ draw.rectangle([(db_x, db_y), (db_x + db_size, db_y + db_size//3)], fill=secondary_color)
45
+
46
+ # Save the image
47
+ img.save(output_path)
48
+ print(f"Icon created at {output_path}")
49
+
50
+ if __name__ == "__main__":
51
+ output_dir = os.path.dirname(os.path.abspath(__file__))
52
+ output_path = os.path.join(output_dir, "icon.png")
53
+ create_sql_icon(output_path)
@@ -0,0 +1,66 @@
1
+ from PIL import Image, ImageDraw, ImageFont
2
+ import os
3
+ import math
4
+
5
+ def create_frame(size, progress, text=None): # We won't use text parameter anymore
6
+ # Create a new image with a dark background
7
+ img = Image.new('RGBA', size, (44, 62, 80, 255)) # Dark blue-gray background
8
+ draw = ImageDraw.Draw(img)
9
+
10
+ # Calculate dimensions
11
+ width, height = size
12
+ center_x = width // 2
13
+ center_y = height // 2
14
+
15
+ # Create a subtle circular pattern
16
+ radius = 60
17
+ num_dots = 12
18
+ dot_size = 4
19
+ trail_length = 6
20
+
21
+ for i in range(num_dots):
22
+ # Calculate dot position
23
+ angle = (progress * 360 - i * (360 / num_dots)) % 360
24
+ x = center_x + radius * math.cos(math.radians(angle))
25
+ y = center_y + radius * math.sin(math.radians(angle))
26
+
27
+ # Calculate dot opacity based on position in trail
28
+ opacity = int(255 * (1 - (i / trail_length))) if i < trail_length else 0
29
+
30
+ if opacity > 0:
31
+ # Draw dot with gradient effect
32
+ for size_mult in [1.0, 0.8, 0.6]:
33
+ current_size = int(dot_size * size_mult)
34
+ current_opacity = int(opacity * size_mult)
35
+ draw.ellipse(
36
+ (x - current_size, y - current_size,
37
+ x + current_size, y + current_size),
38
+ fill=(52, 152, 219, current_opacity) # Bright blue with fading opacity
39
+ )
40
+
41
+ return img
42
+
43
+ def create_splash_gif():
44
+ size = (400, 300)
45
+ frames = []
46
+
47
+ # Create 60 frames for smooth animation
48
+ for i in range(60):
49
+ progress = i / 60
50
+ frame = create_frame(size, progress)
51
+ frames.append(frame)
52
+
53
+ # Save the animated GIF
54
+ output_path = os.path.join(os.path.dirname(__file__), "splash_screen.gif")
55
+ frames[0].save(
56
+ output_path,
57
+ save_all=True,
58
+ append_images=frames[1:],
59
+ duration=50, # 50ms per frame = 20fps
60
+ loop=0,
61
+ optimize=False
62
+ )
63
+ print(f"Created splash screen GIF at: {output_path}")
64
+
65
+ if __name__ == "__main__":
66
+ create_splash_gif()
Binary file
@@ -0,0 +1,177 @@
1
+ from PyQt6.QtWidgets import QWidget, QLabel, QVBoxLayout
2
+ from PyQt6.QtCore import Qt, QTimer, QPropertyAnimation, QEasingCurve, QPoint, QRect, pyqtProperty
3
+ from PyQt6.QtGui import QPainter, QColor, QFont, QMovie, QPainterPath, QLinearGradient
4
+ import os
5
+
6
+ class AnimatedSplashScreen(QWidget):
7
+ def __init__(self):
8
+ super().__init__()
9
+
10
+ # Initialize properties for animations first
11
+ self._opacity = 0.0
12
+ self._progress = 0.0
13
+ self.next_widget = None
14
+
15
+ # Set up the window properties
16
+ self.setWindowFlags(
17
+ Qt.WindowType.WindowStaysOnTopHint |
18
+ Qt.WindowType.FramelessWindowHint |
19
+ Qt.WindowType.SplashScreen
20
+ )
21
+
22
+ # Set widget attributes for proper compositing
23
+ self.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground)
24
+ self.setAttribute(Qt.WidgetAttribute.WA_NoSystemBackground)
25
+ self.setAttribute(Qt.WidgetAttribute.WA_TransparentForMouseEvents, False)
26
+
27
+ # Set fixed size
28
+ self.setFixedSize(400, 300)
29
+
30
+ # Center the splash screen on the screen
31
+ screen_geometry = self.screen().geometry()
32
+ self.move(
33
+ (screen_geometry.width() - self.width()) // 2,
34
+ (screen_geometry.height() - self.height()) // 2
35
+ )
36
+
37
+ # Create layout
38
+ layout = QVBoxLayout(self)
39
+ layout.setContentsMargins(20, 20, 20, 20)
40
+ layout.setSpacing(10)
41
+
42
+ # Create background container for the title and subtitle
43
+ self.content_container = QWidget(self)
44
+ content_layout = QVBoxLayout(self.content_container)
45
+ content_layout.setContentsMargins(20, 20, 20, 20)
46
+ content_layout.setSpacing(10)
47
+
48
+ # Create title label
49
+ self.title_label = QLabel("SQLShell", self.content_container)
50
+ self.title_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
51
+ self.title_label.setStyleSheet("""
52
+ QLabel {
53
+ color: #3498DB;
54
+ font-size: 32px;
55
+ font-weight: bold;
56
+ font-family: 'Segoe UI', Arial, sans-serif;
57
+ background: transparent;
58
+ }
59
+ """)
60
+ content_layout.addWidget(self.title_label)
61
+
62
+ # Create subtitle label
63
+ self.subtitle_label = QLabel("Loading...", self.content_container)
64
+ self.subtitle_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
65
+ self.subtitle_label.setStyleSheet("""
66
+ QLabel {
67
+ color: #2C3E50;
68
+ font-size: 16px;
69
+ font-family: 'Segoe UI', Arial, sans-serif;
70
+ background: transparent;
71
+ }
72
+ """)
73
+ content_layout.addWidget(self.subtitle_label)
74
+
75
+ # Add content container to main layout
76
+ layout.addWidget(self.content_container)
77
+
78
+ # Create movie label (background)
79
+ self.movie_label = QLabel(self)
80
+ self.movie_label.setGeometry(0, 0, self.width(), self.height())
81
+ self.movie_label.lower() # Put it at the back
82
+
83
+ # Create overlay for fade effect (between movie and content)
84
+ self.overlay = QLabel(self)
85
+ self.overlay.setStyleSheet("background-color: rgba(0, 0, 0, 0);")
86
+ self.overlay.setGeometry(0, 0, self.width(), self.height())
87
+ self.overlay.lower() # Put it behind the content but above the movie
88
+
89
+ # Create text label for animated text
90
+ self.text_label = QLabel(self)
91
+ self.text_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
92
+ self.text_label.setStyleSheet("color: rgba(255, 255, 255, 0); background: transparent;")
93
+ self.text_label.setGeometry(0, 0, self.width(), self.height())
94
+ self.text_label.lower() # Put it behind the content
95
+
96
+ # Create progress bar (always on top)
97
+ self.progress_bar = QLabel(self)
98
+ self.progress_bar.setFixedHeight(4)
99
+ self.progress_bar.setStyleSheet("background-color: #3498DB; border-radius: 2px;")
100
+ self.progress_bar.move(100, self.height() - 40)
101
+ self.progress_bar.setFixedWidth(0)
102
+ self.progress_bar.raise_() # Ensure it's on top
103
+
104
+ # Set up the loading animation
105
+ self.movie = QMovie(os.path.join(os.path.dirname(__file__), "resources", "splash_screen.gif"))
106
+ self.movie.setScaledSize(self.size())
107
+ self.movie_label.setMovie(self.movie)
108
+
109
+ # Set up fade animation
110
+ self.fade_anim = QPropertyAnimation(self, b"opacity")
111
+ self.fade_anim.setDuration(1000)
112
+ self.fade_anim.setStartValue(0.0)
113
+ self.fade_anim.setEndValue(1.0)
114
+ self.fade_anim.setEasingCurve(QEasingCurve.Type.InOutQuad)
115
+
116
+ # Set up progress animation
117
+ self.progress_anim = QPropertyAnimation(self, b"progress")
118
+ self.progress_anim.setDuration(2000)
119
+ self.progress_anim.setStartValue(0.0)
120
+ self.progress_anim.setEndValue(1.0)
121
+ self.progress_anim.setEasingCurve(QEasingCurve.Type.InOutQuad)
122
+
123
+ # Start animations after everything is initialized
124
+ QTimer.singleShot(100, self.start_animations) # Small delay to ensure everything is ready
125
+
126
+ def start_animations(self):
127
+ """Start all animations"""
128
+ self.movie.start()
129
+ self.fade_anim.start()
130
+ self.progress_anim.start()
131
+ self.progress_anim.finished.connect(self._on_animation_finished)
132
+
133
+ @pyqtProperty(float)
134
+ def opacity(self):
135
+ return self._opacity
136
+
137
+ @opacity.setter
138
+ def opacity(self, value):
139
+ self._opacity = value
140
+ # Update opacity of overlay and text
141
+ self.overlay.setStyleSheet(f"background-color: rgba(0, 0, 0, {int(100 * value)});")
142
+ self.text_label.setStyleSheet(f"""
143
+ QLabel {{
144
+ color: rgba(255, 255, 255, {int(255 * value)});
145
+ background: transparent;
146
+ text-shadow: 2px 2px 4px rgba(0, 0, 0, {int(180 * value)}),
147
+ 0px 0px 10px rgba(52, 152, 219, {int(160 * value)});
148
+ }}
149
+ """)
150
+
151
+ @pyqtProperty(float)
152
+ def progress(self):
153
+ return self._progress
154
+
155
+ @progress.setter
156
+ def progress(self, value):
157
+ self._progress = value
158
+ # Update progress bar width
159
+ self.progress_bar.setFixedWidth(int(200 * value))
160
+
161
+ def _on_animation_finished(self):
162
+ """Handle animation completion"""
163
+ if self.next_widget:
164
+ QTimer.singleShot(500, self._finish_splash)
165
+
166
+ def _finish_splash(self):
167
+ """Clean up and show the main window"""
168
+ self.movie.stop()
169
+ self.fade_anim.stop()
170
+ self.progress_anim.stop()
171
+ self.close()
172
+ if self.next_widget:
173
+ self.next_widget.show()
174
+
175
+ def finish(self, widget):
176
+ """Store the widget to show after animation completes"""
177
+ self.next_widget = widget
@@ -110,28 +110,9 @@ if __name__ == '__main__':
110
110
  print(f"Number of products: {len(product_df)}")
111
111
 
112
112
  # Print sample queries
113
- print("\nSample SQL queries for joining the data:")
113
+ print("\nSample SQL queries")
114
114
  print("""
115
- -- Join sales with customer data
116
- SELECT s.*, c.FirstName, c.LastName, c.CustomerType
117
- FROM test_data.sample_sales_data s
118
- JOIN test_data.customer_data c ON s.CustomerID = c.CustomerID;
119
-
120
- -- Join sales with product data
121
- SELECT s.*, p.ProductName, p.Category, p.Brand
122
- FROM test_data.sample_sales_data s
123
- JOIN test_data.product_catalog p ON s.ProductID = p.ProductID;
124
-
125
- -- Three-way join with aggregation
126
- SELECT
127
- p.Category,
128
- c.CustomerType,
129
- COUNT(*) as NumOrders,
130
- SUM(s.TotalAmount) as TotalRevenue,
131
- AVG(s.Quantity) as AvgQuantity
132
- FROM test_data.sample_sales_data s
133
- JOIN test_data.customer_data c ON s.CustomerID = c.CustomerID
134
- JOIN test_data.product_catalog p ON s.ProductID = p.ProductID
135
- GROUP BY p.Category, c.CustomerType
136
- ORDER BY p.Category, c.CustomerType;
115
+ select * from product_catalog;
116
+ select * from customer_data;
117
+ select * from sample_sales_data;
137
118
  """)
Binary file
@@ -0,0 +1,123 @@
1
+ from PyQt6.QtCore import Qt, QRegularExpression
2
+ from PyQt6.QtGui import QFont, QColor, QSyntaxHighlighter, QTextCharFormat
3
+
4
+ class SQLSyntaxHighlighter(QSyntaxHighlighter):
5
+ def __init__(self, document):
6
+ super().__init__(document)
7
+ self.highlighting_rules = []
8
+
9
+ # SQL Keywords
10
+ keyword_format = QTextCharFormat()
11
+ keyword_format.setForeground(QColor("#0000FF")) # Blue
12
+ keyword_format.setFontWeight(QFont.Weight.Bold)
13
+ keywords = [
14
+ "\\bSELECT\\b", "\\bFROM\\b", "\\bWHERE\\b", "\\bAND\\b", "\\bOR\\b",
15
+ "\\bINNER\\b", "\\bOUTER\\b", "\\bLEFT\\b", "\\bRIGHT\\b", "\\bJOIN\\b",
16
+ "\\bON\\b", "\\bGROUP\\b", "\\bBY\\b", "\\bHAVING\\b", "\\bORDER\\b",
17
+ "\\bLIMIT\\b", "\\bOFFSET\\b", "\\bUNION\\b", "\\bEXCEPT\\b", "\\bINTERSECT\\b",
18
+ "\\bCREATE\\b", "\\bTABLE\\b", "\\bINDEX\\b", "\\bVIEW\\b", "\\bINSERT\\b",
19
+ "\\bINTO\\b", "\\bVALUES\\b", "\\bUPDATE\\b", "\\bSET\\b", "\\bDELETE\\b",
20
+ "\\bTRUNCATE\\b", "\\bALTER\\b", "\\bADD\\b", "\\bDROP\\b", "\\bCOLUMN\\b",
21
+ "\\bCONSTRAINT\\b", "\\bPRIMARY\\b", "\\bKEY\\b", "\\bFOREIGN\\b", "\\bREFERENCES\\b",
22
+ "\\bUNIQUE\\b", "\\bNOT\\b", "\\bNULL\\b", "\\bIS\\b", "\\bDISTINCT\\b",
23
+ "\\bCASE\\b", "\\bWHEN\\b", "\\bTHEN\\b", "\\bELSE\\b", "\\bEND\\b",
24
+ "\\bAS\\b", "\\bWITH\\b", "\\bBETWEEN\\b", "\\bLIKE\\b", "\\bIN\\b",
25
+ "\\bEXISTS\\b", "\\bALL\\b", "\\bANY\\b", "\\bSOME\\b", "\\bDESC\\b", "\\bASC\\b"
26
+ ]
27
+ for pattern in keywords:
28
+ regex = QRegularExpression(pattern, QRegularExpression.PatternOption.CaseInsensitiveOption)
29
+ self.highlighting_rules.append((regex, keyword_format))
30
+
31
+ # Functions
32
+ function_format = QTextCharFormat()
33
+ function_format.setForeground(QColor("#AA00AA")) # Purple
34
+ functions = [
35
+ "\\bAVG\\b", "\\bCOUNT\\b", "\\bSUM\\b", "\\bMAX\\b", "\\bMIN\\b",
36
+ "\\bCOALESCE\\b", "\\bNVL\\b", "\\bNULLIF\\b", "\\bCAST\\b", "\\bCONVERT\\b",
37
+ "\\bLOWER\\b", "\\bUPPER\\b", "\\bTRIM\\b", "\\bLTRIM\\b", "\\bRTRIM\\b",
38
+ "\\bLENGTH\\b", "\\bSUBSTRING\\b", "\\bREPLACE\\b", "\\bCONCAT\\b",
39
+ "\\bROUND\\b", "\\bFLOOR\\b", "\\bCEIL\\b", "\\bABS\\b", "\\bMOD\\b",
40
+ "\\bCURRENT_DATE\\b", "\\bCURRENT_TIME\\b", "\\bCURRENT_TIMESTAMP\\b",
41
+ "\\bEXTRACT\\b", "\\bDATE_PART\\b", "\\bTO_CHAR\\b", "\\bTO_DATE\\b"
42
+ ]
43
+ for pattern in functions:
44
+ regex = QRegularExpression(pattern, QRegularExpression.PatternOption.CaseInsensitiveOption)
45
+ self.highlighting_rules.append((regex, function_format))
46
+
47
+ # Numbers
48
+ number_format = QTextCharFormat()
49
+ number_format.setForeground(QColor("#009900")) # Green
50
+ self.highlighting_rules.append((
51
+ QRegularExpression("\\b[0-9]+\\b"),
52
+ number_format
53
+ ))
54
+
55
+ # Single-line string literals
56
+ string_format = QTextCharFormat()
57
+ string_format.setForeground(QColor("#CC6600")) # Orange/Brown
58
+ self.highlighting_rules.append((
59
+ QRegularExpression("'[^']*'"),
60
+ string_format
61
+ ))
62
+ self.highlighting_rules.append((
63
+ QRegularExpression("\"[^\"]*\""),
64
+ string_format
65
+ ))
66
+
67
+ # Comments
68
+ comment_format = QTextCharFormat()
69
+ comment_format.setForeground(QColor("#777777")) # Gray
70
+ comment_format.setFontItalic(True)
71
+ self.highlighting_rules.append((
72
+ QRegularExpression("--[^\n]*"),
73
+ comment_format
74
+ ))
75
+
76
+ # Multi-line comments
77
+ self.comment_start_expression = QRegularExpression("/\\*")
78
+ self.comment_end_expression = QRegularExpression("\\*/")
79
+ self.multi_line_comment_format = comment_format
80
+
81
+ def highlightBlock(self, text):
82
+ # Apply regular expression highlighting rules
83
+ for pattern, format in self.highlighting_rules:
84
+ match_iterator = pattern.globalMatch(text)
85
+ while match_iterator.hasNext():
86
+ match = match_iterator.next()
87
+ self.setFormat(match.capturedStart(), match.capturedLength(), format)
88
+
89
+ # Handle multi-line comments
90
+ self.setCurrentBlockState(0)
91
+
92
+ # If previous block was inside a comment, check if this block continues it
93
+ start_index = 0
94
+ if self.previousBlockState() != 1:
95
+ # Find the start of a comment
96
+ start_match = self.comment_start_expression.match(text)
97
+ if start_match.hasMatch():
98
+ start_index = start_match.capturedStart()
99
+ else:
100
+ return
101
+
102
+ while start_index >= 0:
103
+ # Find the end of the comment
104
+ end_match = self.comment_end_expression.match(text, start_index)
105
+
106
+ # If end match found
107
+ if end_match.hasMatch():
108
+ end_index = end_match.capturedStart()
109
+ comment_length = end_index - start_index + end_match.capturedLength()
110
+ self.setFormat(start_index, comment_length, self.multi_line_comment_format)
111
+
112
+ # Look for next comment
113
+ start_match = self.comment_start_expression.match(text, start_index + comment_length)
114
+ if start_match.hasMatch():
115
+ start_index = start_match.capturedStart()
116
+ else:
117
+ start_index = -1
118
+ else:
119
+ # No end found, comment continues to next block
120
+ self.setCurrentBlockState(1) # Still inside comment
121
+ comment_length = len(text) - start_index
122
+ self.setFormat(start_index, comment_length, self.multi_line_comment_format)
123
+ start_index = -1
@@ -0,0 +1,120 @@
1
+ Metadata-Version: 2.4
2
+ Name: sqlshell
3
+ Version: 0.1.8
4
+ Summary: A powerful SQL shell with GUI interface for data analysis
5
+ Home-page: https://github.com/yourusername/sqlshell
6
+ Author: SQLShell Team
7
+ License: MIT
8
+ Project-URL: Homepage, https://github.com/oyvinrog/SQLShell
9
+ Keywords: sql,data analysis,gui,duckdb
10
+ Classifier: Development Status :: 3 - Alpha
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.8
14
+ Classifier: Programming Language :: Python :: 3.9
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Requires-Python: >=3.8
18
+ Description-Content-Type: text/markdown
19
+ Requires-Dist: pandas>=2.0.0
20
+ Requires-Dist: numpy>=1.24.0
21
+ Requires-Dist: PyQt6>=6.4.0
22
+ Requires-Dist: duckdb>=0.9.0
23
+ Requires-Dist: openpyxl>=3.1.0
24
+ Requires-Dist: pyarrow>=14.0.1
25
+ Requires-Dist: fastparquet>=2023.10.1
26
+ Requires-Dist: xlrd>=2.0.1
27
+ Dynamic: home-page
28
+ Dynamic: requires-python
29
+
30
+ # SQLShell
31
+
32
+ <div align="center">
33
+
34
+ ![SQLShell Interface](sqlshell_logo.png)
35
+
36
+ **A modern SQL REPL interface for seamless querying of Excel, Parquet, and SQLite databases**
37
+
38
+ ![SQLShell Interface](sqlshell_demo.png)
39
+
40
+ </div>
41
+
42
+ ## 🚀 Key Features
43
+
44
+ - **Interactive SQL Interface** - Rich syntax highlighting for enhanced query writing
45
+ - **DuckDB Integration** - Built-in support for local DuckDB database (pool.db)
46
+ - **Multi-Format Support** - Import and query Excel (.xlsx, .xls) and CSV files effortlessly
47
+ - **Modern UI** - Clean, tabular results display with intuitive controls
48
+ - **Productivity Tools** - Streamlined workflow with keyboard shortcuts (e.g., Ctrl+Enter for query execution)
49
+
50
+ ## 📦 Installation
51
+
52
+ ### Linux Setup with Virtual Environment
53
+
54
+ ```bash
55
+ # Create and activate virtual environment
56
+ python3 -m venv ~/.venv/sqlshell
57
+ source ~/.venv/sqlshell/bin/activate
58
+
59
+ # Install SQLShell
60
+ pip install sqlshell
61
+
62
+ # Configure shell alias
63
+ echo 'alias sqls="~/.venv/sqlshell/bin/sqls"' >> ~/.bashrc # or ~/.zshrc for Zsh
64
+ source ~/.bashrc # or source ~/.zshrc
65
+ ```
66
+
67
+ ### Windows Quick Start
68
+ SQLShell is immediately available via the `sqls` command after installation:
69
+ ```bash
70
+ pip install sqlshell
71
+ ```
72
+
73
+ ## 🎯 Getting Started
74
+
75
+ 1. **Launch the Application**
76
+ ```bash
77
+ sqls
78
+ ```
79
+
80
+ 2. **Database Connection**
81
+ - SQLShell automatically connects to a local DuckDB database named 'pool.db'
82
+
83
+ 3. **Working with Excel Files**
84
+ - Click "Browse Excel" to select your file
85
+ - File contents are loaded as 'imported_data' table
86
+ - Query using standard SQL syntax
87
+
88
+ 4. **Query Execution**
89
+ - Enter SQL in the editor
90
+ - Execute using Ctrl+Enter or the "Execute" button
91
+ - View results in the structured output panel
92
+
93
+ ## 📝 Query Examples
94
+
95
+ ### Basic Join Operation
96
+ ```sql
97
+ SELECT *
98
+ FROM sample_sales_data cd
99
+ INNER JOIN product_catalog pc ON pc.productid = cd.productid
100
+ LIMIT 3;
101
+ ```
102
+
103
+ ### Multi-Statement Queries
104
+ ```sql
105
+ -- Create a temporary view
106
+ CREATE OR REPLACE TEMPORARY VIEW test_v AS
107
+ SELECT *
108
+ FROM sample_sales_data cd
109
+ INNER JOIN product_catalog pc ON pc.productid = cd.productid;
110
+
111
+ -- Query the view
112
+ SELECT DISTINCT productid
113
+ FROM test_v;
114
+ ```
115
+
116
+ ## 💡 Pro Tips
117
+
118
+ - Use temporary views for complex query organization
119
+ - Leverage keyboard shortcuts for efficient workflow
120
+ - Explore the multi-format support for various data sources
@@ -0,0 +1,21 @@
1
+ sqlshell/__init__.py,sha256=DqhqqdKdvfwO2iUG1Yd7WPmInpG-OcGhqP8LgblopgI,164
2
+ sqlshell/create_test_data.py,sha256=AzrEsKlZsR1H1Xlp7IKOzWQ2N6FsVISJbc6CerI8IJ0,1954
3
+ sqlshell/editor.py,sha256=4252dxINzJd1jr7CqgSI6IxUYHdkZ1OGZ1qBYN5-MKM,14396
4
+ sqlshell/main.py,sha256=0eQlAQnRkFV14Ot8vJikG7Vq_zkSAqqohu50Y8UREyQ,75480
5
+ sqlshell/setup.py,sha256=bAIXTpgAHhBRmPdT13Klzq16cjd4w4NOYSbyV_rxjlQ,1245
6
+ sqlshell/splash_screen.py,sha256=XkXvSURgQzZfxJvP231Ue4J2E49ph21tWbvfGU03Ogk,6914
7
+ sqlshell/sqlshell_demo.png,sha256=dPp9J1FVqQVfrh-gekosuha2Jw2p2--wxbOmt2kr7fg,133550
8
+ sqlshell/syntax_highlighter.py,sha256=mPwsD8N4XzAUx0IgwlelyfjUhe0xmH0Ug3UI9hTcHz0,5861
9
+ sqlshell/data/create_test_data.py,sha256=sUTcf50V8-bVwYV2VNTLK65c-iHiU4wb99By67I10zM,5404
10
+ sqlshell/resources/__init__.py,sha256=VLTJ_5pUHhctRiV8UZDvG-jnsjgT6JQvW-ZPzIJqBIY,44
11
+ sqlshell/resources/create_icon.py,sha256=ubNYyBYx5HtYpV8eiGY8Fb1VWUoQt-npaqUckiCimnQ,2030
12
+ sqlshell/resources/create_splash.py,sha256=cj6BpMtD1crBkcSxt-ssJIFIZv43UDqLME8FF0fgkoA,2104
13
+ sqlshell/resources/splash_screen.gif,sha256=H24DQBdK1EsqQTWZkgInjM5ouOzY4cMesUoza10auNg,3070484
14
+ sqlshell/sqlshell/__init__.py,sha256=6Wp5nabfTzH5rkC-2jYo_ZjCuw8utmj21Jpy8vBuliI,100
15
+ sqlshell/sqlshell/create_test_data.py,sha256=TFXgWeK1l3l_c4Dg38yS8Df4sBUfOZcBucXngtpThvk,4624
16
+ sqlshell/sqlshell/create_test_databases.py,sha256=oqryFJJahqLFsAjBFM4r9Fe1ea7djDcRpT9U_aBf7PU,3573
17
+ sqlshell-0.1.8.dist-info/METADATA,sha256=bIt-ocCENwgCT7ZxBMOUOaABM0PWonDQ7x2rYy2j2fU,3323
18
+ sqlshell-0.1.8.dist-info/WHEEL,sha256=1tXe9gY0PYatrMPMDd6jXqjfpz_B-Wqm32CPfRC58XU,91
19
+ sqlshell-0.1.8.dist-info/entry_points.txt,sha256=Kd0fOvyOW7UiTgTVY7abVOmDIH2Y2nawGTp5kVadac4,44
20
+ sqlshell-0.1.8.dist-info/top_level.txt,sha256=ahwsMFhvAqI97ZkT2xvHL5iZCO1p13mNiUOFkdSFwms,9
21
+ sqlshell-0.1.8.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (76.0.0)
2
+ Generator: setuptools (77.0.3)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5