Contributing¶
Guide for contributing to elastic-script development.
Getting Started¶
Prerequisites¶
- Java 21+ - Required for Elasticsearch development
- Git - Version control
- Python 3.9+ - For notebooks and testing
Clone the Repository¶
git clone https://github.com/bahaaldine/moltler.git
cd elastic-script
# Initialize Elasticsearch submodule
git submodule init
git submodule update
Quick Start¶
Use the quick-start script to set up everything:
This will:
- ✅ Build the elastic-script plugin
- ✅ Start Elasticsearch with the plugin
- ✅ Load sample data
- ✅ Set up Jupyter notebooks
- ✅ Launch the notebook server
Development Workflow¶
1. Make Your Changes¶
Edit files in the elastic-script/ directory:
elastic-script/
├── src/main/java/org/elasticsearch/xpack/escript/
│ ├── parser/ # ANTLR grammar
│ ├── handlers/ # Statement handlers
│ ├── functions/ # Built-in functions
│ ├── executors/ # Execution engine
│ └── actions/ # REST API
└── src/test/java/ # Unit tests
2. Rebuild the Plugin¶
After making changes:
3. Restart Elasticsearch¶
4. Test Your Changes¶
# Run unit tests
./gradlew :elastic-script:test
# Run E2E tests
cd tests/e2e
python run_notebook_tests.py
Adding New Functions¶
1. Choose the Right Category¶
| Category | Location | Example Functions |
|---|---|---|
| String | primitives/StringBuiltInFunctions.java | LENGTH, UPPER, TRIM |
| Number | primitives/NumberBuiltInFunctions.java | ABS, ROUND, SQRT |
| Array | primitives/ArrayBuiltInFunctions.java | ARRAY_LENGTH, ARRAY_APPEND |
| Date | primitives/DateBuiltInFunctions.java | CURRENT_DATE, DATE_ADD |
| Document | primitives/DocumentBuiltInFunctions.java | DOCUMENT_GET, DOCUMENT_KEYS |
| Elasticsearch | datasources/ESFunctions.java | ES_GET, ES_INDEX |
| AI | ai/OpenAIFunctions.java | LLM_COMPLETE |
| Integration | thirdparty/ | SLACK_SEND, K8S_GET_PODS |
2. Implement the Function¶
// In the appropriate *Functions.java file:
public static void register(BuiltInFunctionRegistry registry) {
registry.register("MY_FUNCTION", (args) -> {
// Validate arguments
if (args.size() != 2) {
throw new IllegalArgumentException(
"MY_FUNCTION expects 2 arguments"
);
}
String input = (String) args.get(0);
int count = ((Number) args.get(1)).intValue();
// Implement logic
return input.repeat(count);
});
}
3. Add Documentation¶
Update docs/functions/ with your new function:
### MY_FUNCTION
Repeats a string a specified number of times.
\`\`\`sql
DECLARE result STRING = MY_FUNCTION('hello', 3);
-- Returns: 'hellohellohello'
\`\`\`
**Syntax:** `MY_FUNCTION(string, count)`
4. Add Tests¶
// In src/test/java/.../MyFunctionTests.java
@Test
public void testMyFunction() {
String result = executeProcedure("""
CREATE PROCEDURE test()
BEGIN
RETURN MY_FUNCTION('hi', 2);
END PROCEDURE;
CALL test()
""");
assertEquals("hihi", result);
}
Adding New Statement Types¶
1. Update the Grammar¶
Edit ElasticScript.g4:
statement
: declareStatement
| setStatement
| myNewStatement // Add your statement type
// ...
;
myNewStatement
: MY_KEYWORD expression ';'
;
// Add lexer token
MY_KEYWORD: 'MY_KEYWORD';
2. Regenerate Parser¶
3. Create Handler¶
// handlers/MyNewStatementHandler.java
public class MyNewStatementHandler {
public CompletableFuture<Object> handle(
MyNewStatementContext ctx,
ExecutionContext context,
ProcedureExecutor executor
) {
// Implementation
return CompletableFuture.completedFuture(result);
}
}
4. Register in Executor¶
// In ProcedureExecutor.java
if (statement instanceof MyNewStatementContext) {
return myNewStatementHandler.handle(
(MyNewStatementContext) statement,
context,
this
);
}
Code Style¶
Java¶
- Follow Elasticsearch coding conventions
- Use descriptive variable names
- Add Javadoc for public methods
- Handle errors with appropriate exceptions
/**
* Executes a procedure by name.
*
* @param name the procedure name
* @param args the procedure arguments
* @return the procedure result
* @throws ProcedureNotFoundException if procedure doesn't exist
*/
public CompletableFuture<Object> callProcedure(
String name,
List<Object> args
) {
// Implementation
}
Grammar¶
- Use UPPER_CASE for keywords
- Use camelCase for rule names
- Add comments for complex rules
Pull Request Process¶
- Fork the repository
- Create a branch for your feature/fix
- Write tests for your changes
- Update documentation as needed
- Submit a PR with a clear description
PR Checklist¶
- Unit tests pass (
./gradlew :elastic-script:test) - E2E tests pass (
python tests/e2e/run_notebook_tests.py) - Documentation updated
- Code follows style guidelines
- Commit messages are clear
Getting Help¶
- Issues: Open a GitHub issue for bugs or features
- Discussions: Use GitHub Discussions for questions
- Documentation: Check the docs at elastic-script docs